@tetrascience-npm/tetrascience-react-ui 0.6.0 → 0.7.0-beta.103.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (184) hide show
  1. package/README.md +55 -0
  2. package/dist/components/ai/chain-of-thought.cjs +1 -1
  3. package/dist/components/ai/chain-of-thought.cjs.map +1 -1
  4. package/dist/components/ai/chain-of-thought.js +5 -5
  5. package/dist/components/ai/chain-of-thought.js.map +1 -1
  6. package/dist/components/ai/conversation.cjs +2 -2
  7. package/dist/components/ai/conversation.cjs.map +1 -1
  8. package/dist/components/ai/conversation.js +2 -2
  9. package/dist/components/ai/conversation.js.map +1 -1
  10. package/dist/components/ai/queue.cjs +1 -1
  11. package/dist/components/ai/queue.cjs.map +1 -1
  12. package/dist/components/ai/queue.js +9 -9
  13. package/dist/components/ai/queue.js.map +1 -1
  14. package/dist/components/charts/AreaGraph/AreaGraph.cjs +1 -1
  15. package/dist/components/charts/AreaGraph/AreaGraph.cjs.map +1 -1
  16. package/dist/components/charts/AreaGraph/AreaGraph.js +165 -103
  17. package/dist/components/charts/AreaGraph/AreaGraph.js.map +1 -1
  18. package/dist/components/charts/BarGraph/BarGraph.cjs +1 -1
  19. package/dist/components/charts/BarGraph/BarGraph.cjs.map +1 -1
  20. package/dist/components/charts/BarGraph/BarGraph.js +135 -90
  21. package/dist/components/charts/BarGraph/BarGraph.js.map +1 -1
  22. package/dist/components/charts/Boxplot/Boxplot.cjs +1 -1
  23. package/dist/components/charts/Boxplot/Boxplot.cjs.map +1 -1
  24. package/dist/components/charts/Boxplot/Boxplot.js +130 -92
  25. package/dist/components/charts/Boxplot/Boxplot.js.map +1 -1
  26. package/dist/components/charts/ChartTooltip/ChartTooltip.cjs +2 -0
  27. package/dist/components/charts/ChartTooltip/ChartTooltip.cjs.map +1 -0
  28. package/dist/components/charts/ChartTooltip/ChartTooltip.js +163 -0
  29. package/dist/components/charts/ChartTooltip/ChartTooltip.js.map +1 -0
  30. package/dist/components/charts/ChartTooltip/lines.cjs +2 -0
  31. package/dist/components/charts/ChartTooltip/lines.cjs.map +1 -0
  32. package/dist/components/charts/ChartTooltip/lines.js +29 -0
  33. package/dist/components/charts/ChartTooltip/lines.js.map +1 -0
  34. package/dist/components/charts/Chromatogram/Chromatogram.cjs +1 -1
  35. package/dist/components/charts/Chromatogram/Chromatogram.cjs.map +1 -1
  36. package/dist/components/charts/Chromatogram/Chromatogram.js +75 -61
  37. package/dist/components/charts/Chromatogram/Chromatogram.js.map +1 -1
  38. package/dist/components/charts/ChromatogramChart/ChromatogramChart.cjs +1 -1
  39. package/dist/components/charts/ChromatogramChart/ChromatogramChart.cjs.map +1 -1
  40. package/dist/components/charts/ChromatogramChart/ChromatogramChart.js +116 -108
  41. package/dist/components/charts/ChromatogramChart/ChromatogramChart.js.map +1 -1
  42. package/dist/components/charts/ChromatogramChart/annotations.cjs +1 -1
  43. package/dist/components/charts/ChromatogramChart/annotations.cjs.map +1 -1
  44. package/dist/components/charts/ChromatogramChart/annotations.js +32 -32
  45. package/dist/components/charts/ChromatogramChart/annotations.js.map +1 -1
  46. package/dist/components/charts/ChromatogramChart/boundaryMarkers.cjs +1 -1
  47. package/dist/components/charts/ChromatogramChart/boundaryMarkers.cjs.map +1 -1
  48. package/dist/components/charts/ChromatogramChart/boundaryMarkers.js +6 -6
  49. package/dist/components/charts/ChromatogramChart/boundaryMarkers.js.map +1 -1
  50. package/dist/components/charts/ChromatogramChart/constants.cjs +1 -1
  51. package/dist/components/charts/ChromatogramChart/constants.cjs.map +1 -1
  52. package/dist/components/charts/ChromatogramChart/constants.js +11 -5
  53. package/dist/components/charts/ChromatogramChart/constants.js.map +1 -1
  54. package/dist/components/charts/ChromatogramChart/dataProcessing.cjs +1 -1
  55. package/dist/components/charts/ChromatogramChart/dataProcessing.cjs.map +1 -1
  56. package/dist/components/charts/ChromatogramChart/dataProcessing.js +38 -49
  57. package/dist/components/charts/ChromatogramChart/dataProcessing.js.map +1 -1
  58. package/dist/components/charts/DotPlot/DotPlot.cjs +1 -1
  59. package/dist/components/charts/DotPlot/DotPlot.cjs.map +1 -1
  60. package/dist/components/charts/DotPlot/DotPlot.js +112 -88
  61. package/dist/components/charts/DotPlot/DotPlot.js.map +1 -1
  62. package/dist/components/charts/Histogram/Histogram.cjs +1 -1
  63. package/dist/components/charts/Histogram/Histogram.cjs.map +1 -1
  64. package/dist/components/charts/Histogram/Histogram.js +132 -115
  65. package/dist/components/charts/Histogram/Histogram.js.map +1 -1
  66. package/dist/components/charts/LineGraph/LineGraph.cjs +1 -1
  67. package/dist/components/charts/LineGraph/LineGraph.cjs.map +1 -1
  68. package/dist/components/charts/LineGraph/LineGraph.js +151 -111
  69. package/dist/components/charts/LineGraph/LineGraph.js.map +1 -1
  70. package/dist/components/charts/PieChart/PieChart.cjs +1 -1
  71. package/dist/components/charts/PieChart/PieChart.cjs.map +1 -1
  72. package/dist/components/charts/PieChart/PieChart.js +81 -70
  73. package/dist/components/charts/PieChart/PieChart.js.map +1 -1
  74. package/dist/components/charts/PlateMap/PlateMap.cjs +1 -1
  75. package/dist/components/charts/PlateMap/PlateMap.cjs.map +1 -1
  76. package/dist/components/charts/PlateMap/PlateMap.js +271 -256
  77. package/dist/components/charts/PlateMap/PlateMap.js.map +1 -1
  78. package/dist/components/charts/PlateMap/constants.cjs +1 -1
  79. package/dist/components/charts/PlateMap/constants.cjs.map +1 -1
  80. package/dist/components/charts/PlateMap/constants.js +20 -29
  81. package/dist/components/charts/PlateMap/constants.js.map +1 -1
  82. package/dist/components/charts/ScatterGraph/ScatterGraph.cjs +1 -1
  83. package/dist/components/charts/ScatterGraph/ScatterGraph.cjs.map +1 -1
  84. package/dist/components/charts/ScatterGraph/ScatterGraph.js +154 -106
  85. package/dist/components/charts/ScatterGraph/ScatterGraph.js.map +1 -1
  86. package/dist/components/composed/DataAppShell/DataAppShell.cjs +1 -1
  87. package/dist/components/composed/DataAppShell/DataAppShell.cjs.map +1 -1
  88. package/dist/components/composed/DataAppShell/DataAppShell.js +118 -111
  89. package/dist/components/composed/DataAppShell/DataAppShell.js.map +1 -1
  90. package/dist/components/composed/PlateMapEditor/PlateMapGrid.cjs +1 -1
  91. package/dist/components/composed/PlateMapEditor/PlateMapGrid.cjs.map +1 -1
  92. package/dist/components/composed/PlateMapEditor/PlateMapGrid.js +1 -1
  93. package/dist/components/composed/PlateMapEditor/PlateMapGrid.js.map +1 -1
  94. package/dist/components/composed/PlateMapEditor/WellLegend.cjs +1 -1
  95. package/dist/components/composed/PlateMapEditor/WellLegend.cjs.map +1 -1
  96. package/dist/components/composed/PlateMapEditor/WellLegend.js +8 -8
  97. package/dist/components/composed/PlateMapEditor/WellLegend.js.map +1 -1
  98. package/dist/components/composed/RichListItem/RichListItem.cjs +1 -1
  99. package/dist/components/composed/RichListItem/RichListItem.cjs.map +1 -1
  100. package/dist/components/composed/RichListItem/RichListItem.js +16 -16
  101. package/dist/components/composed/RichListItem/RichListItem.js.map +1 -1
  102. package/dist/components/ui/accordion.cjs +1 -1
  103. package/dist/components/ui/accordion.cjs.map +1 -1
  104. package/dist/components/ui/accordion.js +1 -1
  105. package/dist/components/ui/accordion.js.map +1 -1
  106. package/dist/components/ui/badge.cjs +1 -1
  107. package/dist/components/ui/badge.cjs.map +1 -1
  108. package/dist/components/ui/badge.js +8 -8
  109. package/dist/components/ui/badge.js.map +1 -1
  110. package/dist/components/ui/button.cjs +1 -1
  111. package/dist/components/ui/button.cjs.map +1 -1
  112. package/dist/components/ui/button.js +11 -11
  113. package/dist/components/ui/button.js.map +1 -1
  114. package/dist/components/ui/checkbox.cjs +1 -1
  115. package/dist/components/ui/checkbox.cjs.map +1 -1
  116. package/dist/components/ui/checkbox.js +1 -1
  117. package/dist/components/ui/checkbox.js.map +1 -1
  118. package/dist/components/ui/combobox.cjs +1 -1
  119. package/dist/components/ui/combobox.cjs.map +1 -1
  120. package/dist/components/ui/combobox.js +12 -12
  121. package/dist/components/ui/combobox.js.map +1 -1
  122. package/dist/components/ui/input-group.cjs +1 -1
  123. package/dist/components/ui/input-group.cjs.map +1 -1
  124. package/dist/components/ui/input-group.js +19 -19
  125. package/dist/components/ui/input-group.js.map +1 -1
  126. package/dist/components/ui/item.cjs +1 -1
  127. package/dist/components/ui/item.cjs.map +1 -1
  128. package/dist/components/ui/item.js +1 -1
  129. package/dist/components/ui/item.js.map +1 -1
  130. package/dist/components/ui/menubar.cjs +1 -1
  131. package/dist/components/ui/menubar.cjs.map +1 -1
  132. package/dist/components/ui/menubar.js +1 -1
  133. package/dist/components/ui/menubar.js.map +1 -1
  134. package/dist/components/ui/navigation-menu.cjs +1 -1
  135. package/dist/components/ui/navigation-menu.cjs.map +1 -1
  136. package/dist/components/ui/navigation-menu.js +54 -54
  137. package/dist/components/ui/navigation-menu.js.map +1 -1
  138. package/dist/components/ui/radio-group.cjs +1 -1
  139. package/dist/components/ui/radio-group.cjs.map +1 -1
  140. package/dist/components/ui/radio-group.js +1 -1
  141. package/dist/components/ui/radio-group.js.map +1 -1
  142. package/dist/components/ui/resizable.cjs +1 -1
  143. package/dist/components/ui/resizable.cjs.map +1 -1
  144. package/dist/components/ui/resizable.js +27 -15
  145. package/dist/components/ui/resizable.js.map +1 -1
  146. package/dist/components/ui/select.cjs +1 -1
  147. package/dist/components/ui/select.cjs.map +1 -1
  148. package/dist/components/ui/select.js +1 -1
  149. package/dist/components/ui/select.js.map +1 -1
  150. package/dist/components/ui/slider.cjs +1 -1
  151. package/dist/components/ui/slider.cjs.map +1 -1
  152. package/dist/components/ui/slider.js +9 -9
  153. package/dist/components/ui/slider.js.map +1 -1
  154. package/dist/components/ui/table.cjs +1 -1
  155. package/dist/components/ui/table.cjs.map +1 -1
  156. package/dist/components/ui/table.js +13 -13
  157. package/dist/components/ui/table.js.map +1 -1
  158. package/dist/components/ui/tabs.cjs +1 -1
  159. package/dist/components/ui/tabs.cjs.map +1 -1
  160. package/dist/components/ui/tabs.js +7 -7
  161. package/dist/components/ui/tabs.js.map +1 -1
  162. package/dist/components/ui/toggle.cjs +1 -1
  163. package/dist/components/ui/toggle.cjs.map +1 -1
  164. package/dist/components/ui/toggle.js +12 -12
  165. package/dist/components/ui/toggle.js.map +1 -1
  166. package/dist/hooks/use-element-size.cjs +2 -0
  167. package/dist/hooks/use-element-size.cjs.map +1 -0
  168. package/dist/hooks/use-element-size.js +21 -0
  169. package/dist/hooks/use-element-size.js.map +1 -0
  170. package/dist/hooks/use-plotly-theme.cjs +1 -1
  171. package/dist/hooks/use-plotly-theme.cjs.map +1 -1
  172. package/dist/hooks/use-plotly-theme.js +4 -2
  173. package/dist/hooks/use-plotly-theme.js.map +1 -1
  174. package/dist/index.cjs +1 -1
  175. package/dist/index.css +1 -1
  176. package/dist/index.d.ts +254 -77
  177. package/dist/index.js +587 -581
  178. package/dist/index.js.map +1 -1
  179. package/dist/index.tailwind.css +1 -1
  180. package/dist/utils/colors.cjs +1 -1
  181. package/dist/utils/colors.cjs.map +1 -1
  182. package/dist/utils/colors.js +38 -93
  183. package/dist/utils/colors.js.map +1 -1
  184. package/package.json +18 -12
