@anvme/nanocharts 1.0.0 → 1.0.2

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 CHANGED
@@ -27,8 +27,8 @@ import '@anvme/nanocharts/style.css';
27
27
  ### CDN
28
28
 
29
29
  ```html
30
- <link href="https://cdn.jsdelivr.net/npm/@anvme/nanocharts@1.0.0/dist/style.min.css" rel="stylesheet">
31
- <script src="https://cdn.jsdelivr.net/npm/@anvme/nanocharts@1.0.0/dist/nanocharts.min.global.js"></script>
30
+ <link href="https://cdn.jsdelivr.net/npm/@anvme/nanocharts@1.0.2/dist/style.min.css" rel="stylesheet">
31
+ <script src="https://cdn.jsdelivr.net/npm/@anvme/nanocharts@1.0.2/dist/nanocharts.min.global.js"></script>
32
32
  ```
33
33
 
34
34
  ## Usage
package/dist/index.cjs CHANGED
@@ -55,6 +55,21 @@ function attachHoverListeners(container, svgEl, onUpdate, onLeave) {
55
55
  }, { passive: true });
56
56
  container.addEventListener("touchend", onLeave, { passive: true });
57
57
  }
58
+ function observeResize(container, render) {
59
+ if (typeof ResizeObserver === "undefined") return;
60
+ var parent = container.parentElement || container;
61
+ var lastW = parent.clientWidth;
62
+ var ro = new ResizeObserver(function() {
63
+ var newW = parent.clientWidth;
64
+ if (newW && newW !== lastW) {
65
+ lastW = newW;
66
+ ro.disconnect();
67
+ container.style.width = "";
68
+ render();
69
+ }
70
+ });
71
+ ro.observe(parent);
72
+ }
58
73
 
59
74
  // src/line-chart.ts
