@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 +2 -2
- package/dist/index.cjs +34 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +34 -2
- package/dist/index.js.map +1 -1
- package/dist/index.min.cjs +1 -1
- package/dist/index.min.cjs.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/nanocharts.global.js +34 -2
- package/dist/nanocharts.global.js.map +1 -1
- package/dist/nanocharts.min.global.js +1 -1
- package/dist/nanocharts.min.global.js.map +1 -1
- package/dist/style.css +22 -0
- package/dist/style.min.css +1 -1
- package/package.json +1 -1
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.
|
|
31
|
-
<script src="https://cdn.jsdelivr.net/npm/@anvme/nanocharts@1.0.
|
|
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
|
|
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
|
|
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;
|
package/dist/index.cjs.map
CHANGED
|
@@ -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":"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","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
|
|
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
|
|
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;
|