@@ -1 +1 @@
1
- {"version":3,"file":"AreaGraph.js","sources":["../../../../src/components/charts/AreaGraph/AreaGraph.tsx"],"sourcesContent":["import Plotly from \"plotly.js-dist\";\nimport React, { useEffect, useRef, useMemo } from \"react\";\n\nimport { usePlotlyTheme } from \"@/hooks/use-plotly-theme\";\n\ninterface AreaDataSeries {\n x: number[];\n y: number[];\n name: string;\n color: string;\n fill?: \"tozeroy\" | \"tonexty\" | \"toself\";\n}\n\ntype AreaGraphVariant = \"normal\" | \"stacked\";\n\ninterface AreaGraphProps {\n dataSeries: AreaDataSeries[];\n width?: number;\n height?: number;\n xRange?: [number, number];\n yRange?: [number, number];\n variant?: AreaGraphVariant;\n xTitle?: string;\n yTitle?: string;\n title?: string;\n}\n\nconst AreaGraph: React.FC<AreaGraphProps> = ({\n dataSeries,\n width = 1000,\n height = 600,\n xRange,\n yRange,\n variant = \"normal\",\n xTitle = \"Columns\",\n yTitle = \"Rows\",\n title = \"Area Graph\",\n}) => {\n const plotRef = useRef<HTMLDivElement>(null);\n const theme = usePlotlyTheme();\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: variant === \"stacked\" ? 0 : minY - yPadding,\n yMax: maxY + yPadding,\n };\n }, [dataSeries, variant]);\n\n const effectiveXRange = useMemo(\n () => xRange || [xMin, xMax],\n [xRange, xMin, xMax],\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 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 let data;\n\n if (variant === \"stacked\") {\n // For stacked mode, we need to calculate cumulative values\n const cumulativeY = new Array(dataSeries[0]?.x.length || 0).fill(0);\n\n data = dataSeries.map((series, index) => {\n // Calculate cumulative values for this series\n const stackedY = series.y.map((value, i) => {\n const result = cumulativeY[i] + value;\n cumulativeY[i] = result;\n return result;\n });\n\n return {\n x: series.x,\n y: stackedY,\n type: \"scatter\" as const,\n mode: \"lines\" as const,\n name: series.name,\n fill: index === 0 ? (\"tozeroy\" as const) : (\"tonexty\" as const),\n fillcolor: series.color,\n line: {\n color: series.color,\n width: 2,\n },\n };\n });\n } else {\n // Normal mode - each area fills independently from zero\n data = dataSeries.map((series) => ({\n x: series.x,\n y: series.y,\n type: \"scatter\" as const,\n mode: \"lines\" as const,\n name: series.name,\n fill: series.fill || (\"tozeroy\" as const),\n fillcolor: series.color,\n line: {\n color: series.color,\n width: 2,\n },\n }));\n }\n\n const layout = {\n width,\n height: height,\n title: titleOptions,\n margin: { l: 80, r: 40, b: 80, t: 80, pad: 0 },\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: 15,\n },\n gridcolor: theme.gridColor,\n range: xRange,\n autorange: !xRange,\n tickmode: \"array\" as const,\n tickvals: xTicks,\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: 15,\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: 13,\n color: theme.legendColor,\n family: \"Inter, sans-serif\",\n weight: 500,\n lineheight: 18,\n },\n },\n showlegend: true,\n };\n\n const config = {\n responsive: true,\n displayModeBar: false,\n displaylogo: false,\n };\n\n Plotly.newPlot(plotRef.current, data, layout, config);\n\n // Capture ref value for cleanup\n const plotElement = plotRef.current;\n\n // Cleanup function\n return () => {\n if (plotElement) {\n Plotly.purge(plotElement);\n }\n };\n }, [dataSeries, width, height, xRange, yRange, effectiveXRange, effectiveYRange, variant, xTitle, yTitle, titleOptions, tickOptions, xTicks, yTicks, theme]);\n\n return (\n <div className=\"area-graph-container\">\n <div ref={plotRef} style={{ width: \"100%\", height: \"100%\" }} />\n </div>\n );\n};\n\nexport { AreaGraph };\nexport type { AreaDataSeries, AreaGraphVariant, AreaGraphProps };\n"],"names":["AreaGraph","dataSeries","width","height","xRange","yRange","variant","xTitle","yTitle","title","plotRef","useRef","theme","usePlotlyTheme","xMin","xMax","yMin","yMax","useMemo","minX","maxX","minY","maxY","series","x","y","xPadding","yPadding","effectiveXRange","effectiveYRange","xTicks","range","step","ticks","current","yTicks","tickOptions","titleOptions","useEffect","data","cumulativeY","index","stackedY","value","i","result","layout","config","Plotly","plotElement","jsx"],"mappings":"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"}
1
+ {"version":3,"file":"AreaGraph.js","sources":["../../../../src/components/charts/AreaGraph/AreaGraph.tsx"],"sourcesContent":["import Plotly from \"plotly.js-dist\";\nimport React, { useEffect, useRef, useMemo } from \"react\";\n\nimport { chartTooltipLines, useChartTooltip } from \"../ChartTooltip\";\n\nimport { useElementSize } from \"@/hooks/use-element-size\";\nimport { usePlotlyTheme } from \"@/hooks/use-plotly-theme\";\nimport { cn } from \"@/lib/utils\";\nimport { seriesColor } from \"@/utils/colors\";\n\ninterface AreaDataSeries {\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 fill?: \"tozeroy\" | \"tonexty\" | \"toself\";\n}\n\ntype AreaGraphVariant = \"normal\" | \"stacked\";\n\n/** Top margin reserving room for the 32px title; reduced when no title is set */\nconst TITLE_MARGIN_TOP = 80;\nconst NO_TITLE_MARGIN_TOP = 40;\n\ninterface AreaGraphProps {\n dataSeries: AreaDataSeries[];\n /**\n * Fixed width in pixels. When omitted, the chart fills its container and\n * tracks the container's width via a `ResizeObserver`.\n */\n width?: number;\n /**\n * Fixed height in pixels. When omitted, the chart fills its container and\n * tracks the container's height via a `ResizeObserver`.\n */\n height?: number;\n xRange?: [number, number];\n yRange?: [number, number];\n variant?: AreaGraphVariant;\n xTitle?: string;\n yTitle?: string;\n title?: string;\n /**\n * Categorical labels for the x-axis ticks. When provided, the x data values\n * still drive area positioning but the displayed tick labels match these\n * strings in order (e.g. [\"Mon\", \"Tue\", …]). Should align 1:1 with the\n * unique, ordered x values across all series.\n */\n xTickText?: string[];\n}\n\nconst AreaGraph: React.FC<AreaGraphProps> = ({\n dataSeries,\n width,\n height,\n xRange,\n yRange,\n variant = \"normal\",\n xTitle,\n yTitle,\n title,\n xTickText,\n}) => {\n const plotRef = useRef<HTMLDivElement>(null);\n const theme = usePlotlyTheme();\n\n // When width/height are omitted the chart fills its container; otherwise the\n // explicit pixel size wins. The container is measured either way (cheap) but\n // only used as the resolved size for the omitted dimension(s).\n const [containerRef, measured] = useElementSize<HTMLDivElement>();\n const resolvedWidth = width ?? measured.width;\n const resolvedHeight = height ?? measured.height;\n const hasSize = resolvedWidth > 0 && resolvedHeight > 0;\n // Fill is per-dimension: omit width to fill the container width, omit height\n // to fill its height (so e.g. a fixed width with a container-driven height works).\n const fillWidth = width === undefined;\n const fillHeight = height === undefined;\n\n // Hold the latest resolved size in a ref so the newPlot effect can read it\n // without listing it as a dependency — size changes are handled by a\n // separate relayout effect rather than by tearing down and recreating the plot.\n const sizeRef = useRef({ width: resolvedWidth, height: resolvedHeight });\n sizeRef.current = { width: resolvedWidth, height: resolvedHeight };\n const plotInitedRef = useRef(false);\n // Size last applied to the plot, so the resize effect can skip a redundant\n // relayout right after newPlot already drew at that size.\n const appliedSizeRef = useRef({ width: 0, height: 0 });\n const { bindTooltip, tooltipElement } = useChartTooltip({\n // Stacked traces carry the original series values as customdata;\n // display those instead of the cumulative stack heights\n getLines: (points) =>\n chartTooltipLines(\n points.map((point) =>\n typeof point.customdata === \"number\"\n ? { ...point, y: point.customdata }\n : point,\n ),\n { xLabel: xTitle, yLabel: yTitle },\n ),\n });\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: variant === \"stacked\" ? 0 : minY - yPadding,\n yMax: maxY + yPadding,\n };\n }, [dataSeries, variant]);\n\n const effectiveXRange = useMemo(\n () => xRange || [xMin, xMax],\n [xRange, xMin, xMax],\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 // When categorical labels are supplied, ticks must sit on the actual data\n // x-positions rather than the computed nice-step values above. Sorted\n // ascending so labels map deterministically to x regardless of series order.\n const xDataValues = useMemo(\n () => [...new Set(dataSeries.flatMap((s) => s.x))].sort((a, b) => a - b),\n [dataSeries],\n );\n\n // Only apply categorical labels when they align 1:1 with the tick positions;\n // a mismatch would silently mis-label ticks, so fall back to numeric ticks.\n const useCategoricalX = !!xTickText && xTickText.length === xDataValues.length;\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 title\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 : undefined,\n [title, theme],\n );\n\n useEffect(() => {\n if (!plotRef.current || !hasSize) return;\n\n let data;\n\n if (variant === \"stacked\") {\n // For stacked mode, we need to calculate cumulative values\n const cumulativeY = new Array(dataSeries[0]?.x.length || 0).fill(0);\n\n data = dataSeries.map((series, index) => {\n // Calculate cumulative values for this series\n const stackedY = series.y.map((value, i) => {\n const result = cumulativeY[i] + value;\n cumulativeY[i] = result;\n return result;\n });\n\n const color = seriesColor(index, series.color);\n return {\n x: series.x,\n y: stackedY,\n // Tooltips report the series' own values, not the stacked sums\n customdata: series.y,\n type: \"scatter\" as const,\n mode: \"lines\" as const,\n name: series.name,\n hoverinfo: \"none\" as const,\n fill: index === 0 ? (\"tozeroy\" as const) : (\"tonexty\" as const),\n fillcolor: color,\n line: {\n color,\n width: 2,\n },\n };\n });\n } else {\n // Normal mode - each area fills independently from zero\n data = dataSeries.map((series, index) => {\n const color = seriesColor(index, series.color);\n return {\n x: series.x,\n y: series.y,\n type: \"scatter\" as const,\n mode: \"lines\" as const,\n name: series.name,\n hoverinfo: \"none\" as const,\n fill: series.fill || (\"tozeroy\" as const),\n fillcolor: color,\n line: {\n color,\n width: 2,\n },\n };\n });\n }\n\n const layout = {\n width: sizeRef.current.width,\n height: sizeRef.current.height,\n ...(titleOptions ? { title: titleOptions } : {}),\n margin: {\n l: 80,\n r: 40,\n // Reserve room for tick labels, the x-axis title, and the\n // container-anchored bottom legend stacked beneath them.\n b: 96,\n t: title ? TITLE_MARGIN_TOP : NO_TITLE_MARGIN_TOP,\n pad: 0,\n },\n paper_bgcolor: theme.paperBg,\n plot_bgcolor: theme.plotBg,\n font: {\n family: \"Inter, sans-serif\",\n },\n dragmode: false as const,\n xaxis: {\n title: {\n text: xTitle,\n font: {\n size: 16,\n color: theme.textSecondary,\n family: \"Inter, sans-serif\",\n weight: 400,\n },\n standoff: 15,\n },\n gridcolor: theme.gridColor,\n range: xRange,\n autorange: !xRange,\n tickmode: \"array\" as const,\n tickvals: useCategoricalX ? xDataValues : xTicks,\n ...(useCategoricalX ? { ticktext: xTickText } : {}),\n showgrid: true,\n // Reserve space for tick labels + the axis title so the bottom legend\n // can't overlap them at small sizes (SW-2157).\n automargin: 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: 15,\n },\n gridcolor: theme.gridColor,\n range: yRange,\n autorange: !yRange,\n tickmode: \"array\" as const,\n tickvals: yTicks,\n showgrid: true,\n automargin: true,\n ...tickOptions,\n },\n legend: {\n // Anchor to the bottom of the container (not the plot area) so the\n // legend always clears the x-axis tick labels + title — a paper-relative\n // fractional offset collapses into the ticks at small heights (SW-2157).\n x: 0.5,\n y: 0,\n xanchor: \"center\" as const,\n yanchor: \"bottom\" as const,\n yref: \"container\" 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 showlegend: true,\n };\n\n const config = {\n // We drive sizing explicitly from the measured container, so Plotly's own\n // window-resize responsiveness is disabled (it can't see container resizes).\n responsive: false,\n displayModeBar: false,\n displaylogo: false,\n };\n\n Plotly.newPlot(plotRef.current, data, layout, config);\n bindTooltip(plotRef.current);\n\n // Capture ref value for cleanup\n const plotElement = plotRef.current;\n plotInitedRef.current = true;\n appliedSizeRef.current = { ...sizeRef.current };\n\n // Cleanup function\n return () => {\n if (plotElement) {\n Plotly.purge(plotElement);\n plotInitedRef.current = false;\n }\n };\n }, [dataSeries, hasSize, xRange, yRange, effectiveXRange, effectiveYRange, variant, xTitle, yTitle, title, titleOptions, tickOptions, xTicks, yTicks, xDataValues, useCategoricalX, xTickText, theme, bindTooltip]);\n\n // Resize in place when the measured/overridden size changes — far cheaper\n // than recreating the plot (and it preserves tooltip/event bindings).\n useEffect(() => {\n const plotElement = plotRef.current;\n if (!plotElement || !plotInitedRef.current || resolvedWidth <= 0 || resolvedHeight <= 0) {\n return;\n }\n // newPlot already drew at the current size; skip the redundant relayout\n // (it would queue an automargin redraw that can reject if we unmount first).\n if (\n appliedSizeRef.current.width === resolvedWidth &&\n appliedSizeRef.current.height === resolvedHeight\n ) {\n return;\n }\n appliedSizeRef.current = { width: resolvedWidth, height: resolvedHeight };\n // Swallow rejections from a relayout that races an unmount/purge.\n void Plotly.relayout(plotElement, { width: resolvedWidth, height: resolvedHeight }).catch(\n () => {},\n );\n }, [resolvedWidth, resolvedHeight]);\n\n return (\n <div\n ref={containerRef}\n className={cn(\"area-graph-container relative\", fillWidth && \"w-full\", fillHeight && \"h-full\")}\n >\n <div ref={plotRef} style={{ width: \"100%\", height: \"100%\" }} />\n {tooltipElement}\n </div>\n );\n};\n\nexport { AreaGraph };\nexport type { AreaDataSeries, AreaGraphVariant, AreaGraphProps };\n"],"names":["TITLE_MARGIN_TOP","NO_TITLE_MARGIN_TOP","AreaGraph","dataSeries","width","height","xRange","yRange","variant","xTitle","yTitle","title","xTickText","plotRef","useRef","theme","usePlotlyTheme","containerRef","measured","useElementSize","resolvedWidth","resolvedHeight","hasSize","fillWidth","fillHeight","sizeRef","plotInitedRef","appliedSizeRef","bindTooltip","tooltipElement","useChartTooltip","points","chartTooltipLines","point","xMin","xMax","yMin","yMax","useMemo","minX","maxX","minY","maxY","series","x","y","xPadding","yPadding","effectiveXRange","effectiveYRange","xTicks","range","step","ticks","current","yTicks","xDataValues","s","a","b","useCategoricalX","tickOptions","titleOptions","useEffect","data","cumulativeY","index","stackedY","value","i","result","color","seriesColor","layout","config","Plotly","plotElement","jsxs","cn","jsx"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const P=require("react/jsx-runtime"),v=require("plotly.js-dist"),s=require("react"),z=require("../../../hooks/use-plotly-theme.cjs"),A=({dataSeries:a,width:d=1e3,height:p=600,xRange:h,yRange:c,variant:f="group",xTitle:y="Columns",yTitle:M="Rows",title:x="Bar Graph",barWidth:k=24})=>{const m=s.useRef(null),t=z.usePlotlyTheme(),{yMin:w,yMax:b}=s.useMemo(()=>{let o=Number.MAX_VALUE,e=Number.MIN_VALUE,n=Number.MAX_VALUE,r=Number.MIN_VALUE;a.forEach(N=>{N.x.forEach(u=>{o=Math.min(o,u),e=Math.max(e,u)}),N.y.forEach(u=>{n=Math.min(n,u),r=Math.max(r,u)})});const l=(e-o)*.1,_=(r-n)*.1;return{xMin:o-l,xMax:e+l,yMin:f==="stack"?0:n-_,yMax:r+_}},[a,f]),i=s.useMemo(()=>c||[w,b],[c,w,b]),E=s.useMemo(()=>[...new Set(a.flatMap(o=>o.x))],[a]),C=s.useMemo(()=>{const o=i[1]-i[0];let e=Math.pow(10,Math.floor(Math.log10(o)));o/e>10&&(e=e*2),o/e<4&&(e=e/2);const n=[];let r=Math.ceil(i[0]/e)*e;for(;r<=i[1];)n.push(r),r+=e;return n},[i]),I=s.useMemo(()=>{switch(f){case"stack":return"stack";case"overlay":return"overlay";default:return"group"}},[f]),g=s.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]);return s.useEffect(()=>{if(!m.current)return;const o=a.map(l=>({x:l.x,y:l.y,type:"bar",name:l.name,marker:{color:l.color},width:k,error_y:l.error_y})),e={title:{text:x,font:{size:32,family:"Inter, sans-serif",color:t.textColor}},width:d,height:p,margin:{l:80,r:30,b:80,t:60,pad:0},paper_bgcolor:t.paperBg,plot_bgcolor:t.plotBg,font:{family:"Inter, sans-serif"},barmode:I,bargap:.15,dragmode:!1,xaxis:{title:{text:y,font:{size:16,color:t.textSecondary,family:"Inter, sans-serif",weight:400},standoff:32},gridcolor:t.gridColor,range:h,autorange:!h,tickmode:"array",tickvals:E,showgrid:!0,...g},yaxis:{title:{text:M,font:{size:16,color:t.textSecondary,family:"Inter, sans-serif",weight:400},standoff:30},gridcolor:t.gridColor,range:c,autorange:!c,tickmode:"array",tickvals:C,showgrid:!0,...g},legend:{x:.5,y:-.2,xanchor:"center",yanchor:"top",orientation:"h",font:{size:16,color:t.legendColor,family:"Inter, sans-serif",weight:500}},showlegend:a.length>1},n={responsive:!0,displayModeBar:!1,displaylogo:!1};v.newPlot(m.current,o,e,n);const r=m.current;return()=>{r&&v.purge(r)}},[a,d,p,h,c,y,M,x,k,I,g,E,C,t]),P.jsx("div",{className:"bar-graph-container",children:P.jsx("div",{ref:m,style:{width:"100%",height:"100%"}})})};exports.BarGraph=A;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const G=require("react/jsx-runtime"),_=require("plotly.js-dist"),o=require("react"),Y=require("../ChartTooltip/ChartTooltip.cjs"),H=require("../../../hooks/use-element-size.cjs"),W=require("../../../hooks/use-plotly-theme.cjs"),D=require("../../../lib/utils.cjs"),F=require("../../../utils/colors.cjs"),J=60,K=30,Q=({dataSeries:a,width:z,height:C,xRange:x,yRange:h,variant:g="group",xTitle:b,yTitle:k,title:m,barWidth:N=24,xTickText:p})=>{const u=o.useRef(null),r=W.usePlotlyTheme(),{bindTooltip:P,tooltipElement:T}=Y.useChartTooltip({xLabel:b,yLabel:k}),[U,q]=H.useElementSize(),s=z??q.width,c=C??q.height,A=s>0&&c>0,V=z===void 0,S=C===void 0,y=o.useRef({width:s,height:c});y.current={width:s,height:c};const E=o.useRef(!1),M=o.useRef({width:0,height:0}),{yMin:L,yMax:R}=o.useMemo(()=>{let t=Number.MAX_VALUE,e=Number.MIN_VALUE,i=Number.MAX_VALUE,n=Number.MIN_VALUE;a.forEach(j=>{j.x.forEach(d=>{t=Math.min(t,d),e=Math.max(e,d)}),j.y.forEach(d=>{i=Math.min(i,d),n=Math.max(n,d)})});const l=(e-t)*.1,w=(n-i)*.1;return{xMin:t-l,xMax:e+l,yMin:g==="stack"?0:i-w,yMax:n+w}},[a,g]),f=o.useMemo(()=>h||[L,R],[h,L,R]),v=o.useMemo(()=>[...new Set(a.flatMap(t=>t.x))].sort((t,e)=>t-e),[a]),B=!!p&&p.length===v.length,O=o.useMemo(()=>{const t=f[1]-f[0];let e=Math.pow(10,Math.floor(Math.log10(t)));t/e>10&&(e=e*2),t/e<4&&(e=e/2);const i=[];let n=Math.ceil(f[0]/e)*e;for(;n<=f[1];)i.push(n),n+=e;return i},[f]),X=o.useMemo(()=>{switch(g){case"stack":return"stack";case"overlay":return"overlay";default:return"group"}},[g]),I=o.useMemo(()=>({tickcolor:r.tickColor,ticklen:12,tickwidth:1,ticks:"outside",tickfont:{size:16,color:r.textColor,family:"Inter, sans-serif",weight:400},linecolor:r.lineColor,linewidth:1,position:0,zeroline:!1}),[r]);return o.useEffect(()=>{if(!u.current||!A)return;const t=a.map((l,w)=>({x:l.x,y:l.y,type:"bar",name:l.name,hoverinfo:"none",marker:{color:F.seriesColor(w,l.color)},width:N,error_y:l.error_y})),e={...m?{title:{text:m,font:{size:32,family:"Inter, sans-serif",color:r.textColor}}}:{},width:y.current.width,height:y.current.height,margin:{l:80,r:30,b:96,t:m?J:K,pad:0},paper_bgcolor:r.paperBg,plot_bgcolor:r.plotBg,font:{family:"Inter, sans-serif"},barmode:X,bargap:.15,dragmode:!1,xaxis:{title:{text:b,font:{size:16,color:r.textSecondary,family:"Inter, sans-serif",weight:400},standoff:32},gridcolor:r.gridColor,range:x,autorange:!x,tickmode:"array",tickvals:v,...B?{ticktext:p}:{},showgrid:!0,automargin:!0,...I},yaxis:{title:{text:k,font:{size:16,color:r.textSecondary,family:"Inter, sans-serif",weight:400},standoff:30},gridcolor:r.gridColor,range:h,autorange:!h,tickmode:"array",tickvals:O,showgrid:!0,automargin:!0,...I},legend:{x:.5,y:0,xanchor:"center",yanchor:"bottom",yref:"container",orientation:"h",font:{size:16,color:r.legendColor,family:"Inter, sans-serif",weight:500}},showlegend:a.length>1},i={responsive:!1,displayModeBar:!1,displaylogo:!1};_.newPlot(u.current,t,e,i),P(u.current);const n=u.current;return E.current=!0,M.current={...y.current},()=>{n&&(_.purge(n),E.current=!1)}},[a,A,x,h,b,k,m,N,X,I,v,O,B,p,r,P]),o.useEffect(()=>{const t=u.current;!t||!E.current||s<=0||c<=0||M.current.width===s&&M.current.height===c||(M.current={width:s,height:c},_.relayout(t,{width:s,height:c}).catch(()=>{}))},[s,c]),G.jsxs("div",{ref:U,className:D.cn("bar-graph-container relative",V&&"w-full",S&&"h-full"),children:[G.jsx("div",{ref:u,style:{width:"100%",height:"100%"}}),T]})};exports.BarGraph=Q;
2
2
  //# sourceMappingURL=BarGraph.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"BarGraph.cjs","sources":["../../../../src/components/charts/BarGraph/BarGraph.tsx"],"sourcesContent":["import Plotly from \"plotly.js-dist\";\nimport React, { useEffect, useRef, useMemo } from \"react\";\n\nimport { usePlotlyTheme } from \"@/hooks/use-plotly-theme\";\n\ninterface BarDataSeries {\n x: number[];\n y: number[];\n name: string;\n color: string;\n error_y?: {\n type: \"data\";\n array: number[];\n visible: boolean;\n };\n}\n\ntype BarGraphVariant = \"group\" | \"stack\" | \"overlay\";\n\ninterface BarGraphProps {\n dataSeries: BarDataSeries[];\n width?: number;\n height?: number;\n xRange?: [number, number];\n yRange?: [number, number];\n variant?: BarGraphVariant;\n xTitle?: string;\n yTitle?: string;\n title?: string;\n barWidth?: number;\n}\n\nconst BarGraph: React.FC<BarGraphProps> = ({\n dataSeries,\n width = 1000,\n height = 600,\n xRange,\n yRange,\n variant = \"group\",\n xTitle = \"Columns\",\n yTitle = \"Rows\",\n title = \"Bar Graph\",\n barWidth = 24,\n}) => {\n const plotRef = useRef<HTMLDivElement>(null);\n const theme = usePlotlyTheme();\n\n const { yMin, yMax } = useMemo(() => {\n let minX = Number.MAX_VALUE;\n let maxX = Number.MIN_VALUE;\n let minY = Number.MAX_VALUE;\n let maxY = Number.MIN_VALUE;\n\n dataSeries.forEach((series) => {\n series.x.forEach((x) => {\n minX = Math.min(minX, x);\n maxX = Math.max(maxX, x);\n });\n series.y.forEach((y) => {\n minY = Math.min(minY, y);\n maxY = Math.max(maxY, y);\n });\n });\n\n const xPadding = (maxX - minX) * 0.1;\n const yPadding = (maxY - minY) * 0.1;\n\n return {\n xMin: minX - xPadding,\n xMax: maxX + xPadding,\n yMin: variant === \"stack\" ? 0 : minY - yPadding,\n yMax: maxY + yPadding,\n };\n }, [dataSeries, variant]);\n\n const effectiveYRange = useMemo(\n () => yRange || [yMin, yMax],\n [yRange, yMin, yMax],\n );\n\n const xTicks = useMemo(\n () => [...new Set(dataSeries.flatMap((s) => s.x))],\n [dataSeries],\n );\n\n const yTicks = useMemo(() => {\n const range = effectiveYRange[1] - effectiveYRange[0];\n let step = Math.pow(10, Math.floor(Math.log10(range)));\n\n if (range / step > 10) step = step * 2;\n if (range / step < 4) step = step / 2;\n\n const ticks = [];\n let current = Math.ceil(effectiveYRange[0] / step) * step;\n while (current <= effectiveYRange[1]) {\n ticks.push(current);\n current += step;\n }\n return ticks;\n }, [effectiveYRange]);\n\n const barMode = useMemo((): \"group\" | \"stack\" | \"overlay\" => {\n switch (variant) {\n case \"stack\":\n return \"stack\";\n case \"overlay\":\n return \"overlay\";\n case \"group\":\n default:\n return \"group\";\n }\n }, [variant]);\n\n const tickOptions = useMemo(\n () => ({\n tickcolor: theme.tickColor,\n ticklen: 12,\n tickwidth: 1,\n ticks: \"outside\" as const,\n tickfont: {\n size: 16,\n color: theme.textColor,\n family: \"Inter, sans-serif\",\n weight: 400,\n },\n linecolor: theme.lineColor,\n linewidth: 1,\n position: 0,\n zeroline: false,\n }),\n [theme],\n );\n\n useEffect(() => {\n if (!plotRef.current) return;\n\n const data = dataSeries.map((series) => ({\n x: series.x,\n y: series.y,\n type: \"bar\" as const,\n name: series.name,\n marker: {\n color: series.color,\n },\n width: barWidth,\n error_y: series.error_y,\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: 0 },\n paper_bgcolor: theme.paperBg,\n plot_bgcolor: theme.plotBg,\n font: {\n family: \"Inter, sans-serif\",\n },\n barmode: barMode,\n bargap: 0.15,\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 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: dataSeries.length > 1,\n };\n\n const config = {\n responsive: true,\n displayModeBar: false,\n displaylogo: false,\n };\n\n Plotly.newPlot(plotRef.current, data, layout, config);\n\n // Capture ref value for cleanup\n const plotElement = plotRef.current;\n\n // Cleanup function\n return () => {\n if (plotElement) {\n Plotly.purge(plotElement);\n }\n };\n }, [dataSeries, width, height, xRange, yRange, xTitle, yTitle, title, barWidth, barMode, tickOptions, xTicks, yTicks, theme]);\n\n return (\n <div className=\"bar-graph-container\">\n <div ref={plotRef} style={{ width: \"100%\", height: \"100%\" }} />\n </div>\n );\n};\n\nexport { BarGraph };\nexport type { BarDataSeries, BarGraphVariant, BarGraphProps };\n"],"names":["BarGraph","dataSeries","width","height","xRange","yRange","variant","xTitle","yTitle","title","barWidth","plotRef","useRef","theme","usePlotlyTheme","yMin","yMax","useMemo","minX","maxX","minY","maxY","series","x","y","xPadding","yPadding","effectiveYRange","xTicks","s","yTicks","range","step","ticks","current","barMode","tickOptions","useEffect","data","layout","config","Plotly","plotElement","jsx"],"mappings":"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"}