60
75
  function NanoLineChart(containerId, config) {
@@ -63,7 +78,8 @@ function NanoLineChart(containerId, config) {
63
78
  var xLabel = config.xLabel || "";
64
79
  var yLabel = config.yLabel || "";
65
80
  var colors = config.colors || ["#215CAF", "#007894", "#00C9A7", "#DE4437", "#F69C3D"];
66
- var padding = { top: 20, right: 30, bottom: 50, left: 60 };
81
+ var dp = config.padding || {};
82
+ var padding = { top: dp.top || 0, right: dp.right || 0, bottom: dp.bottom || 0, left: dp.left || 0 };
67
83
  var smooth = config.smooth === true;
68
84
  var areaFill = config.areaFill === true;
69
85
  var areaOpacity = config.areaOpacity !== void 0 ? config.areaOpacity : 0.1;
@@ -156,6 +172,11 @@ function NanoLineChart(containerId, config) {
156
172
  labelMarkup += "</div>";
157
173
  container.style.cssText = "position:relative;width:" + chartWidth + "px;height:" + chartHeight + "px";
158
174
  container.innerHTML = svgMarkup + labelMarkup;
175
+ if (!config.width) {
176
+ observeResize(container, function() {
177
+ NanoLineChart(containerId, config);
178
+ });
179
+ }
159
180
  if (!hoverEnabled) return;
160
181
  var svg = container.firstChild;
161
182
  var indicator = null;
@@ -228,7 +249,8 @@ function NanoBarChart(containerId, config) {
228
249
  var gridDashed = config.gridDashed === true;
229
250
  var hoverEnabled = config.hover !== false;
230
251
  var barGap = config.barGap !== void 0 ? config.barGap : 0.2;
231
- var padding = { top: 20, right: 30, bottom: 50, left: horizontal ? 80 : 60 };
252
+ var dp = config.padding || {};
253
+ var padding = { top: dp.top || 0, right: dp.right || 0, bottom: dp.bottom || 0, left: dp.left || 0 };
232
254
  var container = document.getElementById(containerId);
233
255
  if (!container || !data.length || !data[0].length) return;
234
256
  var chartWidth = config.width || container.clientWidth || 600;
@@ -399,6 +421,11 @@ function NanoBarChart(containerId, config) {
399
421
  labelMarkup += "</div>";
400
422
  container.style.cssText = "position:relative;width:" + chartWidth + "px;height:" + chartHeight + "px";
401
423
  container.innerHTML = svgMarkup + labelMarkup;
424
+ if (!config.width) {
425
+ observeResize(container, function() {
426
+ NanoBarChart(containerId, config);
427
+ });
428
+ }
402
429
  if (!hoverEnabled) return;
403
430
  var svgEl = container.firstChild;
404
431
  var highlight = null;
@@ -546,6 +573,11 @@ function NanoPieChart(containerId, config) {
546
573
  labelMarkup += "</div>";
547
574
  container.style.cssText = "position:relative;width:" + chartWidth + "px;height:" + chartHeight + "px";
548
575
  container.innerHTML = svgMarkup + labelMarkup;
576
+ if (!config.width) {
577
+ observeResize(container, function() {
578
+ NanoPieChart(containerId, config);
579
+ });
580
+ }
549
581
  if (!hoverEnabled) return;
550
582
  var svgEl = container.firstChild;
551
583
  var highlight = null;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/shared.ts","../src/line-chart.ts","../src/bar-chart.ts","../src/pie-chart.ts"],"sourcesContent":["export { NanoLineChart } from './line-chart';\nexport type { LineChartConfig } from './line-chart';\nexport { NanoBarChart } from './bar-chart';\nexport type { BarChartConfig } from './bar-chart';\nexport { NanoPieChart } from './pie-chart';\nexport type { PieChartConfig } from './pie-chart';\n\nimport { NanoLineChart } from './line-chart';\nimport { NanoBarChart } from './bar-chart';\nimport { NanoPieChart } from './pie-chart';\n\n// UMD-style globals for script-tag usage\nif (typeof window !== 'undefined') {\n (window as any).NanoLineChart = NanoLineChart;\n (window as any).NanoBarChart = NanoBarChart;\n (window as any).NanoPieChart = NanoPieChart;\n}\n","export interface Padding {\n top: number;\n right: number;\n bottom: number;\n left: number;\n}\n\nexport var SVG_NS = 'http://www.w3.org/2000/svg';\n\n/**\n * Attaches RAF-throttled hover listeners (mouse + touch + resize).\n * Each chart provides its own onUpdate(mx, my) and onLeave() callbacks.\n */\nexport function attachHoverListeners(\n container: HTMLElement,\n svgEl: SVGSVGElement,\n onUpdate: (mx: number, my: number) => void,\n onLeave: () => void\n): void {\n var rafPending = false;\n var lastCX = 0, lastCY = 0;\n\n function schedule() {\n if (!rafPending) {\n rafPending = true;\n requestAnimationFrame(function () {\n rafPending = false;\n var r = svgEl.getBoundingClientRect();\n onUpdate(lastCX - r.left, lastCY - r.top);\n });\n }\n }\n\n container.addEventListener('mousemove', function (e: MouseEvent) {\n lastCX = e.clientX; lastCY = e.clientY;\n schedule();\n }, { passive: true });\n\n container.addEventListener('mouseleave', onLeave, { passive: true });\n\n container.addEventListener('touchmove', function (e: TouchEvent) {\n var t = e.touches[0];\n lastCX = t.clientX; lastCY = t.clientY;\n schedule();\n }, { passive: true });\n\n container.addEventListener('touchend', onLeave, { passive: true });\n}\n","import { Padding, SVG_NS, attachHoverListeners } from './shared';\n\n/**\n * Configuration for a chart instance.\n */\nexport interface LineChartConfig {\n /** Array of data series. Each inner array is one series of numeric values. */\n data: number[][];\n /** X-axis labels. Must match the length of each data series. */\n labels: string[];\n /** X-axis title. */\n xLabel?: string;\n /** Y-axis title. */\n yLabel?: string;\n /** Colors for each series. Defaults to Thruscan brand palette. */\n colors?: string[];\n /** Chart width in pixels. Defaults to container's clientWidth or 600. */\n width?: number;\n /** Chart height in pixels. Defaults to 350. */\n height?: number;\n /** Catmull-Rom spline smoothing. Default false. */\n smooth?: boolean;\n /** Semi-transparent fill under each series. Default false. */\n areaFill?: boolean;\n /** Area fill opacity. Default 0.1. */\n areaOpacity?: number;\n /** Show X/Y tick labels. Default true. */\n showTicks?: boolean;\n /** Show grid lines. Default true. */\n showGrid?: boolean;\n /** Dashed grid lines. Default false. */\n gridDashed?: boolean;\n /** Series stroke width. Default 2.5. */\n strokeWidth?: number;\n /** Enable hover tooltip + indicator. Default true. */\n hover?: boolean;\n}\n\n\n/**\n * Creates a high-performance SVG+HTML hybrid line chart inside the specified container.\n */\nexport function NanoLineChart(containerId: string, config: LineChartConfig): void {\n var data = config.data;\n var labels = config.labels;\n var xLabel = config.xLabel || '';\n var yLabel = config.yLabel || '';\n var colors = config.colors || ['#215CAF', '#007894', '#00C9A7', '#DE4437', '#F69C3D'];\n var padding: Padding = { top: 20, right: 30, bottom: 50, left: 60 };\n\n var smooth = config.smooth === true;\n var areaFill = config.areaFill === true;\n var areaOpacity = config.areaOpacity !== undefined ? config.areaOpacity : 0.1;\n var showTicks = config.showTicks !== false;\n var showGrid = config.showGrid !== false;\n var gridDashed = config.gridDashed === true;\n var strokeWidth = config.strokeWidth !== undefined ? config.strokeWidth : 2.5;\n var hoverEnabled = config.hover !== false;\n\n var container = document.getElementById(containerId)!;\n if (!container || !data.length || !data[0].length) return;\n var chartWidth = config.width || container.clientWidth || 600;\n var chartHeight = config.height || 350;\n var plotWidth = chartWidth - padding.left - padding.right;\n var plotHeight = chartHeight - padding.top - padding.bottom;\n var plotBottom = padding.top + plotHeight;\n\n // ── Phase 1: Pure math (zero DOM) ──\n var seriesIndex: number, pointIndex: number, minValue: number, maxValue: number;\n minValue = maxValue = data[0][0];\n for (seriesIndex = 0; seriesIndex < data.length; seriesIndex++)\n for (pointIndex = 0; pointIndex < data[seriesIndex].length; pointIndex++) {\n if (data[seriesIndex][pointIndex] < minValue) minValue = data[seriesIndex][pointIndex];\n if (data[seriesIndex][pointIndex] > maxValue) maxValue = data[seriesIndex][pointIndex];\n }\n var range = maxValue - minValue || 1;\n minValue -= range * 0.05;\n maxValue += range * 0.05;\n range = maxValue - minValue;\n\n var pointCount = labels.length;\n var stepX = pointCount > 1 ? plotWidth / (pointCount - 1) : 0;\n var tickCount = 6;\n var tickStep = range / (tickCount - 1);\n\n // Int16Array — half memory of Float32Array, perfect for integer pixel coords\n var totalCoords = data.length * pointCount;\n var coordsX = new Int16Array(totalCoords);\n var coordsY = new Int16Array(totalCoords);\n for (seriesIndex = 0; seriesIndex < data.length; seriesIndex++)\n for (pointIndex = 0; pointIndex < pointCount; pointIndex++) {\n var coordIndex = seriesIndex * pointCount + pointIndex;\n coordsX[coordIndex] = (padding.left + pointIndex * stepX) | 0;\n coordsY[coordIndex] = (padding.top + plotHeight - ((data[seriesIndex][pointIndex] - minValue) / range) * plotHeight) | 0;\n }\n\n // Grid Y positions + labels\n var gridYPositions = new Int16Array(tickCount);\n var gridLabels = new Array(tickCount);\n var tickIndex: number;\n for (tickIndex = 0; tickIndex < tickCount; tickIndex++) {\n var tickValue = minValue + tickIndex * tickStep;\n gridYPositions[tickIndex] = (padding.top + plotHeight - ((tickValue - minValue) / range) * plotHeight) | 0;\n gridLabels[tickIndex] = tickValue.toFixed(1);\n }\n\n // ── Phase 2: Build SVG string ──\n var svgMarkup = '<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"' + chartWidth + '\" height=\"' + chartHeight + '\" viewBox=\"0 0 ' + chartWidth + ' ' + chartHeight + '\" class=\"chart\">';\n\n // Grid path\n if (showGrid) {\n var gridPath = '';\n for (tickIndex = 0; tickIndex < tickCount; tickIndex++)\n gridPath += 'M' + padding.left + ',' + gridYPositions[tickIndex] + 'H' + (padding.left + plotWidth);\n svgMarkup += '<path d=\"' + gridPath + '\" class=\"chart-grid\"' + (gridDashed ? ' stroke-dasharray=\"3 4\"' : '') + '/>';\n }\n\n // Series paths\n for (seriesIndex = 0; seriesIndex < data.length; seriesIndex++) {\n var ci = seriesIndex * pointCount;\n var pathData = 'M' + coordsX[ci] + ',' + coordsY[ci];\n\n if (smooth) {\n // Catmull-Rom → Cubic Bezier, directly from Int16Array coords\n for (pointIndex = 0; pointIndex < pointCount - 1; pointIndex++) {\n var prevI = pointIndex ? pointIndex - 1 : 0;\n var next2I = pointIndex + 2 < pointCount ? pointIndex + 2 : pointCount - 1;\n var curX = coordsX[ci + pointIndex], curY = coordsY[ci + pointIndex];\n var nextX = coordsX[ci + pointIndex + 1], nextY = coordsY[ci + pointIndex + 1];\n var prevX = coordsX[ci + prevI], prevY = coordsY[ci + prevI];\n var next2X = coordsX[ci + next2I], next2Y = coordsY[ci + next2I];\n pathData += ' C' + ((curX + (nextX - prevX) / 6) | 0) + ',' + ((curY + (nextY - prevY) / 6) | 0)\n + ' ' + ((nextX - (next2X - curX) / 6) | 0) + ',' + ((nextY - (next2Y - curY) / 6) | 0)\n + ' ' + nextX + ',' + nextY;\n }\n } else {\n for (pointIndex = 1; pointIndex < pointCount; pointIndex++)\n pathData += 'L' + coordsX[ci + pointIndex] + ',' + coordsY[ci + pointIndex];\n }\n\n // Area fill path (before series line so line draws on top)\n if (areaFill) {\n var firstX = coordsX[ci], lastX = coordsX[ci + pointCount - 1];\n svgMarkup += '<path d=\"' + pathData + ' L' + lastX + ',' + plotBottom + ' L' + firstX + ',' + plotBottom + ' Z\"'\n + ' fill=\"' + colors[seriesIndex % colors.length] + '\" fill-opacity=\"' + areaOpacity + '\" stroke=\"none\" pointer-events=\"none\"/>';\n }\n\n svgMarkup += '<path d=\"' + pathData + '\" class=\"chart-series\" stroke=\"' + colors[seriesIndex % colors.length] + '\"'\n + (strokeWidth !== 2.5 ? ' stroke-width=\"' + strokeWidth + '\"' : '') + '/>';\n }\n\n svgMarkup += '</svg>';\n\n // ── Phase 3: Build HTML label overlay ──\n var labelMarkup = '<div class=\"chart-labels\">';\n\n if (showTicks) {\n // Y tick labels\n for (tickIndex = 0; tickIndex < tickCount; tickIndex++)\n labelMarkup += '<span class=\"chart-tick-y\" style=\"left:' + (padding.left - 4) + 'px;top:' + (gridYPositions[tickIndex] - 1) + 'px\">' + gridLabels[tickIndex] + '</span>';\n\n // X tick labels\n for (pointIndex = 0; pointIndex < pointCount; pointIndex++)\n labelMarkup += '<span class=\"chart-tick-x\" style=\"left:' + coordsX[pointIndex] + 'px;top:' + (padding.top + plotHeight + 6) + 'px\">' + labels[pointIndex] + '</span>';\n }\n\n // Axis titles\n if (xLabel)\n labelMarkup += '<span class=\"chart-title\" style=\"left:' + (padding.left + (plotWidth >> 1)) + 'px;top:' + (chartHeight - 10) + 'px\">' + xLabel + '</span>';\n if (yLabel)\n labelMarkup += '<span class=\"chart-title\" style=\"left:4px;top:' + (padding.top - 14) + 'px;transform:none;text-align:left\">' + yLabel + '</span>';\n\n labelMarkup += '</div>';\n\n // ── Phase 4: Single innerHTML write (SVG + HTML labels) ──\n container.style.cssText = 'position:relative;width:' + chartWidth + 'px;height:' + chartHeight + 'px';\n container.innerHTML = svgMarkup + labelMarkup;\n\n // ── Phase 5: Lazy hover ──\n if (!hoverEnabled) return;\n\n var svg = container.firstChild as SVGSVGElement;\n var indicator: SVGCircleElement | null = null;\n var tooltip: HTMLDivElement | null = null;\n\n function ensureHoverElements() {\n if (!indicator) {\n indicator = document.createElementNS(SVG_NS, 'circle') as SVGCircleElement;\n indicator.setAttribute('r', '5');\n indicator.setAttribute('class', 'chart-indicator');\n indicator.style.display = 'none';\n svg.appendChild(indicator);\n }\n if (!tooltip) {\n tooltip = document.createElement('div') as HTMLDivElement;\n tooltip.className = 'chart-tooltip';\n container.appendChild(tooltip);\n }\n }\n\n attachHoverListeners(container, svg,\n function (mouseX, mouseY) {\n if (mouseX < padding.left || mouseX > padding.left + plotWidth || mouseY < padding.top || mouseY > padding.top + plotHeight) {\n if (indicator) indicator.style.display = 'none';\n if (tooltip) tooltip.style.opacity = '0';\n return;\n }\n\n ensureHoverElements();\n\n var relativeX = mouseX - padding.left;\n if (relativeX < 0) relativeX = 0;\n if (relativeX > plotWidth) relativeX = plotWidth;\n var nearestIndex = (relativeX / stepX + 0.5) | 0;\n if (nearestIndex >= pointCount) nearestIndex = pointCount - 1;\n\n var bestSeriesIndex = 0;\n var bestDistance = Math.abs(coordsY[nearestIndex] - mouseY);\n for (var searchIndex = 1; searchIndex < data.length; searchIndex++) {\n var distance = Math.abs(coordsY[searchIndex * pointCount + nearestIndex] - mouseY);\n if (distance < bestDistance) { bestDistance = distance; bestSeriesIndex = searchIndex; }\n }\n\n var pointX = coordsX[bestSeriesIndex * pointCount + nearestIndex];\n var pointY = coordsY[bestSeriesIndex * pointCount + nearestIndex];\n\n indicator!.setAttribute('transform', 'translate(' + pointX + ',' + pointY + ')');\n indicator!.setAttribute('fill', colors[bestSeriesIndex % colors.length]);\n indicator!.style.display = '';\n\n tooltip!.innerHTML = '<b>Series ' + (bestSeriesIndex + 1) + '</b><br>' +\n xLabel + ': ' + labels[nearestIndex] + '<br>' + yLabel + ': ' + data[bestSeriesIndex][nearestIndex];\n tooltip!.style.transform = 'translate(' + pointX + 'px,' + (pointY - 40) + 'px) translate(-50%,-100%)';\n tooltip!.style.opacity = '1';\n },\n function () {\n if (indicator) indicator.style.display = 'none';\n if (tooltip) tooltip.style.opacity = '0';\n }\n );\n}\n\n","import { Padding, SVG_NS, attachHoverListeners } from './shared';\n\n/**\n * Configuration for a bar chart instance.\n */\nexport interface BarChartConfig {\n /** Array of data series. Each inner array is one series of numeric values. */\n data: number[][];\n /** Category labels. Must match the length of each data series. */\n labels: string[];\n /** X-axis title. */\n xLabel?: string;\n /** Y-axis title. */\n yLabel?: string;\n /** Colors for each series. Defaults to Thruscan brand palette. */\n colors?: string[];\n /** Chart width in pixels. Defaults to container's clientWidth or 600. */\n width?: number;\n /** Chart height in pixels. Defaults to 350. */\n height?: number;\n /** Stack series instead of grouping side-by-side. Default false. */\n stacked?: boolean;\n /** Horizontal bars (categories on Y-axis). Default false. */\n horizontal?: boolean;\n /** Gap between bar groups as fraction of group width (0–1). Default 0.2. */\n barGap?: number;\n /** Show tick labels. Default true. */\n showTicks?: boolean;\n /** Show grid lines. Default true. */\n showGrid?: boolean;\n /** Dashed grid lines. Default false. */\n gridDashed?: boolean;\n /** Enable hover tooltip + indicator. Default true. */\n hover?: boolean;\n}\n\n\n/**\n * Creates a high-performance SVG+HTML hybrid bar chart inside the specified container.\n */\nexport function NanoBarChart(containerId: string, config: BarChartConfig): void {\n var data = config.data;\n var labels = config.labels;\n var xLabel = config.xLabel || '';\n var yLabel = config.yLabel || '';\n var colors = config.colors || ['#215CAF', '#007894', '#00C9A7', '#DE4437', '#F69C3D'];\n var stacked = config.stacked === true;\n var horizontal = config.horizontal === true;\n var showTicks = config.showTicks !== false;\n var showGrid = config.showGrid !== false;\n var gridDashed = config.gridDashed === true;\n var hoverEnabled = config.hover !== false;\n var barGap = config.barGap !== undefined ? config.barGap : 0.2;\n var padding: Padding = { top: 20, right: 30, bottom: 50, left: horizontal ? 80 : 60 };\n\n var container = document.getElementById(containerId)!;\n if (!container || !data.length || !data[0].length) return;\n var chartWidth = config.width || container.clientWidth || 600;\n var chartHeight = config.height || 350;\n var plotWidth = chartWidth - padding.left - padding.right;\n var plotHeight = chartHeight - padding.top - padding.bottom;\n var plotBottom = padding.top + plotHeight;\n\n var seriesCount = data.length;\n var catCount = labels.length;\n var si: number, ci: number, val: number, ti: number;\n\n // ── Phase 1: Pure math (zero DOM) ──\n\n // Find min/max\n var minVal: number, maxVal: number;\n if (stacked) {\n minVal = 0;\n maxVal = 0;\n for (ci = 0; ci < catCount; ci++) {\n var colSum = 0;\n for (si = 0; si < seriesCount; si++) {\n colSum += data[si][ci];\n if (data[si][ci] < minVal) minVal = data[si][ci];\n }\n if (colSum > maxVal) maxVal = colSum;\n }\n } else {\n minVal = maxVal = data[0][0];\n for (si = 0; si < seriesCount; si++)\n for (ci = 0; ci < catCount; ci++) {\n val = data[si][ci];\n if (val < minVal) minVal = val;\n if (val > maxVal) maxVal = val;\n }\n }\n\n if (minVal > 0) minVal = 0;\n if (maxVal < 0) maxVal = 0;\n\n var range = maxVal - minVal || 1;\n maxVal += range * 0.05;\n range = maxVal - minVal;\n\n // Grid tick positions + labels\n var tickCount = 6;\n var tickStep = range / (tickCount - 1);\n var gridPositions = new Int16Array(tickCount);\n var gridLabels = new Array<string>(tickCount);\n\n var totalBars = seriesCount * catCount;\n var barX = new Int16Array(totalBars);\n var barY = new Int16Array(totalBars);\n var barW = new Int16Array(totalBars);\n var barH = new Int16Array(totalBars);\n var groupSize: number;\n var zeroY = 0;\n\n if (horizontal) {\n // ── Horizontal: categories on Y, values on X ──\n groupSize = plotHeight / catCount;\n var zeroX = (padding.left + ((0 - minVal) / range) * plotWidth) | 0;\n\n for (ti = 0; ti < tickCount; ti++) {\n var tickVal = minVal + ti * tickStep;\n gridPositions[ti] = (padding.left + ((tickVal - minVal) / range) * plotWidth) | 0;\n gridLabels[ti] = tickVal % 1 === 0 ? tickVal.toString() : tickVal.toFixed(1);\n }\n\n var hBarHeight = ((groupSize * (1 - barGap)) / seriesCount) | 0;\n var hGroupStart = ((groupSize - hBarHeight * seriesCount) / 2) | 0;\n\n for (si = 0; si < seriesCount; si++)\n for (ci = 0; ci < catCount; ci++) {\n var idx = si * catCount + ci;\n val = data[si][ci];\n var valX = (padding.left + ((val - minVal) / range) * plotWidth) | 0;\n\n barY[idx] = (padding.top + ci * groupSize + hGroupStart + si * hBarHeight) | 0;\n barH[idx] = hBarHeight;\n\n if (val >= 0) {\n barX[idx] = zeroX;\n barW[idx] = (valX - zeroX || 1) as number;\n } else {\n barX[idx] = valX;\n barW[idx] = (zeroX - valX || 1) as number;\n }\n }\n } else {\n // ── Vertical: categories on X, values on Y ──\n groupSize = plotWidth / catCount;\n\n zeroY = (padding.top + plotHeight - ((0 - minVal) / range) * plotHeight) | 0;\n\n for (ti = 0; ti < tickCount; ti++) {\n var tickVal = minVal + ti * tickStep;\n gridPositions[ti] = (padding.top + plotHeight - ((tickVal - minVal) / range) * plotHeight) | 0;\n gridLabels[ti] = tickVal % 1 === 0 ? tickVal.toString() : tickVal.toFixed(1);\n }\n\n if (stacked) {\n var stackBarWidth = (groupSize * (1 - barGap)) | 0;\n var stackBarOffset = ((groupSize - stackBarWidth) / 2) | 0;\n\n for (ci = 0; ci < catCount; ci++) {\n var cumPos = 0;\n for (si = 0; si < seriesCount; si++) {\n var idx = si * catCount + ci;\n val = data[si][ci];\n var baseY = (padding.top + plotHeight - ((cumPos - minVal) / range) * plotHeight) | 0;\n var topY = (padding.top + plotHeight - ((cumPos + val - minVal) / range) * plotHeight) | 0;\n cumPos += val;\n\n barX[idx] = (padding.left + ci * groupSize + stackBarOffset) | 0;\n barY[idx] = Math.min(baseY, topY);\n barW[idx] = stackBarWidth;\n barH[idx] = (Math.abs(topY - baseY) || 1) as number;\n }\n }\n } else {\n var singleBarWidth = ((groupSize * (1 - barGap)) / seriesCount) | 0;\n var groupBarStart = ((groupSize - singleBarWidth * seriesCount) / 2) | 0;\n\n for (si = 0; si < seriesCount; si++)\n for (ci = 0; ci < catCount; ci++) {\n var idx = si * catCount + ci;\n val = data[si][ci];\n var topY = (padding.top + plotHeight - ((val - minVal) / range) * plotHeight) | 0;\n\n barX[idx] = (padding.left + ci * groupSize + groupBarStart + si * singleBarWidth) | 0;\n barW[idx] = singleBarWidth;\n\n if (val >= 0) {\n barY[idx] = topY;\n barH[idx] = (zeroY - topY || 1) as number;\n } else {\n barY[idx] = zeroY;\n barH[idx] = (topY - zeroY || 1) as number;\n }\n }\n }\n }\n\n // ── Phase 2: Build SVG string ──\n var svgMarkup = '<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"' + chartWidth + '\" height=\"' + chartHeight + '\" viewBox=\"0 0 ' + chartWidth + ' ' + chartHeight + '\" class=\"chart\">';\n\n // Grid\n if (showGrid) {\n var gridPath = '';\n if (horizontal) {\n for (ti = 0; ti < tickCount; ti++)\n gridPath += 'M' + gridPositions[ti] + ',' + padding.top + 'V' + plotBottom;\n } else {\n for (ti = 0; ti < tickCount; ti++)\n gridPath += 'M' + padding.left + ',' + gridPositions[ti] + 'H' + (padding.left + plotWidth);\n }\n svgMarkup += '<path d=\"' + gridPath + '\" class=\"chart-grid\"' + (gridDashed ? ' stroke-dasharray=\"3 4\"' : '') + '/>';\n }\n\n // Zero line (if bi-polar)\n if (minVal < 0) {\n if (horizontal) {\n var zx = (padding.left + ((0 - minVal) / range) * plotWidth) | 0;\n svgMarkup += '<line x1=\"' + zx + '\" y1=\"' + padding.top + '\" x2=\"' + zx + '\" y2=\"' + plotBottom +\n '\" stroke=\"#999\" stroke-width=\"1\" shape-rendering=\"crispEdges\"/>';\n } else {\n svgMarkup += '<line x1=\"' + padding.left + '\" y1=\"' + zeroY + '\" x2=\"' + (padding.left + plotWidth) + '\" y2=\"' + zeroY +\n '\" stroke=\"#999\" stroke-width=\"1\" shape-rendering=\"crispEdges\"/>';\n }\n }\n\n // Bars\n for (si = 0; si < seriesCount; si++) {\n var color = colors[si % colors.length];\n for (ci = 0; ci < catCount; ci++) {\n var idx = si * catCount + ci;\n svgMarkup += '<rect x=\"' + barX[idx] + '\" y=\"' + barY[idx] + '\" width=\"' + barW[idx] + '\" height=\"' + barH[idx] +\n '\" fill=\"' + color + '\" class=\"chart-bar\"/>';\n }\n }\n\n svgMarkup += '</svg>';\n\n // ── Phase 3: Build HTML label overlay ──\n var labelMarkup = '<div class=\"chart-labels\">';\n\n if (showTicks) {\n if (horizontal) {\n // Value tick labels on X-axis (bottom)\n for (ti = 0; ti < tickCount; ti++)\n labelMarkup += '<span class=\"chart-tick-x\" style=\"left:' + gridPositions[ti] + 'px;top:' + (plotBottom + 6) + 'px\">' + gridLabels[ti] + '</span>';\n\n // Category labels on Y-axis (left, centered on each group)\n for (ci = 0; ci < catCount; ci++) {\n var centerY = (padding.top + ci * groupSize + groupSize / 2) | 0;\n labelMarkup += '<span class=\"chart-tick-y\" style=\"left:' + (padding.left - 4) + 'px;top:' + (centerY - 1) + 'px\">' + labels[ci] + '</span>';\n }\n } else {\n // Value tick labels on Y-axis\n for (ti = 0; ti < tickCount; ti++)\n labelMarkup += '<span class=\"chart-tick-y\" style=\"left:' + (padding.left - 4) + 'px;top:' + (gridPositions[ti] - 1) + 'px\">' + gridLabels[ti] + '</span>';\n\n // Category labels on X-axis (bottom)\n for (ci = 0; ci < catCount; ci++) {\n var centerX = (padding.left + ci * groupSize + groupSize / 2) | 0;\n labelMarkup += '<span class=\"chart-tick-x\" style=\"left:' + centerX + 'px;top:' + (plotBottom + 6) + 'px\">' + labels[ci] + '</span>';\n }\n }\n }\n\n // Axis titles\n if (xLabel)\n labelMarkup += '<span class=\"chart-title\" style=\"left:' + (padding.left + (plotWidth >> 1)) + 'px;top:' + (chartHeight - 10) + 'px\">' + xLabel + '</span>';\n if (yLabel)\n labelMarkup += '<span class=\"chart-title\" style=\"left:4px;top:' + (padding.top - 14) + 'px;transform:none;text-align:left\">' + yLabel + '</span>';\n\n labelMarkup += '</div>';\n\n // ── Phase 4: Single innerHTML write ──\n container.style.cssText = 'position:relative;width:' + chartWidth + 'px;height:' + chartHeight + 'px';\n container.innerHTML = svgMarkup + labelMarkup;\n\n // ── Phase 5: Lazy hover ──\n if (!hoverEnabled) return;\n\n var svgEl = container.firstChild as SVGSVGElement;\n var highlight: SVGRectElement | null = null;\n var tooltip: HTMLDivElement | null = null;\n\n function ensureHover() {\n if (!highlight) {\n highlight = document.createElementNS(SVG_NS, 'rect') as SVGRectElement;\n highlight.setAttribute('class', 'chart-indicator');\n highlight.setAttribute('fill', 'rgba(255,255,255,0.3)');\n highlight.setAttribute('stroke', '#333');\n highlight.setAttribute('stroke-width', '1');\n highlight.style.display = 'none';\n svgEl.appendChild(highlight);\n }\n if (!tooltip) {\n tooltip = document.createElement('div') as HTMLDivElement;\n tooltip.className = 'chart-tooltip';\n container.appendChild(tooltip);\n }\n }\n\n attachHoverListeners(container, svgEl,\n function (mx, my) {\n if (mx < padding.left || mx > padding.left + plotWidth || my < padding.top || my > plotBottom) {\n if (highlight) highlight.style.display = 'none';\n if (tooltip) tooltip.style.opacity = '0';\n return;\n }\n\n // Snap to category, then find nearest bar by distance to center\n var nearCat: number;\n if (horizontal) {\n nearCat = ((my - padding.top) / groupSize) | 0;\n } else {\n nearCat = ((mx - padding.left) / groupSize) | 0;\n }\n if (nearCat >= catCount) nearCat = catCount - 1;\n if (nearCat < 0) nearCat = 0;\n\n var bestIdx = -1;\n var bestDist = Infinity;\n for (si = 0; si < seriesCount; si++) {\n var idx = si * catCount + nearCat;\n var cx = barX[idx] + (barW[idx] >> 1);\n var cy = barY[idx] + (barH[idx] >> 1);\n var dx = mx - cx, dy = my - cy;\n var dist = dx * dx + dy * dy;\n if (dist < bestDist) { bestDist = dist; bestIdx = idx; }\n }\n\n if (bestIdx === -1) return;\n\n ensureHover();\n\n var bsi = (bestIdx / catCount) | 0;\n var bci = bestIdx % catCount;\n\n highlight!.setAttribute('x', '' + barX[bestIdx]);\n highlight!.setAttribute('y', '' + barY[bestIdx]);\n highlight!.setAttribute('width', '' + barW[bestIdx]);\n highlight!.setAttribute('height', '' + barH[bestIdx]);\n highlight!.setAttribute('stroke', colors[bsi % colors.length]);\n highlight!.style.display = '';\n\n var tipX: number, tipY: number;\n if (horizontal) {\n tipX = barX[bestIdx] + barW[bestIdx];\n tipY = barY[bestIdx] + (barH[bestIdx] >> 1);\n tooltip!.style.transform = 'translate(' + (tipX + 8) + 'px,' + tipY + 'px) translate(0,-50%)';\n } else {\n tipX = barX[bestIdx] + (barW[bestIdx] >> 1);\n tipY = barY[bestIdx];\n tooltip!.style.transform = 'translate(' + tipX + 'px,' + (tipY - 10) + 'px) translate(-50%,-100%)';\n }\n\n tooltip!.innerHTML = (seriesCount > 1 ? '<b>Series ' + (bsi + 1) + '</b><br>' : '') +\n labels[bci] + ': ' + data[bsi][bci];\n tooltip!.style.opacity = '1';\n },\n function () {\n if (highlight) highlight.style.display = 'none';\n if (tooltip) tooltip.style.opacity = '0';\n }\n );\n}\n","import { SVG_NS, attachHoverListeners } from './shared';\n\n/**\n * Configuration for a pie chart instance.\n */\nexport interface PieChartConfig {\n /** One numeric value per slice. */\n data: number[];\n /** Label per slice. Must match data length. */\n labels: string[];\n /** Color per slice. Defaults to Thruscan brand palette. */\n colors?: string[];\n /** Chart width in pixels. Defaults to container's clientWidth or 350. */\n width?: number;\n /** Chart height in pixels. Defaults to width (square). */\n height?: number;\n /** Donut mode (hollow center). Default false. */\n donut?: boolean;\n /** Donut ring thickness in pixels. Default 60. */\n donutWidth?: number;\n /** Show labels outside slices. Default true. */\n showLabels?: boolean;\n /** Enable hover tooltip. Default true. */\n hover?: boolean;\n}\n\nvar TWO_PI = Math.PI * 2;\n\n/**\n * Creates a high-performance SVG+HTML hybrid pie/donut chart inside the specified container.\n */\nexport function NanoPieChart(containerId: string, config: PieChartConfig): void {\n var data = config.data;\n var labels = config.labels;\n var colors = config.colors || ['#215CAF', '#007894', '#00C9A7', '#DE4437', '#F69C3D', '#0d3a6e', '#003d4a', '#006651'];\n var isDonut = config.donut === true;\n var donutWidth = config.donutWidth !== undefined ? config.donutWidth : 60;\n var showLabels = config.showLabels !== false;\n var hoverEnabled = config.hover !== false;\n\n var container = document.getElementById(containerId)!;\n if (!container) return;\n var chartWidth = config.width || container.clientWidth || 350;\n var chartHeight = config.height || chartWidth;\n var sliceCount = data.length;\n\n var centerX = chartWidth / 2;\n var centerY = chartHeight / 2;\n var outerR = Math.min(centerX, centerY) - (showLabels ? 40 : 10);\n var innerR = isDonut ? Math.max(outerR - donutWidth, 0) : 0;\n\n // ── Phase 1: Pure math (zero DOM) ──\n var i: number;\n var total = 0;\n for (i = 0; i < sliceCount; i++) total += data[i];\n\n // Pre-compute per-slice: startAngle, endAngle, percentage\n var startAngles = new Float64Array(sliceCount);\n var endAngles = new Float64Array(sliceCount);\n var percentages = new Float64Array(sliceCount);\n var angle = -Math.PI / 2; // start at 12 o'clock\n\n for (i = 0; i < sliceCount; i++) {\n startAngles[i] = angle;\n var sliceAngle = total > 0 ? (data[i] / total) * TWO_PI : 0;\n percentages[i] = total > 0 ? (data[i] / total) * 100 : 0;\n angle += sliceAngle;\n endAngles[i] = angle;\n }\n\n // ── Phase 2: Build SVG string ──\n var svgMarkup = '<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"' + chartWidth + '\" height=\"' + chartHeight + '\" viewBox=\"0 0 ' + chartWidth + ' ' + chartHeight + '\" class=\"chart\">';\n\n for (i = 0; i < sliceCount; i++) {\n // Skip tiny slices (<0.5°) to avoid rendering artifacts\n if (endAngles[i] - startAngles[i] < 0.009) continue;\n\n var color = colors[i % colors.length];\n var cos1 = Math.cos(startAngles[i]), sin1 = Math.sin(startAngles[i]);\n var cos2 = Math.cos(endAngles[i]), sin2 = Math.sin(endAngles[i]);\n var largeArc = endAngles[i] - startAngles[i] > Math.PI ? 1 : 0;\n\n var ox1 = centerX + outerR * cos1, oy1 = centerY + outerR * sin1;\n var ox2 = centerX + outerR * cos2, oy2 = centerY + outerR * sin2;\n\n var pathData: string;\n if (isDonut) {\n var ix1 = centerX + innerR * cos1, iy1 = centerY + innerR * sin1;\n var ix2 = centerX + innerR * cos2, iy2 = centerY + innerR * sin2;\n // Outer arc clockwise, line to inner, inner arc counter-clockwise, close\n pathData = 'M' + ox1.toFixed(2) + ',' + oy1.toFixed(2)\n + 'A' + outerR + ',' + outerR + ' 0 ' + largeArc + ' 1 ' + ox2.toFixed(2) + ',' + oy2.toFixed(2)\n + 'L' + ix2.toFixed(2) + ',' + iy2.toFixed(2)\n + 'A' + innerR + ',' + innerR + ' 0 ' + largeArc + ' 0 ' + ix1.toFixed(2) + ',' + iy1.toFixed(2)\n + 'Z';\n } else {\n // Move to center, line to arc start, arc, close\n pathData = 'M' + centerX.toFixed(2) + ',' + centerY.toFixed(2)\n + 'L' + ox1.toFixed(2) + ',' + oy1.toFixed(2)\n + 'A' + outerR + ',' + outerR + ' 0 ' + largeArc + ' 1 ' + ox2.toFixed(2) + ',' + oy2.toFixed(2)\n + 'Z';\n }\n\n svgMarkup += '<path d=\"' + pathData + '\" fill=\"' + color + '\" class=\"chart-slice\"/>';\n }\n\n svgMarkup += '</svg>';\n\n // ── Phase 3: Build HTML label overlay ──\n var labelMarkup = '<div class=\"chart-labels\">';\n\n if (showLabels) {\n var labelR = outerR + 20;\n for (i = 0; i < sliceCount; i++) {\n // Skip labels for tiny slices (<5%)\n if (percentages[i] < 5) continue;\n\n var midAngle = (startAngles[i] + endAngles[i]) / 2;\n var lx = centerX + labelR * Math.cos(midAngle);\n var ly = centerY + labelR * Math.sin(midAngle);\n\n labelMarkup += '<span style=\"left:' + lx.toFixed(1) + 'px;top:' + ly.toFixed(1)\n + 'px;transform:translate(-50%,-50%);text-align:center\">'\n + labels[i] + ' ' + percentages[i].toFixed(0) + '%</span>';\n }\n }\n\n labelMarkup += '</div>';\n\n // ── Phase 4: Single innerHTML write ──\n container.style.cssText = 'position:relative;width:' + chartWidth + 'px;height:' + chartHeight + 'px';\n container.innerHTML = svgMarkup + labelMarkup;\n\n // ── Phase 5: Lazy hover ──\n if (!hoverEnabled) return;\n\n var svgEl = container.firstChild as SVGSVGElement;\n var highlight: SVGPathElement | null = null;\n var tooltip: HTMLDivElement | null = null;\n var lastSlice = -1;\n\n function ensureHover() {\n if (!highlight) {\n highlight = document.createElementNS(SVG_NS, 'path') as SVGPathElement;\n highlight.setAttribute('class', 'chart-indicator');\n highlight.setAttribute('fill', 'none');\n highlight.setAttribute('stroke', '#fff');\n highlight.setAttribute('stroke-width', '3');\n highlight.style.display = 'none';\n svgEl.appendChild(highlight);\n }\n if (!tooltip) {\n tooltip = document.createElement('div') as HTMLDivElement;\n tooltip.className = 'chart-tooltip';\n container.appendChild(tooltip);\n }\n }\n\n attachHoverListeners(container, svgEl,\n function (mx, my) {\n var dx = mx - centerX, dy = my - centerY;\n var dist = Math.sqrt(dx * dx + dy * dy);\n\n // Outside pie or inside donut hole\n if (dist > outerR || dist < innerR) {\n if (highlight) highlight.style.display = 'none';\n if (tooltip) tooltip.style.opacity = '0';\n lastSlice = -1;\n return;\n }\n\n // Find slice by angle\n var hoverAngle = Math.atan2(dy, dx);\n // Normalize to match our startAngles range [-π/2, 3π/2)\n if (hoverAngle < -Math.PI / 2) hoverAngle += TWO_PI;\n\n var hitSlice = -1;\n for (var s = 0; s < sliceCount; s++) {\n if (hoverAngle >= startAngles[s] && hoverAngle < endAngles[s]) {\n hitSlice = s;\n break;\n }\n }\n\n if (hitSlice === -1) return;\n\n ensureHover();\n\n // Only rebuild highlight path if slice changed\n if (hitSlice !== lastSlice) {\n lastSlice = hitSlice;\n // Reuse the same arc path as the slice for the highlight outline\n var cos1 = Math.cos(startAngles[hitSlice]), sin1 = Math.sin(startAngles[hitSlice]);\n var cos2 = Math.cos(endAngles[hitSlice]), sin2 = Math.sin(endAngles[hitSlice]);\n var largeArc = endAngles[hitSlice] - startAngles[hitSlice] > Math.PI ? 1 : 0;\n var ox1 = centerX + outerR * cos1, oy1 = centerY + outerR * sin1;\n var ox2 = centerX + outerR * cos2, oy2 = centerY + outerR * sin2;\n\n var hPath: string;\n if (isDonut) {\n var ix1 = centerX + innerR * cos1, iy1 = centerY + innerR * sin1;\n var ix2 = centerX + innerR * cos2, iy2 = centerY + innerR * sin2;\n hPath = 'M' + ox1.toFixed(2) + ',' + oy1.toFixed(2)\n + 'A' + outerR + ',' + outerR + ' 0 ' + largeArc + ' 1 ' + ox2.toFixed(2) + ',' + oy2.toFixed(2)\n + 'L' + ix2.toFixed(2) + ',' + iy2.toFixed(2)\n + 'A' + innerR + ',' + innerR + ' 0 ' + largeArc + ' 0 ' + ix1.toFixed(2) + ',' + iy1.toFixed(2)\n + 'Z';\n } else {\n hPath = 'M' + centerX.toFixed(2) + ',' + centerY.toFixed(2)\n + 'L' + ox1.toFixed(2) + ',' + oy1.toFixed(2)\n + 'A' + outerR + ',' + outerR + ' 0 ' + largeArc + ' 1 ' + ox2.toFixed(2) + ',' + oy2.toFixed(2)\n + 'Z';\n }\n highlight!.setAttribute('d', hPath);\n }\n\n highlight!.style.display = '';\n\n // Tooltip near cursor\n tooltip!.innerHTML = '<b>' + labels[hitSlice] + '</b><br>'\n + data[hitSlice] + ' (' + percentages[hitSlice].toFixed(1) + '%)';\n tooltip!.style.transform = 'translate(' + mx + 'px,' + (my - 40) + 'px) translate(-50%,-100%)';\n tooltip!.style.opacity = '1';\n },\n function () {\n if (highlight) highlight.style.display = 'none';\n if (tooltip) tooltip.style.opacity = '0';\n lastSlice = -1;\n }\n );\n}\n"],"mappings":"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","names":["idx","cos1","sin1","cos2","sin2","largeArc","ox1","oy1","ox2","oy2","ix1","iy1","ix2","iy2"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/shared.ts","../src/line-chart.ts","../src/bar-chart.ts","../src/pie-chart.ts"],"sourcesContent":["export { NanoLineChart } from './line-chart';\nexport type { LineChartConfig } from './line-chart';\nexport { NanoBarChart } from './bar-chart';\nexport type { BarChartConfig } from './bar-chart';\nexport { NanoPieChart } from './pie-chart';\nexport type { PieChartConfig } from './pie-chart';\n\nimport { NanoLineChart } from './line-chart';\nimport { NanoBarChart } from './bar-chart';\nimport { NanoPieChart } from './pie-chart';\n\n// UMD-style globals for script-tag usage\nif (typeof window !== 'undefined') {\n (window as any).NanoLineChart = NanoLineChart;\n (window as any).NanoBarChart = NanoBarChart;\n (window as any).NanoPieChart = NanoPieChart;\n}\n","export interface Padding {\n top: number;\n right: number;\n bottom: number;\n left: number;\n}\n\nexport var SVG_NS = 'http://www.w3.org/2000/svg';\n\n/**\n * Attaches RAF-throttled hover listeners (mouse + touch + resize).\n * Each chart provides its own onUpdate(mx, my) and onLeave() callbacks.\n */\nexport function attachHoverListeners(\n container: HTMLElement,\n svgEl: SVGSVGElement,\n onUpdate: (mx: number, my: number) => void,\n onLeave: () => void\n): void {\n var rafPending = false;\n var lastCX = 0, lastCY = 0;\n\n function schedule() {\n if (!rafPending) {\n rafPending = true;\n requestAnimationFrame(function () {\n rafPending = false;\n var r = svgEl.getBoundingClientRect();\n onUpdate(lastCX - r.left, lastCY - r.top);\n });\n }\n }\n\n container.addEventListener('mousemove', function (e: MouseEvent) {\n lastCX = e.clientX; lastCY = e.clientY;\n schedule();\n }, { passive: true });\n\n container.addEventListener('mouseleave', onLeave, { passive: true });\n\n container.addEventListener('touchmove', function (e: TouchEvent) {\n var t = e.touches[0];\n lastCX = t.clientX; lastCY = t.clientY;\n schedule();\n }, { passive: true });\n\n container.addEventListener('touchend', onLeave, { passive: true });\n}\n\n/**\n * Watches the container's parent for width changes and re-renders the chart.\n * Disconnects before re-render to prevent loops (render sets fixed width).\n * The re-render will call observeResize again, keeping it alive.\n */\nexport function observeResize(\n container: HTMLElement,\n render: () => void\n): void {\n if (typeof ResizeObserver === 'undefined') return;\n var parent = container.parentElement || container;\n var lastW = parent.clientWidth;\n var ro = new ResizeObserver(function () {\n var newW = parent.clientWidth;\n if (newW && newW !== lastW) {\n lastW = newW;\n ro.disconnect();\n container.style.width = '';\n render();\n }\n });\n ro.observe(parent);\n}\n","import { Padding, SVG_NS, attachHoverListeners, observeResize } from './shared';\n\n/**\n * Configuration for a chart instance.\n */\nexport interface LineChartConfig {\n /** Array of data series. Each inner array is one series of numeric values. */\n data: number[][];\n /** X-axis labels. Must match the length of each data series. */\n labels: string[];\n /** X-axis title. */\n xLabel?: string;\n /** Y-axis title. */\n yLabel?: string;\n /** Colors for each series. Defaults to Thruscan brand palette. */\n colors?: string[];\n /** Chart width in pixels. Defaults to container's clientWidth or 600. */\n width?: number;\n /** Chart height in pixels. Defaults to 350. */\n height?: number;\n /** Catmull-Rom spline smoothing. Default false. */\n smooth?: boolean;\n /** Semi-transparent fill under each series. Default false. */\n areaFill?: boolean;\n /** Area fill opacity. Default 0.1. */\n areaOpacity?: number;\n /** Show X/Y tick labels. Default true. */\n showTicks?: boolean;\n /** Show grid lines. Default true. */\n showGrid?: boolean;\n /** Dashed grid lines. Default false. */\n gridDashed?: boolean;\n /** Series stroke width. Default 2.5. */\n strokeWidth?: number;\n /** Enable hover tooltip + indicator. Default true. */\n hover?: boolean;\n /** Chart padding {top, right, bottom, left}. Default {top:20, right:30, bottom:50, left:60}. */\n padding?: Partial<Padding>;\n}\n\n\n/**\n * Creates a high-performance SVG+HTML hybrid line chart inside the specified container.\n */\nexport function NanoLineChart(containerId: string, config: LineChartConfig): void {\n var data = config.data;\n var labels = config.labels;\n var xLabel = config.xLabel || '';\n var yLabel = config.yLabel || '';\n var colors = config.colors || ['#215CAF', '#007894', '#00C9A7', '#DE4437', '#F69C3D'];\n var dp = config.padding || {};\n var padding: Padding = { top: dp.top || 0, right: dp.right || 0, bottom: dp.bottom || 0, left: dp.left || 0 };\n\n var smooth = config.smooth === true;\n var areaFill = config.areaFill === true;\n var areaOpacity = config.areaOpacity !== undefined ? config.areaOpacity : 0.1;\n var showTicks = config.showTicks !== false;\n var showGrid = config.showGrid !== false;\n var gridDashed = config.gridDashed === true;\n var strokeWidth = config.strokeWidth !== undefined ? config.strokeWidth : 2.5;\n var hoverEnabled = config.hover !== false;\n\n var container = document.getElementById(containerId)!;\n if (!container || !data.length || !data[0].length) return;\n var chartWidth = config.width || container.clientWidth || 600;\n var chartHeight = config.height || 350;\n var plotWidth = chartWidth - padding.left - padding.right;\n var plotHeight = chartHeight - padding.top - padding.bottom;\n var plotBottom = padding.top + plotHeight;\n\n // ── Phase 1: Pure math (zero DOM) ──\n var seriesIndex: number, pointIndex: number, minValue: number, maxValue: number;\n minValue = maxValue = data[0][0];\n for (seriesIndex = 0; seriesIndex < data.length; seriesIndex++)\n for (pointIndex = 0; pointIndex < data[seriesIndex].length; pointIndex++) {\n if (data[seriesIndex][pointIndex] < minValue) minValue = data[seriesIndex][pointIndex];\n if (data[seriesIndex][pointIndex] > maxValue) maxValue = data[seriesIndex][pointIndex];\n }\n var range = maxValue - minValue || 1;\n minValue -= range * 0.05;\n maxValue += range * 0.05;\n range = maxValue - minValue;\n\n var pointCount = labels.length;\n var stepX = pointCount > 1 ? plotWidth / (pointCount - 1) : 0;\n var tickCount = 6;\n var tickStep = range / (tickCount - 1);\n\n // Int16Array — half memory of Float32Array, perfect for integer pixel coords\n var totalCoords = data.length * pointCount;\n var coordsX = new Int16Array(totalCoords);\n var coordsY = new Int16Array(totalCoords);\n for (seriesIndex = 0; seriesIndex < data.length; seriesIndex++)\n for (pointIndex = 0; pointIndex < pointCount; pointIndex++) {\n var coordIndex = seriesIndex * pointCount + pointIndex;\n coordsX[coordIndex] = (padding.left + pointIndex * stepX) | 0;\n coordsY[coordIndex] = (padding.top + plotHeight - ((data[seriesIndex][pointIndex] - minValue) / range) * plotHeight) | 0;\n }\n\n // Grid Y positions + labels\n var gridYPositions = new Int16Array(tickCount);\n var gridLabels = new Array(tickCount);\n var tickIndex: number;\n for (tickIndex = 0; tickIndex < tickCount; tickIndex++) {\n var tickValue = minValue + tickIndex * tickStep;\n gridYPositions[tickIndex] = (padding.top + plotHeight - ((tickValue - minValue) / range) * plotHeight) | 0;\n gridLabels[tickIndex] = tickValue.toFixed(1);\n }\n\n // ── Phase 2: Build SVG string ──\n var svgMarkup = '<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"' + chartWidth + '\" height=\"' + chartHeight + '\" viewBox=\"0 0 ' + chartWidth + ' ' + chartHeight + '\" class=\"chart\">';\n\n // Grid path\n if (showGrid) {\n var gridPath = '';\n for (tickIndex = 0; tickIndex < tickCount; tickIndex++)\n gridPath += 'M' + padding.left + ',' + gridYPositions[tickIndex] + 'H' + (padding.left + plotWidth);\n svgMarkup += '<path d=\"' + gridPath + '\" class=\"chart-grid\"' + (gridDashed ? ' stroke-dasharray=\"3 4\"' : '') + '/>';\n }\n\n // Series paths\n for (seriesIndex = 0; seriesIndex < data.length; seriesIndex++) {\n var ci = seriesIndex * pointCount;\n var pathData = 'M' + coordsX[ci] + ',' + coordsY[ci];\n\n if (smooth) {\n // Catmull-Rom → Cubic Bezier, directly from Int16Array coords\n for (pointIndex = 0; pointIndex < pointCount - 1; pointIndex++) {\n var prevI = pointIndex ? pointIndex - 1 : 0;\n var next2I = pointIndex + 2 < pointCount ? pointIndex + 2 : pointCount - 1;\n var curX = coordsX[ci + pointIndex], curY = coordsY[ci + pointIndex];\n var nextX = coordsX[ci + pointIndex + 1], nextY = coordsY[ci + pointIndex + 1];\n var prevX = coordsX[ci + prevI], prevY = coordsY[ci + prevI];\n var next2X = coordsX[ci + next2I], next2Y = coordsY[ci + next2I];\n pathData += ' C' + ((curX + (nextX - prevX) / 6) | 0) + ',' + ((curY + (nextY - prevY) / 6) | 0)\n + ' ' + ((nextX - (next2X - curX) / 6) | 0) + ',' + ((nextY - (next2Y - curY) / 6) | 0)\n + ' ' + nextX + ',' + nextY;\n }\n } else {\n for (pointIndex = 1; pointIndex < pointCount; pointIndex++)\n pathData += 'L' + coordsX[ci + pointIndex] + ',' + coordsY[ci + pointIndex];\n }\n\n // Area fill path (before series line so line draws on top)\n if (areaFill) {\n var firstX = coordsX[ci], lastX = coordsX[ci + pointCount - 1];\n svgMarkup += '<path d=\"' + pathData + ' L' + lastX + ',' + plotBottom + ' L' + firstX + ',' + plotBottom + ' Z\"'\n + ' fill=\"' + colors[seriesIndex % colors.length] + '\" fill-opacity=\"' + areaOpacity + '\" stroke=\"none\" pointer-events=\"none\"/>';\n }\n\n svgMarkup += '<path d=\"' + pathData + '\" class=\"chart-series\" stroke=\"' + colors[seriesIndex % colors.length] + '\"'\n + (strokeWidth !== 2.5 ? ' stroke-width=\"' + strokeWidth + '\"' : '') + '/>';\n }\n\n svgMarkup += '</svg>';\n\n // ── Phase 3: Build HTML label overlay ──\n var labelMarkup = '<div class=\"chart-labels\">';\n\n if (showTicks) {\n // Y tick labels\n for (tickIndex = 0; tickIndex < tickCount; tickIndex++)\n labelMarkup += '<span class=\"chart-tick-y\" style=\"left:' + (padding.left - 4) + 'px;top:' + (gridYPositions[tickIndex] - 1) + 'px\">' + gridLabels[tickIndex] + '</span>';\n\n // X tick labels\n for (pointIndex = 0; pointIndex < pointCount; pointIndex++)\n labelMarkup += '<span class=\"chart-tick-x\" style=\"left:' + coordsX[pointIndex] + 'px;top:' + (padding.top + plotHeight + 6) + 'px\">' + labels[pointIndex] + '</span>';\n }\n\n // Axis titles\n if (xLabel)\n labelMarkup += '<span class=\"chart-title\" style=\"left:' + (padding.left + (plotWidth >> 1)) + 'px;top:' + (chartHeight - 10) + 'px\">' + xLabel + '</span>';\n if (yLabel)\n labelMarkup += '<span class=\"chart-title\" style=\"left:4px;top:' + (padding.top - 14) + 'px;transform:none;text-align:left\">' + yLabel + '</span>';\n\n labelMarkup += '</div>';\n\n // ── Phase 4: Single innerHTML write (SVG + HTML labels) ──\n container.style.cssText = 'position:relative;width:' + chartWidth + 'px;height:' + chartHeight + 'px';\n container.innerHTML = svgMarkup + labelMarkup;\n\n // ── Phase 5: Auto-resize ──\n if (!config.width) {\n observeResize(container, function () { NanoLineChart(containerId, config); });\n }\n\n // ── Phase 6: Lazy hover ──\n if (!hoverEnabled) return;\n\n var svg = container.firstChild as SVGSVGElement;\n var indicator: SVGCircleElement | null = null;\n var tooltip: HTMLDivElement | null = null;\n\n function ensureHoverElements() {\n if (!indicator) {\n indicator = document.createElementNS(SVG_NS, 'circle') as SVGCircleElement;\n indicator.setAttribute('r', '5');\n indicator.setAttribute('class', 'chart-indicator');\n indicator.style.display = 'none';\n svg.appendChild(indicator);\n }\n if (!tooltip) {\n tooltip = document.createElement('div') as HTMLDivElement;\n tooltip.className = 'chart-tooltip';\n container.appendChild(tooltip);\n }\n }\n\n attachHoverListeners(container, svg,\n function (mouseX, mouseY) {\n if (mouseX < padding.left || mouseX > padding.left + plotWidth || mouseY < padding.top || mouseY > padding.top + plotHeight) {\n if (indicator) indicator.style.display = 'none';\n if (tooltip) tooltip.style.opacity = '0';\n return;\n }\n\n ensureHoverElements();\n\n var relativeX = mouseX - padding.left;\n if (relativeX < 0) relativeX = 0;\n if (relativeX > plotWidth) relativeX = plotWidth;\n var nearestIndex = (relativeX / stepX + 0.5) | 0;\n if (nearestIndex >= pointCount) nearestIndex = pointCount - 1;\n\n var bestSeriesIndex = 0;\n var bestDistance = Math.abs(coordsY[nearestIndex] - mouseY);\n for (var searchIndex = 1; searchIndex < data.length; searchIndex++) {\n var distance = Math.abs(coordsY[searchIndex * pointCount + nearestIndex] - mouseY);\n if (distance < bestDistance) { bestDistance = distance; bestSeriesIndex = searchIndex; }\n }\n\n var pointX = coordsX[bestSeriesIndex * pointCount + nearestIndex];\n var pointY = coordsY[bestSeriesIndex * pointCount + nearestIndex];\n\n indicator!.setAttribute('transform', 'translate(' + pointX + ',' + pointY + ')');\n indicator!.setAttribute('fill', colors[bestSeriesIndex % colors.length]);\n indicator!.style.display = '';\n\n tooltip!.innerHTML = '<b>Series ' + (bestSeriesIndex + 1) + '</b><br>' +\n xLabel + ': ' + labels[nearestIndex] + '<br>' + yLabel + ': ' + data[bestSeriesIndex][nearestIndex];\n tooltip!.style.transform = 'translate(' + pointX + 'px,' + (pointY - 40) + 'px) translate(-50%,-100%)';\n tooltip!.style.opacity = '1';\n },\n function () {\n if (indicator) indicator.style.display = 'none';\n if (tooltip) tooltip.style.opacity = '0';\n }\n );\n}\n\n","import { Padding, SVG_NS, attachHoverListeners, observeResize } from './shared';\n\n/**\n * Configuration for a bar chart instance.\n */\nexport interface BarChartConfig {\n /** Array of data series. Each inner array is one series of numeric values. */\n data: number[][];\n /** Category labels. Must match the length of each data series. */\n labels: string[];\n /** X-axis title. */\n xLabel?: string;\n /** Y-axis title. */\n yLabel?: string;\n /** Colors for each series. Defaults to Thruscan brand palette. */\n colors?: string[];\n /** Chart width in pixels. Defaults to container's clientWidth or 600. */\n width?: number;\n /** Chart height in pixels. Defaults to 350. */\n height?: number;\n /** Stack series instead of grouping side-by-side. Default false. */\n stacked?: boolean;\n /** Horizontal bars (categories on Y-axis). Default false. */\n horizontal?: boolean;\n /** Gap between bar groups as fraction of group width (0–1). Default 0.2. */\n barGap?: number;\n /** Show tick labels. Default true. */\n showTicks?: boolean;\n /** Show grid lines. Default true. */\n showGrid?: boolean;\n /** Dashed grid lines. Default false. */\n gridDashed?: boolean;\n /** Enable hover tooltip + indicator. Default true. */\n hover?: boolean;\n /** Chart padding {top, right, bottom, left}. Default {top:20, right:30, bottom:50, left:60} (left:80 for horizontal). */\n padding?: Partial<Padding>;\n}\n\n\n/**\n * Creates a high-performance SVG+HTML hybrid bar chart inside the specified container.\n */\nexport function NanoBarChart(containerId: string, config: BarChartConfig): void {\n var data = config.data;\n var labels = config.labels;\n var xLabel = config.xLabel || '';\n var yLabel = config.yLabel || '';\n var colors = config.colors || ['#215CAF', '#007894', '#00C9A7', '#DE4437', '#F69C3D'];\n var stacked = config.stacked === true;\n var horizontal = config.horizontal === true;\n var showTicks = config.showTicks !== false;\n var showGrid = config.showGrid !== false;\n var gridDashed = config.gridDashed === true;\n var hoverEnabled = config.hover !== false;\n var barGap = config.barGap !== undefined ? config.barGap : 0.2;\n var dp = config.padding || {};\n var padding: Padding = { top: dp.top || 0, right: dp.right || 0, bottom: dp.bottom || 0, left: dp.left || 0 };\n\n var container = document.getElementById(containerId)!;\n if (!container || !data.length || !data[0].length) return;\n var chartWidth = config.width || container.clientWidth || 600;\n var chartHeight = config.height || 350;\n var plotWidth = chartWidth - padding.left - padding.right;\n var plotHeight = chartHeight - padding.top - padding.bottom;\n var plotBottom = padding.top + plotHeight;\n\n var seriesCount = data.length;\n var catCount = labels.length;\n var si: number, ci: number, val: number, ti: number;\n\n // ── Phase 1: Pure math (zero DOM) ──\n\n // Find min/max\n var minVal: number, maxVal: number;\n if (stacked) {\n minVal = 0;\n maxVal = 0;\n for (ci = 0; ci < catCount; ci++) {\n var colSum = 0;\n for (si = 0; si < seriesCount; si++) {\n colSum += data[si][ci];\n if (data[si][ci] < minVal) minVal = data[si][ci];\n }\n if (colSum > maxVal) maxVal = colSum;\n }\n } else {\n minVal = maxVal = data[0][0];\n for (si = 0; si < seriesCount; si++)\n for (ci = 0; ci < catCount; ci++) {\n val = data[si][ci];\n if (val < minVal) minVal = val;\n if (val > maxVal) maxVal = val;\n }\n }\n\n if (minVal > 0) minVal = 0;\n if (maxVal < 0) maxVal = 0;\n\n var range = maxVal - minVal || 1;\n maxVal += range * 0.05;\n range = maxVal - minVal;\n\n // Grid tick positions + labels\n var tickCount = 6;\n var tickStep = range / (tickCount - 1);\n var gridPositions = new Int16Array(tickCount);\n var gridLabels = new Array<string>(tickCount);\n\n var totalBars = seriesCount * catCount;\n var barX = new Int16Array(totalBars);\n var barY = new Int16Array(totalBars);\n var barW = new Int16Array(totalBars);\n var barH = new Int16Array(totalBars);\n var groupSize: number;\n var zeroY = 0;\n\n if (horizontal) {\n // ── Horizontal: categories on Y, values on X ──\n groupSize = plotHeight / catCount;\n var zeroX = (padding.left + ((0 - minVal) / range) * plotWidth) | 0;\n\n for (ti = 0; ti < tickCount; ti++) {\n var tickVal = minVal + ti * tickStep;\n gridPositions[ti] = (padding.left + ((tickVal - minVal) / range) * plotWidth) | 0;\n gridLabels[ti] = tickVal % 1 === 0 ? tickVal.toString() : tickVal.toFixed(1);\n }\n\n var hBarHeight = ((groupSize * (1 - barGap)) / seriesCount) | 0;\n var hGroupStart = ((groupSize - hBarHeight * seriesCount) / 2) | 0;\n\n for (si = 0; si < seriesCount; si++)\n for (ci = 0; ci < catCount; ci++) {\n var idx = si * catCount + ci;\n val = data[si][ci];\n var valX = (padding.left + ((val - minVal) / range) * plotWidth) | 0;\n\n barY[idx] = (padding.top + ci * groupSize + hGroupStart + si * hBarHeight) | 0;\n barH[idx] = hBarHeight;\n\n if (val >= 0) {\n barX[idx] = zeroX;\n barW[idx] = (valX - zeroX || 1) as number;\n } else {\n barX[idx] = valX;\n barW[idx] = (zeroX - valX || 1) as number;\n }\n }\n } else {\n // ── Vertical: categories on X, values on Y ──\n groupSize = plotWidth / catCount;\n\n zeroY = (padding.top + plotHeight - ((0 - minVal) / range) * plotHeight) | 0;\n\n for (ti = 0; ti < tickCount; ti++) {\n var tickVal = minVal + ti * tickStep;\n gridPositions[ti] = (padding.top + plotHeight - ((tickVal - minVal) / range) * plotHeight) | 0;\n gridLabels[ti] = tickVal % 1 === 0 ? tickVal.toString() : tickVal.toFixed(1);\n }\n\n if (stacked) {\n var stackBarWidth = (groupSize * (1 - barGap)) | 0;\n var stackBarOffset = ((groupSize - stackBarWidth) / 2) | 0;\n\n for (ci = 0; ci < catCount; ci++) {\n var cumPos = 0;\n for (si = 0; si < seriesCount; si++) {\n var idx = si * catCount + ci;\n val = data[si][ci];\n var baseY = (padding.top + plotHeight - ((cumPos - minVal) / range) * plotHeight) | 0;\n var topY = (padding.top + plotHeight - ((cumPos + val - minVal) / range) * plotHeight) | 0;\n cumPos += val;\n\n barX[idx] = (padding.left + ci * groupSize + stackBarOffset) | 0;\n barY[idx] = Math.min(baseY, topY);\n barW[idx] = stackBarWidth;\n barH[idx] = (Math.abs(topY - baseY) || 1) as number;\n }\n }\n } else {\n var singleBarWidth = ((groupSize * (1 - barGap)) / seriesCount) | 0;\n var groupBarStart = ((groupSize - singleBarWidth * seriesCount) / 2) | 0;\n\n for (si = 0; si < seriesCount; si++)\n for (ci = 0; ci < catCount; ci++) {\n var idx = si * catCount + ci;\n val = data[si][ci];\n var topY = (padding.top + plotHeight - ((val - minVal) / range) * plotHeight) | 0;\n\n barX[idx] = (padding.left + ci * groupSize + groupBarStart + si * singleBarWidth) | 0;\n barW[idx] = singleBarWidth;\n\n if (val >= 0) {\n barY[idx] = topY;\n barH[idx] = (zeroY - topY || 1) as number;\n } else {\n barY[idx] = zeroY;\n barH[idx] = (topY - zeroY || 1) as number;\n }\n }\n }\n }\n\n // ── Phase 2: Build SVG string ──\n var svgMarkup = '<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"' + chartWidth + '\" height=\"' + chartHeight + '\" viewBox=\"0 0 ' + chartWidth + ' ' + chartHeight + '\" class=\"chart\">';\n\n // Grid\n if (showGrid) {\n var gridPath = '';\n if (horizontal) {\n for (ti = 0; ti < tickCount; ti++)\n gridPath += 'M' + gridPositions[ti] + ',' + padding.top + 'V' + plotBottom;\n } else {\n for (ti = 0; ti < tickCount; ti++)\n gridPath += 'M' + padding.left + ',' + gridPositions[ti] + 'H' + (padding.left + plotWidth);\n }\n svgMarkup += '<path d=\"' + gridPath + '\" class=\"chart-grid\"' + (gridDashed ? ' stroke-dasharray=\"3 4\"' : '') + '/>';\n }\n\n // Zero line (if bi-polar)\n if (minVal < 0) {\n if (horizontal) {\n var zx = (padding.left + ((0 - minVal) / range) * plotWidth) | 0;\n svgMarkup += '<line x1=\"' + zx + '\" y1=\"' + padding.top + '\" x2=\"' + zx + '\" y2=\"' + plotBottom +\n '\" stroke=\"#999\" stroke-width=\"1\" shape-rendering=\"crispEdges\"/>';\n } else {\n svgMarkup += '<line x1=\"' + padding.left + '\" y1=\"' + zeroY + '\" x2=\"' + (padding.left + plotWidth) + '\" y2=\"' + zeroY +\n '\" stroke=\"#999\" stroke-width=\"1\" shape-rendering=\"crispEdges\"/>';\n }\n }\n\n // Bars\n for (si = 0; si < seriesCount; si++) {\n var color = colors[si % colors.length];\n for (ci = 0; ci < catCount; ci++) {\n var idx = si * catCount + ci;\n svgMarkup += '<rect x=\"' + barX[idx] + '\" y=\"' + barY[idx] + '\" width=\"' + barW[idx] + '\" height=\"' + barH[idx] +\n '\" fill=\"' + color + '\" class=\"chart-bar\"/>';\n }\n }\n\n svgMarkup += '</svg>';\n\n // ── Phase 3: Build HTML label overlay ──\n var labelMarkup = '<div class=\"chart-labels\">';\n\n if (showTicks) {\n if (horizontal) {\n // Value tick labels on X-axis (bottom)\n for (ti = 0; ti < tickCount; ti++)\n labelMarkup += '<span class=\"chart-tick-x\" style=\"left:' + gridPositions[ti] + 'px;top:' + (plotBottom + 6) + 'px\">' + gridLabels[ti] + '</span>';\n\n // Category labels on Y-axis (left, centered on each group)\n for (ci = 0; ci < catCount; ci++) {\n var centerY = (padding.top + ci * groupSize + groupSize / 2) | 0;\n labelMarkup += '<span class=\"chart-tick-y\" style=\"left:' + (padding.left - 4) + 'px;top:' + (centerY - 1) + 'px\">' + labels[ci] + '</span>';\n }\n } else {\n // Value tick labels on Y-axis\n for (ti = 0; ti < tickCount; ti++)\n labelMarkup += '<span class=\"chart-tick-y\" style=\"left:' + (padding.left - 4) + 'px;top:' + (gridPositions[ti] - 1) + 'px\">' + gridLabels[ti] + '</span>';\n\n // Category labels on X-axis (bottom)\n for (ci = 0; ci < catCount; ci++) {\n var centerX = (padding.left + ci * groupSize + groupSize / 2) | 0;\n labelMarkup += '<span class=\"chart-tick-x\" style=\"left:' + centerX + 'px;top:' + (plotBottom + 6) + 'px\">' + labels[ci] + '</span>';\n }\n }\n }\n\n // Axis titles\n if (xLabel)\n labelMarkup += '<span class=\"chart-title\" style=\"left:' + (padding.left + (plotWidth >> 1)) + 'px;top:' + (chartHeight - 10) + 'px\">' + xLabel + '</span>';\n if (yLabel)\n labelMarkup += '<span class=\"chart-title\" style=\"left:4px;top:' + (padding.top - 14) + 'px;transform:none;text-align:left\">' + yLabel + '</span>';\n\n labelMarkup += '</div>';\n\n // ── Phase 4: Single innerHTML write ──\n container.style.cssText = 'position:relative;width:' + chartWidth + 'px;height:' + chartHeight + 'px';\n container.innerHTML = svgMarkup + labelMarkup;\n\n // ── Phase 5: Auto-resize ──\n if (!config.width) {\n observeResize(container, function () { NanoBarChart(containerId, config); });\n }\n\n // ── Phase 6: Lazy hover ──\n if (!hoverEnabled) return;\n\n var svgEl = container.firstChild as SVGSVGElement;\n var highlight: SVGRectElement | null = null;\n var tooltip: HTMLDivElement | null = null;\n\n function ensureHover() {\n if (!highlight) {\n highlight = document.createElementNS(SVG_NS, 'rect') as SVGRectElement;\n highlight.setAttribute('class', 'chart-indicator');\n highlight.setAttribute('fill', 'rgba(255,255,255,0.3)');\n highlight.setAttribute('stroke', '#333');\n highlight.setAttribute('stroke-width', '1');\n highlight.style.display = 'none';\n svgEl.appendChild(highlight);\n }\n if (!tooltip) {\n tooltip = document.createElement('div') as HTMLDivElement;\n tooltip.className = 'chart-tooltip';\n container.appendChild(tooltip);\n }\n }\n\n attachHoverListeners(container, svgEl,\n function (mx, my) {\n if (mx < padding.left || mx > padding.left + plotWidth || my < padding.top || my > plotBottom) {\n if (highlight) highlight.style.display = 'none';\n if (tooltip) tooltip.style.opacity = '0';\n return;\n }\n\n // Snap to category, then find nearest bar by distance to center\n var nearCat: number;\n if (horizontal) {\n nearCat = ((my - padding.top) / groupSize) | 0;\n } else {\n nearCat = ((mx - padding.left) / groupSize) | 0;\n }\n if (nearCat >= catCount) nearCat = catCount - 1;\n if (nearCat < 0) nearCat = 0;\n\n var bestIdx = -1;\n var bestDist = Infinity;\n for (si = 0; si < seriesCount; si++) {\n var idx = si * catCount + nearCat;\n var cx = barX[idx] + (barW[idx] >> 1);\n var cy = barY[idx] + (barH[idx] >> 1);\n var dx = mx - cx, dy = my - cy;\n var dist = dx * dx + dy * dy;\n if (dist < bestDist) { bestDist = dist; bestIdx = idx; }\n }\n\n if (bestIdx === -1) return;\n\n ensureHover();\n\n var bsi = (bestIdx / catCount) | 0;\n var bci = bestIdx % catCount;\n\n highlight!.setAttribute('x', '' + barX[bestIdx]);\n highlight!.setAttribute('y', '' + barY[bestIdx]);\n highlight!.setAttribute('width', '' + barW[bestIdx]);\n highlight!.setAttribute('height', '' + barH[bestIdx]);\n highlight!.setAttribute('stroke', colors[bsi % colors.length]);\n highlight!.style.display = '';\n\n var tipX: number, tipY: number;\n if (horizontal) {\n tipX = barX[bestIdx] + barW[bestIdx];\n tipY = barY[bestIdx] + (barH[bestIdx] >> 1);\n tooltip!.style.transform = 'translate(' + (tipX + 8) + 'px,' + tipY + 'px) translate(0,-50%)';\n } else {\n tipX = barX[bestIdx] + (barW[bestIdx] >> 1);\n tipY = barY[bestIdx];\n tooltip!.style.transform = 'translate(' + tipX + 'px,' + (tipY - 10) + 'px) translate(-50%,-100%)';\n }\n\n tooltip!.innerHTML = (seriesCount > 1 ? '<b>Series ' + (bsi + 1) + '</b><br>' : '') +\n labels[bci] + ': ' + data[bsi][bci];\n tooltip!.style.opacity = '1';\n },\n function () {\n if (highlight) highlight.style.display = 'none';\n if (tooltip) tooltip.style.opacity = '0';\n }\n );\n}\n","import { SVG_NS, attachHoverListeners, observeResize } from './shared';\n\n/**\n * Configuration for a pie chart instance.\n */\nexport interface PieChartConfig {\n /** One numeric value per slice. */\n data: number[];\n /** Label per slice. Must match data length. */\n labels: string[];\n /** Color per slice. Defaults to Thruscan brand palette. */\n colors?: string[];\n /** Chart width in pixels. Defaults to container's clientWidth or 350. */\n width?: number;\n /** Chart height in pixels. Defaults to width (square). */\n height?: number;\n /** Donut mode (hollow center). Default false. */\n donut?: boolean;\n /** Donut ring thickness in pixels. Default 60. */\n donutWidth?: number;\n /** Show labels outside slices. Default true. */\n showLabels?: boolean;\n /** Enable hover tooltip. Default true. */\n hover?: boolean;\n}\n\nvar TWO_PI = Math.PI * 2;\n\n/**\n * Creates a high-performance SVG+HTML hybrid pie/donut chart inside the specified container.\n */\nexport function NanoPieChart(containerId: string, config: PieChartConfig): void {\n var data = config.data;\n var labels = config.labels;\n var colors = config.colors || ['#215CAF', '#007894', '#00C9A7', '#DE4437', '#F69C3D', '#0d3a6e', '#003d4a', '#006651'];\n var isDonut = config.donut === true;\n var donutWidth = config.donutWidth !== undefined ? config.donutWidth : 60;\n var showLabels = config.showLabels !== false;\n var hoverEnabled = config.hover !== false;\n\n var container = document.getElementById(containerId)!;\n if (!container) return;\n var chartWidth = config.width || container.clientWidth || 350;\n var chartHeight = config.height || chartWidth;\n var sliceCount = data.length;\n\n var centerX = chartWidth / 2;\n var centerY = chartHeight / 2;\n var outerR = Math.min(centerX, centerY) - (showLabels ? 40 : 10);\n var innerR = isDonut ? Math.max(outerR - donutWidth, 0) : 0;\n\n // ── Phase 1: Pure math (zero DOM) ──\n var i: number;\n var total = 0;\n for (i = 0; i < sliceCount; i++) total += data[i];\n\n // Pre-compute per-slice: startAngle, endAngle, percentage\n var startAngles = new Float64Array(sliceCount);\n var endAngles = new Float64Array(sliceCount);\n var percentages = new Float64Array(sliceCount);\n var angle = -Math.PI / 2; // start at 12 o'clock\n\n for (i = 0; i < sliceCount; i++) {\n startAngles[i] = angle;\n var sliceAngle = total > 0 ? (data[i] / total) * TWO_PI : 0;\n percentages[i] = total > 0 ? (data[i] / total) * 100 : 0;\n angle += sliceAngle;\n endAngles[i] = angle;\n }\n\n // ── Phase 2: Build SVG string ──\n var svgMarkup = '<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"' + chartWidth + '\" height=\"' + chartHeight + '\" viewBox=\"0 0 ' + chartWidth + ' ' + chartHeight + '\" class=\"chart\">';\n\n for (i = 0; i < sliceCount; i++) {\n // Skip tiny slices (<0.5°) to avoid rendering artifacts\n if (endAngles[i] - startAngles[i] < 0.009) continue;\n\n var color = colors[i % colors.length];\n var cos1 = Math.cos(startAngles[i]), sin1 = Math.sin(startAngles[i]);\n var cos2 = Math.cos(endAngles[i]), sin2 = Math.sin(endAngles[i]);\n var largeArc = endAngles[i] - startAngles[i] > Math.PI ? 1 : 0;\n\n var ox1 = centerX + outerR * cos1, oy1 = centerY + outerR * sin1;\n var ox2 = centerX + outerR * cos2, oy2 = centerY + outerR * sin2;\n\n var pathData: string;\n if (isDonut) {\n var ix1 = centerX + innerR * cos1, iy1 = centerY + innerR * sin1;\n var ix2 = centerX + innerR * cos2, iy2 = centerY + innerR * sin2;\n // Outer arc clockwise, line to inner, inner arc counter-clockwise, close\n pathData = 'M' + ox1.toFixed(2) + ',' + oy1.toFixed(2)\n + 'A' + outerR + ',' + outerR + ' 0 ' + largeArc + ' 1 ' + ox2.toFixed(2) + ',' + oy2.toFixed(2)\n + 'L' + ix2.toFixed(2) + ',' + iy2.toFixed(2)\n + 'A' + innerR + ',' + innerR + ' 0 ' + largeArc + ' 0 ' + ix1.toFixed(2) + ',' + iy1.toFixed(2)\n + 'Z';\n } else {\n // Move to center, line to arc start, arc, close\n pathData = 'M' + centerX.toFixed(2) + ',' + centerY.toFixed(2)\n + 'L' + ox1.toFixed(2) + ',' + oy1.toFixed(2)\n + 'A' + outerR + ',' + outerR + ' 0 ' + largeArc + ' 1 ' + ox2.toFixed(2) + ',' + oy2.toFixed(2)\n + 'Z';\n }\n\n svgMarkup += '<path d=\"' + pathData + '\" fill=\"' + color + '\" class=\"chart-slice\"/>';\n }\n\n svgMarkup += '</svg>';\n\n // ── Phase 3: Build HTML label overlay ──\n var labelMarkup = '<div class=\"chart-labels\">';\n\n if (showLabels) {\n var labelR = outerR + 20;\n for (i = 0; i < sliceCount; i++) {\n // Skip labels for tiny slices (<5%)\n if (percentages[i] < 5) continue;\n\n var midAngle = (startAngles[i] + endAngles[i]) / 2;\n var lx = centerX + labelR * Math.cos(midAngle);\n var ly = centerY + labelR * Math.sin(midAngle);\n\n labelMarkup += '<span style=\"left:' + lx.toFixed(1) + 'px;top:' + ly.toFixed(1)\n + 'px;transform:translate(-50%,-50%);text-align:center\">'\n + labels[i] + ' ' + percentages[i].toFixed(0) + '%</span>';\n }\n }\n\n labelMarkup += '</div>';\n\n // ── Phase 4: Single innerHTML write ──\n container.style.cssText = 'position:relative;width:' + chartWidth + 'px;height:' + chartHeight + 'px';\n container.innerHTML = svgMarkup + labelMarkup;\n\n // ── Phase 5: Auto-resize ──\n if (!config.width) {\n observeResize(container, function () { NanoPieChart(containerId, config); });\n }\n\n // ── Phase 6: Lazy hover ──\n if (!hoverEnabled) return;\n\n var svgEl = container.firstChild as SVGSVGElement;\n var highlight: SVGPathElement | null = null;\n var tooltip: HTMLDivElement | null = null;\n var lastSlice = -1;\n\n function ensureHover() {\n if (!highlight) {\n highlight = document.createElementNS(SVG_NS, 'path') as SVGPathElement;\n highlight.setAttribute('class', 'chart-indicator');\n highlight.setAttribute('fill', 'none');\n highlight.setAttribute('stroke', '#fff');\n highlight.setAttribute('stroke-width', '3');\n highlight.style.display = 'none';\n svgEl.appendChild(highlight);\n }\n if (!tooltip) {\n tooltip = document.createElement('div') as HTMLDivElement;\n tooltip.className = 'chart-tooltip';\n container.appendChild(tooltip);\n }\n }\n\n attachHoverListeners(container, svgEl,\n function (mx, my) {\n var dx = mx - centerX, dy = my - centerY;\n var dist = Math.sqrt(dx * dx + dy * dy);\n\n // Outside pie or inside donut hole\n if (dist > outerR || dist < innerR) {\n if (highlight) highlight.style.display = 'none';\n if (tooltip) tooltip.style.opacity = '0';\n lastSlice = -1;\n return;\n }\n\n // Find slice by angle\n var hoverAngle = Math.atan2(dy, dx);\n // Normalize to match our startAngles range [-π/2, 3π/2)\n if (hoverAngle < -Math.PI / 2) hoverAngle += TWO_PI;\n\n var hitSlice = -1;\n for (var s = 0; s < sliceCount; s++) {\n if (hoverAngle >= startAngles[s] && hoverAngle < endAngles[s]) {\n hitSlice = s;\n break;\n }\n }\n\n if (hitSlice === -1) return;\n\n ensureHover();\n\n // Only rebuild highlight path if slice changed\n if (hitSlice !== lastSlice) {\n lastSlice = hitSlice;\n // Reuse the same arc path as the slice for the highlight outline\n var cos1 = Math.cos(startAngles[hitSlice]), sin1 = Math.sin(startAngles[hitSlice]);\n var cos2 = Math.cos(endAngles[hitSlice]), sin2 = Math.sin(endAngles[hitSlice]);\n var largeArc = endAngles[hitSlice] - startAngles[hitSlice] > Math.PI ? 1 : 0;\n var ox1 = centerX + outerR * cos1, oy1 = centerY + outerR * sin1;\n var ox2 = centerX + outerR * cos2, oy2 = centerY + outerR * sin2;\n\n var hPath: string;\n if (isDonut) {\n var ix1 = centerX + innerR * cos1, iy1 = centerY + innerR * sin1;\n var ix2 = centerX + innerR * cos2, iy2 = centerY + innerR * sin2;\n hPath = 'M' + ox1.toFixed(2) + ',' + oy1.toFixed(2)\n + 'A' + outerR + ',' + outerR + ' 0 ' + largeArc + ' 1 ' + ox2.toFixed(2) + ',' + oy2.toFixed(2)\n + 'L' + ix2.toFixed(2) + ',' + iy2.toFixed(2)\n + 'A' + innerR + ',' + innerR + ' 0 ' + largeArc + ' 0 ' + ix1.toFixed(2) + ',' + iy1.toFixed(2)\n + 'Z';\n } else {\n hPath = 'M' + centerX.toFixed(2) + ',' + centerY.toFixed(2)\n + 'L' + ox1.toFixed(2) + ',' + oy1.toFixed(2)\n + 'A' + outerR + ',' + outerR + ' 0 ' + largeArc + ' 1 ' + ox2.toFixed(2) + ',' + oy2.toFixed(2)\n + 'Z';\n }\n highlight!.setAttribute('d', hPath);\n }\n\n highlight!.style.display = '';\n\n // Tooltip near cursor\n tooltip!.innerHTML = '<b>' + labels[hitSlice] + '</b><br>'\n + data[hitSlice] + ' (' + percentages[hitSlice].toFixed(1) + '%)';\n tooltip!.style.transform = 'translate(' + mx + 'px,' + (my - 40) + 'px) translate(-50%,-100%)';\n tooltip!.style.opacity = '1';\n },\n function () {\n if (highlight) highlight.style.display = 'none';\n if (tooltip) tooltip.style.opacity = '0';\n lastSlice = -1;\n }\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACOO,IAAI,SAAS;AAMb,SAAS,qBACd,WACA,OACA,UACA,SACM;AACN,MAAI,aAAa;AACjB,MAAI,SAAS,GAAG,SAAS;AAEzB,WAAS,WAAW;AAClB,QAAI,CAAC,YAAY;AACf,mBAAa;AACb,4BAAsB,WAAY;AAChC,qBAAa;AACb,YAAI,IAAI,MAAM,sBAAsB;AACpC,iBAAS,SAAS,EAAE,MAAM,SAAS,EAAE,GAAG;AAAA,MAC1C,CAAC;AAAA,IACH;AAAA,EACF;AAEA,YAAU,iBAAiB,aAAa,SAAU,GAAe;AAC/D,aAAS,EAAE;AAAS,aAAS,EAAE;AAC/B,aAAS;AAAA,EACX,GAAG,EAAE,SAAS,KAAK,CAAC;AAEpB,YAAU,iBAAiB,cAAc,SAAS,EAAE,SAAS,KAAK,CAAC;AAEnE,YAAU,iBAAiB,aAAa,SAAU,GAAe;AAC/D,QAAI,IAAI,EAAE,QAAQ,CAAC;AACnB,aAAS,EAAE;AAAS,aAAS,EAAE;AAC/B,aAAS;AAAA,EACX,GAAG,EAAE,SAAS,KAAK,CAAC;AAEpB,YAAU,iBAAiB,YAAY,SAAS,EAAE,SAAS,KAAK,CAAC;AACnE;AAOO,SAAS,cACd,WACA,QACM;AACN,MAAI,OAAO,mBAAmB,YAAa;AAC3C,MAAI,SAAS,UAAU,iBAAiB;AACxC,MAAI,QAAQ,OAAO;AACnB,MAAI,KAAK,IAAI,eAAe,WAAY;AACtC,QAAI,OAAO,OAAO;AAClB,QAAI,QAAQ,SAAS,OAAO;AAC1B,cAAQ;AACR,SAAG,WAAW;AACd,gBAAU,MAAM,QAAQ;AACxB,aAAO;AAAA,IACT;AAAA,EACF,CAAC;AACD,KAAG,QAAQ,MAAM;AACnB;;;AC3BO,SAAS,cAAc,aAAqB,QAA+B;AAChF,MAAI,OAAO,OAAO;AAClB,MAAI,SAAS,OAAO;AACpB,MAAI,SAAS,OAAO,UAAU;AAC9B,MAAI,SAAS,OAAO,UAAU;AAC9B,MAAI,SAAS,OAAO,UAAU,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;AACpF,MAAI,KAAK,OAAO,WAAW,CAAC;AAC5B,MAAI,UAAmB,EAAE,KAAK,GAAG,OAAO,GAAG,OAAO,GAAG,SAAS,GAAG,QAAQ,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,EAAE;AAE5G,MAAI,SAAS,OAAO,WAAW;AAC/B,MAAI,WAAW,OAAO,aAAa;AACnC,MAAI,cAAc,OAAO,gBAAgB,SAAY,OAAO,cAAc;AAC1E,MAAI,YAAY,OAAO,cAAc;AACrC,MAAI,WAAW,OAAO,aAAa;AACnC,MAAI,aAAa,OAAO,eAAe;AACvC,MAAI,cAAc,OAAO,gBAAgB,SAAY,OAAO,cAAc;AAC1E,MAAI,eAAe,OAAO,UAAU;AAEpC,MAAI,YAAY,SAAS,eAAe,WAAW;AACnD,MAAI,CAAC,aAAa,CAAC,KAAK,UAAU,CAAC,KAAK,CAAC,EAAE,OAAQ;AACnD,MAAI,aAAa,OAAO,SAAS,UAAU,eAAe;AAC1D,MAAI,cAAc,OAAO,UAAU;AACnC,MAAI,YAAY,aAAa,QAAQ,OAAO,QAAQ;AACpD,MAAI,aAAa,cAAc,QAAQ,MAAM,QAAQ;AACrD,MAAI,aAAa,QAAQ,MAAM;AAG/B,MAAI,aAAqB,YAAoB,UAAkB;AAC/D,aAAW,WAAW,KAAK,CAAC,EAAE,CAAC;AAC/B,OAAK,cAAc,GAAG,cAAc,KAAK,QAAQ;AAC/C,SAAK,aAAa,GAAG,aAAa,KAAK,WAAW,EAAE,QAAQ,cAAc;AACxE,UAAI,KAAK,WAAW,EAAE,UAAU,IAAI,SAAU,YAAW,KAAK,WAAW,EAAE,UAAU;AACrF,UAAI,KAAK,WAAW,EAAE,UAAU,IAAI,SAAU,YAAW,KAAK,WAAW,EAAE,UAAU;AAAA,IACvF;AACF,MAAI,QAAQ,WAAW,YAAY;AACnC,cAAY,QAAQ;AACpB,cAAY,QAAQ;AACpB,UAAQ,WAAW;AAEnB,MAAI,aAAa,OAAO;AACxB,MAAI,QAAQ,aAAa,IAAI,aAAa,aAAa,KAAK;AAC5D,MAAI,YAAY;AAChB,MAAI,WAAW,SAAS,YAAY;AAGpC,MAAI,cAAc,KAAK,SAAS;AAChC,MAAI,UAAU,IAAI,WAAW,WAAW;AACxC,MAAI,UAAU,IAAI,WAAW,WAAW;AACxC,OAAK,cAAc,GAAG,cAAc,KAAK,QAAQ;AAC/C,SAAK,aAAa,GAAG,aAAa,YAAY,cAAc;AAC1D,UAAI,aAAa,cAAc,aAAa;AAC5C,cAAQ,UAAU,IAAK,QAAQ,OAAO,aAAa,QAAS;AAC5D,cAAQ,UAAU,IAAK,QAAQ,MAAM,cAAe,KAAK,WAAW,EAAE,UAAU,IAAI,YAAY,QAAS,aAAc;AAAA,IACzH;AAGF,MAAI,iBAAiB,IAAI,WAAW,SAAS;AAC7C,MAAI,aAAa,IAAI,MAAM,SAAS;AACpC,MAAI;AACJ,OAAK,YAAY,GAAG,YAAY,WAAW,aAAa;AACtD,QAAI,YAAY,WAAW,YAAY;AACvC,mBAAe,SAAS,IAAK,QAAQ,MAAM,cAAe,YAAY,YAAY,QAAS,aAAc;AACzG,eAAW,SAAS,IAAI,UAAU,QAAQ,CAAC;AAAA,EAC7C;AAGA,MAAI,YAAY,oDAAoD,aAAa,eAAe,cAAc,oBAAoB,aAAa,MAAM,cAAc;AAGnK,MAAI,UAAU;AACZ,QAAI,WAAW;AACf,SAAK,YAAY,GAAG,YAAY,WAAW;AACzC,kBAAY,MAAM,QAAQ,OAAO,MAAM,eAAe,SAAS,IAAI,OAAO,QAAQ,OAAO;AAC3F,iBAAa,cAAc,WAAW,0BAA0B,aAAa,4BAA4B,MAAM;AAAA,EACjH;AAGA,OAAK,cAAc,GAAG,cAAc,KAAK,QAAQ,eAAe;AAC9D,QAAI,KAAK,cAAc;AACvB,QAAI,WAAW,MAAM,QAAQ,EAAE,IAAI,MAAM,QAAQ,EAAE;AAEnD,QAAI,QAAQ;AAEV,WAAK,aAAa,GAAG,aAAa,aAAa,GAAG,cAAc;AAC9D,YAAI,QAAQ,aAAa,aAAa,IAAI;AAC1C,YAAI,SAAS,aAAa,IAAI,aAAa,aAAa,IAAI,aAAa;AACzE,YAAI,OAAO,QAAQ,KAAK,UAAU,GAAG,OAAO,QAAQ,KAAK,UAAU;AACnE,YAAI,QAAQ,QAAQ,KAAK,aAAa,CAAC,GAAG,QAAQ,QAAQ,KAAK,aAAa,CAAC;AAC7E,YAAI,QAAQ,QAAQ,KAAK,KAAK,GAAG,QAAQ,QAAQ,KAAK,KAAK;AAC3D,YAAI,SAAS,QAAQ,KAAK,MAAM,GAAG,SAAS,QAAQ,KAAK,MAAM;AAC/D,oBAAY,QAAS,QAAQ,QAAQ,SAAS,IAAK,KAAK,OAAQ,QAAQ,QAAQ,SAAS,IAAK,KAC1F,OAAQ,SAAS,SAAS,QAAQ,IAAK,KAAK,OAAQ,SAAS,SAAS,QAAQ,IAAK,KACnF,MAAM,QAAQ,MAAM;AAAA,MAC1B;AAAA,IACF,OAAO;AACL,WAAK,aAAa,GAAG,aAAa,YAAY;AAC5C,oBAAY,MAAM,QAAQ,KAAK,UAAU,IAAI,MAAM,QAAQ,KAAK,UAAU;AAAA,IAC9E;AAGA,QAAI,UAAU;AACZ,UAAI,SAAS,QAAQ,EAAE,GAAG,QAAQ,QAAQ,KAAK,aAAa,CAAC;AAC7D,mBAAa,cAAc,WAAW,OAAO,QAAQ,MAAM,aAAa,OAAO,SAAS,MAAM,aAAa,eAC3F,OAAO,cAAc,OAAO,MAAM,IAAI,qBAAqB,cAAc;AAAA,IAC3F;AAEA,iBAAa,cAAc,WAAW,oCAAoC,OAAO,cAAc,OAAO,MAAM,IAAI,OAC3G,gBAAgB,MAAM,oBAAoB,cAAc,MAAM,MAAM;AAAA,EAC3E;AAEA,eAAa;AAGb,MAAI,cAAc;AAElB,MAAI,WAAW;AAEb,SAAK,YAAY,GAAG,YAAY,WAAW;AACzC,qBAAe,6CAA6C,QAAQ,OAAO,KAAK,aAAa,eAAe,SAAS,IAAI,KAAK,SAAS,WAAW,SAAS,IAAI;AAGjK,SAAK,aAAa,GAAG,aAAa,YAAY;AAC5C,qBAAe,4CAA4C,QAAQ,UAAU,IAAI,aAAa,QAAQ,MAAM,aAAa,KAAK,SAAS,OAAO,UAAU,IAAI;AAAA,EAChK;AAGA,MAAI;AACF,mBAAe,4CAA4C,QAAQ,QAAQ,aAAa,MAAM,aAAa,cAAc,MAAM,SAAS,SAAS;AACnJ,MAAI;AACF,mBAAe,oDAAoD,QAAQ,MAAM,MAAM,wCAAwC,SAAS;AAE1I,iBAAe;AAGf,YAAU,MAAM,UAAU,6BAA6B,aAAa,eAAe,cAAc;AACjG,YAAU,YAAY,YAAY;AAGlC,MAAI,CAAC,OAAO,OAAO;AACjB,kBAAc,WAAW,WAAY;AAAE,oBAAc,aAAa,MAAM;AAAA,IAAG,CAAC;AAAA,EAC9E;AAGA,MAAI,CAAC,aAAc;AAEnB,MAAI,MAAM,UAAU;AACpB,MAAI,YAAqC;AACzC,MAAI,UAAiC;AAErC,WAAS,sBAAsB;AAC7B,QAAI,CAAC,WAAW;AACd,kBAAY,SAAS,gBAAgB,QAAQ,QAAQ;AACrD,gBAAU,aAAa,KAAK,GAAG;AAC/B,gBAAU,aAAa,SAAS,iBAAiB;AACjD,gBAAU,MAAM,UAAU;AAC1B,UAAI,YAAY,SAAS;AAAA,IAC3B;AACA,QAAI,CAAC,SAAS;AACZ,gBAAU,SAAS,cAAc,KAAK;AACtC,cAAQ,YAAY;AACpB,gBAAU,YAAY,OAAO;AAAA,IAC/B;AAAA,EACF;AAEA;AAAA,IAAqB;AAAA,IAAW;AAAA,IAC9B,SAAU,QAAQ,QAAQ;AACxB,UAAI,SAAS,QAAQ,QAAQ,SAAS,QAAQ,OAAO,aAAa,SAAS,QAAQ,OAAO,SAAS,QAAQ,MAAM,YAAY;AAC3H,YAAI,UAAW,WAAU,MAAM,UAAU;AACzC,YAAI,QAAS,SAAQ,MAAM,UAAU;AACrC;AAAA,MACF;AAEA,0BAAoB;AAEpB,UAAI,YAAY,SAAS,QAAQ;AACjC,UAAI,YAAY,EAAG,aAAY;AAC/B,UAAI,YAAY,UAAW,aAAY;AACvC,UAAI,eAAgB,YAAY,QAAQ,MAAO;AAC/C,UAAI,gBAAgB,WAAY,gBAAe,aAAa;AAE5D,UAAI,kBAAkB;AACtB,UAAI,eAAe,KAAK,IAAI,QAAQ,YAAY,IAAI,MAAM;AAC1D,eAAS,cAAc,GAAG,cAAc,KAAK,QAAQ,eAAe;AAClE,YAAI,WAAW,KAAK,IAAI,QAAQ,cAAc,aAAa,YAAY,IAAI,MAAM;AACjF,YAAI,WAAW,cAAc;AAAE,yBAAe;AAAU,4BAAkB;AAAA,QAAa;AAAA,MACzF;AAEA,UAAI,SAAS,QAAQ,kBAAkB,aAAa,YAAY;AAChE,UAAI,SAAS,QAAQ,kBAAkB,aAAa,YAAY;AAEhE,gBAAW,aAAa,aAAa,eAAe,SAAS,MAAM,SAAS,GAAG;AAC/E,gBAAW,aAAa,QAAQ,OAAO,kBAAkB,OAAO,MAAM,CAAC;AACvE,gBAAW,MAAM,UAAU;AAE3B,cAAS,YAAY,gBAAgB,kBAAkB,KAAK,aAC1D,SAAS,OAAO,OAAO,YAAY,IAAI,SAAS,SAAS,OAAO,KAAK,eAAe,EAAE,YAAY;AACpG,cAAS,MAAM,YAAY,eAAe,SAAS,SAAS,SAAS,MAAM;AAC3E,cAAS,MAAM,UAAU;AAAA,IAC3B;AAAA,IACA,WAAY;AACV,UAAI,UAAW,WAAU,MAAM,UAAU;AACzC,UAAI,QAAS,SAAQ,MAAM,UAAU;AAAA,IACvC;AAAA,EACF;AACF;;;AC9MO,SAAS,aAAa,aAAqB,QAA8B;AAC9E,MAAI,OAAO,OAAO;AAClB,MAAI,SAAS,OAAO;AACpB,MAAI,SAAS,OAAO,UAAU;AAC9B,MAAI,SAAS,OAAO,UAAU;AAC9B,MAAI,SAAS,OAAO,UAAU,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;AACpF,MAAI,UAAU,OAAO,YAAY;AACjC,MAAI,aAAa,OAAO,eAAe;AACvC,MAAI,YAAY,OAAO,cAAc;AACrC,MAAI,WAAW,OAAO,aAAa;AACnC,MAAI,aAAa,OAAO,eAAe;AACvC,MAAI,eAAe,OAAO,UAAU;AACpC,MAAI,SAAS,OAAO,WAAW,SAAY,OAAO,SAAS;AAC3D,MAAI,KAAK,OAAO,WAAW,CAAC;AAC5B,MAAI,UAAmB,EAAE,KAAK,GAAG,OAAO,GAAG,OAAO,GAAG,SAAS,GAAG,QAAQ,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,EAAE;AAE5G,MAAI,YAAY,SAAS,eAAe,WAAW;AACnD,MAAI,CAAC,aAAa,CAAC,KAAK,UAAU,CAAC,KAAK,CAAC,EAAE,OAAQ;AACnD,MAAI,aAAa,OAAO,SAAS,UAAU,eAAe;AAC1D,MAAI,cAAc,OAAO,UAAU;AACnC,MAAI,YAAY,aAAa,QAAQ,OAAO,QAAQ;AACpD,MAAI,aAAa,cAAc,QAAQ,MAAM,QAAQ;AACrD,MAAI,aAAa,QAAQ,MAAM;AAE/B,MAAI,cAAc,KAAK;AACvB,MAAI,WAAW,OAAO;AACtB,MAAI,IAAY,IAAY,KAAa;AAKzC,MAAI,QAAgB;AACpB,MAAI,SAAS;AACX,aAAS;AACT,aAAS;AACT,SAAK,KAAK,GAAG,KAAK,UAAU,MAAM;AAChC,UAAI,SAAS;AACb,WAAK,KAAK,GAAG,KAAK,aAAa,MAAM;AACnC,kBAAU,KAAK,EAAE,EAAE,EAAE;AACrB,YAAI,KAAK,EAAE,EAAE,EAAE,IAAI,OAAQ,UAAS,KAAK,EAAE,EAAE,EAAE;AAAA,MACjD;AACA,UAAI,SAAS,OAAQ,UAAS;AAAA,IAChC;AAAA,EACF,OAAO;AACL,aAAS,SAAS,KAAK,CAAC,EAAE,CAAC;AAC3B,SAAK,KAAK,GAAG,KAAK,aAAa;AAC7B,WAAK,KAAK,GAAG,KAAK,UAAU,MAAM;AAChC,cAAM,KAAK,EAAE,EAAE,EAAE;AACjB,YAAI,MAAM,OAAQ,UAAS;AAC3B,YAAI,MAAM,OAAQ,UAAS;AAAA,MAC7B;AAAA,EACJ;AAEA,MAAI,SAAS,EAAG,UAAS;AACzB,MAAI,SAAS,EAAG,UAAS;AAEzB,MAAI,QAAQ,SAAS,UAAU;AAC/B,YAAU,QAAQ;AAClB,UAAQ,SAAS;AAGjB,MAAI,YAAY;AAChB,MAAI,WAAW,SAAS,YAAY;AACpC,MAAI,gBAAgB,IAAI,WAAW,SAAS;AAC5C,MAAI,aAAa,IAAI,MAAc,SAAS;AAE5C,MAAI,YAAY,cAAc;AAC9B,MAAI,OAAO,IAAI,WAAW,SAAS;AACnC,MAAI,OAAO,IAAI,WAAW,SAAS;AACnC,MAAI,OAAO,IAAI,WAAW,SAAS;AACnC,MAAI,OAAO,IAAI,WAAW,SAAS;AACnC,MAAI;AACJ,MAAI,QAAQ;AAEZ,MAAI,YAAY;AAEd,gBAAY,aAAa;AACzB,QAAI,QAAS,QAAQ,QAAS,IAAI,UAAU,QAAS,YAAa;AAElE,SAAK,KAAK,GAAG,KAAK,WAAW,MAAM;AACjC,UAAI,UAAU,SAAS,KAAK;AAC5B,oBAAc,EAAE,IAAK,QAAQ,QAAS,UAAU,UAAU,QAAS,YAAa;AAChF,iBAAW,EAAE,IAAI,UAAU,MAAM,IAAI,QAAQ,SAAS,IAAI,QAAQ,QAAQ,CAAC;AAAA,IAC7E;AAEA,QAAI,aAAe,aAAa,IAAI,UAAW,cAAe;AAC9D,QAAI,eAAgB,YAAY,aAAa,eAAe,IAAK;AAEjE,SAAK,KAAK,GAAG,KAAK,aAAa;AAC7B,WAAK,KAAK,GAAG,KAAK,UAAU,MAAM;AAChC,YAAI,MAAM,KAAK,WAAW;AAC1B,cAAM,KAAK,EAAE,EAAE,EAAE;AACjB,YAAI,OAAQ,QAAQ,QAAS,MAAM,UAAU,QAAS,YAAa;AAEnE,aAAK,GAAG,IAAK,QAAQ,MAAM,KAAK,YAAY,cAAc,KAAK,aAAc;AAC7E,aAAK,GAAG,IAAI;AAEZ,YAAI,OAAO,GAAG;AACZ,eAAK,GAAG,IAAI;AACZ,eAAK,GAAG,IAAK,OAAO,SAAS;AAAA,QAC/B,OAAO;AACL,eAAK,GAAG,IAAI;AACZ,eAAK,GAAG,IAAK,QAAQ,QAAQ;AAAA,QAC/B;AAAA,MACF;AAAA,EACJ,OAAO;AAEL,gBAAY,YAAY;AAExB,YAAS,QAAQ,MAAM,cAAe,IAAI,UAAU,QAAS,aAAc;AAE3E,SAAK,KAAK,GAAG,KAAK,WAAW,MAAM;AACjC,UAAI,UAAU,SAAS,KAAK;AAC5B,oBAAc,EAAE,IAAK,QAAQ,MAAM,cAAe,UAAU,UAAU,QAAS,aAAc;AAC7F,iBAAW,EAAE,IAAI,UAAU,MAAM,IAAI,QAAQ,SAAS,IAAI,QAAQ,QAAQ,CAAC;AAAA,IAC7E;AAEA,QAAI,SAAS;AACX,UAAI,gBAAiB,aAAa,IAAI,UAAW;AACjD,UAAI,kBAAmB,YAAY,iBAAiB,IAAK;AAEzD,WAAK,KAAK,GAAG,KAAK,UAAU,MAAM;AAChC,YAAI,SAAS;AACb,aAAK,KAAK,GAAG,KAAK,aAAa,MAAM;AACnC,cAAI,MAAM,KAAK,WAAW;AAC1B,gBAAM,KAAK,EAAE,EAAE,EAAE;AACjB,cAAI,QAAS,QAAQ,MAAM,cAAe,SAAS,UAAU,QAAS,aAAc;AACpF,cAAI,OAAQ,QAAQ,MAAM,cAAe,SAAS,MAAM,UAAU,QAAS,aAAc;AACzF,oBAAU;AAEV,eAAK,GAAG,IAAK,QAAQ,OAAO,KAAK,YAAY,iBAAkB;AAC/D,eAAK,GAAG,IAAI,KAAK,IAAI,OAAO,IAAI;AAChC,eAAK,GAAG,IAAI;AACZ,eAAK,GAAG,IAAK,KAAK,IAAI,OAAO,KAAK,KAAK;AAAA,QACzC;AAAA,MACF;AAAA,IACF,OAAO;AACL,UAAI,iBAAmB,aAAa,IAAI,UAAW,cAAe;AAClE,UAAI,iBAAkB,YAAY,iBAAiB,eAAe,IAAK;AAEvE,WAAK,KAAK,GAAG,KAAK,aAAa;AAC7B,aAAK,KAAK,GAAG,KAAK,UAAU,MAAM;AAChC,cAAI,MAAM,KAAK,WAAW;AAC1B,gBAAM,KAAK,EAAE,EAAE,EAAE;AACjB,cAAI,OAAQ,QAAQ,MAAM,cAAe,MAAM,UAAU,QAAS,aAAc;AAEhF,eAAK,GAAG,IAAK,QAAQ,OAAO,KAAK,YAAY,gBAAgB,KAAK,iBAAkB;AACpF,eAAK,GAAG,IAAI;AAEZ,cAAI,OAAO,GAAG;AACZ,iBAAK,GAAG,IAAI;AACZ,iBAAK,GAAG,IAAK,QAAQ,QAAQ;AAAA,UAC/B,OAAO;AACL,iBAAK,GAAG,IAAI;AACZ,iBAAK,GAAG,IAAK,OAAO,SAAS;AAAA,UAC/B;AAAA,QACF;AAAA,IACJ;AAAA,EACF;AAGA,MAAI,YAAY,oDAAoD,aAAa,eAAe,cAAc,oBAAoB,aAAa,MAAM,cAAc;AAGnK,MAAI,UAAU;AACZ,QAAI,WAAW;AACf,QAAI,YAAY;AACd,WAAK,KAAK,GAAG,KAAK,WAAW;AAC3B,oBAAY,MAAM,cAAc,EAAE,IAAI,MAAM,QAAQ,MAAM,MAAM;AAAA,IACpE,OAAO;AACL,WAAK,KAAK,GAAG,KAAK,WAAW;AAC3B,oBAAY,MAAM,QAAQ,OAAO,MAAM,cAAc,EAAE,IAAI,OAAO,QAAQ,OAAO;AAAA,IACrF;AACA,iBAAa,cAAc,WAAW,0BAA0B,aAAa,4BAA4B,MAAM;AAAA,EACjH;AAGA,MAAI,SAAS,GAAG;AACd,QAAI,YAAY;AACd,UAAI,KAAM,QAAQ,QAAS,IAAI,UAAU,QAAS,YAAa;AAC/D,mBAAa,eAAe,KAAK,WAAW,QAAQ,MAAM,WAAW,KAAK,WAAW,aACnF;AAAA,IACJ,OAAO;AACL,mBAAa,eAAe,QAAQ,OAAO,WAAW,QAAQ,YAAY,QAAQ,OAAO,aAAa,WAAW,QAC/G;AAAA,IACJ;AAAA,EACF;AAGA,OAAK,KAAK,GAAG,KAAK,aAAa,MAAM;AACnC,QAAI,QAAQ,OAAO,KAAK,OAAO,MAAM;AACrC,SAAK,KAAK,GAAG,KAAK,UAAU,MAAM;AAChC,UAAI,MAAM,KAAK,WAAW;AAC1B,mBAAa,cAAc,KAAK,GAAG,IAAI,UAAU,KAAK,GAAG,IAAI,cAAc,KAAK,GAAG,IAAI,eAAe,KAAK,GAAG,IAC5G,aAAa,QAAQ;AAAA,IACzB;AAAA,EACF;AAEA,eAAa;AAGb,MAAI,cAAc;AAElB,MAAI,WAAW;AACb,QAAI,YAAY;AAEd,WAAK,KAAK,GAAG,KAAK,WAAW;AAC3B,uBAAe,4CAA4C,cAAc,EAAE,IAAI,aAAa,aAAa,KAAK,SAAS,WAAW,EAAE,IAAI;AAG1I,WAAK,KAAK,GAAG,KAAK,UAAU,MAAM;AAChC,YAAI,UAAW,QAAQ,MAAM,KAAK,YAAY,YAAY,IAAK;AAC/D,uBAAe,6CAA6C,QAAQ,OAAO,KAAK,aAAa,UAAU,KAAK,SAAS,OAAO,EAAE,IAAI;AAAA,MACpI;AAAA,IACF,OAAO;AAEL,WAAK,KAAK,GAAG,KAAK,WAAW;AAC3B,uBAAe,6CAA6C,QAAQ,OAAO,KAAK,aAAa,cAAc,EAAE,IAAI,KAAK,SAAS,WAAW,EAAE,IAAI;AAGlJ,WAAK,KAAK,GAAG,KAAK,UAAU,MAAM;AAChC,YAAI,UAAW,QAAQ,OAAO,KAAK,YAAY,YAAY,IAAK;AAChE,uBAAe,4CAA4C,UAAU,aAAa,aAAa,KAAK,SAAS,OAAO,EAAE,IAAI;AAAA,MAC5H;AAAA,IACF;AAAA,EACF;AAGA,MAAI;AACF,mBAAe,4CAA4C,QAAQ,QAAQ,aAAa,MAAM,aAAa,cAAc,MAAM,SAAS,SAAS;AACnJ,MAAI;AACF,mBAAe,oDAAoD,QAAQ,MAAM,MAAM,wCAAwC,SAAS;AAE1I,iBAAe;AAGf,YAAU,MAAM,UAAU,6BAA6B,aAAa,eAAe,cAAc;AACjG,YAAU,YAAY,YAAY;AAGlC,MAAI,CAAC,OAAO,OAAO;AACjB,kBAAc,WAAW,WAAY;AAAE,mBAAa,aAAa,MAAM;AAAA,IAAG,CAAC;AAAA,EAC7E;AAGA,MAAI,CAAC,aAAc;AAEnB,MAAI,QAAQ,UAAU;AACtB,MAAI,YAAmC;AACvC,MAAI,UAAiC;AAErC,WAAS,cAAc;AACrB,QAAI,CAAC,WAAW;AACd,kBAAY,SAAS,gBAAgB,QAAQ,MAAM;AACnD,gBAAU,aAAa,SAAS,iBAAiB;AACjD,gBAAU,aAAa,QAAQ,uBAAuB;AACtD,gBAAU,aAAa,UAAU,MAAM;AACvC,gBAAU,aAAa,gBAAgB,GAAG;AAC1C,gBAAU,MAAM,UAAU;AAC1B,YAAM,YAAY,SAAS;AAAA,IAC7B;AACA,QAAI,CAAC,SAAS;AACZ,gBAAU,SAAS,cAAc,KAAK;AACtC,cAAQ,YAAY;AACpB,gBAAU,YAAY,OAAO;AAAA,IAC/B;AAAA,EACF;AAEA;AAAA,IAAqB;AAAA,IAAW;AAAA,IAC9B,SAAU,IAAI,IAAI;AAChB,UAAI,KAAK,QAAQ,QAAQ,KAAK,QAAQ,OAAO,aAAa,KAAK,QAAQ,OAAO,KAAK,YAAY;AAC7F,YAAI,UAAW,WAAU,MAAM,UAAU;AACzC,YAAI,QAAS,SAAQ,MAAM,UAAU;AACrC;AAAA,MACF;AAGA,UAAI;AACJ,UAAI,YAAY;AACd,mBAAY,KAAK,QAAQ,OAAO,YAAa;AAAA,MAC/C,OAAO;AACL,mBAAY,KAAK,QAAQ,QAAQ,YAAa;AAAA,MAChD;AACA,UAAI,WAAW,SAAU,WAAU,WAAW;AAC9C,UAAI,UAAU,EAAG,WAAU;AAE3B,UAAI,UAAU;AACd,UAAI,WAAW;AACf,WAAK,KAAK,GAAG,KAAK,aAAa,MAAM;AACnC,YAAIA,OAAM,KAAK,WAAW;AAC1B,YAAI,KAAK,KAAKA,IAAG,KAAK,KAAKA,IAAG,KAAK;AACnC,YAAI,KAAK,KAAKA,IAAG,KAAK,KAAKA,IAAG,KAAK;AACnC,YAAI,KAAK,KAAK,IAAI,KAAK,KAAK;AAC5B,YAAI,OAAO,KAAK,KAAK,KAAK;AAC1B,YAAI,OAAO,UAAU;AAAE,qBAAW;AAAM,oBAAUA;AAAA,QAAK;AAAA,MACzD;AAEA,UAAI,YAAY,GAAI;AAEpB,kBAAY;AAEZ,UAAI,MAAO,UAAU,WAAY;AACjC,UAAI,MAAM,UAAU;AAEpB,gBAAW,aAAa,KAAK,KAAK,KAAK,OAAO,CAAC;AAC/C,gBAAW,aAAa,KAAK,KAAK,KAAK,OAAO,CAAC;AAC/C,gBAAW,aAAa,SAAS,KAAK,KAAK,OAAO,CAAC;AACnD,gBAAW,aAAa,UAAU,KAAK,KAAK,OAAO,CAAC;AACpD,gBAAW,aAAa,UAAU,OAAO,MAAM,OAAO,MAAM,CAAC;AAC7D,gBAAW,MAAM,UAAU;AAE3B,UAAI,MAAc;AAClB,UAAI,YAAY;AACd,eAAO,KAAK,OAAO,IAAI,KAAK,OAAO;AACnC,eAAO,KAAK,OAAO,KAAK,KAAK,OAAO,KAAK;AACzC,gBAAS,MAAM,YAAY,gBAAgB,OAAO,KAAK,QAAQ,OAAO;AAAA,MACxE,OAAO;AACL,eAAO,KAAK,OAAO,KAAK,KAAK,OAAO,KAAK;AACzC,eAAO,KAAK,OAAO;AACnB,gBAAS,MAAM,YAAY,eAAe,OAAO,SAAS,OAAO,MAAM;AAAA,MACzE;AAEA,cAAS,aAAa,cAAc,IAAI,gBAAgB,MAAM,KAAK,aAAa,MAC9E,OAAO,GAAG,IAAI,OAAO,KAAK,GAAG,EAAE,GAAG;AACpC,cAAS,MAAM,UAAU;AAAA,IAC3B;AAAA,IACA,WAAY;AACV,UAAI,UAAW,WAAU,MAAM,UAAU;AACzC,UAAI,QAAS,SAAQ,MAAM,UAAU;AAAA,IACvC;AAAA,EACF;AACF;;;AC3VA,IAAI,SAAS,KAAK,KAAK;AAKhB,SAAS,aAAa,aAAqB,QAA8B;AAC9E,MAAI,OAAO,OAAO;AAClB,MAAI,SAAS,OAAO;AACpB,MAAI,SAAS,OAAO,UAAU,CAAC,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AACrH,MAAI,UAAU,OAAO,UAAU;AAC/B,MAAI,aAAa,OAAO,eAAe,SAAY,OAAO,aAAa;AACvE,MAAI,aAAa,OAAO,eAAe;AACvC,MAAI,eAAe,OAAO,UAAU;AAEpC,MAAI,YAAY,SAAS,eAAe,WAAW;AACnD,MAAI,CAAC,UAAW;AAChB,MAAI,aAAa,OAAO,SAAS,UAAU,eAAe;AAC1D,MAAI,cAAc,OAAO,UAAU;AACnC,MAAI,aAAa,KAAK;AAEtB,MAAI,UAAU,aAAa;AAC3B,MAAI,UAAU,cAAc;AAC5B,MAAI,SAAS,KAAK,IAAI,SAAS,OAAO,KAAK,aAAa,KAAK;AAC7D,MAAI,SAAS,UAAU,KAAK,IAAI,SAAS,YAAY,CAAC,IAAI;AAG1D,MAAI;AACJ,MAAI,QAAQ;AACZ,OAAK,IAAI,GAAG,IAAI,YAAY,IAAK,UAAS,KAAK,CAAC;AAGhD,MAAI,cAAc,IAAI,aAAa,UAAU;AAC7C,MAAI,YAAY,IAAI,aAAa,UAAU;AAC3C,MAAI,cAAc,IAAI,aAAa,UAAU;AAC7C,MAAI,QAAQ,CAAC,KAAK,KAAK;AAEvB,OAAK,IAAI,GAAG,IAAI,YAAY,KAAK;AAC/B,gBAAY,CAAC,IAAI;AACjB,QAAI,aAAa,QAAQ,IAAK,KAAK,CAAC,IAAI,QAAS,SAAS;AAC1D,gBAAY,CAAC,IAAI,QAAQ,IAAK,KAAK,CAAC,IAAI,QAAS,MAAM;AACvD,aAAS;AACT,cAAU,CAAC,IAAI;AAAA,EACjB;AAGA,MAAI,YAAY,oDAAoD,aAAa,eAAe,cAAc,oBAAoB,aAAa,MAAM,cAAc;AAEnK,OAAK,IAAI,GAAG,IAAI,YAAY,KAAK;AAE/B,QAAI,UAAU,CAAC,IAAI,YAAY,CAAC,IAAI,KAAO;AAE3C,QAAI,QAAQ,OAAO,IAAI,OAAO,MAAM;AACpC,QAAI,OAAO,KAAK,IAAI,YAAY,CAAC,CAAC,GAAG,OAAO,KAAK,IAAI,YAAY,CAAC,CAAC;AACnE,QAAI,OAAO,KAAK,IAAI,UAAU,CAAC,CAAC,GAAG,OAAO,KAAK,IAAI,UAAU,CAAC,CAAC;AAC/D,QAAI,WAAW,UAAU,CAAC,IAAI,YAAY,CAAC,IAAI,KAAK,KAAK,IAAI;AAE7D,QAAI,MAAM,UAAU,SAAS,MAAM,MAAM,UAAU,SAAS;AAC5D,QAAI,MAAM,UAAU,SAAS,MAAM,MAAM,UAAU,SAAS;AAE5D,QAAI;AACJ,QAAI,SAAS;AACX,UAAI,MAAM,UAAU,SAAS,MAAM,MAAM,UAAU,SAAS;AAC5D,UAAI,MAAM,UAAU,SAAS,MAAM,MAAM,UAAU,SAAS;AAE5D,iBAAW,MAAM,IAAI,QAAQ,CAAC,IAAI,MAAM,IAAI,QAAQ,CAAC,IACjD,MAAM,SAAS,MAAM,SAAS,QAAQ,WAAW,QAAQ,IAAI,QAAQ,CAAC,IAAI,MAAM,IAAI,QAAQ,CAAC,IAC7F,MAAM,IAAI,QAAQ,CAAC,IAAI,MAAM,IAAI,QAAQ,CAAC,IAC1C,MAAM,SAAS,MAAM,SAAS,QAAQ,WAAW,QAAQ,IAAI,QAAQ,CAAC,IAAI,MAAM,IAAI,QAAQ,CAAC,IAC7F;AAAA,IACN,OAAO;AAEL,iBAAW,MAAM,QAAQ,QAAQ,CAAC,IAAI,MAAM,QAAQ,QAAQ,CAAC,IACzD,MAAM,IAAI,QAAQ,CAAC,IAAI,MAAM,IAAI,QAAQ,CAAC,IAC1C,MAAM,SAAS,MAAM,SAAS,QAAQ,WAAW,QAAQ,IAAI,QAAQ,CAAC,IAAI,MAAM,IAAI,QAAQ,CAAC,IAC7F;AAAA,IACN;AAEA,iBAAa,cAAc,WAAW,aAAa,QAAQ;AAAA,EAC7D;AAEA,eAAa;AAGb,MAAI,cAAc;AAElB,MAAI,YAAY;AACd,QAAI,SAAS,SAAS;AACtB,SAAK,IAAI,GAAG,IAAI,YAAY,KAAK;AAE/B,UAAI,YAAY,CAAC,IAAI,EAAG;AAExB,UAAI,YAAY,YAAY,CAAC,IAAI,UAAU,CAAC,KAAK;AACjD,UAAI,KAAK,UAAU,SAAS,KAAK,IAAI,QAAQ;AAC7C,UAAI,KAAK,UAAU,SAAS,KAAK,IAAI,QAAQ;AAE7C,qBAAe,uBAAuB,GAAG,QAAQ,CAAC,IAAI,YAAY,GAAG,QAAQ,CAAC,IAC1E,0DACA,OAAO,CAAC,IAAI,MAAM,YAAY,CAAC,EAAE,QAAQ,CAAC,IAAI;AAAA,IACpD;AAAA,EACF;AAEA,iBAAe;AAGf,YAAU,MAAM,UAAU,6BAA6B,aAAa,eAAe,cAAc;AACjG,YAAU,YAAY,YAAY;AAGlC,MAAI,CAAC,OAAO,OAAO;AACjB,kBAAc,WAAW,WAAY;AAAE,mBAAa,aAAa,MAAM;AAAA,IAAG,CAAC;AAAA,EAC7E;AAGA,MAAI,CAAC,aAAc;AAEnB,MAAI,QAAQ,UAAU;AACtB,MAAI,YAAmC;AACvC,MAAI,UAAiC;AACrC,MAAI,YAAY;AAEhB,WAAS,cAAc;AACrB,QAAI,CAAC,WAAW;AACd,kBAAY,SAAS,gBAAgB,QAAQ,MAAM;AACnD,gBAAU,aAAa,SAAS,iBAAiB;AACjD,gBAAU,aAAa,QAAQ,MAAM;AACrC,gBAAU,aAAa,UAAU,MAAM;AACvC,gBAAU,aAAa,gBAAgB,GAAG;AAC1C,gBAAU,MAAM,UAAU;AAC1B,YAAM,YAAY,SAAS;AAAA,IAC7B;AACA,QAAI,CAAC,SAAS;AACZ,gBAAU,SAAS,cAAc,KAAK;AACtC,cAAQ,YAAY;AACpB,gBAAU,YAAY,OAAO;AAAA,IAC/B;AAAA,EACF;AAEA;AAAA,IAAqB;AAAA,IAAW;AAAA,IAC9B,SAAU,IAAI,IAAI;AAChB,UAAI,KAAK,KAAK,SAAS,KAAK,KAAK;AACjC,UAAI,OAAO,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE;AAGtC,UAAI,OAAO,UAAU,OAAO,QAAQ;AAClC,YAAI,UAAW,WAAU,MAAM,UAAU;AACzC,YAAI,QAAS,SAAQ,MAAM,UAAU;AACrC,oBAAY;AACZ;AAAA,MACF;AAGA,UAAI,aAAa,KAAK,MAAM,IAAI,EAAE;AAElC,UAAI,aAAa,CAAC,KAAK,KAAK,EAAG,eAAc;AAE7C,UAAI,WAAW;AACf,eAAS,IAAI,GAAG,IAAI,YAAY,KAAK;AACnC,YAAI,cAAc,YAAY,CAAC,KAAK,aAAa,UAAU,CAAC,GAAG;AAC7D,qBAAW;AACX;AAAA,QACF;AAAA,MACF;AAEA,UAAI,aAAa,GAAI;AAErB,kBAAY;AAGZ,UAAI,aAAa,WAAW;AAC1B,oBAAY;AAEZ,YAAIC,QAAO,KAAK,IAAI,YAAY,QAAQ,CAAC,GAAGC,QAAO,KAAK,IAAI,YAAY,QAAQ,CAAC;AACjF,YAAIC,QAAO,KAAK,IAAI,UAAU,QAAQ,CAAC,GAAGC,QAAO,KAAK,IAAI,UAAU,QAAQ,CAAC;AAC7E,YAAIC,YAAW,UAAU,QAAQ,IAAI,YAAY,QAAQ,IAAI,KAAK,KAAK,IAAI;AAC3E,YAAIC,OAAM,UAAU,SAASL,OAAMM,OAAM,UAAU,SAASL;AAC5D,YAAIM,OAAM,UAAU,SAASL,OAAMM,OAAM,UAAU,SAASL;AAE5D,YAAI;AACJ,YAAI,SAAS;AACX,cAAIM,OAAM,UAAU,SAAST,OAAMU,OAAM,UAAU,SAAST;AAC5D,cAAIU,OAAM,UAAU,SAAST,OAAMU,OAAM,UAAU,SAAST;AAC5D,kBAAQ,MAAME,KAAI,QAAQ,CAAC,IAAI,MAAMC,KAAI,QAAQ,CAAC,IAC9C,MAAM,SAAS,MAAM,SAAS,QAAQF,YAAW,QAAQG,KAAI,QAAQ,CAAC,IAAI,MAAMC,KAAI,QAAQ,CAAC,IAC7F,MAAMG,KAAI,QAAQ,CAAC,IAAI,MAAMC,KAAI,QAAQ,CAAC,IAC1C,MAAM,SAAS,MAAM,SAAS,QAAQR,YAAW,QAAQK,KAAI,QAAQ,CAAC,IAAI,MAAMC,KAAI,QAAQ,CAAC,IAC7F;AAAA,QACN,OAAO;AACL,kBAAQ,MAAM,QAAQ,QAAQ,CAAC,IAAI,MAAM,QAAQ,QAAQ,CAAC,IACtD,MAAML,KAAI,QAAQ,CAAC,IAAI,MAAMC,KAAI,QAAQ,CAAC,IAC1C,MAAM,SAAS,MAAM,SAAS,QAAQF,YAAW,QAAQG,KAAI,QAAQ,CAAC,IAAI,MAAMC,KAAI,QAAQ,CAAC,IAC7F;AAAA,QACN;AACA,kBAAW,aAAa,KAAK,KAAK;AAAA,MACpC;AAEA,gBAAW,MAAM,UAAU;AAG3B,cAAS,YAAY,QAAQ,OAAO,QAAQ,IAAI,aAC5C,KAAK,QAAQ,IAAI,OAAO,YAAY,QAAQ,EAAE,QAAQ,CAAC,IAAI;AAC/D,cAAS,MAAM,YAAY,eAAe,KAAK,SAAS,KAAK,MAAM;AACnE,cAAS,MAAM,UAAU;AAAA,IAC3B;AAAA,IACA,WAAY;AACV,UAAI,UAAW,WAAU,MAAM,UAAU;AACzC,UAAI,QAAS,SAAQ,MAAM,UAAU;AACrC,kBAAY;AAAA,IACd;AAAA,EACF;AACF;;;AJ/NA,IAAI,OAAO,WAAW,aAAa;AACjC,EAAC,OAAe,gBAAgB;AAChC,EAAC,OAAe,eAAe;AAC/B,EAAC,OAAe,eAAe;AACjC;","names":["idx","cos1","sin1","cos2","sin2","largeArc","ox1","oy1","ox2","oy2","ix1","iy1","ix2","iy2"]}
package/dist/index.d.cts CHANGED
@@ -1,3 +1,10 @@
1
+ interface Padding {
2
+ top: number;
3
+ right: number;
4
+ bottom: number;
5
+ left: number;
6
+ }
7
+
1
8
  /**
2
9
  * Configuration for a chart instance.
3
10
  */
@@ -32,6 +39,8 @@ interface LineChartConfig {
32
39
  strokeWidth?: number;
33
40
  /** Enable hover tooltip + indicator. Default true. */
34
41
  hover?: boolean;
42
+ /** Chart padding {top, right, bottom, left}. Default {top:20, right:30, bottom:50, left:60}. */
43
+ padding?: Partial<Padding>;
35
44
  }
36
45
  /**
37
46
  * Creates a high-performance SVG+HTML hybrid line chart inside the specified container.
@@ -70,6 +79,8 @@ interface BarChartConfig {
70
79
  gridDashed?: boolean;
71
80
  /** Enable hover tooltip + indicator. Default true. */
72
81
  hover?: boolean;
82
+ /** Chart padding {top, right, bottom, left}. Default {top:20, right:30, bottom:50, left:60} (left:80 for horizontal). */
83
+ padding?: Partial<Padding>;
73
84
  }
74
85
  /**
75
86
  * Creates a high-performance SVG+HTML hybrid bar chart inside the specified container.
package/dist/index.d.ts CHANGED
@@ -1,3 +1,10 @@
1
+ interface Padding {
2
+ top: number;
3
+ right: number;
4
+ bottom: number;
5
+ left: number;
6
+ }
7
+
1
8
  /**
2
9
  * Configuration for a chart instance.
3
10
  */
@@ -32,6 +39,8 @@ interface LineChartConfig {
32
39
  strokeWidth?: number;
33
40
  /** Enable hover tooltip + indicator. Default true. */
34
41
  hover?: boolean;
42
+ /** Chart padding {top, right, bottom, left}. Default {top:20, right:30, bottom:50, left:60}. */
43
+ padding?: Partial<Padding>;
35
44
  }
36
45
  /**
37
46
  * Creates a high-performance SVG+HTML hybrid line chart inside the specified container.
@@ -70,6 +79,8 @@ interface BarChartConfig {
70
79
  gridDashed?: boolean;
71
80
  /** Enable hover tooltip + indicator. Default true. */
72
81
  hover?: boolean;
82
+ /** Chart padding {top, right, bottom, left}. Default {top:20, right:30, bottom:50, left:60} (left:80 for horizontal). */
83
+ padding?: Partial<Padding>;
73
84
  }
74
85
  /**
75
86
  * Creates a high-performance SVG+HTML hybrid bar chart inside the specified container.
package/dist/index.js CHANGED
@@ -27,6 +27,21 @@ function attachHoverListeners(container, svgEl, onUpdate, onLeave) {
27
27
  }, { passive: true });
28
28
  container.addEventListener("touchend", onLeave, { passive: true });
29
29
  }
30
+ function observeResize(container, render) {
31
+ if (typeof ResizeObserver === "undefined") return;
32
+ var parent = container.parentElement || container;
33
+ var lastW = parent.clientWidth;
34
+ var ro = new ResizeObserver(function() {
35
+ var newW = parent.clientWidth;
36
+ if (newW && newW !== lastW) {
37
+ lastW = newW;
38
+ ro.disconnect();
39
+ container.style.width = "";
40
+ render();
41
+ }
42
+ });
43
+ ro.observe(parent);
44
+ }
30
45
 
31
46
  // src/line-chart.ts
32
47
  function NanoLineChart(containerId, config) {
@@ -35,7 +50,8 @@ function NanoLineChart(containerId, config) {
35
50
  var xLabel = config.xLabel || "";
36
51
  var yLabel = config.yLabel || "";
37
52
  var colors = config.colors || ["#215CAF", "#007894", "#00C9A7", "#DE4437", "#F69C3D"];
38
- var padding = { top: 20, right: 30, bottom: 50, left: 60 };
53
+ var dp = config.padding || {};
54
+ var padding = { top: dp.top || 0, right: dp.right || 0, bottom: dp.bottom || 0, left: dp.left || 0 };
39
55
  var smooth = config.smooth === true;
40
56
  var areaFill = config.areaFill === true;
41
57
  var areaOpacity = config.areaOpacity !== void 0 ? config.areaOpacity : 0.1;
@@ -128,6 +144,11 @@ function NanoLineChart(containerId, config) {
128
144
  labelMarkup += "</div>";
129
145
  container.style.cssText = "position:relative;width:" + chartWidth + "px;height:" + chartHeight + "px";
130
146
  container.innerHTML = svgMarkup + labelMarkup;
147
+ if (!config.width) {
148
+ observeResize(container, function() {
149
+ NanoLineChart(containerId, config);
150
+ });
151
+ }
131
152
  if (!hoverEnabled) return;
132
153
  var svg = container.firstChild;
133
154
  var indicator = null;
@@ -200,7 +221,8 @@ function NanoBarChart(containerId, config) {
200
221
  var gridDashed = config.gridDashed === true;
201
222
  var hoverEnabled = config.hover !== false;
202
223
  var barGap = config.barGap !== void 0 ? config.barGap : 0.2;
203
- var padding = { top: 20, right: 30, bottom: 50, left: horizontal ? 80 : 60 };
224
+ var dp = config.padding || {};
225
+ var padding = { top: dp.top || 0, right: dp.right || 0, bottom: dp.bottom || 0, left: dp.left || 0 };
204
226
  var container = document.getElementById(containerId);
205
227
  if (!container || !data.length || !data[0].length) return;
206
228
  var chartWidth = config.width || container.clientWidth || 600;
@@ -371,6 +393,11 @@ function NanoBarChart(containerId, config) {
371
393
  labelMarkup += "</div>";
372
394
  container.style.cssText = "position:relative;width:" + chartWidth + "px;height:" + chartHeight + "px";
373
395
  container.innerHTML = svgMarkup + labelMarkup;
396
+ if (!config.width) {
397
+ observeResize(container, function() {
398
+ NanoBarChart(containerId, config);
399
+ });
400
+ }
374
401
  if (!hoverEnabled) return;
375
402
  var svgEl = container.firstChild;
376
403
  var highlight = null;
@@ -518,6 +545,11 @@ function NanoPieChart(containerId, config) {
518
545
  labelMarkup += "</div>";
519
546
  container.style.cssText = "position:relative;width:" + chartWidth + "px;height:" + chartHeight + "px";
520
547
  container.innerHTML = svgMarkup + labelMarkup;
548
+ if (!config.width) {
549
+ observeResize(container, function() {
550
+ NanoPieChart(containerId, config);
551
+ });
552
+ }
521
553
  if (!hoverEnabled) return;
522
554
  var svgEl = container.firstChild;
523
555
  var highlight = null;