1
+ {"version":3,"file":"BarGraph.cjs","sources":["../../../../src/components/charts/BarGraph/BarGraph.tsx"],"sourcesContent":["import Plotly from \"plotly.js-dist\";\nimport React, { useEffect, useRef, useMemo } from \"react\";\n\nimport { useChartTooltip } from \"../ChartTooltip\";\n\nimport { useElementSize } from \"@/hooks/use-element-size\";\nimport { usePlotlyTheme } from \"@/hooks/use-plotly-theme\";\nimport { cn } from \"@/lib/utils\";\nimport { seriesColor } from \"@/utils/colors\";\n\ninterface BarDataSeries {\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 error_y?: {\n type: \"data\";\n array: number[];\n visible: boolean;\n };\n}\n\ntype BarGraphVariant = \"group\" | \"stack\" | \"overlay\";\n\n/** Top margin reserving room for the 32px title; reduced when no title is set */\nconst TITLE_MARGIN_TOP = 60;\nconst NO_TITLE_MARGIN_TOP = 30;\n\ninterface BarGraphProps {\n dataSeries: BarDataSeries[];\n /**\n * Fixed width in pixels. When omitted, the chart fills its container and\n * tracks the container's width via a `ResizeObserver`.\n */\n width?: number;\n /**\n * Fixed height in pixels. When omitted, the chart fills its container and\n * tracks the container's height via a `ResizeObserver`.\n */\n height?: number;\n xRange?: [number, number];\n yRange?: [number, number];\n variant?: BarGraphVariant;\n xTitle?: string;\n yTitle?: string;\n title?: string;\n barWidth?: number;\n /**\n * Categorical labels for the x-axis ticks. When provided, the x data values\n * still drive bar positioning but the displayed tick labels match these\n * strings in order (e.g. [\"Mon\", \"Tue\", …]). Should align 1:1 with the\n * unique, ordered x values across all series.\n */\n xTickText?: string[];\n}\n\nconst BarGraph: React.FC<BarGraphProps> = ({\n dataSeries,\n width,\n height,\n xRange,\n yRange,\n variant = \"group\",\n xTitle,\n yTitle,\n title,\n barWidth = 24,\n xTickText,\n}) => {\n const plotRef = useRef<HTMLDivElement>(null);\n const theme = usePlotlyTheme();\n const { bindTooltip, tooltipElement } = useChartTooltip({ xLabel: xTitle, yLabel: yTitle });\n\n // Omitted width/height → fill the container and track its measured size;\n // explicit pixel values override. See AreaGraph for the reference pattern.\n const [containerRef, measured] = useElementSize<HTMLDivElement>();\n const resolvedWidth = width ?? measured.width;\n const resolvedHeight = height ?? measured.height;\n const hasSize = resolvedWidth > 0 && resolvedHeight > 0;\n // Fill is per-dimension: omit width to fill the container width, omit height\n // to fill its height (so e.g. a fixed width with a container-driven height works).\n const fillWidth = width === undefined;\n const fillHeight = height === undefined;\n const sizeRef = useRef({ width: resolvedWidth, height: resolvedHeight });\n sizeRef.current = { width: resolvedWidth, height: resolvedHeight };\n const plotInitedRef = useRef(false);\n // Size last applied to the plot, so the resize effect can skip a redundant\n // relayout right after newPlot already drew at that size.\n const appliedSizeRef = useRef({ width: 0, height: 0 });\n\n const { yMin, yMax } = useMemo(() => {\n let minX = Number.MAX_VALUE;\n let maxX = Number.MIN_VALUE;\n let minY = Number.MAX_VALUE;\n let maxY = Number.MIN_VALUE;\n\n dataSeries.forEach((series) => {\n series.x.forEach((x) => {\n minX = Math.min(minX, x);\n maxX = Math.max(maxX, x);\n });\n series.y.forEach((y) => {\n minY = Math.min(minY, y);\n maxY = Math.max(maxY, y);\n });\n });\n\n const xPadding = (maxX - minX) * 0.1;\n const yPadding = (maxY - minY) * 0.1;\n\n return {\n xMin: minX - xPadding,\n xMax: maxX + xPadding,\n yMin: variant === \"stack\" ? 0 : minY - yPadding,\n yMax: maxY + yPadding,\n };\n }, [dataSeries, variant]);\n\n const effectiveYRange = useMemo(\n () => yRange || [yMin, yMax],\n [yRange, yMin, yMax],\n );\n\n const xTicks = useMemo(\n () => [...new Set(dataSeries.flatMap((s) => s.x))].sort((a, b) => a - b),\n [dataSeries],\n );\n\n // Only apply categorical labels when they align 1:1 with the tick positions;\n // a mismatch would silently mis-label ticks, so fall back to numeric ticks.\n const useCategoricalX = !!xTickText && xTickText.length === xTicks.length;\n\n const 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 barMode = useMemo((): \"group\" | \"stack\" | \"overlay\" => {\n switch (variant) {\n case \"stack\":\n return \"stack\";\n case \"overlay\":\n return \"overlay\";\n case \"group\":\n default:\n return \"group\";\n }\n }, [variant]);\n\n const tickOptions = useMemo(\n () => ({\n tickcolor: theme.tickColor,\n ticklen: 12,\n tickwidth: 1,\n ticks: \"outside\" as const,\n tickfont: {\n size: 16,\n color: theme.textColor,\n family: \"Inter, sans-serif\",\n weight: 400,\n },\n linecolor: theme.lineColor,\n linewidth: 1,\n position: 0,\n zeroline: false,\n }),\n [theme],\n );\n\n useEffect(() => {\n if (!plotRef.current || !hasSize) return;\n\n const data = dataSeries.map((series, index) => ({\n x: series.x,\n y: series.y,\n type: \"bar\" as const,\n name: series.name,\n hoverinfo: \"none\" as const,\n marker: {\n color: seriesColor(index, series.color),\n },\n width: barWidth,\n error_y: series.error_y,\n }));\n\n const layout = {\n ...(title\n ? {\n title: {\n text: title,\n font: {\n size: 32,\n family: \"Inter, sans-serif\",\n color: theme.textColor,\n },\n },\n }\n : {}),\n width: sizeRef.current.width,\n height: sizeRef.current.height,\n margin: {\n l: 80,\n r: 30,\n // Reserve room for tick labels, the x-axis title, and the\n // container-anchored bottom legend stacked beneath them.\n b: 96,\n t: title ? TITLE_MARGIN_TOP : NO_TITLE_MARGIN_TOP,\n pad: 0,\n },\n paper_bgcolor: theme.paperBg,\n plot_bgcolor: theme.plotBg,\n font: {\n family: \"Inter, sans-serif\",\n },\n barmode: barMode,\n bargap: 0.15,\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 ...(useCategoricalX ? { ticktext: xTickText } : {}),\n showgrid: true,\n // Reserve space for tick labels + the axis title so the bottom legend\n // can't overlap them at small sizes (SW-2157).\n automargin: 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 automargin: true,\n ...tickOptions,\n },\n legend: {\n // Anchor to the bottom of the container (not the plot area) so the\n // legend always clears the x-axis tick labels + title — a paper-relative\n // fractional offset collapses into the ticks at small heights (SW-2157).\n x: 0.5,\n y: 0,\n xanchor: \"center\" as const,\n yanchor: \"bottom\" as const,\n yref: \"container\" 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: dataSeries.length > 1,\n };\n\n const config = {\n // Sizing is driven from the measured container; disable Plotly's own\n // window-resize responsiveness (it can't see container resizes).\n responsive: false,\n displayModeBar: false,\n displaylogo: false,\n };\n\n Plotly.newPlot(plotRef.current, data, layout, config);\n bindTooltip(plotRef.current);\n\n // Capture ref value for cleanup\n const plotElement = plotRef.current;\n plotInitedRef.current = true;\n appliedSizeRef.current = { ...sizeRef.current };\n\n // Cleanup function\n return () => {\n if (plotElement) {\n Plotly.purge(plotElement);\n plotInitedRef.current = false;\n }\n };\n }, [dataSeries, hasSize, xRange, yRange, xTitle, yTitle, title, barWidth, barMode, tickOptions, xTicks, yTicks, useCategoricalX, xTickText, theme, bindTooltip]);\n\n // Resize in place when the measured/overridden size changes — cheaper than\n // recreating the plot, and it preserves tooltip/event bindings.\n useEffect(() => {\n const plotElement = plotRef.current;\n if (!plotElement || !plotInitedRef.current || resolvedWidth <= 0 || resolvedHeight <= 0) {\n return;\n }\n // newPlot already drew at the current size; skip the redundant relayout\n // (it would queue an automargin redraw that can reject if we unmount first).\n if (\n appliedSizeRef.current.width === resolvedWidth &&\n appliedSizeRef.current.height === resolvedHeight\n ) {\n return;\n }\n appliedSizeRef.current = { width: resolvedWidth, height: resolvedHeight };\n // Swallow rejections from a relayout that races an unmount/purge.\n void Plotly.relayout(plotElement, { width: resolvedWidth, height: resolvedHeight }).catch(\n () => {},\n );\n }, [resolvedWidth, resolvedHeight]);\n\n return (\n <div\n ref={containerRef}\n className={cn(\"bar-graph-container relative\", fillWidth && \"w-full\", fillHeight && \"h-full\")}\n >\n <div ref={plotRef} style={{ width: \"100%\", height: \"100%\" }} />\n {tooltipElement}\n </div>\n );\n};\n\nexport { BarGraph };\nexport type { BarDataSeries, BarGraphVariant, BarGraphProps };\n"],"names":["TITLE_MARGIN_TOP","NO_TITLE_MARGIN_TOP","BarGraph","dataSeries","width","height","xRange","yRange","variant","xTitle","yTitle","title","barWidth","xTickText","plotRef","useRef","theme","usePlotlyTheme","bindTooltip","tooltipElement","useChartTooltip","containerRef","measured","useElementSize","resolvedWidth","resolvedHeight","hasSize","fillWidth","fillHeight","sizeRef","plotInitedRef","appliedSizeRef","yMin","yMax","useMemo","minX","maxX","minY","maxY","series","x","y","xPadding","yPadding","effectiveYRange","xTicks","s","a","b","useCategoricalX","yTicks","range","step","ticks","current","barMode","tickOptions","useEffect","data","index","seriesColor","layout","config","Plotly","plotElement","jsxs","cn","jsx"],"mappings":"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"}
@@ -1,52 +1,59 @@
1
- import { jsx as z } from "react/jsx-runtime";
2
- import A from "plotly.js-dist";
3
- import { useRef as v, useMemo as i, useEffect as B } from "react";
4
- import { usePlotlyTheme as P } from "../../../hooks/use-plotly-theme.js";
5
- const Y = ({
6
- dataSeries: a,
7
- width: g = 1e3,
8
- height: d = 600,
9
- xRange: p,
10
- yRange: c,
11
- variant: m = "group",
12
- xTitle: y = "Columns",
13
- yTitle: x = "Rows",
14
- title: M = "Bar Graph",
15
- barWidth: k = 24
1
+ import { jsxs as q, jsx as D } from "react/jsx-runtime";
2
+ import z from "plotly.js-dist";
3
+ import { useRef as x, useMemo as h, useEffect as Y } from "react";
4
+ import { useChartTooltip as F } from "../ChartTooltip/ChartTooltip.js";
5
+ import { useElementSize as J } from "../../../hooks/use-element-size.js";
6
+ import { usePlotlyTheme as K } from "../../../hooks/use-plotly-theme.js";
7
+ import { cn as Q } from "../../../lib/utils.js";
8
+ import { seriesColor as S } from "../../../utils/colors.js";
9
+ const Z = 60, $ = 30, st = ({
10
+ dataSeries: s,
11
+ width: C,
12
+ height: N,
13
+ xRange: k,
14
+ yRange: f,
15
+ variant: d = "group",
16
+ xTitle: b,
17
+ yTitle: E,
18
+ title: g,
19
+ barWidth: A = 24,
20
+ xTickText: p
16
21
  }) => {
17
- const u = v(null), t = P(), { yMin: w, yMax: b } = i(() => {
18
- let r = Number.MAX_VALUE, o = Number.MIN_VALUE, n = Number.MAX_VALUE, e = Number.MIN_VALUE;
19
- a.forEach((N) => {
20
- N.x.forEach((f) => {
21
- r = Math.min(r, f), o = Math.max(o, f);
22
- }), N.y.forEach((f) => {
23
- n = Math.min(n, f), e = Math.max(e, f);
22
+ const a = x(null), e = K(), { bindTooltip: L, tooltipElement: j } = F({ xLabel: b, yLabel: E }), [H, P] = J(), i = C ?? P.width, c = N ?? P.height, X = i > 0 && c > 0, T = C === void 0, W = N === void 0, y = x({ width: i, height: c });
23
+ y.current = { width: i, height: c };
24
+ const I = x(!1), w = x({ width: 0, height: 0 }), { yMin: B, yMax: O } = h(() => {
25
+ let o = Number.MAX_VALUE, t = Number.MIN_VALUE, n = Number.MAX_VALUE, r = Number.MIN_VALUE;
26
+ s.forEach((R) => {
27
+ R.x.forEach((m) => {
28
+ o = Math.min(o, m), t = Math.max(t, m);
29
+ }), R.y.forEach((m) => {
30
+ n = Math.min(n, m), r = Math.max(r, m);
24
31
  });
25
32
  });
26
- const l = (o - r) * 0.1, _ = (e - n) * 0.1;
33
+ const l = (t - o) * 0.1, M = (r - n) * 0.1;
27
34
  return {
28
- xMin: r - l,
29
- xMax: o + l,
30
- yMin: m === "stack" ? 0 : n - _,
31
- yMax: e + _
35
+ xMin: o - l,
36
+ xMax: t + l,
37
+ yMin: d === "stack" ? 0 : n - M,
38
+ yMax: r + M
32
39
  };
33
- }, [a, m]), s = i(
34
- () => c || [w, b],
35
- [c, w, b]
36
- ), E = i(
37
- () => [...new Set(a.flatMap((r) => r.x))],
38
- [a]
39
- ), C = i(() => {
40
- const r = s[1] - s[0];
41
- let o = Math.pow(10, Math.floor(Math.log10(r)));
42
- r / o > 10 && (o = o * 2), r / o < 4 && (o = o / 2);
40
+ }, [s, d]), u = h(
41
+ () => f || [B, O],
42
+ [f, B, O]
43
+ ), _ = h(
44
+ () => [...new Set(s.flatMap((o) => o.x))].sort((o, t) => o - t),
45
+ [s]
46
+ ), U = !!p && p.length === _.length, V = h(() => {
47
+ const o = u[1] - u[0];
48
+ let t = Math.pow(10, Math.floor(Math.log10(o)));
49
+ o / t > 10 && (t = t * 2), o / t < 4 && (t = t / 2);
43
50
  const n = [];
44
- let e = Math.ceil(s[0] / o) * o;
45
- for (; e <= s[1]; )
46
- n.push(e), e += o;
51
+ let r = Math.ceil(u[0] / t) * t;
52
+ for (; r <= u[1]; )
53
+ n.push(r), r += t;
47
54
  return n;
48
- }, [s]), I = i(() => {
49
- switch (m) {
55
+ }, [u]), G = h(() => {
56
+ switch (d) {
50
57
  case "stack":
51
58
  return "stack";
52
59
  case "overlay":
@@ -54,122 +61,160 @@ const Y = ({
54
61
  default:
55
62
  return "group";
56
63
  }
57
- }, [m]), h = i(
64
+ }, [d]), v = h(
58
65
  () => ({
59
- tickcolor: t.tickColor,
66
+ tickcolor: e.tickColor,
60
67
  ticklen: 12,
61
68
  tickwidth: 1,
62
69
  ticks: "outside",
63
70
  tickfont: {
64
71
  size: 16,
65
- color: t.textColor,
72
+ color: e.textColor,
66
73
  family: "Inter, sans-serif",
67
74
  weight: 400
68
75
  },
69
- linecolor: t.lineColor,
76
+ linecolor: e.lineColor,
70
77
  linewidth: 1,
71
78
  position: 0,
72
79
  zeroline: !1
73
80
  }),
74
- [t]
81
+ [e]
75
82
  );
76
- return B(() => {
77
- if (!u.current) return;
78
- const r = a.map((l) => ({
83
+ return Y(() => {
84
+ if (!a.current || !X) return;
85
+ const o = s.map((l, M) => ({
79
86
  x: l.x,
80
87
  y: l.y,
81
88
  type: "bar",
82
89
  name: l.name,
90
+ hoverinfo: "none",
83
91
  marker: {
84
- color: l.color
92
+ color: S(M, l.color)
85
93
  },
86
- width: k,
94
+ width: A,
87
95
  error_y: l.error_y
88
- })), o = {
89
- title: {
90
- text: M,
91
- font: {
92
- size: 32,
93
- family: "Inter, sans-serif",
94
- color: t.textColor
96
+ })), t = {
97
+ ...g ? {
98
+ title: {
99
+ text: g,
100
+ font: {
101
+ size: 32,
102
+ family: "Inter, sans-serif",
103
+ color: e.textColor
104
+ }
95
105
  }
106
+ } : {},
107
+ width: y.current.width,
108
+ height: y.current.height,
109
+ margin: {
110
+ l: 80,
111
+ r: 30,
112
+ // Reserve room for tick labels, the x-axis title, and the
113
+ // container-anchored bottom legend stacked beneath them.
114
+ b: 96,
115
+ t: g ? Z : $,
116
+ pad: 0
96
117
  },
97
- width: g,
98
- height: d,
99
- margin: { l: 80, r: 30, b: 80, t: 60, pad: 0 },
100
- paper_bgcolor: t.paperBg,
101
- plot_bgcolor: t.plotBg,
118
+ paper_bgcolor: e.paperBg,
119
+ plot_bgcolor: e.plotBg,
102
120
  font: {
103
121
  family: "Inter, sans-serif"
104
122
  },
105
- barmode: I,
123
+ barmode: G,
106
124
  bargap: 0.15,
107
125
  dragmode: !1,
108
126
  xaxis: {
109
127
  title: {
110
- text: y,
128
+ text: b,
111
129
  font: {
112
130
  size: 16,
113
- color: t.textSecondary,
131
+ color: e.textSecondary,
114
132
  family: "Inter, sans-serif",
115
133
  weight: 400
116
134
  },
117
135
  standoff: 32
118
136
  },
119
- gridcolor: t.gridColor,
120
- range: p,
121
- autorange: !p,
137
+ gridcolor: e.gridColor,
138
+ range: k,
139
+ autorange: !k,
122
140
  tickmode: "array",
123
- tickvals: E,
141
+ tickvals: _,
142
+ ...U ? { ticktext: p } : {},
124
143
  showgrid: !0,
125
- ...h
144
+ // Reserve space for tick labels + the axis title so the bottom legend
145
+ // can't overlap them at small sizes (SW-2157).
146
+ automargin: !0,
147
+ ...v
126
148
  },
127
149
  yaxis: {
128
150
  title: {
129
- text: x,
151
+ text: E,
130
152
  font: {
131
153
  size: 16,
132
- color: t.textSecondary,
154
+ color: e.textSecondary,
133
155
  family: "Inter, sans-serif",
134
156
  weight: 400
135
157
  },
136
158
  standoff: 30
137
159
  },
138
- gridcolor: t.gridColor,
139
- range: c,
140
- autorange: !c,
160
+ gridcolor: e.gridColor,
161
+ range: f,
162
+ autorange: !f,
141
163
  tickmode: "array",
142
- tickvals: C,
164
+ tickvals: V,
143
165
  showgrid: !0,
144
- ...h
166
+ automargin: !0,
167
+ ...v
145
168
  },
146
169
  legend: {
170
+ // Anchor to the bottom of the container (not the plot area) so the
171
+ // legend always clears the x-axis tick labels + title — a paper-relative
172
+ // fractional offset collapses into the ticks at small heights (SW-2157).
147
173
  x: 0.5,
148
- y: -0.2,
174
+ y: 0,
149
175
  xanchor: "center",
150
- yanchor: "top",
176
+ yanchor: "bottom",
177
+ yref: "container",
151
178
  orientation: "h",
152
179
  font: {
153
180
  size: 16,
154
- color: t.legendColor,
181
+ color: e.legendColor,
155
182
  family: "Inter, sans-serif",
156
183
  weight: 500
157
184
  }
158
185
  },
159
- showlegend: a.length > 1
186
+ showlegend: s.length > 1
160
187
  }, n = {
161
- responsive: !0,
188
+ // Sizing is driven from the measured container; disable Plotly's own
189
+ // window-resize responsiveness (it can't see container resizes).
190
+ responsive: !1,
162
191
  displayModeBar: !1,
163
192
  displaylogo: !1
164
193
  };
165
- A.newPlot(u.current, r, o, n);
166
- const e = u.current;
167
- return () => {
168
- e && A.purge(e);
194
+ z.newPlot(a.current, o, t, n), L(a.current);
195
+ const r = a.current;
196
+ return I.current = !0, w.current = { ...y.current }, () => {
197
+ r && (z.purge(r), I.current = !1);
169
198
  };
170
- }, [a, g, d, p, c, y, x, M, k, I, h, E, C, t]), /* @__PURE__ */ z("div", { className: "bar-graph-container", children: /* @__PURE__ */ z("div", { ref: u, style: { width: "100%", height: "100%" } }) });
199
+ }, [s, X, k, f, b, E, g, A, G, v, _, V, U, p, e, L]), Y(() => {
200
+ const o = a.current;
201
+ !o || !I.current || i <= 0 || c <= 0 || w.current.width === i && w.current.height === c || (w.current = { width: i, height: c }, z.relayout(o, { width: i, height: c }).catch(
202
+ () => {
203
+ }
204
+ ));
205
+ }, [i, c]), /* @__PURE__ */ q(
206
+ "div",
207
+ {
208
+ ref: H,
209
+ className: Q("bar-graph-container relative", T && "w-full", W && "h-full"),
210
+ children: [
211
+ /* @__PURE__ */ D("div", { ref: a, style: { width: "100%", height: "100%" } }),
212
+ j
213
+ ]
214
+ }
215
+ );
171
216
  };
172
217
  export {
173
- Y as BarGraph
218
+ st as BarGraph
174
219
  };
175
220
  //# sourceMappingURL=BarGraph.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"BarGraph.js","sources":["../../../../src/components/charts/BarGraph/BarGraph.tsx"],"sourcesContent":["import Plotly from \"plotly.js-dist\";\nimport React, { useEffect, useRef, useMemo } from \"react\";\n\nimport { usePlotlyTheme } from \"@/hooks/use-plotly-theme\";\n\ninterface BarDataSeries {\n x: number[];\n y: number[];\n name: string;\n color: string;\n error_y?: {\n type: \"data\";\n array: number[];\n visible: boolean;\n };\n}\n\ntype BarGraphVariant = \"group\" | \"stack\" | \"overlay\";\n\ninterface BarGraphProps {\n dataSeries: BarDataSeries[];\n width?: number;\n height?: number;\n xRange?: [number, number];\n yRange?: [number, number];\n variant?: BarGraphVariant;\n xTitle?: string;\n yTitle?: string;\n title?: string;\n barWidth?: number;\n}\n\nconst BarGraph: React.FC<BarGraphProps> = ({\n dataSeries,\n width = 1000,\n height = 600,\n xRange,\n yRange,\n variant = \"group\",\n xTitle = \"Columns\",\n yTitle = \"Rows\",\n title = \"Bar Graph\",\n barWidth = 24,\n}) => {\n const plotRef = useRef<HTMLDivElement>(null);\n const theme = usePlotlyTheme();\n\n const { yMin, yMax } = useMemo(() => {\n let minX = Number.MAX_VALUE;\n let maxX = Number.MIN_VALUE;\n let minY = Number.MAX_VALUE;\n let maxY = Number.MIN_VALUE;\n\n dataSeries.forEach((series) => {\n series.x.forEach((x) => {\n minX = Math.min(minX, x);\n maxX = Math.max(maxX, x);\n });\n series.y.forEach((y) => {\n minY = Math.min(minY, y);\n maxY = Math.max(maxY, y);\n });\n });\n\n const xPadding = (maxX - minX) * 0.1;\n const yPadding = (maxY - minY) * 0.1;\n\n return {\n xMin: minX - xPadding,\n xMax: maxX + xPadding,\n yMin: variant === \"stack\" ? 0 : minY - yPadding,\n yMax: maxY + yPadding,\n };\n }, [dataSeries, variant]);\n\n const effectiveYRange = useMemo(\n () => yRange || [yMin, yMax],\n [yRange, yMin, yMax],\n );\n\n const xTicks = useMemo(\n () => [...new Set(dataSeries.flatMap((s) => s.x))],\n [dataSeries],\n );\n\n const yTicks = useMemo(() => {\n const range = effectiveYRange[1] - effectiveYRange[0];\n let step = Math.pow(10, Math.floor(Math.log10(range)));\n\n if (range / step > 10) step = step * 2;\n if (range / step < 4) step = step / 2;\n\n const ticks = [];\n let current = Math.ceil(effectiveYRange[0] / step) * step;\n while (current <= effectiveYRange[1]) {\n ticks.push(current);\n current += step;\n }\n return ticks;\n }, [effectiveYRange]);\n\n const barMode = useMemo((): \"group\" | \"stack\" | \"overlay\" => {\n switch (variant) {\n case \"stack\":\n return \"stack\";\n case \"overlay\":\n return \"overlay\";\n case \"group\":\n default:\n return \"group\";\n }\n }, [variant]);\n\n const tickOptions = useMemo(\n () => ({\n tickcolor: theme.tickColor,\n ticklen: 12,\n tickwidth: 1,\n ticks: \"outside\" as const,\n tickfont: {\n size: 16,\n color: theme.textColor,\n family: \"Inter, sans-serif\",\n weight: 400,\n },\n linecolor: theme.lineColor,\n linewidth: 1,\n position: 0,\n zeroline: false,\n }),\n [theme],\n );\n\n useEffect(() => {\n if (!plotRef.current) return;\n\n const data = dataSeries.map((series) => ({\n x: series.x,\n y: series.y,\n type: \"bar\" as const,\n name: series.name,\n marker: {\n color: series.color,\n },\n width: barWidth,\n error_y: series.error_y,\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: 0 },\n paper_bgcolor: theme.paperBg,\n plot_bgcolor: theme.plotBg,\n font: {\n family: \"Inter, sans-serif\",\n },\n barmode: barMode,\n bargap: 0.15,\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 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: dataSeries.length > 1,\n };\n\n const config = {\n responsive: true,\n displayModeBar: false,\n displaylogo: false,\n };\n\n Plotly.newPlot(plotRef.current, data, layout, config);\n\n // Capture ref value for cleanup\n const plotElement = plotRef.current;\n\n // Cleanup function\n return () => {\n if (plotElement) {\n Plotly.purge(plotElement);\n }\n };\n }, [dataSeries, width, height, xRange, yRange, xTitle, yTitle, title, barWidth, barMode, tickOptions, xTicks, yTicks, theme]);\n\n return (\n <div className=\"bar-graph-container\">\n <div ref={plotRef} style={{ width: \"100%\", height: \"100%\" }} />\n </div>\n );\n};\n\nexport { BarGraph };\nexport type { BarDataSeries, BarGraphVariant, BarGraphProps };\n"],"names":["BarGraph","dataSeries","width","height","xRange","yRange","variant","xTitle","yTitle","title","barWidth","plotRef","useRef","theme","usePlotlyTheme","yMin","yMax","useMemo","minX","maxX","minY","maxY","series","x","y","xPadding","yPadding","effectiveYRange","xTicks","s","yTicks","range","step","ticks","current","barMode","tickOptions","useEffect","data","layout","config","Plotly","plotElement","jsx"],"mappings":"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"}
1
+ {"version":3,"file":"BarGraph.js","sources":["../../../../src/components/charts/BarGraph/BarGraph.tsx"],"sourcesContent":["import Plotly from \"plotly.js-dist\";\nimport React, { useEffect, useRef, useMemo } from \"react\";\n\nimport { useChartTooltip } from \"../ChartTooltip\";\n\nimport { useElementSize } from \"@/hooks/use-element-size\";\nimport { usePlotlyTheme } from \"@/hooks/use-plotly-theme\";\nimport { cn } from \"@/lib/utils\";\nimport { seriesColor } from \"@/utils/colors\";\n\ninterface BarDataSeries {\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 error_y?: {\n type: \"data\";\n array: number[];\n visible: boolean;\n };\n}\n\ntype BarGraphVariant = \"group\" | \"stack\" | \"overlay\";\n\n/** Top margin reserving room for the 32px title; reduced when no title is set */\nconst TITLE_MARGIN_TOP = 60;\nconst NO_TITLE_MARGIN_TOP = 30;\n\ninterface BarGraphProps {\n dataSeries: BarDataSeries[];\n /**\n * Fixed width in pixels. When omitted, the chart fills its container and\n * tracks the container's width via a `ResizeObserver`.\n */\n width?: number;\n /**\n * Fixed height in pixels. When omitted, the chart fills its container and\n * tracks the container's height via a `ResizeObserver`.\n */\n height?: number;\n xRange?: [number, number];\n yRange?: [number, number];\n variant?: BarGraphVariant;\n xTitle?: string;\n yTitle?: string;\n title?: string;\n barWidth?: number;\n /**\n * Categorical labels for the x-axis ticks. When provided, the x data values\n * still drive bar positioning but the displayed tick labels match these\n * strings in order (e.g. [\"Mon\", \"Tue\", …]). Should align 1:1 with the\n * unique, ordered x values across all series.\n */\n xTickText?: string[];\n}\n\nconst BarGraph: React.FC<BarGraphProps> = ({\n dataSeries,\n width,\n height,\n xRange,\n yRange,\n variant = \"group\",\n xTitle,\n yTitle,\n title,\n barWidth = 24,\n xTickText,\n}) => {\n const plotRef = useRef<HTMLDivElement>(null);\n const theme = usePlotlyTheme();\n const { bindTooltip, tooltipElement } = useChartTooltip({ xLabel: xTitle, yLabel: yTitle });\n\n // Omitted width/height → fill the container and track its measured size;\n // explicit pixel values override. See AreaGraph for the reference pattern.\n const [containerRef, measured] = useElementSize<HTMLDivElement>();\n const resolvedWidth = width ?? measured.width;\n const resolvedHeight = height ?? measured.height;\n const hasSize = resolvedWidth > 0 && resolvedHeight > 0;\n // Fill is per-dimension: omit width to fill the container width, omit height\n // to fill its height (so e.g. a fixed width with a container-driven height works).\n const fillWidth = width === undefined;\n const fillHeight = height === undefined;\n const sizeRef = useRef({ width: resolvedWidth, height: resolvedHeight });\n sizeRef.current = { width: resolvedWidth, height: resolvedHeight };\n const plotInitedRef = useRef(false);\n // Size last applied to the plot, so the resize effect can skip a redundant\n // relayout right after newPlot already drew at that size.\n const appliedSizeRef = useRef({ width: 0, height: 0 });\n\n const { yMin, yMax } = useMemo(() => {\n let minX = Number.MAX_VALUE;\n let maxX = Number.MIN_VALUE;\n let minY = Number.MAX_VALUE;\n let maxY = Number.MIN_VALUE;\n\n dataSeries.forEach((series) => {\n series.x.forEach((x) => {\n minX = Math.min(minX, x);\n maxX = Math.max(maxX, x);\n });\n series.y.forEach((y) => {\n minY = Math.min(minY, y);\n maxY = Math.max(maxY, y);\n });\n });\n\n const xPadding = (maxX - minX) * 0.1;\n const yPadding = (maxY - minY) * 0.1;\n\n return {\n xMin: minX - xPadding,\n xMax: maxX + xPadding,\n yMin: variant === \"stack\" ? 0 : minY - yPadding,\n yMax: maxY + yPadding,\n };\n }, [dataSeries, variant]);\n\n const effectiveYRange = useMemo(\n () => yRange || [yMin, yMax],\n [yRange, yMin, yMax],\n );\n\n const xTicks = useMemo(\n () => [...new Set(dataSeries.flatMap((s) => s.x))].sort((a, b) => a - b),\n [dataSeries],\n );\n\n // Only apply categorical labels when they align 1:1 with the tick positions;\n // a mismatch would silently mis-label ticks, so fall back to numeric ticks.\n const useCategoricalX = !!xTickText && xTickText.length === xTicks.length;\n\n const 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 barMode = useMemo((): \"group\" | \"stack\" | \"overlay\" => {\n switch (variant) {\n case \"stack\":\n return \"stack\";\n case \"overlay\":\n return \"overlay\";\n case \"group\":\n default:\n return \"group\";\n }\n }, [variant]);\n\n const tickOptions = useMemo(\n () => ({\n tickcolor: theme.tickColor,\n ticklen: 12,\n tickwidth: 1,\n ticks: \"outside\" as const,\n tickfont: {\n size: 16,\n color: theme.textColor,\n family: \"Inter, sans-serif\",\n weight: 400,\n },\n linecolor: theme.lineColor,\n linewidth: 1,\n position: 0,\n zeroline: false,\n }),\n [theme],\n );\n\n useEffect(() => {\n if (!plotRef.current || !hasSize) return;\n\n const data = dataSeries.map((series, index) => ({\n x: series.x,\n y: series.y,\n type: \"bar\" as const,\n name: series.name,\n hoverinfo: \"none\" as const,\n marker: {\n color: seriesColor(index, series.color),\n },\n width: barWidth,\n error_y: series.error_y,\n }));\n\n const layout = {\n ...(title\n ? {\n title: {\n text: title,\n font: {\n size: 32,\n family: \"Inter, sans-serif\",\n color: theme.textColor,\n },\n },\n }\n : {}),\n width: sizeRef.current.width,\n height: sizeRef.current.height,\n margin: {\n l: 80,\n r: 30,\n // Reserve room for tick labels, the x-axis title, and the\n // container-anchored bottom legend stacked beneath them.\n b: 96,\n t: title ? TITLE_MARGIN_TOP : NO_TITLE_MARGIN_TOP,\n pad: 0,\n },\n paper_bgcolor: theme.paperBg,\n plot_bgcolor: theme.plotBg,\n font: {\n family: \"Inter, sans-serif\",\n },\n barmode: barMode,\n bargap: 0.15,\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 ...(useCategoricalX ? { ticktext: xTickText } : {}),\n showgrid: true,\n // Reserve space for tick labels + the axis title so the bottom legend\n // can't overlap them at small sizes (SW-2157).\n automargin: 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 automargin: true,\n ...tickOptions,\n },\n legend: {\n // Anchor to the bottom of the container (not the plot area) so the\n // legend always clears the x-axis tick labels + title — a paper-relative\n // fractional offset collapses into the ticks at small heights (SW-2157).\n x: 0.5,\n y: 0,\n xanchor: \"center\" as const,\n yanchor: \"bottom\" as const,\n yref: \"container\" 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: dataSeries.length > 1,\n };\n\n const config = {\n // Sizing is driven from the measured container; disable Plotly's own\n // window-resize responsiveness (it can't see container resizes).\n responsive: false,\n displayModeBar: false,\n displaylogo: false,\n };\n\n Plotly.newPlot(plotRef.current, data, layout, config);\n bindTooltip(plotRef.current);\n\n // Capture ref value for cleanup\n const plotElement = plotRef.current;\n plotInitedRef.current = true;\n appliedSizeRef.current = { ...sizeRef.current };\n\n // Cleanup function\n return () => {\n if (plotElement) {\n Plotly.purge(plotElement);\n plotInitedRef.current = false;\n }\n };\n }, [dataSeries, hasSize, xRange, yRange, xTitle, yTitle, title, barWidth, barMode, tickOptions, xTicks, yTicks, useCategoricalX, xTickText, theme, bindTooltip]);\n\n // Resize in place when the measured/overridden size changes — cheaper than\n // recreating the plot, and it preserves tooltip/event bindings.\n useEffect(() => {\n const plotElement = plotRef.current;\n if (!plotElement || !plotInitedRef.current || resolvedWidth <= 0 || resolvedHeight <= 0) {\n return;\n }\n // newPlot already drew at the current size; skip the redundant relayout\n // (it would queue an automargin redraw that can reject if we unmount first).\n if (\n appliedSizeRef.current.width === resolvedWidth &&\n appliedSizeRef.current.height === resolvedHeight\n ) {\n return;\n }\n appliedSizeRef.current = { width: resolvedWidth, height: resolvedHeight };\n // Swallow rejections from a relayout that races an unmount/purge.\n void Plotly.relayout(plotElement, { width: resolvedWidth, height: resolvedHeight }).catch(\n () => {},\n );\n }, [resolvedWidth, resolvedHeight]);\n\n return (\n <div\n ref={containerRef}\n className={cn(\"bar-graph-container relative\", fillWidth && \"w-full\", fillHeight && \"h-full\")}\n >\n <div ref={plotRef} style={{ width: \"100%\", height: \"100%\" }} />\n {tooltipElement}\n </div>\n );\n};\n\nexport { BarGraph };\nexport type { BarDataSeries, BarGraphVariant, BarGraphProps };\n"],"names":["TITLE_MARGIN_TOP","NO_TITLE_MARGIN_TOP","BarGraph","dataSeries","width","height","xRange","yRange","variant","xTitle","yTitle","title","barWidth","xTickText","plotRef","useRef","theme","usePlotlyTheme","bindTooltip","tooltipElement","useChartTooltip","containerRef","measured","useElementSize","resolvedWidth","resolvedHeight","hasSize","fillWidth","fillHeight","sizeRef","plotInitedRef","appliedSizeRef","yMin","yMax","useMemo","minX","maxX","minY","maxY","series","x","y","xPadding","yPadding","effectiveYRange","xTicks","s","a","b","useCategoricalX","yTicks","range","step","ticks","current","barMode","tickOptions","useEffect","data","index","seriesColor","layout","config","Plotly","plotElement","jsxs","cn","jsx"],"mappings":";;;;;;;;AA0BA,MAAMA,IAAmB,IACnBC,IAAsB,IA8BtBC,KAAoC,CAAC;AAAA,EACzC,YAAAC;AAAA,EACA,OAAAC;AAAA,EACA,QAAAC;AAAA,EACA,QAAAC;AAAA,EACA,QAAAC;AAAA,EACA,SAAAC,IAAU;AAAA,EACV,QAAAC;AAAA,EACA,QAAAC;AAAA,EACA,OAAAC;AAAA,EACA,UAAAC,IAAW;AAAA,EACX,WAAAC;AACF,MAAM;AACJ,QAAMC,IAAUC,EAAuB,IAAI,GACrCC,IAAQC,EAAA,GACR,EAAE,aAAAC,GAAa,gBAAAC,EAAA,IAAmBC,EAAgB,EAAE,QAAQX,GAAQ,QAAQC,GAAQ,GAIpF,CAACW,GAAcC,CAAQ,IAAIC,EAAA,GAC3BC,IAAgBpB,KAASkB,EAAS,OAClCG,IAAiBpB,KAAUiB,EAAS,QACpCI,IAAUF,IAAgB,KAAKC,IAAiB,GAGhDE,IAAYvB,MAAU,QACtBwB,IAAavB,MAAW,QACxBwB,IAAUd,EAAO,EAAE,OAAOS,GAAe,QAAQC,GAAgB;AACvE,EAAAI,EAAQ,UAAU,EAAE,OAAOL,GAAe,QAAQC,EAAA;AAClD,QAAMK,IAAgBf,EAAO,EAAK,GAG5BgB,IAAiBhB,EAAO,EAAE,OAAO,GAAG,QAAQ,GAAG,GAE/C,EAAE,MAAAiB,GAAM,MAAAC,EAAA,IAASC,EAAQ,MAAM;AACnC,QAAIC,IAAO,OAAO,WACdC,IAAO,OAAO,WACdC,IAAO,OAAO,WACdC,IAAO,OAAO;AAElB,IAAAnC,EAAW,QAAQ,CAACoC,MAAW;AAC7B,MAAAA,EAAO,EAAE,QAAQ,CAACC,MAAM;AACtB,QAAAL,IAAO,KAAK,IAAIA,GAAMK,CAAC,GACvBJ,IAAO,KAAK,IAAIA,GAAMI,CAAC;AAAA,MACzB,CAAC,GACDD,EAAO,EAAE,QAAQ,CAACE,MAAM;AACtB,QAAAJ,IAAO,KAAK,IAAIA,GAAMI,CAAC,GACvBH,IAAO,KAAK,IAAIA,GAAMG,CAAC;AAAA,MACzB,CAAC;AAAA,IACH,CAAC;AAED,UAAMC,KAAYN,IAAOD,KAAQ,KAC3BQ,KAAYL,IAAOD,KAAQ;AAEjC,WAAO;AAAA,MACL,MAAMF,IAAOO;AAAA,MACb,MAAMN,IAAOM;AAAA,MACb,MAAMlC,MAAY,UAAU,IAAI6B,IAAOM;AAAA,MACvC,MAAML,IAAOK;AAAA,IAAA;AAAA,EAEjB,GAAG,CAACxC,GAAYK,CAAO,CAAC,GAElBoC,IAAkBV;AAAA,IACtB,MAAM3B,KAAU,CAACyB,GAAMC,CAAI;AAAA,IAC3B,CAAC1B,GAAQyB,GAAMC,CAAI;AAAA,EAAA,GAGfY,IAASX;AAAA,IACb,MAAM,CAAC,GAAG,IAAI,IAAI/B,EAAW,QAAQ,CAAC2C,MAAMA,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,CAACC,GAAGC,MAAMD,IAAIC,CAAC;AAAA,IACvE,CAAC7C,CAAU;AAAA,EAAA,GAKP8C,IAAkB,CAAC,CAACpC,KAAaA,EAAU,WAAWgC,EAAO,QAE7DK,IAAShB,EAAQ,MAAM;AAC3B,UAAMiB,IAAQP,EAAgB,CAAC,IAAIA,EAAgB,CAAC;AACpD,QAAIQ,IAAO,KAAK,IAAI,IAAI,KAAK,MAAM,KAAK,MAAMD,CAAK,CAAC,CAAC;AAErD,IAAIA,IAAQC,IAAO,OAAIA,IAAOA,IAAO,IACjCD,IAAQC,IAAO,MAAGA,IAAOA,IAAO;AAEpC,UAAMC,IAAQ,CAAA;AACd,QAAIC,IAAU,KAAK,KAAKV,EAAgB,CAAC,IAAIQ,CAAI,IAAIA;AACrD,WAAOE,KAAWV,EAAgB,CAAC;AACjC,MAAAS,EAAM,KAAKC,CAAO,GAClBA,KAAWF;AAEb,WAAOC;AAAA,EACT,GAAG,CAACT,CAAe,CAAC,GAEdW,IAAUrB,EAAQ,MAAqC;AAC3D,YAAQ1B,GAAA;AAAA,MACN,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MAET;AACE,eAAO;AAAA,IAAA;AAAA,EAEb,GAAG,CAACA,CAAO,CAAC,GAENgD,IAActB;AAAA,IAClB,OAAO;AAAA,MACL,WAAWlB,EAAM;AAAA,MACjB,SAAS;AAAA,MACT,WAAW;AAAA,MACX,OAAO;AAAA,MACP,UAAU;AAAA,QACR,MAAM;AAAA,QACN,OAAOA,EAAM;AAAA,QACb,QAAQ;AAAA,QACR,QAAQ;AAAA,MAAA;AAAA,MAEV,WAAWA,EAAM;AAAA,MACjB,WAAW;AAAA,MACX,UAAU;AAAA,MACV,UAAU;AAAA,IAAA;AAAA,IAEZ,CAACA,CAAK;AAAA,EAAA;AAGR,SAAAyC,EAAU,MAAM;AACd,QAAI,CAAC3C,EAAQ,WAAW,CAACY,EAAS;AAElC,UAAMgC,IAAOvD,EAAW,IAAI,CAACoC,GAAQoB,OAAW;AAAA,MAC9C,GAAGpB,EAAO;AAAA,MACV,GAAGA,EAAO;AAAA,MACV,MAAM;AAAA,MACN,MAAMA,EAAO;AAAA,MACb,WAAW;AAAA,MACX,QAAQ;AAAA,QACN,OAAOqB,EAAYD,GAAOpB,EAAO,KAAK;AAAA,MAAA;AAAA,MAExC,OAAO3B;AAAA,MACP,SAAS2B,EAAO;AAAA,IAAA,EAChB,GAEIsB,IAAS;AAAA,MACb,GAAIlD,IACA;AAAA,QACE,OAAO;AAAA,UACL,MAAMA;AAAA,UACN,MAAM;AAAA,YACJ,MAAM;AAAA,YACN,QAAQ;AAAA,YACR,OAAOK,EAAM;AAAA,UAAA;AAAA,QACf;AAAA,MACF,IAEF,CAAA;AAAA,MACJ,OAAOa,EAAQ,QAAQ;AAAA,MACvB,QAAQA,EAAQ,QAAQ;AAAA,MACxB,QAAQ;AAAA,QACN,GAAG;AAAA,QACH,GAAG;AAAA;AAAA;AAAA,QAGH,GAAG;AAAA,QACH,GAAGlB,IAAQX,IAAmBC;AAAA,QAC9B,KAAK;AAAA,MAAA;AAAA,MAEP,eAAee,EAAM;AAAA,MACrB,cAAcA,EAAM;AAAA,MACpB,MAAM;AAAA,QACJ,QAAQ;AAAA,MAAA;AAAA,MAEV,SAASuC;AAAA,MACT,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,OAAO;AAAA,QACL,OAAO;AAAA,UACL,MAAM9C;AAAA,UACN,MAAM;AAAA,YACJ,MAAM;AAAA,YACN,OAAOO,EAAM;AAAA,YACb,QAAQ;AAAA,YACR,QAAQ;AAAA,UAAA;AAAA,UAEV,UAAU;AAAA,QAAA;AAAA,QAEZ,WAAWA,EAAM;AAAA,QACjB,OAAOV;AAAA,QACP,WAAW,CAACA;AAAA,QACZ,UAAU;AAAA,QACV,UAAUuC;AAAA,QACV,GAAII,IAAkB,EAAE,UAAUpC,EAAA,IAAc,CAAA;AAAA,QAChD,UAAU;AAAA;AAAA;AAAA,QAGV,YAAY;AAAA,QACZ,GAAG2C;AAAA,MAAA;AAAA,MAEL,OAAO;AAAA,QACL,OAAO;AAAA,UACL,MAAM9C;AAAA,UACN,MAAM;AAAA,YACJ,MAAM;AAAA,YACN,OAAOM,EAAM;AAAA,YACb,QAAQ;AAAA,YACR,QAAQ;AAAA,UAAA;AAAA,UAEV,UAAU;AAAA,QAAA;AAAA,QAEZ,WAAWA,EAAM;AAAA,QACjB,OAAOT;AAAA,QACP,WAAW,CAACA;AAAA,QACZ,UAAU;AAAA,QACV,UAAU2C;AAAA,QACV,UAAU;AAAA,QACV,YAAY;AAAA,QACZ,GAAGM;AAAA,MAAA;AAAA,MAEL,QAAQ;AAAA;AAAA;AAAA;AAAA,QAIN,GAAG;AAAA,QACH,GAAG;AAAA,QACH,SAAS;AAAA,QACT,SAAS;AAAA,QACT,MAAM;AAAA,QACN,aAAa;AAAA,QACb,MAAM;AAAA,UACJ,MAAM;AAAA,UACN,OAAOxC,EAAM;AAAA,UACb,QAAQ;AAAA,UACR,QAAQ;AAAA,QAAA;AAAA,MACV;AAAA,MAEF,YAAYb,EAAW,SAAS;AAAA,IAAA,GAG5B2D,IAAS;AAAA;AAAA;AAAA,MAGb,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,aAAa;AAAA,IAAA;AAGf,IAAAC,EAAO,QAAQjD,EAAQ,SAAS4C,GAAMG,GAAQC,CAAM,GACpD5C,EAAYJ,EAAQ,OAAO;AAG3B,UAAMkD,IAAclD,EAAQ;AAC5B,WAAAgB,EAAc,UAAU,IACxBC,EAAe,UAAU,EAAE,GAAGF,EAAQ,QAAA,GAG/B,MAAM;AACX,MAAImC,MACFD,EAAO,MAAMC,CAAW,GACxBlC,EAAc,UAAU;AAAA,IAE5B;AAAA,EACF,GAAG,CAAC3B,GAAYuB,GAASpB,GAAQC,GAAQE,GAAQC,GAAQC,GAAOC,GAAU2C,GAASC,GAAaX,GAAQK,GAAQD,GAAiBpC,GAAWG,GAAOE,CAAW,CAAC,GAI/JuC,EAAU,MAAM;AACd,UAAMO,IAAclD,EAAQ;AAC5B,IAAI,CAACkD,KAAe,CAAClC,EAAc,WAAWN,KAAiB,KAAKC,KAAkB,KAMpFM,EAAe,QAAQ,UAAUP,KACjCO,EAAe,QAAQ,WAAWN,MAIpCM,EAAe,UAAU,EAAE,OAAOP,GAAe,QAAQC,EAAA,GAEpDsC,EAAO,SAASC,GAAa,EAAE,OAAOxC,GAAe,QAAQC,EAAA,CAAgB,EAAE;AAAA,MAClF,MAAM;AAAA,MAAC;AAAA,IAAA;AAAA,EAEX,GAAG,CAACD,GAAeC,CAAc,CAAC,GAGhC,gBAAAwC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAK5C;AAAA,MACL,WAAW6C,EAAG,gCAAgCvC,KAAa,UAAUC,KAAc,QAAQ;AAAA,MAE3F,UAAA;AAAA,QAAA,gBAAAuC,EAAC,OAAA,EAAI,KAAKrD,GAAS,OAAO,EAAE,OAAO,QAAQ,QAAQ,OAAA,EAAO,CAAG;AAAA,QAC5DK;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGP;"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const I=require("react/jsx-runtime"),C=require("plotly.js-dist"),i=require("react"),E=require("../../../hooks/use-plotly-theme.cjs"),P=-1.8,j=({dataSeries:a,width:h=1e3,height:m=600,xRange:u,yRange:c,xTitle:d="Columns",yTitle:g="Rows",title:x="Boxplot",showPoints:y=!1})=>{const f=i.useRef(null),t=E.usePlotlyTheme(),{yMin:M,yMax:w}=i.useMemo(()=>{let r=Number.MAX_VALUE,o=Number.MIN_VALUE;a.forEach(n=>{n.y.forEach(e=>{r=Math.min(r,e),o=Math.max(o,e)})});const l=(o-r)*.1;return{yMin:r-l,yMax:o+l}},[a]),s=i.useMemo(()=>c||[M,w],[c,M,w]),k=i.useMemo(()=>{const r=s[1]-s[0];let o=Math.pow(10,Math.floor(Math.log10(r)));r/o>10&&(o=o*2),r/o<4&&(o=o/2);const l=[];let n=Math.ceil(s[0]/o)*o;for(;n<=s[1];)l.push(n),n+=o;return l},[s]),p=i.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]),b=i.useMemo(()=>({text:x,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}}),[x,t]);return i.useEffect(()=>{if(!f.current)return;const r=a.map(e=>({y:e.y,x:e.x,type:"box",name:e.name,marker:{color:e.color},line:{color:e.color},fillcolor:e.color+"40",boxpoints:y?e.boxpoints||"outliers":!1,jitter:e.jitter||.3,pointpos:e.pointpos||P})),o={width:h,height:m,title:b,margin:{l:80,r:40,b:80,t:80,pad:0},paper_bgcolor:t.paperBg,plot_bgcolor:t.plotBg,font:{family:"Inter, sans-serif"},dragmode:!1,xaxis:{title:{text:d,font:{size:16,color:t.textSecondary,family:"Inter, sans-serif",weight:400},standoff:15},gridcolor:t.gridColor,range:u,autorange:!u,showgrid:!0,...p},yaxis:{title:{text:g,font:{size:16,color:t.textSecondary,family:"Inter, sans-serif",weight:400},standoff:15},gridcolor:t.gridColor,range:c,autorange:!c,tickmode:"array",tickvals:k,showgrid:!0,...p},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}},showlegend:!0},l={responsive:!0,displayModeBar:!1,displaylogo:!1};C.newPlot(f.current,r,o,l);const n=f.current;return()=>{n&&C.purge(n)}},[a,h,m,u,c,s,d,g,y,b,p,k,t]),I.jsx("div",{className:"boxplot-container",children:I.jsx("div",{ref:f,style:{width:"100%",height:"100%"}})})};exports.Boxplot=j;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const O=require("react/jsx-runtime"),b=require("plotly.js-dist"),r=require("react"),A=require("../ChartTooltip/ChartTooltip.cjs"),U=require("../../../hooks/use-element-size.cjs"),W=require("../../../hooks/use-plotly-theme.cjs"),Y=require("../../../lib/utils.cjs"),H=require("../../../utils/colors.cjs"),V=-1.8,D=({dataSeries:d,width:v,height:k,xRange:m,yRange:f,xTitle:y,yTitle:x,title:E="Boxplot",showPoints:z=!1})=>{const u=r.useRef(null),e=W.usePlotlyTheme(),{bindTooltip:I,tooltipElement:R}=A.useChartTooltip({xLabel:y,yLabel:x}),[S,C]=U.useElementSize(),i=v??C.width,l=k??C.height,q=i>0&&l>0,T=v===void 0,_=k===void 0,g=r.useRef({width:i,height:l});g.current={width:i,height:l};const w=r.useRef(!1),p=r.useRef({width:0,height:0}),{yMin:P,yMax:j}=r.useMemo(()=>{let o=Number.MAX_VALUE,t=Number.MIN_VALUE;d.forEach(s=>{s.y.forEach(n=>{o=Math.min(o,n),t=Math.max(t,n)})});const c=(t-o)*.1;return{yMin:o-c,yMax:t+c}},[d]),h=r.useMemo(()=>f||[P,j],[f,P,j]),B=r.useMemo(()=>{const o=h[1]-h[0];let t=Math.pow(10,Math.floor(Math.log10(o)));o/t>10&&(t=t*2),o/t<4&&(t=t/2);const c=[];let s=Math.ceil(h[0]/t)*t;for(;s<=h[1];)c.push(s),s+=t;return c},[h]),M=r.useMemo(()=>({tickcolor:e.tickColor,ticklen:12,tickwidth:1,ticks:"outside",tickfont:{size:16,color:e.textColor,family:"Inter, sans-serif",weight:400},linecolor:e.lineColor,linewidth:1,position:0,zeroline:!1}),[e]),N=r.useMemo(()=>({text:E,x:.5,y:.95,xanchor:"center",yanchor:"top",font:{size:32,weight:600,family:"Inter, sans-serif",color:e.textColor,lineheight:1.2,standoff:30}}),[E,e]);return r.useEffect(()=>{if(!u.current||!q)return;const o=d.map((n,L)=>{const a=H.seriesColor(L,n.color);return{y:n.y,x:n.x,type:"box",name:n.name,hoverinfo:"none",marker:{color:a},line:{color:a},fillcolor:typeof a=="string"&&a.startsWith("#")&&a.length===7?`${a}40`:a,boxpoints:z?n.boxpoints||"outliers":!1,jitter:n.jitter||.3,pointpos:n.pointpos||V}}),t={width:g.current.width,height:g.current.height,title:N,margin:{l:80,r:40,b:96,t:80,pad:0},paper_bgcolor:e.paperBg,plot_bgcolor:e.plotBg,font:{family:"Inter, sans-serif"},dragmode:!1,xaxis:{title:{text:y,font:{size:16,color:e.textSecondary,family:"Inter, sans-serif",weight:400},standoff:15},gridcolor:e.gridColor,range:m,autorange:!m,showgrid:!0,automargin:!0,...M},yaxis:{title:{text:x,font:{size:16,color:e.textSecondary,family:"Inter, sans-serif",weight:400},standoff:15},gridcolor:e.gridColor,range:f,autorange:!f,tickmode:"array",tickvals:B,showgrid:!0,automargin:!0,...M},legend:{x:.5,y:0,xanchor:"center",yanchor:"bottom",yref:"container",orientation:"h",font:{size:13,color:e.legendColor,family:"Inter, sans-serif",weight:500,lineheight:18}},showlegend:!0},c={responsive:!1,displayModeBar:!1,displaylogo:!1};b.newPlot(u.current,o,t,c),I(u.current);const s=u.current;return w.current=!0,p.current={...g.current},()=>{s&&(b.purge(s),w.current=!1)}},[d,q,m,f,h,y,x,z,N,M,B,e,I]),r.useEffect(()=>{const o=u.current;!o||!w.current||i<=0||l<=0||p.current.width===i&&p.current.height===l||(p.current={width:i,height:l},b.relayout(o,{width:i,height:l}).catch(()=>{}))},[i,l]),O.jsxs("div",{ref:S,className:Y.cn("boxplot-container relative",T&&"w-full",_&&"h-full"),children:[O.jsx("div",{ref:u,style:{width:"100%",height:"100%"}}),R]})};exports.Boxplot=D;
2
2
  //# sourceMappingURL=Boxplot.cjs.map