web-mojo 2.4.2 → 2.4.4
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/CHANGELOG.md +74 -0
- package/dist/admin-models.cjs.js +1 -1
- package/dist/admin-models.cjs.js.map +1 -1
- package/dist/admin-models.es.js +1 -1
- package/dist/admin-models.es.js.map +1 -1
- package/dist/admin.cjs.js +1 -1
- package/dist/admin.es.js +1 -1
- package/dist/auth.cjs.js +1 -1
- package/dist/auth.es.js +1 -1
- package/dist/charts.cjs.js +1 -1
- package/dist/charts.css +103 -5
- package/dist/charts.es.js +1 -1
- package/dist/chunks/{AssistantPanelView-BXCzelH4.js → AssistantPanelView-B3orPoag.js} +2 -2
- package/dist/chunks/{AssistantPanelView-BXCzelH4.js.map → AssistantPanelView-B3orPoag.js.map} +1 -1
- package/dist/chunks/{AssistantPanelView-C6NWEmh9.js → AssistantPanelView-GeIHDvyN.js} +2 -2
- package/dist/chunks/{AssistantPanelView-C6NWEmh9.js.map → AssistantPanelView-GeIHDvyN.js.map} +1 -1
- package/dist/chunks/admin-FvzwR-f7.js +2 -0
- package/dist/chunks/admin-FvzwR-f7.js.map +1 -0
- package/dist/chunks/admin-yjCkhxvU.js +2 -0
- package/dist/chunks/admin-yjCkhxvU.js.map +1 -0
- package/dist/chunks/exportChart-CmfLeCi8.js +2 -0
- package/dist/chunks/exportChart-CmfLeCi8.js.map +1 -0
- package/dist/chunks/exportChart-Ue-zU0_c.js +2 -0
- package/dist/chunks/exportChart-Ue-zU0_c.js.map +1 -0
- package/dist/chunks/{version-zXMtMDDM.js → version-CpR8sTVV.js} +2 -2
- package/dist/chunks/{version-zXMtMDDM.js.map → version-CpR8sTVV.js.map} +1 -1
- package/dist/chunks/{version-CKDlDMOh.js → version-CsLH6aiB.js} +2 -2
- package/dist/chunks/{version-CKDlDMOh.js.map → version-CsLH6aiB.js.map} +1 -1
- package/dist/css/web-mojo.css +1 -1
- package/dist/docit.cjs.js +1 -1
- package/dist/docit.es.js +1 -1
- package/dist/index.cjs.js +1 -1
- package/dist/index.es.js +1 -1
- package/dist/lightbox.cjs.js +1 -1
- package/dist/lightbox.es.js +1 -1
- package/package.json +1 -1
- package/dist/chunks/admin-C6ij_cgY.js +0 -2
- package/dist/chunks/admin-C6ij_cgY.js.map +0 -1
- package/dist/chunks/admin-XYw72vIH.js +0 -2
- package/dist/chunks/admin-XYw72vIH.js.map +0 -1
- package/dist/chunks/exportChart-DPLrRNXy.js +0 -2
- package/dist/chunks/exportChart-DPLrRNXy.js.map +0 -1
- package/dist/chunks/exportChart-DyBUhg6g.js +0 -2
- package/dist/chunks/exportChart-DyBUhg6g.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"exportChart-DPLrRNXy.js","sources":["../../src/extensions/charts/SeriesChart.js","../../src/extensions/charts/PieChart.js","../../src/extensions/charts/MetricsChart.js","../../src/extensions/charts/MiniChart.js","../../src/extensions/charts/MetricsMiniChart.js","../../src/extensions/charts/MetricsMiniChartWidget.js","../../src/extensions/charts/exportChart.js"],"sourcesContent":["/**\n * SeriesChart — native SVG multi-dataset line/bar/area chart.\n *\n * Replaces the prior Chart.js-backed SeriesChart and the interim\n * MiniSeriesChart. No runtime Chart.js dependency.\n *\n * Highlights:\n * - Multiple datasets on a shared X axis (line, bar, area).\n * - Bar charts default to STACKED — pass `stacked: false` (or `grouped: true`)\n * to opt out. `stacked: 'auto'` (default) → bar stacks, line/area don't.\n * - Built-in palette + golden-angle HSL fallback. Per-series `color`\n * and per-chart `colors` / `colorGenerator` always win.\n * - Click-to-toggle legend, hover-isolated highlighting, animated `setData`.\n * - Accepts three data shapes:\n * 1. { labels, datasets: [{ label, data, color?, fill?, smoothing? }] }\n * 2. { labels, series: [{ name, data, color?, fill?, smoothing? }] }\n * 3. [v0, v1, v2, ...] (single-series shorthand)\n */\n\nimport View from '@core/View.js';\nimport dataFormatter from '@core/utils/DataFormatter.js';\n\nconst SERIES_COLORS = [\n '#36A2EB', '#FF6384', '#FFCE56', '#4BC0C0', '#9966FF',\n '#FF9F40', '#66BB6A', '#EF5350', '#AB47BC', '#26C6DA'\n];\n\n// Golden angle in degrees, gives visually distinct hues for any N.\nconst GOLDEN_ANGLE = 137.508;\n\nconst defaultColorGenerator = (i) =>\n `hsl(${((i * GOLDEN_ANGLE) % 360).toFixed(0)}, 65%, 52%)`;\n\nclass SeriesChart extends View {\n constructor(options = {}) {\n super({\n className: 'mini-series-chart',\n ...options\n });\n\n // Chart type\n this.chartType = options.chartType || 'line';\n\n // Stacking — 'auto' resolves to true for bar, false otherwise.\n // grouped:true is documented alias for stacked:false on bar charts.\n if (options.grouped === true) {\n this.stacked = false;\n } else if (options.stacked === undefined) {\n this.stacked = 'auto';\n } else {\n this.stacked = options.stacked;\n }\n\n // Dimensions\n this.width = options.width || '100%';\n this.height = options.height || 200;\n\n // Axis label visibility — gridlines (showGrid) stay independent.\n // padBottom/padLeft shrink to a small breathing margin when the\n // corresponding label set is hidden so the plot reclaims the space.\n this.showXLabels = options.showXLabels !== false;\n this.showYLabels = options.showYLabels !== false;\n\n this.padTop = 10;\n this.padRight = 12;\n this.padBottom = this.showXLabels ? 24 : 8;\n this.padLeft = this.showYLabels ? 40 : 8;\n // Per-paint override (set by _buildGeometry when X-labels need extra\n // room for rotation). Resets every paint; null falls back to padBottom.\n this._padBottomOverride = null;\n\n // Line / area\n this.strokeWidth = options.strokeWidth || 2;\n this.smoothing = options.smoothing ?? 0.3;\n this.showDots = options.showDots !== false;\n this.dotRadius = options.dotRadius || 3;\n this.fill = options.fill ?? (this.chartType === 'area');\n\n // Bar\n this.barGap = options.barGap ?? 2;\n this.groupGap = options.groupGap ?? 6;\n\n // Grid\n this.showGrid = options.showGrid !== false;\n this.gridLines = options.gridLines || 5;\n\n // Legend\n this.showLegend = options.showLegend !== false;\n this.legendPosition = options.legendPosition || 'top';\n this.legendJustify = this._normalizeLegendJustify(options.legendJustify);\n\n // Tooltip\n this.showTooltip = options.showTooltip !== false;\n\n // Hover-highlight: dim all other series when the cursor enters a\n // bar or dot so the active series pops. Off by default — pass\n // `highlightOnHover: true` to re-enable. Was on by default in\n // earlier releases; consumers found the dim flicker distracting on\n // stacked-bar charts in particular.\n this.highlightOnHover = options.highlightOnHover === true;\n\n // Colors\n this.colors = Array.isArray(options.colors) && options.colors.length\n ? [...options.colors]\n : [...SERIES_COLORS];\n this.colorGenerator = options.colorGenerator || defaultColorGenerator;\n\n // Formatting\n this.valueFormatter = options.valueFormatter || null;\n this.xLabelFormat = options.xLabelFormat || null;\n this.xLabelFormatter = options.xLabelFormatter || null;\n this.dataFormatter = dataFormatter;\n\n // Animation\n this.animate = options.animate !== false;\n this.animationDuration = options.animationDuration || 300;\n\n // Crosshair tracking (Chart.js-style \"mode: index\" tooltip on line/area)\n // Off by default. When on AND chartType !== 'bar', a transparent rect\n // overlays the plot area; mousemove snaps to the nearest column and\n // shows a crosshair + per-dataset ghost dot + multi-row tooltip.\n this.crosshairTracking = options.crosshairTracking === true;\n // null → use the CSS default (Bootstrap-aware via currentColor).\n // A non-null value sets `stroke` directly on the line element.\n this.crosshairColor = options.crosshairColor || null;\n this.crosshairWidth = options.crosshairWidth || 1;\n\n // Data\n this._rawData = options.data || null;\n this._labels = [];\n this._datasets = [];\n this._hidden = new Set(); // indices of hidden datasets\n\n // Render bookkeeping\n this._tweenId = 0;\n this._currentGeometry = null; // last rendered geometry, used as tween source\n\n // Crosshair-tracking DOM cache (rebuilt on each paint).\n this._crosshairLayer = null;\n this._crosshairLine = null;\n this._ghostDots = null;\n this._hitRect = null;\n }\n\n // ── template ──────────────────────────────────────────────────────\n\n getTemplate() {\n const widthStyle = typeof this.width === 'number' ? `${this.width}px` : this.width;\n const heightStyle = typeof this.height === 'number' ? `${this.height}px` : this.height;\n\n return `\n <div class=\"mini-series-wrapper mini-series-legend-${this.legendPosition} mini-series-legend-justify-${this.legendJustify}\">\n ${this.showLegend ? '<div class=\"mini-series-legend\"></div>' : ''}\n <div class=\"mini-series-svg-area\" style=\"width:${widthStyle}; height:${heightStyle};\">\n <svg class=\"mini-series-svg\" width=\"100%\" height=\"100%\"\n preserveAspectRatio=\"none\" style=\"display:block;\">\n </svg>\n ${this.showTooltip ? '<div class=\"mini-series-tooltip\" style=\"display:none;\"></div>' : ''}\n </div>\n </div>\n `;\n }\n\n // ── lifecycle ─────────────────────────────────────────────────────\n\n async onAfterRender() {\n this.svg = this.element.querySelector('.mini-series-svg');\n this.tooltipEl = this.element.querySelector('.mini-series-tooltip');\n this.legendEl = this.element.querySelector('.mini-series-legend');\n\n this._updateDimensions();\n this._setupResizeObserver();\n\n if (this._rawData) {\n this._parseData(this._rawData);\n this._renderChart({ animate: false });\n this._renderLegend();\n }\n }\n\n async onBeforeDestroy() {\n if (this._resizeObserver) {\n this._resizeObserver.disconnect();\n this._resizeObserver = null;\n }\n this._tweenId++;\n await super.onBeforeDestroy();\n }\n\n // ── public API ────────────────────────────────────────────────────\n\n setData(data, options = {}) {\n this._rawData = data;\n this._parseData(data);\n if (this.svg) {\n const animate = options.animate ?? this.animate;\n this._renderChart({ animate });\n this._renderLegend();\n }\n }\n\n setChartType(newType) {\n if (newType === this.chartType) return;\n this.chartType = newType;\n if (this.fill === undefined) this.fill = (newType === 'area');\n if (this.svg) {\n this._renderChart({ animate: false });\n this._renderLegend();\n }\n }\n\n toggleSeries(index) {\n if (this._hidden.has(index)) this._hidden.delete(index);\n else this._hidden.add(index);\n if (this.svg) {\n this._renderChart({ animate: this.animate });\n this._renderLegend();\n }\n this.emit?.('chart:series-toggled', {\n chart: this, index, hidden: this._hidden.has(index)\n });\n }\n\n // ── dimensions ────────────────────────────────────────────────────\n\n _updateDimensions() {\n if (!this.svg) return;\n const rect = this.svg.getBoundingClientRect();\n this._w = rect.width || 300;\n this._h = rect.height || (typeof this.height === 'number' ? this.height : 200);\n this.svg.setAttribute('viewBox', `0 0 ${this._w} ${this._h}`);\n }\n\n _setupResizeObserver() {\n if (typeof ResizeObserver === 'undefined') return;\n this._resizeObserver = new ResizeObserver(() => {\n this._updateDimensions();\n if (this._datasets.length > 0) this._renderChart({ animate: false });\n });\n if (this.svg) this._resizeObserver.observe(this.svg);\n }\n\n // ── data normalisation ────────────────────────────────────────────\n\n _parseData(data) {\n if (!data) { this._labels = []; this._datasets = []; return; }\n\n let labels = [];\n let datasets = [];\n\n if (Array.isArray(data)) {\n // [v0, v1, ...] single-series shorthand\n labels = data.map((_, i) => String(i + 1));\n datasets = [{ label: 'Series 1', data: [...data] }];\n } else if (data.labels && data.datasets) {\n labels = data.labels;\n datasets = data.datasets.map((ds, i) => ({\n label: ds.label || `Series ${i + 1}`,\n data: ds.data || [],\n color: ds.color || ds.borderColor,\n fill: ds.fill,\n smoothing: ds.smoothing,\n fillColor: ds.backgroundColor || ds.fillColor\n }));\n } else if (data.labels && data.series) {\n labels = data.labels;\n datasets = data.series.map((s, i) => ({\n label: s.name || s.label || `Series ${i + 1}`,\n data: s.data || [],\n color: s.color || s.borderColor,\n fill: s.fill,\n smoothing: s.smoothing,\n fillColor: s.backgroundColor || s.fillColor\n }));\n }\n\n // Resolve color and fill once, here.\n this._labels = labels;\n this._datasets = datasets.map((ds, i) => {\n const color = ds.color || this.colors[i] || this.colorGenerator(i);\n const fill = ds.fill ?? (this.chartType === 'area' ? true : (this.chartType === 'bar' ? true : this.fill));\n const fillColor = ds.fillColor || this._toRgba(color, this.chartType === 'bar' ? 0.85 : 0.18);\n return {\n label: ds.label,\n data: ds.data,\n color,\n fillColor,\n fill,\n smoothing: ds.smoothing ?? this.smoothing\n };\n });\n\n // Trim hidden indices that no longer exist.\n if (this._hidden.size) {\n this._hidden = new Set([...this._hidden].filter(i => i < this._datasets.length));\n }\n }\n\n _isStacked() {\n if (this.stacked === 'auto') return this.chartType === 'bar';\n return !!this.stacked;\n }\n\n _visibleDatasets() {\n return this._datasets\n .map((ds, i) => ({ ds, i }))\n .filter(({ i }) => !this._hidden.has(i));\n }\n\n // ── chart area helpers ────────────────────────────────────────────\n\n get _plotLeft() { return this.padLeft; }\n get _plotTop() { return this.padTop; }\n get _plotRight() { return this._w - this.padRight; }\n get _plotBottom() { return this._h - (this._padBottomOverride ?? this.padBottom); }\n get _plotW() { return this._plotRight - this._plotLeft; }\n get _plotH() { return this._plotBottom - this._plotTop; }\n\n _calcBounds() {\n let min = Infinity, max = -Infinity;\n const visible = this._visibleDatasets();\n\n if (this._isStacked() && this.chartType === 'bar') {\n const count = this._labels.length || (visible[0]?.ds.data.length || 0);\n for (let i = 0; i < count; i++) {\n let pos = 0, neg = 0;\n for (const { ds } of visible) {\n const v = +ds.data[i] || 0;\n if (v >= 0) pos += v; else neg += v;\n }\n if (pos > max) max = pos;\n if (neg < min) min = neg;\n }\n if (!isFinite(min)) min = 0;\n if (!isFinite(max)) max = 1;\n } else {\n for (const { ds } of visible) {\n for (const v of ds.data) {\n if (v < min) min = v;\n if (v > max) max = v;\n }\n }\n }\n\n if (!isFinite(min)) { min = 0; max = 1; }\n if (min === max) { min -= 1; max += 1; }\n const range = max - min;\n max += range * 0.05;\n if (min > 0) min = Math.max(0, min - range * 0.05);\n return { min, max };\n }\n\n _yToPixel(value, min, max) {\n return this._plotBottom - ((value - min) / (max - min)) * this._plotH;\n }\n\n _xToPixel(index, count) {\n if (count <= 1) return this._plotLeft + this._plotW / 2;\n return this._plotLeft + (index / (count - 1)) * this._plotW;\n }\n\n // ── render ────────────────────────────────────────────────────────\n\n _renderChart({ animate = false } = {}) {\n if (!this.svg) return;\n this._updateDimensions();\n\n // Cancel any in-flight tween.\n this._tweenId++;\n const tweenId = this._tweenId;\n\n // Hide the crosshair before rebuilding so it doesn't paint at a stale\n // column while the next geometry is being computed.\n if (this.crosshairTracking) this._clearCrosshair();\n\n if (this._datasets.length === 0) {\n this.svg.innerHTML = '';\n this._currentGeometry = null;\n return;\n }\n\n const { min, max } = this._calcBounds();\n const count = this._labels.length || (this._datasets[0]?.data.length || 0);\n\n const targetGeometry = this._buildGeometry(min, max, count);\n\n const previous = this._currentGeometry;\n const canTween = animate && previous\n && previous.chartType === targetGeometry.chartType\n && this.animationDuration > 0\n && typeof requestAnimationFrame !== 'undefined';\n\n if (!canTween) {\n this._paintFrame(targetGeometry);\n this._currentGeometry = targetGeometry;\n return;\n }\n\n // Tween from previous geometry → target geometry.\n const start = performance.now();\n const duration = this.animationDuration;\n const ease = (t) => 1 - Math.pow(1 - t, 3); // easeOutCubic\n\n const step = (now) => {\n if (this._tweenId !== tweenId) return; // cancelled\n const t = Math.min(1, (now - start) / duration);\n const k = ease(t);\n const interp = this._interpolateGeometry(previous, targetGeometry, k);\n this._paintFrame(interp);\n if (t < 1) requestAnimationFrame(step);\n else this._currentGeometry = targetGeometry;\n };\n requestAnimationFrame(step);\n }\n\n _buildGeometry(min, max, count) {\n // Reset per-paint pad override; pre-flight may bump it for rotation.\n this._padBottomOverride = null;\n\n // Snap (min, max) to \"nice\" tick boundaries so Y labels read as\n // 0/25/50/75/100 instead of 0/28.77/57.54/...\n const ticks = this._niceTicks(min, max, this.gridLines);\n min = ticks.niceMin;\n max = ticks.niceMax;\n const tickStep = ticks.step;\n const tickCount = ticks.count;\n\n // Pre-flight: format X labels and decide whether they need rotation.\n // Slot width depends on chart type; line/area labels sit AT data\n // points so the slot is between them. Skipped entirely when X labels\n // are hidden — _padBottomOverride stays null and padBottom (already\n // shrunk to 8 in the constructor) reclaims the space.\n const formattedX = [];\n let xLabelsRotated = false;\n if (this.showXLabels) {\n const maxXLabels = Math.max(2, Math.floor(this._plotW / 60));\n const stepX = Math.max(1, Math.ceil(count / maxXLabels));\n for (let i = 0; i < count; i += stepX) {\n const raw = this._labels[i] !== undefined ? this._labels[i] : '';\n formattedX.push({ index: i, text: this._truncateLabel(this._formatXLabel(raw)) });\n }\n const slotW = (this.chartType === 'bar')\n ? this._plotW / Math.max(1, count)\n : this._plotW / Math.max(1, count - 1);\n const widest = formattedX.reduce((m, l) => Math.max(m, l.text.length * 6.5), 0);\n xLabelsRotated = widest > slotW * 0.9;\n if (xLabelsRotated) this._padBottomOverride = 48;\n }\n\n // baseline / plot dims now reflect the (possibly bumped) padBottom.\n const baseline = this._yToPixel(Math.max(min, Math.min(0, max)), min, max);\n const visible = this._visibleDatasets();\n\n const geom = {\n chartType: this.chartType,\n min, max, count, baseline,\n xLabelsRotated,\n grid: [],\n yLabels: [],\n xLabels: [],\n lines: [],\n bars: []\n };\n\n // Grid + Y-axis labels — anchored to nice tick values. Grid lines\n // always populate (gated separately by showGrid in _paintFrame);\n // Y-label generation skips when showYLabels is false.\n for (let i = 0; i < tickCount; i++) {\n const value = min + i * tickStep;\n const y = this._yToPixel(value, min, max);\n geom.grid.push({ x1: this._plotLeft, y1: y, x2: this._plotRight, y2: y });\n if (this.showYLabels) {\n geom.yLabels.push({\n x: this._plotLeft - 4,\n y: y + 3,\n text: this._formatAxisValue(value, tickStep)\n });\n }\n }\n\n // X-axis labels. formattedX is empty when showXLabels is false, so\n // this loop is a no-op in that case.\n for (const { index, text } of formattedX) {\n const x = (this.chartType === 'bar')\n ? this._barSlotCenter(index, count)\n : this._xToPixel(index, count);\n geom.xLabels.push({ x, y: this._plotBottom + 14, text });\n }\n\n if (this.chartType === 'bar') {\n this._buildBars(geom, visible, min, max, count);\n } else {\n this._buildLines(geom, visible, min, max, count);\n }\n\n return geom;\n }\n\n _barSlotCenter(i, count) {\n if (count <= 0) return this._plotLeft;\n const slotW = this._plotW / count;\n return this._plotLeft + i * slotW + slotW / 2;\n }\n\n _buildBars(geom, visible, min, max, count) {\n const stacked = this._isStacked();\n const slotW = this._plotW / Math.max(count, 1);\n const groupW = Math.max(2, slotW - this.groupGap);\n\n if (stacked) {\n const barW = groupW;\n for (let i = 0; i < count; i++) {\n let posCum = 0, negCum = 0;\n for (const { ds, i: dsIdx } of visible) {\n const v = +ds.data[i] || 0;\n if (v === 0) continue;\n let yTop, yBottom;\n if (v >= 0) {\n yTop = this._yToPixel(posCum + v, min, max);\n yBottom = this._yToPixel(posCum, min, max);\n posCum += v;\n } else {\n yTop = this._yToPixel(negCum, min, max);\n yBottom = this._yToPixel(negCum + v, min, max);\n negCum += v;\n }\n const x = this._plotLeft + i * slotW + (slotW - barW) / 2;\n geom.bars.push({\n x, y: Math.min(yTop, yBottom),\n w: barW,\n h: Math.max(0.5, Math.abs(yBottom - yTop)),\n color: ds.color, fillColor: ds.fillColor,\n dsIdx, dataIdx: i, value: v, label: this._labels[i]\n });\n }\n }\n } else {\n const numSeries = visible.length || 1;\n const barW = Math.max(1, (groupW - (numSeries - 1) * this.barGap) / numSeries);\n for (let s = 0; s < numSeries; s++) {\n const { ds, i: dsIdx } = visible[s];\n for (let i = 0; i < count; i++) {\n const v = +ds.data[i] || 0;\n const slotX = this._plotLeft + i * slotW + (slotW - groupW) / 2;\n const x = slotX + s * (barW + this.barGap);\n const y = this._yToPixel(v, min, max);\n const h = Math.abs(geom.baseline - y);\n geom.bars.push({\n x, y: Math.min(y, geom.baseline),\n w: barW, h: Math.max(h, 0.5),\n color: ds.color, fillColor: ds.fillColor,\n dsIdx, dataIdx: i, value: v, label: this._labels[i]\n });\n }\n }\n }\n }\n\n _buildLines(geom, visible, min, max, count) {\n for (const { ds, i: dsIdx } of visible) {\n const points = ds.data.map((v, i) => ({\n x: this._xToPixel(i, count),\n y: this._yToPixel(+v || 0, min, max),\n value: +v || 0,\n index: i,\n label: this._labels[i]\n }));\n geom.lines.push({\n dsIdx,\n color: ds.color,\n fillColor: ds.fillColor,\n fill: ds.fill,\n smoothing: ds.smoothing ?? this.smoothing,\n points\n });\n }\n }\n\n _paintFrame(geom) {\n if (!this.svg) return;\n this.svg.innerHTML = '';\n\n // Grid\n if (this.showGrid) {\n for (const g of geom.grid) {\n this.svg.appendChild(this._svgEl('line', {\n x1: g.x1, y1: g.y1, x2: g.x2, y2: g.y2,\n stroke: 'var(--bs-border-color, #dee2e6)',\n 'stroke-width': 0.5,\n 'stroke-dasharray': '3,3'\n }));\n }\n }\n\n // Y-axis labels\n if (this.showYLabels) {\n for (const l of geom.yLabels) {\n const t = this._svgEl('text', {\n x: l.x, y: l.y, 'text-anchor': 'end',\n 'font-size': '10', fill: 'var(--bs-secondary-color, #6c757d)'\n });\n t.textContent = l.text;\n this.svg.appendChild(t);\n }\n }\n\n // X-axis labels — rotate -45° when they would overlap their slots.\n if (this.showXLabels) {\n for (const l of geom.xLabels) {\n const attrs = {\n x: l.x, y: l.y,\n 'font-size': '10',\n fill: 'var(--bs-secondary-color, #6c757d)'\n };\n if (geom.xLabelsRotated) {\n attrs['text-anchor'] = 'end';\n attrs.transform = `rotate(-45 ${l.x} ${l.y})`;\n } else {\n attrs['text-anchor'] = 'middle';\n }\n const t = this._svgEl('text', attrs);\n t.textContent = l.text;\n this.svg.appendChild(t);\n }\n }\n\n if (geom.chartType === 'bar') {\n this._paintBars(geom);\n } else {\n this._paintLines(geom);\n }\n\n this._attachHoverListeners();\n\n // Crosshair-tracking overlay (line/area only). Mounted last so the\n // hit-rect captures hover above all marks. Does nothing when off.\n if (this.crosshairTracking\n && geom.chartType !== 'bar'\n && geom.lines.length > 0) {\n this._setupCrosshairTracking(geom);\n } else {\n // Drop stale references in case the mode was just turned off.\n this._crosshairLayer = null;\n this._crosshairLine = null;\n this._ghostDots = null;\n this._hitRect = null;\n }\n }\n\n _paintLines(geom) {\n for (const line of geom.lines) {\n // Area fill\n if (line.fill && line.points.length > 1) {\n const path = this._buildLinePath(line.points, line.smoothing)\n + ` L ${line.points[line.points.length - 1].x},${this._plotBottom}`\n + ` L ${line.points[0].x},${this._plotBottom} Z`;\n this.svg.appendChild(this._svgEl('path', {\n d: path, fill: line.fillColor, stroke: 'none',\n class: `mini-series-area mini-series-ds-${line.dsIdx}`\n }));\n }\n // Line\n if (line.points.length > 1) {\n this.svg.appendChild(this._svgEl('path', {\n d: this._buildLinePath(line.points, line.smoothing),\n fill: 'none',\n stroke: line.color,\n 'stroke-width': this.strokeWidth,\n 'stroke-linecap': 'round',\n 'stroke-linejoin': 'round',\n class: `mini-series-line mini-series-ds-${line.dsIdx}`\n }));\n }\n // Dots\n if (this.showDots) {\n for (const p of line.points) {\n this.svg.appendChild(this._svgEl('circle', {\n cx: p.x, cy: p.y, r: this.dotRadius,\n fill: line.color,\n class: `mini-series-dot mini-series-ds-${line.dsIdx}`,\n 'data-ds': line.dsIdx,\n 'data-col': p.index\n }));\n }\n }\n }\n }\n\n _paintBars(geom) {\n for (const b of geom.bars) {\n this.svg.appendChild(this._svgEl('rect', {\n x: b.x, y: b.y, width: b.w, height: b.h,\n fill: b.fillColor || b.color,\n rx: 1,\n class: `mini-series-bar mini-series-ds-${b.dsIdx}`,\n 'data-ds': b.dsIdx,\n 'data-col': b.dataIdx\n }));\n }\n }\n\n // ── crosshair tracking (line/area only) ──────────────────────────\n\n _setupCrosshairTracking(geom) {\n // Build a single <g> containing the vertical line, one ghost dot per\n // visible dataset, and a transparent hit-rect that captures hover.\n const layer = this._svgEl('g', { class: 'mini-series-crosshair-layer' });\n\n const lineAttrs = {\n x1: 0, y1: this._plotTop, x2: 0, y2: this._plotBottom,\n 'stroke-width': this.crosshairWidth,\n class: 'mini-series-crosshair',\n style: 'display:none;'\n };\n if (this.crosshairColor) {\n lineAttrs.stroke = this.crosshairColor;\n } else {\n lineAttrs.stroke = 'currentColor';\n }\n const xLine = this._svgEl('line', lineAttrs);\n layer.appendChild(xLine);\n\n // One ghost dot per visible dataset, in the same order as geom.lines.\n const ghosts = geom.lines.map((line) => {\n const dot = this._svgEl('circle', {\n cx: 0, cy: 0, r: this.dotRadius + 1,\n fill: line.color,\n class: `mini-series-ghost mini-series-ds-${line.dsIdx}`,\n 'data-ds': line.dsIdx,\n style: 'display:none;'\n });\n layer.appendChild(dot);\n return dot;\n });\n\n // Hit-rect — last child of the layer so it's above the ghosts.\n const hit = this._svgEl('rect', {\n x: this._plotLeft, y: this._plotTop,\n width: this._plotW, height: this._plotH,\n class: 'mini-series-hit'\n });\n layer.appendChild(hit);\n\n this.svg.appendChild(layer);\n\n this._crosshairLayer = layer;\n this._crosshairLine = xLine;\n this._ghostDots = ghosts;\n this._hitRect = hit;\n\n // Listeners\n hit.addEventListener('mousemove', (event) => {\n const rect = this.svg.getBoundingClientRect();\n const cursorX = event.clientX - rect.left;\n const colIdx = this._findColumn(cursorX);\n if (colIdx < 0 || !this._currentGeometry) {\n this._clearCrosshair();\n this._hideTooltip();\n return;\n }\n this._paintCrosshair(colIdx, this._currentGeometry);\n if (this.showTooltip) this._showTooltip(colIdx, event);\n });\n hit.addEventListener('mouseleave', () => {\n this._clearCrosshair();\n this._hideTooltip();\n this._clearFade();\n });\n hit.addEventListener('click', (event) => {\n const rect = this.svg.getBoundingClientRect();\n const cursorX = event.clientX - rect.left;\n const colIdx = this._findColumn(cursorX);\n if (colIdx < 0) return;\n // Match Chart.js mode:'index' — emit the column for the first\n // visible dataset. Per-dataset clicks remain available with\n // crosshairTracking: false.\n const firstVisible = this._visibleDatasets()[0];\n if (!firstVisible) return;\n this.emit?.('chart:click', {\n chart: this,\n datasetIndex: firstVisible.i,\n index: colIdx,\n value: firstVisible.ds.data[colIdx],\n label: this._labels[colIdx]\n });\n });\n }\n\n _findColumn(cursorX) {\n const count = this._labels.length\n || (this._datasets[0]?.data.length || 0);\n if (count < 2) return -1;\n if (cursorX < this._plotLeft || cursorX > this._plotRight) return -1;\n const ratio = (cursorX - this._plotLeft) / this._plotW;\n const idx = Math.round(ratio * (count - 1));\n if (idx < 0) return 0;\n if (idx > count - 1) return count - 1;\n return idx;\n }\n\n _paintCrosshair(colIdx, geom) {\n if (!this._crosshairLine || !geom || !geom.lines.length) return;\n\n // All visible lines share the same X grid — pick from the first.\n const firstLine = geom.lines[0];\n const point = firstLine.points[colIdx];\n if (!point) return;\n\n this._crosshairLine.setAttribute('x1', point.x);\n this._crosshairLine.setAttribute('x2', point.x);\n this._crosshairLine.style.display = '';\n\n // Place each ghost dot at its line's (x, y) for this column.\n for (let k = 0; k < geom.lines.length; k++) {\n const dot = this._ghostDots && this._ghostDots[k];\n if (!dot) continue;\n const p = geom.lines[k].points[colIdx];\n if (!p) {\n dot.style.display = 'none';\n continue;\n }\n dot.setAttribute('cx', p.x);\n dot.setAttribute('cy', p.y);\n dot.style.display = '';\n }\n }\n\n _clearCrosshair() {\n if (this._crosshairLine) this._crosshairLine.style.display = 'none';\n if (this._ghostDots) {\n for (const dot of this._ghostDots) dot.style.display = 'none';\n }\n }\n\n _buildLinePath(points, smoothing) {\n if (!points || points.length === 0) return '';\n if (smoothing > 0 && points.length >= 2) {\n let d = `M ${points[0].x},${points[0].y}`;\n for (let i = 0; i < points.length - 1; i++) {\n const cur = points[i], nxt = points[i + 1];\n const cp1x = cur.x + (nxt.x - cur.x) * smoothing;\n const cp2x = nxt.x - (nxt.x - cur.x) * smoothing;\n d += ` C ${cp1x},${cur.y} ${cp2x},${nxt.y} ${nxt.x},${nxt.y}`;\n }\n return d;\n }\n return points.map((p, i) => `${i === 0 ? 'M' : 'L'} ${p.x},${p.y}`).join(' ');\n }\n\n // ── tween helpers ─────────────────────────────────────────────────\n\n _interpolateGeometry(a, b, k) {\n // Use shape of `b` (target) as the canonical structure; tween numeric\n // fields from the matching entry in `a` where one exists.\n const lerp = (x, y) => x + (y - x) * k;\n const out = {\n chartType: b.chartType,\n min: b.min, max: b.max, count: b.count, baseline: b.baseline,\n grid: b.grid,\n yLabels: b.yLabels,\n xLabels: b.xLabels,\n lines: [],\n bars: []\n };\n\n if (b.chartType === 'bar') {\n out.bars = b.bars.map((tb) => {\n const sb = a.bars.find(s => s.dsIdx === tb.dsIdx && s.dataIdx === tb.dataIdx);\n if (!sb) {\n // Animate in from baseline.\n return { ...tb, y: lerp(a.baseline, tb.y), h: lerp(0, tb.h) };\n }\n return {\n ...tb,\n x: lerp(sb.x, tb.x),\n y: lerp(sb.y, tb.y),\n w: lerp(sb.w, tb.w),\n h: lerp(sb.h, tb.h)\n };\n });\n } else {\n out.lines = b.lines.map((tl) => {\n const sl = a.lines.find(s => s.dsIdx === tl.dsIdx);\n const points = tl.points.map((tp, i) => {\n const sp = sl && sl.points[i];\n if (!sp) return { ...tp, y: lerp(a.baseline, tp.y) };\n return { ...tp, x: lerp(sp.x, tp.x), y: lerp(sp.y, tp.y) };\n });\n return { ...tl, points };\n });\n }\n return out;\n }\n\n // ── tooltip / hover ───────────────────────────────────────────────\n\n _attachHoverListeners() {\n if (!this.svg) return;\n\n const els = this.svg.querySelectorAll('.mini-series-bar, .mini-series-dot');\n els.forEach(el => {\n const col = parseInt(el.getAttribute('data-col'), 10);\n const dsIdx = parseInt(el.getAttribute('data-ds'), 10);\n if (isNaN(col) || isNaN(dsIdx)) return;\n\n el.addEventListener('mouseenter', (e) => {\n if (this.showTooltip) this._showTooltip(col, e);\n if (this.highlightOnHover) this._fadeOtherSeries(dsIdx);\n });\n el.addEventListener('mousemove', (e) => {\n if (this.showTooltip) this._moveTooltip(e);\n });\n el.addEventListener('mouseleave', () => {\n this._hideTooltip();\n if (this.highlightOnHover) this._clearFade();\n });\n el.addEventListener('click', () => {\n const value = this._datasets[dsIdx]?.data[col];\n this.emit?.('chart:click', {\n chart: this,\n datasetIndex: dsIdx,\n index: col,\n value,\n label: this._labels[col]\n });\n });\n });\n }\n\n _fadeOtherSeries(activeDsIdx) {\n if (!this.svg) return;\n const all = this.svg.querySelectorAll('[class*=\"mini-series-ds-\"]');\n all.forEach(el => {\n const m = el.getAttribute('class').match(/mini-series-ds-(\\d+)/);\n if (!m) return;\n const idx = parseInt(m[1], 10);\n if (idx !== activeDsIdx) el.classList.add('mini-series-faded');\n else el.classList.remove('mini-series-faded');\n });\n }\n\n _clearFade() {\n if (!this.svg) return;\n this.svg.querySelectorAll('.mini-series-faded')\n .forEach(el => el.classList.remove('mini-series-faded'));\n }\n\n _showTooltip(index, event) {\n if (!this.tooltipEl) return;\n const label = this._labels[index] !== undefined ? this._labels[index] : `#${index + 1}`;\n\n // Build via DOM nodes — colors come from API responses, so we set\n // `style.background` as a property (safe) rather than interpolating\n // into a `style=\"...\"` attribute string.\n this.tooltipEl.innerHTML = '';\n const head = document.createElement('div');\n head.className = 'mini-series-tooltip-label';\n head.textContent = String(this._formatXLabel(label));\n this.tooltipEl.appendChild(head);\n\n for (let i = 0; i < this._datasets.length; i++) {\n if (this._hidden.has(i)) continue;\n const ds = this._datasets[i];\n const v = ds.data[index];\n\n const row = document.createElement('div');\n row.className = 'mini-series-tooltip-row';\n\n const swatch = document.createElement('span');\n swatch.className = 'mini-series-tooltip-swatch';\n swatch.style.background = ds.color;\n row.appendChild(swatch);\n\n const name = document.createElement('span');\n name.textContent = `${ds.label}:`;\n row.appendChild(name);\n\n const strong = document.createElement('strong');\n strong.textContent = this._formatValue(v);\n row.appendChild(strong);\n\n this.tooltipEl.appendChild(row);\n }\n\n this.tooltipEl.style.display = 'block';\n this._moveTooltip(event);\n }\n\n _moveTooltip(event) {\n if (!this.tooltipEl || this.tooltipEl.style.display === 'none') return;\n const area = this.element.querySelector('.mini-series-svg-area');\n if (!area) return;\n const areaRect = area.getBoundingClientRect();\n const x = event.clientX - areaRect.left;\n const y = event.clientY - areaRect.top;\n\n this.tooltipEl.style.left = '0px';\n this.tooltipEl.style.top = '0px';\n this.tooltipEl.style.transform = 'none';\n const tw = this.tooltipEl.offsetWidth;\n const th = this.tooltipEl.offsetHeight;\n const aw = areaRect.width;\n const ah = areaRect.height;\n\n let left = x - tw / 2;\n let top = y - th - 8;\n if (left < 0) left = 0;\n if (left + tw > aw) left = aw - tw;\n if (top < 0) top = y + 12;\n if (top + th > ah) top = ah - th;\n\n this.tooltipEl.style.left = `${left}px`;\n this.tooltipEl.style.top = `${top}px`;\n }\n\n _hideTooltip() {\n if (this.tooltipEl) this.tooltipEl.style.display = 'none';\n }\n\n // ── legend ────────────────────────────────────────────────────────\n\n _normalizeLegendJustify(value) {\n if (value === undefined) return 'start';\n if (value === 'start' || value === 'center' || value === 'end') return value;\n console.warn(`SeriesChart: invalid legendJustify \"${value}\" — expected 'start' | 'center' | 'end'. Falling back to 'start'.`);\n return 'start';\n }\n\n _renderLegend() {\n if (!this.showLegend || !this.legendEl) return;\n this.legendEl.innerHTML = '';\n\n this._datasets.forEach((ds, i) => {\n const item = document.createElement('span');\n item.className = 'mini-series-legend-item';\n if (this._hidden.has(i)) item.classList.add('mini-series-legend-hidden');\n item.setAttribute('role', 'button');\n item.setAttribute('data-ds', String(i));\n\n const swatch = document.createElement('span');\n swatch.className = 'mini-series-legend-swatch';\n swatch.style.background = ds.color;\n item.appendChild(swatch);\n\n const labelEl = document.createElement('span');\n labelEl.className = 'mini-series-legend-label';\n labelEl.textContent = ds.label;\n item.appendChild(labelEl);\n\n item.addEventListener('click', () => this.toggleSeries(i));\n this.legendEl.appendChild(item);\n });\n }\n\n // ── formatters ────────────────────────────────────────────────────\n\n _formatValue(value) {\n if (value === null || value === undefined) return '';\n if (this.valueFormatter) {\n if (typeof this.valueFormatter === 'function') return this.valueFormatter(value);\n return this.dataFormatter.pipe(value, this.valueFormatter);\n }\n if (typeof value === 'number') return value.toLocaleString();\n return String(value);\n }\n\n _formatXLabel(label) {\n if (label === null || label === undefined) return '';\n if (this.xLabelFormatter) return this.xLabelFormatter(label);\n if (this.xLabelFormat) return this.dataFormatter.pipe(label, this.xLabelFormat);\n return String(label);\n }\n\n // ── nice-number axis tick helpers ─────────────────────────────────\n // Heckbert \"Nice Numbers for Graph Labels\" (Graphics Gems, 1990).\n // Snaps a range to the nearest 1/2/5 × 10ⁿ value so axis labels read\n // as 0/25/50/75/100 instead of 0/28.77/57.54/...\n\n _niceNumber(range, round) {\n if (!isFinite(range) || range <= 0) return 1;\n const exponent = Math.floor(Math.log10(range));\n const fraction = range / Math.pow(10, exponent);\n let nice;\n if (round) {\n if (fraction < 1.5) nice = 1;\n else if (fraction < 3) nice = 2;\n else if (fraction < 7) nice = 5;\n else nice = 10;\n } else {\n if (fraction <= 1) nice = 1;\n else if (fraction <= 2) nice = 2;\n else if (fraction <= 5) nice = 5;\n else nice = 10;\n }\n return nice * Math.pow(10, exponent);\n }\n\n _niceTicks(min, max, target) {\n if (min === max) { min -= 1; max += 1; }\n const range = this._niceNumber(max - min, false);\n const step = this._niceNumber(range / Math.max(1, target - 1), true);\n const niceMin = Math.floor(min / step) * step;\n const niceMax = Math.ceil(max / step) * step;\n const count = Math.round((niceMax - niceMin) / step) + 1;\n return { niceMin, niceMax, step, count };\n }\n\n _formatAxisValue(value, step) {\n if (this.valueFormatter) {\n if (typeof this.valueFormatter === 'function') return this.valueFormatter(value);\n return this.dataFormatter.pipe(value, this.valueFormatter);\n }\n if (Math.abs(value) >= 1_000_000_000) return (value / 1_000_000_000).toFixed(1) + 'B';\n if (Math.abs(value) >= 1_000_000) return (value / 1_000_000).toFixed(1) + 'M';\n if (Math.abs(value) >= 1_000) return (value / 1_000).toFixed(1) + 'K';\n if (Number.isInteger(value)) return String(value);\n // Pick decimal precision from the tick step so a step of 0.001 doesn't\n // collapse to \"0.0\". Caller passes step for nice-tick contexts.\n const decimals = step && step > 0 && step < 1\n ? Math.max(0, -Math.floor(Math.log10(step)))\n : 1;\n return value.toFixed(decimals);\n }\n\n // Rotated labels need more headroom; truncation is a fallback for the\n // pathological case (UUIDs, multi-field labels).\n _truncateLabel(text) {\n const s = String(text);\n return s.length > 24 ? s.substring(0, 23) + '…' : s;\n }\n\n // ── color helpers ─────────────────────────────────────────────────\n\n _toRgba(color, alpha) {\n if (!color) return color;\n const s = String(color).trim();\n\n if (s.startsWith('#')) {\n let hex = s.slice(1);\n if (hex.length === 3) hex = hex.split('').map(c => c + c).join('');\n if (hex.length === 6) {\n const r = parseInt(hex.slice(0, 2), 16);\n const g = parseInt(hex.slice(2, 4), 16);\n const b = parseInt(hex.slice(4, 6), 16);\n return `rgba(${r},${g},${b},${alpha})`;\n }\n return s;\n }\n\n let m = s.match(/^rgba?\\(([^)]+)\\)$/i);\n if (m) {\n const parts = m[1].split(',').map(p => p.trim());\n return `rgba(${parts[0]},${parts[1]},${parts[2]},${alpha})`;\n }\n\n m = s.match(/^hsla?\\(([^)]+)\\)$/i);\n if (m) {\n const parts = m[1].split(',').map(p => p.trim());\n return `hsla(${parts[0]},${parts[1]},${parts[2]},${alpha})`;\n }\n\n // Named or unknown — return as-is. Fill won't get alpha; documented.\n return s;\n }\n\n // ── DOM helpers ───────────────────────────────────────────────────\n\n _svgEl(tag, attrs = {}) {\n const el = document.createElementNS('http://www.w3.org/2000/svg', tag);\n for (const [k, v] of Object.entries(attrs)) {\n el.setAttribute(k, String(v));\n }\n return el;\n }\n\n _esc(text) {\n const d = document.createElement('div');\n d.textContent = text;\n return d.innerHTML;\n }\n}\n\nexport default SeriesChart;\n","/**\n * PieChart — native SVG pie / doughnut.\n *\n * Replaces the prior Chart.js-backed PieChart and the interim MiniPieChart.\n * No runtime Chart.js dependency.\n *\n * Accepts three data shapes:\n * 1. [{ label, value, color? }]\n * 2. { labels: [...], datasets: [{ data: [...] }] } (Chart.js shape)\n * 3. { A: 10, B: 20 } (object map)\n *\n * Optional `endpoint:` triggers a REST GET in onInit() and feeds the response\n * into setData — keeps simple admin call sites (no manual fetch) working.\n */\n\nimport View from '@core/View.js';\nimport dataFormatter from '@core/utils/DataFormatter.js';\n\nconst DEFAULT_COLORS = [\n '#36A2EB', '#FF6384', '#FFCE56', '#4BC0C0', '#9966FF',\n '#FF9F40', '#66BB6A', '#EF5350', '#AB47BC', '#26C6DA'\n];\n\nconst GOLDEN_ANGLE = 137.508;\nconst defaultColorGenerator = (i) =>\n `hsl(${((i * GOLDEN_ANGLE) % 360).toFixed(0)}, 65%, 52%)`;\n\nclass PieChart extends View {\n constructor(options = {}) {\n super({\n className: 'mini-pie-chart',\n ...options\n });\n\n this.width = options.width || 200;\n this.height = options.height || 200;\n\n // 0 = solid pie; 0..1 fraction of outer radius for inner hole.\n this.cutout = options.cutout || 0;\n\n // Donut center label. Static string OR a function called with\n // ({ total, segments }) returning a string. `centerSubLabel` is\n // optional smaller text below.\n // ⚠️ Trust boundary: rendered as raw <text> content via SVG; treat\n // as developer-controlled (not from user input).\n this.centerLabel = options.centerLabel ?? null;\n this.centerSubLabel = options.centerSubLabel ?? null;\n\n this.colors = Array.isArray(options.colors) && options.colors.length\n ? [...options.colors]\n : [...DEFAULT_COLORS];\n this.colorGenerator = options.colorGenerator || defaultColorGenerator;\n\n // Legend\n this.showLegend = options.showLegend !== false;\n this.legendPosition = options.legendPosition || 'right'; // 'right' | 'bottom' | 'none'\n if (this.legendPosition === 'none') this.showLegend = false;\n\n // Slice labels\n this.showLabels = options.showLabels === true;\n this.showPercentages = options.showPercentages !== false;\n\n // Tooltip\n this.showTooltip = options.showTooltip !== false;\n\n // Animation\n this.animate = options.animate !== false;\n this.animationDuration = options.animationDuration || 300;\n\n // Formatting\n this.valueFormatter = options.valueFormatter || null;\n this.dataFormatter = dataFormatter;\n\n // REST integration\n this.endpoint = options.endpoint || null;\n\n // Data\n this._rawData = options.data || null;\n this._segments = [];\n this._currentSegments = null; // last painted, for tween source\n this._tweenId = 0;\n }\n\n // ── template ──────────────────────────────────────────────────────\n\n getTemplate() {\n const layoutClass = this.legendPosition === 'bottom'\n ? 'mini-pie-layout-bottom'\n : 'mini-pie-layout-right';\n\n return `\n <div class=\"mini-pie-wrapper ${layoutClass}\">\n <div class=\"mini-pie-svg-area\" style=\"width:${this.width}px; height:${this.height}px;\">\n <svg class=\"mini-pie-svg\" viewBox=\"0 0 ${this.width} ${this.height}\"\n width=\"100%\" height=\"100%\" preserveAspectRatio=\"xMidYMid meet\">\n </svg>\n ${this.showTooltip ? '<div class=\"mini-pie-tooltip\" style=\"display:none;\"></div>' : ''}\n </div>\n ${this.showLegend ? '<div class=\"mini-pie-legend\"></div>' : ''}\n </div>\n `;\n }\n\n // ── lifecycle ─────────────────────────────────────────────────────\n\n async onInit() {\n if (this.endpoint) {\n try {\n const rest = this.getApp()?.rest;\n if (rest) {\n const resp = await rest.GET(this.endpoint);\n if (resp?.success) {\n this._rawData = resp.data?.data ?? resp.data ?? this._rawData;\n }\n }\n } catch (err) {\n console.error('PieChart endpoint fetch failed:', err);\n }\n }\n }\n\n async onAfterRender() {\n this.svg = this.element.querySelector('.mini-pie-svg');\n this.tooltipEl = this.element.querySelector('.mini-pie-tooltip');\n this.legendEl = this.element.querySelector('.mini-pie-legend');\n\n if (this._rawData) {\n this._parseData(this._rawData);\n this._renderPie({ animate: false });\n this._renderLegend();\n }\n }\n\n async onBeforeDestroy() {\n this._tweenId++;\n await super.onBeforeDestroy();\n }\n\n // ── public API ────────────────────────────────────────────────────\n\n setData(data, options = {}) {\n this._rawData = data;\n this._parseData(data);\n if (this.svg) {\n const animate = options.animate ?? this.animate;\n this._renderPie({ animate });\n this._renderLegend();\n }\n }\n\n async refresh() {\n if (!this.endpoint) return;\n const rest = this.getApp()?.rest;\n if (!rest) return;\n try {\n const resp = await rest.GET(this.endpoint);\n if (resp?.success) {\n const next = resp.data?.data ?? resp.data;\n if (next) this.setData(next);\n }\n } catch (err) {\n console.error('PieChart refresh failed:', err);\n }\n }\n\n // ── data normalisation ────────────────────────────────────────────\n\n _parseData(data) {\n let labels = [];\n let values = [];\n let perItemColors = [];\n\n if (Array.isArray(data)) {\n for (const d of data) {\n labels.push(d.label);\n values.push(+d.value || 0);\n perItemColors.push(d.color || null);\n }\n } else if (data && data.labels && data.datasets) {\n labels = data.labels;\n values = (data.datasets[0]?.data || []).map(v => +v || 0);\n const bg = data.datasets[0]?.backgroundColor;\n if (Array.isArray(bg)) perItemColors = bg;\n } else if (data && typeof data === 'object') {\n labels = Object.keys(data);\n values = Object.values(data).map(v => +v || 0);\n }\n\n const total = values.reduce((s, v) => s + v, 0);\n this._segments = labels.map((label, i) => ({\n label,\n value: values[i] || 0,\n pct: total > 0 ? ((values[i] || 0) / total * 100) : 0,\n color: perItemColors[i] || this.colors[i] || this.colorGenerator(i)\n }));\n }\n\n // ── render ────────────────────────────────────────────────────────\n\n _renderPie({ animate = false } = {}) {\n if (!this.svg) return;\n this._tweenId++;\n const tweenId = this._tweenId;\n\n const target = this._buildSegmentGeometry(this._segments);\n const previous = this._currentSegments;\n\n const canTween = animate && previous && this.animationDuration > 0\n && typeof requestAnimationFrame !== 'undefined';\n\n if (!canTween) {\n this._paintPie(target);\n this._currentSegments = target;\n return;\n }\n\n // Build a label-keyed source matched against target so animations\n // come/go from a 0-arc instead of scrambling positions.\n const start = performance.now();\n const duration = this.animationDuration;\n const ease = (t) => 1 - Math.pow(1 - t, 3);\n\n const step = (now) => {\n if (this._tweenId !== tweenId) return;\n const t = Math.min(1, (now - start) / duration);\n const k = ease(t);\n const interp = this._interpolateSegments(previous, target, k);\n this._paintPie(interp);\n if (t < 1) requestAnimationFrame(step);\n else this._currentSegments = target;\n };\n requestAnimationFrame(step);\n }\n\n _buildSegmentGeometry(segments) {\n const result = [];\n let angle = -Math.PI / 2; // start at 12 o'clock\n for (const seg of segments) {\n const slice = (seg.pct / 100) * Math.PI * 2;\n result.push({\n ...seg,\n startAngle: angle,\n endAngle: angle + slice\n });\n angle += slice;\n }\n return result;\n }\n\n _interpolateSegments(prev, target, k) {\n const lerp = (a, b) => a + (b - a) * k;\n const prevByLabel = new Map();\n for (const p of prev) prevByLabel.set(p.label, p);\n\n return target.map(t => {\n const p = prevByLabel.get(t.label);\n if (!p) {\n // New slice — animate from 0-arc at its target start.\n return {\n ...t,\n startAngle: t.startAngle,\n endAngle: lerp(t.startAngle, t.endAngle)\n };\n }\n return {\n ...t,\n startAngle: lerp(p.startAngle, t.startAngle),\n endAngle: lerp(p.endAngle, t.endAngle)\n };\n });\n }\n\n _paintPie(segments) {\n if (!this.svg) return;\n this.svg.innerHTML = '';\n\n if (!segments || segments.length === 0) return;\n\n const cx = this.width / 2;\n const cy = this.height / 2;\n const outerR = Math.min(cx, cy) - 4;\n const innerR = this.cutout > 0 ? outerR * this.cutout : 0;\n\n // Single-segment edge case (full circle)\n const visible = segments.filter(s => Math.abs(s.endAngle - s.startAngle) > 1e-6);\n if (visible.length === 1 && Math.abs(Math.abs(visible[0].endAngle - visible[0].startAngle) - Math.PI * 2) < 1e-3) {\n const seg = visible[0];\n if (innerR > 0) {\n this.svg.appendChild(this._svgEl('circle', {\n cx, cy, r: (outerR + innerR) / 2,\n fill: 'none', stroke: seg.color, 'stroke-width': outerR - innerR\n }));\n } else {\n this.svg.appendChild(this._svgEl('circle', {\n cx, cy, r: outerR, fill: seg.color\n }));\n }\n this._setupHover();\n return;\n }\n\n for (let i = 0; i < segments.length; i++) {\n const seg = segments[i];\n const sliceAngle = seg.endAngle - seg.startAngle;\n if (sliceAngle <= 0) continue;\n\n const startAngle = seg.startAngle;\n const endAngle = seg.endAngle;\n const largeArc = sliceAngle > Math.PI ? 1 : 0;\n\n const x1Outer = cx + outerR * Math.cos(startAngle);\n const y1Outer = cy + outerR * Math.sin(startAngle);\n const x2Outer = cx + outerR * Math.cos(endAngle);\n const y2Outer = cy + outerR * Math.sin(endAngle);\n\n let d;\n if (innerR > 0) {\n const x1Inner = cx + innerR * Math.cos(endAngle);\n const y1Inner = cy + innerR * Math.sin(endAngle);\n const x2Inner = cx + innerR * Math.cos(startAngle);\n const y2Inner = cy + innerR * Math.sin(startAngle);\n\n d = [\n `M ${x1Outer} ${y1Outer}`,\n `A ${outerR} ${outerR} 0 ${largeArc} 1 ${x2Outer} ${y2Outer}`,\n `L ${x1Inner} ${y1Inner}`,\n `A ${innerR} ${innerR} 0 ${largeArc} 0 ${x2Inner} ${y2Inner}`,\n 'Z'\n ].join(' ');\n } else {\n d = [\n `M ${cx} ${cy}`,\n `L ${x1Outer} ${y1Outer}`,\n `A ${outerR} ${outerR} 0 ${largeArc} 1 ${x2Outer} ${y2Outer}`,\n 'Z'\n ].join(' ');\n }\n\n this.svg.appendChild(this._svgEl('path', {\n d,\n fill: seg.color,\n stroke: 'var(--bs-body-bg, #fff)',\n 'stroke-width': 1.5,\n 'data-index': i,\n class: 'mini-pie-segment'\n }));\n\n // Optional slice-edge label\n if (this.showLabels && sliceAngle > 0.05) {\n const mid = (startAngle + endAngle) / 2;\n const labelR = outerR + 12;\n const lx = cx + labelR * Math.cos(mid);\n const ly = cy + labelR * Math.sin(mid);\n const t = this._svgEl('text', {\n x: lx, y: ly,\n 'text-anchor': lx < cx ? 'end' : 'start',\n 'font-size': '10',\n fill: 'var(--bs-body-color, #212529)'\n });\n t.textContent = this.showPercentages\n ? `${seg.label} (${seg.pct.toFixed(1)}%)`\n : seg.label;\n this.svg.appendChild(t);\n }\n }\n\n // Center label (only meaningful when cutout > 0).\n // Resolve dynamic labels from a function or static string.\n if (innerR > 0 && (this.centerLabel != null || this.centerSubLabel != null)) {\n const total = this._segments.reduce((s, seg) => s + seg.value, 0);\n const ctx = { total, segments: this._segments };\n const main = typeof this.centerLabel === 'function'\n ? this.centerLabel(ctx)\n : this.centerLabel;\n const sub = typeof this.centerSubLabel === 'function'\n ? this.centerSubLabel(ctx)\n : this.centerSubLabel;\n\n if (main != null) {\n const mainText = this._svgEl('text', {\n x: cx,\n y: sub != null ? cy - 2 : cy + 6,\n 'text-anchor': 'middle',\n 'dominant-baseline': 'middle',\n 'font-size': '20',\n 'font-weight': '500',\n fill: 'var(--bs-body-color, #212529)',\n class: 'mini-pie-center-label'\n });\n mainText.textContent = String(main);\n this.svg.appendChild(mainText);\n }\n if (sub != null) {\n const subText = this._svgEl('text', {\n x: cx,\n y: cy + 16,\n 'text-anchor': 'middle',\n 'dominant-baseline': 'middle',\n 'font-size': '9',\n 'letter-spacing': '0.12em',\n fill: 'var(--bs-secondary-color, #6c757d)',\n class: 'mini-pie-center-sub'\n });\n subText.textContent = String(sub).toUpperCase();\n this.svg.appendChild(subText);\n }\n }\n\n this._setupHover();\n }\n\n // ── tooltip / hover / click ───────────────────────────────────────\n\n _setupHover() {\n if (!this.svg) return;\n const paths = this.svg.querySelectorAll('.mini-pie-segment, circle');\n paths.forEach((el, idx) => {\n const sliceIdx = el.hasAttribute('data-index')\n ? parseInt(el.getAttribute('data-index'), 10)\n : idx;\n\n el.addEventListener('mouseenter', (e) => {\n if (this.showTooltip) this._showTooltip(sliceIdx, e);\n });\n el.addEventListener('mousemove', (e) => {\n if (this.showTooltip) this._moveTooltip(e);\n });\n el.addEventListener('mouseleave', () => this._hideTooltip());\n el.addEventListener('click', () => {\n const seg = this._segments[sliceIdx];\n if (!seg) return;\n this.emit?.('chart:click', {\n chart: this,\n slice: seg,\n index: sliceIdx,\n value: seg.value,\n label: seg.label\n });\n });\n });\n }\n\n _showTooltip(index, event) {\n const seg = this._segments[index];\n if (!seg || !this.tooltipEl) return;\n\n let displayValue = seg.value;\n if (this.valueFormatter) {\n if (typeof this.valueFormatter === 'function') {\n displayValue = this.valueFormatter(seg.value);\n } else {\n displayValue = this.dataFormatter.pipe(seg.value, this.valueFormatter);\n }\n } else if (typeof seg.value === 'number') {\n displayValue = seg.value.toLocaleString();\n }\n\n this.tooltipEl.innerHTML = `\n <strong>${this._esc(seg.label)}</strong><br>\n ${this._esc(displayValue)} (${seg.pct.toFixed(1)}%)\n `;\n this.tooltipEl.style.display = 'block';\n this._moveTooltip(event);\n }\n\n _moveTooltip(event) {\n if (!this.tooltipEl || this.tooltipEl.style.display === 'none') return;\n const area = this.element.querySelector('.mini-pie-svg-area');\n if (!area) return;\n const areaRect = area.getBoundingClientRect();\n const x = event.clientX - areaRect.left;\n const y = event.clientY - areaRect.top;\n\n this.tooltipEl.style.left = '0px';\n this.tooltipEl.style.top = '0px';\n this.tooltipEl.style.transform = 'none';\n const tw = this.tooltipEl.offsetWidth;\n const th = this.tooltipEl.offsetHeight;\n const aw = areaRect.width;\n const ah = areaRect.height;\n\n let left = x - tw / 2;\n let top = y - th - 8;\n if (left < 0) left = 0;\n if (left + tw > aw) left = aw - tw;\n if (top < 0) top = y + 12;\n if (top + th > ah) top = ah - th;\n\n this.tooltipEl.style.left = `${left}px`;\n this.tooltipEl.style.top = `${top}px`;\n }\n\n _hideTooltip() {\n if (this.tooltipEl) this.tooltipEl.style.display = 'none';\n }\n\n // ── legend ────────────────────────────────────────────────────────\n\n _renderLegend() {\n if (!this.showLegend || !this.legendEl) return;\n this.legendEl.innerHTML = '';\n\n for (const seg of this._segments) {\n const item = document.createElement('div');\n item.className = 'mini-pie-legend-item';\n\n // Set the swatch background as a DOM property — the color value\n // can come from the API, so we never interpolate it into a `style`\n // attribute string.\n const swatch = document.createElement('span');\n swatch.className = 'mini-pie-legend-swatch';\n swatch.style.background = seg.color;\n item.appendChild(swatch);\n\n const labelEl = document.createElement('span');\n labelEl.className = 'mini-pie-legend-label';\n labelEl.textContent = seg.label;\n item.appendChild(labelEl);\n\n const valueEl = document.createElement('span');\n valueEl.className = 'mini-pie-legend-value';\n valueEl.textContent = `${seg.pct.toFixed(1)}%`;\n item.appendChild(valueEl);\n\n this.legendEl.appendChild(item);\n }\n }\n\n // ── helpers ───────────────────────────────────────────────────────\n\n _svgEl(tag, attrs = {}) {\n const el = document.createElementNS('http://www.w3.org/2000/svg', tag);\n for (const [k, v] of Object.entries(attrs)) {\n el.setAttribute(k, String(v));\n }\n return el;\n }\n\n _esc(text) {\n const d = document.createElement('div');\n d.textContent = text;\n return d.innerHTML;\n }\n}\n\nexport default PieChart;\n","/**\n * MetricsChart — composed view that fetches /api/metrics/fetch and displays\n * the results in a native SeriesChart child.\n *\n * Owns: REST fetch, header bar with title + gear menu (granularity, quick\n * date ranges, custom range dialog) + line/bar toggle, loading/error\n * overlays.\n *\n * The actual rendering is delegated to a child SeriesChart mounted via\n * `addChild` with `containerId: 'chart'`.\n *\n * Public API matches the prior MetricsChart so admin callers (CloudWatchChart,\n * AdminDashboardPage, ShortLinkView, PushDashboardPage) need no changes —\n * EXCEPT that `.export(format)` was removed; use `exportChartPng(chart)` from\n * `web-mojo/charts/exportChart` instead.\n */\n\nimport View from '@core/View.js';\nimport Modal from '@core/views/feedback/Modal.js';\nimport SeriesChart from './SeriesChart.js';\n\nclass MetricsChart extends View {\n constructor(options = {}) {\n super({\n ...options,\n className: `mojo-metrics-chart ${options.className || ''}`.trim()\n });\n\n // Title is rendered as raw HTML via Mustache `{{{title}}}` so admin\n // callers can pass icon markup like '<i class=\"bi-graph-up\"></i> API'.\n // ⚠️ Trust boundary: this option must be developer-controlled. Never\n // set `title:` from user input or untrusted API data — it would be a\n // stored XSS vector.\n this.title = options.title || 'Metrics';\n this.chartTitle = options.chartTitle || '';\n\n // Chart configuration\n this.chartType = options.chartType || 'line';\n this.height = options.height || 300;\n this.yAxis = options.yAxis || { label: 'Count', beginAtZero: true };\n // Default to integer formatting — metric counts are typically whole\n // numbers, and DataFormatter's `number` formatter defaults to 2\n // decimals which would render Y-axis ticks as \"60.00, 80.00, ...\"\n // Callers that want decimals can pass tooltip: { y: 'number:2' }.\n this.tooltip = options.tooltip || { y: 'number:0' };\n this.colors = options.colors;\n this.colorGenerator = options.colorGenerator;\n this.legendPosition = options.legendPosition || 'top';\n this.legendJustify = options.legendJustify || 'start';\n this.showLegend = options.showLegend !== false;\n this.showXLabels = options.showXLabels !== false;\n this.showYLabels = options.showYLabels !== false;\n this.highlightOnHover = options.highlightOnHover === true;\n\n // API\n this.endpoint = options.endpoint || '/api/metrics/fetch';\n this.account = options.account || 'global';\n this.granularity = options.granularity || 'hours';\n this.slugs = options.slugs || null;\n this.category = options.category || null;\n this.dateStart = options.dateStart || null;\n this.dateEnd = options.dateEnd || null;\n this.defaultDateRange = options.defaultDateRange || '24h';\n\n // Controls\n this.showGranularity = options.showGranularity !== false;\n this.showDateRange = options.showDateRange !== false;\n this.showTypeSwitch = options.showTypeSwitch !== false;\n\n // Compact header — when true, drop the gear menu entirely and\n // show only a small inline range toggle. Used by dashboard panels\n // where the chart is sub-titled by the surrounding card and we\n // don't want the full granularity picker.\n this.compactHeader = options.compactHeader === true;\n if (this.compactHeader) {\n // In compact mode the gear menu is suppressed; the type switch\n // is also off by default since dashboard charts pin a type.\n this.showGranularity = false;\n this.showTypeSwitch = options.showTypeSwitch === true;\n }\n\n // Pass-through to the series API so KPI-style displays elsewhere\n // (and any caller that wants access to deltas) can request prev_data\n // + deltas in the same call. Note: this changes which endpoint is\n // hit — `series` (point-in-time + deltas) instead of `fetch`\n // (full time-series). Most chart use-cases want `fetch`; only set\n // this when you need deltas.\n this.withDelta = options.withDelta === true;\n if (this.withDelta && options.endpoint === undefined) {\n // Default endpoint switch — only when caller didn't pin one.\n this.endpoint = '/api/metrics/series';\n }\n\n this.granularityOptions = options.granularityOptions || [\n { value: 'minutes', label: 'Minutes' },\n { value: 'hours', label: 'Hours' },\n { value: 'days', label: 'Days' },\n { value: 'weeks', label: 'Weeks' },\n { value: 'months', label: 'Months' }\n ];\n\n this.quickRanges = options.quickRanges || [\n { value: '1h', label: '1H' },\n { value: '24h', label: '24H' },\n { value: '7d', label: '7D' },\n { value: '30d', label: '30D' }\n ];\n\n // Dataset capping (large category sets like countries)\n this.maxDatasets = Number.isFinite(options.maxDatasets) ? options.maxDatasets : null;\n this.groupRemainingLabel = options.groupRemainingLabel || 'Other';\n\n // State\n this.isLoading = false;\n this.lastFetch = null;\n\n if (!this.dateStart || !this.dateEnd) {\n this.setQuickRange(this.defaultDateRange);\n }\n }\n\n // ── lifecycle ─────────────────────────────────────────────────────\n\n async onInit() {\n this.chart = new SeriesChart({\n containerId: 'chart',\n chartType: this.chartType,\n height: this.height,\n valueFormatter: this.tooltip?.y || null,\n xLabelFormat: this._resolveXLabelFormat(),\n colors: this.colors,\n colorGenerator: this.colorGenerator,\n showLegend: this.showLegend,\n legendPosition: this.legendPosition,\n legendJustify: this.legendJustify,\n showXLabels: this.showXLabels,\n showYLabels: this.showYLabels,\n highlightOnHover: this.highlightOnHover\n });\n this.addChild(this.chart);\n }\n\n /**\n * Resolve the xLabelFormat for the child chart. Caller-supplied\n * `tooltip.x` always wins (including explicit `null` for no formatting);\n * otherwise default from the granularity.\n * @private\n */\n _resolveXLabelFormat() {\n if (this.tooltip && this.tooltip.x !== undefined) return this.tooltip.x;\n return MetricsChart.X_LABEL_FORMAT_BY_GRANULARITY[this.granularity] || null;\n }\n\n async onAfterRender() {\n await this.fetchData();\n }\n\n // ── template ──────────────────────────────────────────────────────\n\n async getTemplate() {\n // In compact mode, suppress the header row entirely — no <h5>, no\n // gear menu, no type switch. Used by dashboard panels that have\n // their own card header above the chart.\n const headerHtml = this.compactHeader ? '' : `\n <div class=\"d-flex justify-content-between align-items-center mb-2 mojo-metrics-chart-header\">\n <h5 class=\"mb-0 mojo-metrics-chart-title\">{{{title}}}</h5>\n <div class=\"btn-toolbar\" role=\"toolbar\">\n ${this._renderGearMenuHtml()}\n ${this._renderTypeSwitchHtml()}\n </div>\n </div>`;\n return `\n <div class=\"mojo-metrics-chart-container\">\n ${headerHtml}\n <div class=\"position-relative\" style=\"min-height:${typeof this.height === 'number' ? this.height + 'px' : this.height};\">\n <div data-container=\"chart\"></div>\n <div class=\"chart-overlay d-none\" data-loading>\n <div class=\"d-flex flex-column align-items-center\">\n <div class=\"spinner-border text-primary mb-2\" role=\"status\">\n <span class=\"visually-hidden\">Loading...</span>\n </div>\n <small class=\"text-muted\">Loading metrics…</small>\n </div>\n </div>\n <div class=\"chart-overlay d-none\" data-error>\n <div class=\"alert alert-danger mb-0\">\n <i class=\"bi bi-exclamation-triangle me-1\"></i>\n <span class=\"error-message\"></span>\n <button class=\"btn btn-sm btn-outline-danger ms-2\" data-action=\"retry-fetch\">Retry</button>\n </div>\n </div>\n </div>\n </div>\n `;\n }\n\n _renderGearMenuHtml() {\n const items = [];\n if (this.showGranularity) {\n items.push('<li><h6 class=\"dropdown-header\">Granularity</h6></li>');\n for (const opt of this.granularityOptions) {\n const sel = opt.value === this.granularity ? ' mc-selected' : '';\n items.push(`<li><a class=\"dropdown-item${sel}\" role=\"button\" data-action=\"granularity-changed\" data-value=\"${this._escAttr(opt.value)}\">${this._escHtml(opt.label)}</a></li>`);\n }\n }\n if (this.showDateRange) {\n if (items.length) items.push('<li><hr class=\"dropdown-divider\"></li>');\n items.push('<li><h6 class=\"dropdown-header\">Date Range</h6></li>');\n for (const qr of this.quickRanges) {\n const sel = qr.value === this.defaultDateRange ? ' mc-selected' : '';\n items.push(`<li><a class=\"dropdown-item${sel}\" role=\"button\" data-action=\"quick-range\" data-range=\"${this._escAttr(qr.value)}\">${this._escHtml(qr.label)}</a></li>`);\n }\n items.push('<li><a class=\"dropdown-item\" role=\"button\" data-action=\"show-date-range-dialog\"><i class=\"bi bi-calendar-range me-1\"></i>Custom Range…</a></li>');\n }\n if (!items.length) return '';\n return `\n <style>\n .mc-gear-menu .dropdown-item.mc-selected { background:#f0f0f0; color:inherit; }\n .mc-gear-menu .dropdown-item.mc-selected::before { content:'\\\\F633'; font-family:'bootstrap-icons'; margin-right:0.4rem; font-size:0.75em; }\n </style>\n <div class=\"btn-group btn-group-sm me-2\">\n <button type=\"button\" class=\"btn btn-outline-secondary btn-sm dropdown-toggle\"\n data-bs-toggle=\"dropdown\" aria-expanded=\"false\" title=\"Chart Settings\">\n <i class=\"bi bi-gear\"></i>\n </button>\n <ul class=\"dropdown-menu dropdown-menu-end mc-gear-menu\">${items.join('')}</ul>\n </div>`;\n }\n\n _renderTypeSwitchHtml() {\n if (!this.showTypeSwitch) return '';\n const lineActive = this.chartType === 'line' ? 'btn-primary' : 'btn-outline-primary';\n const barActive = this.chartType === 'bar' ? 'btn-primary' : 'btn-outline-primary';\n return `\n <div class=\"btn-group btn-group-sm\" role=\"group\">\n <button type=\"button\" class=\"btn ${lineActive} btn-sm\" data-action=\"set-chart-type\" data-type=\"line\" title=\"Line\"><i class=\"bi bi-graph-up\"></i></button>\n <button type=\"button\" class=\"btn ${barActive} btn-sm\" data-action=\"set-chart-type\" data-type=\"bar\" title=\"Bar\"><i class=\"bi bi-bar-chart\"></i></button>\n </div>`;\n }\n\n // ── escape helpers (for the few HTML-string interpolation points) ─\n\n _escHtml(s) {\n return String(s ?? '')\n .replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');\n }\n\n _escAttr(s) {\n return String(s ?? '')\n .replace(/&/g, '&').replace(/\"/g, '"')\n .replace(/</g, '<').replace(/>/g, '>');\n }\n\n // ── action handlers ───────────────────────────────────────────────\n\n async onActionGranularityChanged(event, element) {\n const v = element.dataset?.value;\n if (!v || v === this.granularity) return;\n this.granularity = v;\n this.setQuickRange(MetricsChart.GRANULARITY_DEFAULTS[v] || '24h');\n this._updateDropdownActive('granularity-changed', v, 'value');\n // Update the child chart's xLabelFormat to match the new granularity\n // unless the caller pinned `tooltip.x`.\n if (this.chart && (!this.tooltip || this.tooltip.x === undefined)) {\n this.chart.xLabelFormat = this._resolveXLabelFormat();\n }\n await this.fetchData();\n }\n\n async onActionQuickRange(event, element) {\n const range = element.dataset?.range;\n if (!range) return;\n this.setQuickRange(range);\n this._updateDropdownActive('quick-range', range, 'range');\n await this.fetchData();\n }\n\n async onActionShowDateRangeDialog() {\n try {\n const data = await Modal.form({\n title: 'Select Date Range',\n size: 'sm',\n fields: [\n { name: 'dt_start', type: 'datetime-local', label: 'Start', value: this.formatDateTimeLocal(this.dateStart), required: true },\n { name: 'dt_end', type: 'datetime-local', label: 'End', value: this.formatDateTimeLocal(this.dateEnd), required: true }\n ]\n });\n if (data?.dt_start && data?.dt_end) {\n this.dateStart = new Date(data.dt_start);\n this.dateEnd = new Date(data.dt_end);\n this._updateDropdownActive('quick-range', '', 'range');\n await this.fetchData();\n }\n } catch (err) {\n console.error('Date range dialog error:', err);\n }\n }\n\n async onActionSetChartType(event, element) {\n event.stopPropagation();\n const t = element.getAttribute('data-type');\n if (!t || t === this.chartType) return;\n this.chartType = t;\n if (this.chart) this.chart.setChartType(t);\n // Refresh button styles by re-querying the toolbar.\n const btns = this.element?.querySelectorAll('[data-action=\"set-chart-type\"]');\n btns?.forEach(b => {\n const isActive = b.getAttribute('data-type') === t;\n b.classList.toggle('btn-primary', isActive);\n b.classList.toggle('btn-outline-primary', !isActive);\n });\n }\n\n async onActionRetryFetch() {\n return this.fetchData();\n }\n\n _updateDropdownActive(action, activeValue, dataKey) {\n const items = this.element?.querySelectorAll(`[data-action=\"${action}\"]`);\n items?.forEach(item => {\n const v = item.dataset?.[dataKey];\n item.classList.toggle('mc-selected', v === activeValue);\n });\n }\n\n // ── data ──────────────────────────────────────────────────────────\n\n buildApiParams() {\n const params = {\n granularity: this.granularity,\n account: this.account,\n with_labels: true\n };\n if (this.withDelta) params.with_delta = true;\n if (this.slugs && this.slugs.length) {\n // Both /api/metrics/fetch AND /api/metrics/series require\n // `slugs=a,b,c` (plural, comma-separated). The singular\n // `slug=` form returns 400 \"missing required parameter\" on\n // the production backend (dev backend was permissive — this\n // bit us: empirical \"both work\" turned out to be wrong).\n // slugs[]=… also returns 400 / collapses to 'default'.\n params.slugs = this.slugs.join(',');\n }\n if (this.category) params.category = this.category;\n if (this.dateStart) params.dr_start = Math.floor(this.dateStart.getTime() / 1000);\n if (this.dateEnd) params.dr_end = Math.floor(this.dateEnd.getTime() / 1000);\n params._ = Date.now();\n return params;\n }\n\n async fetchData() {\n if (!this.endpoint) return;\n this.isLoading = true;\n this._showLoading();\n\n try {\n const rest = this.getApp()?.rest;\n if (!rest) throw new Error('No REST client available');\n\n const params = this.buildApiParams();\n const response = await rest.GET(this.endpoint, params);\n\n if (!response.success) throw new Error(response.message || 'Network error');\n if (!response.data?.status) throw new Error(response.data?.error || 'Server error');\n\n const metrics = response.data.data;\n const chartData = this.processMetricsData(metrics);\n await this.setData(chartData);\n this.lastFetch = new Date();\n this._hideError();\n\n this.emit?.('metrics:data-loaded', { chart: this, data: metrics, params });\n } catch (err) {\n console.error('Failed to fetch metrics:', err);\n this._showError(`Failed to load metrics: ${err.message}`);\n this.emit?.('metrics:error', { chart: this, error: err });\n } finally {\n this.isLoading = false;\n this._hideLoading();\n }\n }\n\n processMetricsData(data) {\n const { data: metrics, labels } = data || {};\n const entries = Object.entries(metrics || {});\n\n const ranked = entries.map(([metric, values]) => {\n const sanitized = (values || []).map(v => {\n if (v === null || v === undefined || v === '') return 0;\n return typeof v === 'number' ? v : (parseFloat(v) || 0);\n });\n const total = sanitized.reduce((s, v) => s + v, 0);\n return { metric, values: sanitized, total };\n });\n ranked.sort((a, b) => b.total - a.total);\n\n let visible = ranked;\n let other = null;\n if (this.maxDatasets && this.maxDatasets > 0 && ranked.length > this.maxDatasets) {\n visible = ranked.slice(0, this.maxDatasets);\n const remaining = ranked.slice(this.maxDatasets);\n const otherValues = (labels || []).map((_, i) =>\n remaining.reduce((s, e) => s + (e.values[i] || 0), 0)\n );\n other = {\n metric: this.groupRemainingLabel,\n values: otherValues,\n total: otherValues.reduce((s, v) => s + v, 0)\n };\n }\n\n const all = other ? [...visible, other] : visible;\n const datasets = all.map(entry => ({\n label: this.formatMetricLabel(entry.metric),\n data: entry.values\n }));\n\n return { labels: labels || [], datasets };\n }\n\n formatMetricLabel(metric) {\n // Split on both `_` and `:` so slugs like `firewall:blocks` and\n // `incident_events` produce \"Firewall Blocks\" / \"Incident Events\"\n // — clean, capitalized, no slug punctuation in the legend.\n return String(metric)\n .split(/[_:]/)\n .filter(Boolean)\n .map(w => w.charAt(0).toUpperCase() + w.slice(1))\n .join(' ');\n }\n\n async setData(chartData) {\n if (this.chart) this.chart.setData(chartData);\n }\n\n refresh() {\n return this.fetchData();\n }\n\n // ── overlays ──────────────────────────────────────────────────────\n\n _showLoading() {\n const el = this.element?.querySelector('[data-loading]');\n el?.classList.remove('d-none');\n }\n _hideLoading() {\n const el = this.element?.querySelector('[data-loading]');\n el?.classList.add('d-none');\n }\n _showError(msg) {\n const el = this.element?.querySelector('[data-error]');\n const m = el?.querySelector('.error-message');\n if (m) m.textContent = msg;\n el?.classList.remove('d-none');\n }\n _hideError() {\n const el = this.element?.querySelector('[data-error]');\n el?.classList.add('d-none');\n }\n\n // ── date utilities ────────────────────────────────────────────────\n\n static GRANULARITY_DEFAULTS = {\n minutes: '1h',\n hours: '24h',\n days: '30d',\n weeks: '30d',\n months: '30d'\n };\n\n // Default xLabelFormat for the child SeriesChart, picked by granularity.\n // Caller-supplied `tooltip.x` overrides; pass `tooltip: { x: null }` for\n // explicit \"no format\" (raw labels).\n // X-label format defaults per granularity. `time` owns HH/mm tokens;\n // `date` owns YYYY/MMM/D tokens — they're separate formatters in\n // DataFormatter. Also note: a colon inside a format string would break\n // the pipe parser (`:` is the arg separator), so we use formats that\n // don't contain a literal colon (the `time` formatter's HH:mm token\n // string is fine because the `:` is part of the OUTPUT, not the format\n // tokens — DataFormatter's `time` formatter parses the colons in its\n // tokens correctly via its own internal parser).\n static X_LABEL_FORMAT_BY_GRANULARITY = {\n minutes: \"time:'HH:mm'\",\n hours: \"time:'HH:mm'\",\n days: \"date:'MMM D'\",\n weeks: \"date:'MMM D'\",\n months: \"date:'MMM YYYY'\"\n };\n\n setQuickRange(range) {\n const now = new Date();\n let start;\n switch (range) {\n case '1h': start = new Date(now.getTime() - 60 * 60 * 1000); break;\n case '24h': start = new Date(now.getTime() - 24 * 60 * 60 * 1000); break;\n case '7d': start = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000); break;\n case '30d': start = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000); break;\n default: start = new Date(now.getTime() - 24 * 60 * 60 * 1000);\n }\n this.dateStart = start;\n this.dateEnd = now;\n }\n\n formatDateTimeLocal(date) {\n if (!date) return '';\n const y = date.getFullYear();\n const mo = String(date.getMonth() + 1).padStart(2, '0');\n const d = String(date.getDate()).padStart(2, '0');\n const h = String(date.getHours()).padStart(2, '0');\n const mi = String(date.getMinutes()).padStart(2, '0');\n return `${y}-${mo}-${d}T${h}:${mi}`;\n }\n\n // ── public API ────────────────────────────────────────────────────\n\n setGranularity(granularity) {\n this.granularity = granularity;\n if (this.chart && (!this.tooltip || this.tooltip.x === undefined)) {\n this.chart.xLabelFormat = this._resolveXLabelFormat();\n }\n return this.fetchData();\n }\n\n setDateRange(startDate, endDate) {\n this.dateStart = new Date(startDate);\n this.dateEnd = new Date(endDate);\n return this.fetchData();\n }\n\n setMetrics(slugs) {\n this.slugs = [...slugs];\n return this.fetchData();\n }\n\n getStats() {\n return {\n isLoading: this.isLoading,\n lastFetch: this.lastFetch,\n granularity: this.granularity,\n slugs: this.slugs ? [...this.slugs] : [],\n dateRange: { start: this.dateStart, end: this.dateEnd }\n };\n }\n}\n\nexport default MetricsChart;\n","/**\n * MiniChart - Lightweight sparkline chart component\n * Renders simple line or bar charts with minimal configuration\n * Uses SVG for crisp rendering at any size\n */\n\nimport View from '@core/View.js';\nimport dataFormatter from '@core/utils/DataFormatter.js';\n\nexport default class MiniChart extends View {\n constructor(options = {}) {\n super({\n className: 'mini-chart',\n ...options\n });\n\n // Chart type: 'line' or 'bar'\n this.chartType = options.chartType || 'line';\n\n // Data\n this.data = options.data || [];\n\n // Dimensions\n this.width = options.width || '100%'; // Support both number and '100%'\n this.height = options.height || 30;\n this.maintainAspectRatio = options.maintainAspectRatio || false;\n\n // Styling\n this.color = options.color || 'rgba(54, 162, 235, 1)'; // Primary blue\n this.fillColor = options.fillColor || 'rgba(54, 162, 235, 0.1)'; // Light fill\n this.strokeWidth = options.strokeWidth || 2;\n this.barGap = options.barGap || 2;\n\n // Fill area under line\n this.fill = options.fill !== false; // Default true\n\n // Curve smoothing (0 = straight lines, 1 = very smooth)\n this.smoothing = options.smoothing || 0.3;\n\n // Padding\n this.padding = options.padding || 2;\n\n // Min/Max values (auto-calculated if not provided)\n this.minValue = options.minValue;\n this.maxValue = options.maxValue;\n\n // Bar-chart soft bounds (opt-in). softMax/softMin act as a target reference\n // that bars normalize to, but expand if data exceeds them. Distinct from\n // minValue/maxValue, which are hard crops. Bar charts only.\n this.softMin = options.softMin;\n this.softMax = options.softMax;\n\n // Show dots on line chart\n this.showDots = options.showDots || false;\n this.dotRadius = options.dotRadius || 2;\n\n // Animation\n this.animate = options.animate !== false;\n this.animationDuration = options.animationDuration || 300;\n\n // Tooltip\n this.showTooltip = options.showTooltip !== false;\n this.tooltipFormatter = options.tooltipFormatter || null;\n this.tooltipTemplate = options.tooltipTemplate || null; // Function returning HTML\n this.valueFormat = options.valueFormat || null; // DataFormatter string\n this.labelFormat = options.labelFormat || null; // DataFormatter string for labels\n\n // Crosshair\n this.showCrosshair = options.showCrosshair !== false;\n this.crosshairColor = options.crosshairColor || 'rgba(0, 0, 0, 0.2)';\n this.crosshairWidth = options.crosshairWidth || 1;\n\n // X-axis\n this.showXAxis = options.showXAxis || false;\n this.xAxisColor = options.xAxisColor || this.color;\n this.xAxisWidth = options.xAxisWidth || 1;\n this.xAxisDashed = options.xAxisDashed !== false;\n\n // Tooltip state\n this.tooltip = null;\n this.crosshair = null;\n this.hoveredIndex = -1;\n\n // DataFormatter instance\n this.dataFormatter = dataFormatter;\n\n // Labels array (can be set externally or from API)\n this.labels = options.labels || null;\n }\n\n getTemplate() {\n const widthStyle = typeof this.width === 'number' ? `${this.width}px` : this.width;\n const heightStyle = typeof this.height === 'number' ? `${this.height}px` : this.height;\n const preserveAspectRatio = this.maintainAspectRatio ? 'xMidYMid meet' : 'none';\n\n return `\n <div class=\"mini-chart-wrapper\" style=\"position: relative; display: block; width: ${widthStyle}; height: ${heightStyle};\">\n <svg\n class=\"mini-chart-svg\"\n width=\"100%\"\n height=\"100%\"\n viewBox=\"0 0 100 ${this.height}\"\n preserveAspectRatio=\"${preserveAspectRatio}\"\n style=\"display: block;\">\n </svg>\n ${this.showTooltip ? '<div class=\"mini-chart-tooltip\" style=\"display: none;\"></div>' : ''}\n </div>\n `;\n }\n\n async onAfterRender() {\n this.svg = this.element.querySelector('.mini-chart-svg');\n this.tooltip = this.element.querySelector('.mini-chart-tooltip');\n\n // Get actual rendered dimensions\n this.updateDimensions();\n\n if (this.data && this.data.length > 0) {\n this.renderChart();\n }\n\n // Setup hover interactions if tooltip enabled\n if (this.showTooltip && this.svg) {\n this.setupTooltip();\n }\n\n // Setup resize observer for responsive behavior\n this.setupResizeObserver();\n }\n\n updateDimensions() {\n if (!this.svg) return;\n\n const rect = this.svg.getBoundingClientRect();\n this.actualWidth = rect.width || 100;\n this.actualHeight = rect.height || this.height;\n\n // Update viewBox to match aspect ratio\n this.svg.setAttribute('viewBox', `0 0 ${this.actualWidth} ${this.actualHeight}`);\n }\n\n setupResizeObserver() {\n if (typeof ResizeObserver === 'undefined') return;\n\n this.resizeObserver = new ResizeObserver(() => {\n this.updateDimensions();\n if (this.data && this.data.length > 0) {\n this.renderChart();\n }\n });\n\n if (this.svg) {\n this.resizeObserver.observe(this.svg);\n }\n }\n\n renderChart() {\n if (!this.svg || !this.data || this.data.length === 0) return;\n\n // Clear previous content\n this.svg.innerHTML = '';\n\n // Calculate bounds\n const { min, max } = this.calculateBounds();\n\n // Add x-axis line if enabled (render first so it's behind chart)\n if (this.showXAxis) {\n this.renderXAxis(min, max);\n }\n\n if (this.chartType === 'line') {\n this.renderLine(min, max);\n } else if (this.chartType === 'bar') {\n this.renderBar(min, max);\n }\n\n // Add crosshair line (initially hidden)\n if (this.showCrosshair) {\n const height = this.getActualHeight();\n this.crosshair = this.createSVGElement('line', {\n x1: 0,\n y1: 0,\n x2: 0,\n y2: height,\n stroke: this.crosshairColor,\n 'stroke-width': this.crosshairWidth,\n 'stroke-dasharray': '3,3',\n style: 'display: none; pointer-events: none;'\n });\n this.svg.appendChild(this.crosshair);\n }\n\n // Setup tooltip hit areas after rendering chart\n if (this.showTooltip && this.tooltip) {\n this.setupTooltip();\n }\n\n // Apply animation if enabled\n if (this.animate) {\n this.applyAnimation();\n }\n }\n\n renderXAxis(min, max) {\n const width = this.getActualWidth();\n const height = this.getActualHeight();\n\n // Calculate y position for x-axis (at zero if data crosses zero, otherwise at bottom)\n let yPos;\n if (min <= 0 && max >= 0) {\n // Data crosses zero, place axis at zero\n const range = max - min;\n const yScale = (height - this.padding * 2) / range;\n yPos = height - this.padding - ((0 - min) * yScale);\n } else {\n // Place at bottom\n yPos = height - this.padding;\n }\n\n const xAxis = this.createSVGElement('line', {\n x1: this.padding,\n y1: yPos,\n x2: width - this.padding,\n y2: yPos,\n stroke: this.xAxisColor,\n 'stroke-width': this.xAxisWidth,\n 'stroke-dasharray': this.xAxisDashed ? '2,2' : 'none',\n 'stroke-opacity': '0.5'\n });\n\n this.svg.appendChild(xAxis);\n }\n\n calculateBounds() {\n const values = this.data.map(d => typeof d === 'object' ? d.value : d);\n\n let min = this.minValue !== undefined ? this.minValue : Math.min(...values);\n let max = this.maxValue !== undefined ? this.maxValue : Math.max(...values);\n\n // Handle zero-range cases\n const range = max - min;\n if (range === 0) {\n if (this.chartType === 'bar') {\n // For bar charts with all zeros, keep baseline at 0\n if (min === 0) {\n min = 0;\n max = 1;\n } else {\n // For constant non-zero values, add a small symmetric range\n min = min - 1;\n max = max + 1;\n }\n } else {\n // For line charts, add a small symmetric range\n min = min - 1;\n max = max + 1;\n }\n }\n\n return { min, max };\n }\n\n getActualWidth() {\n return this.actualWidth || this.width || 100;\n }\n\n getActualHeight() {\n return this.actualHeight || this.height || 30;\n }\n\n renderLine(min, max) {\n const values = this.data.map(d => typeof d === 'object' ? d.value : d);\n const points = this.calculatePoints(values, min, max);\n\n // Create filled area under line\n if (this.fill) {\n const areaPath = this.createAreaPath(points);\n const area = this.createSVGElement('path', {\n d: areaPath,\n fill: this.fillColor,\n stroke: 'none'\n });\n this.svg.appendChild(area);\n }\n\n // Create line path\n const linePath = this.smoothing > 0\n ? this.createSmoothPath(points)\n : this.createLinePath(points);\n\n const line = this.createSVGElement('path', {\n d: linePath,\n fill: 'none',\n stroke: this.color,\n 'stroke-width': this.strokeWidth,\n 'stroke-linecap': 'round',\n 'stroke-linejoin': 'round'\n });\n this.svg.appendChild(line);\n\n // Add dots if enabled\n if (this.showDots) {\n points.forEach(point => {\n const dot = this.createSVGElement('circle', {\n cx: point.x,\n cy: point.y,\n r: this.dotRadius,\n fill: this.color\n });\n this.svg.appendChild(dot);\n });\n }\n }\n\n renderBar(min, max) {\n const values = this.data.map(d => typeof d === 'object' ? d.value : d);\n if (values.length === 0) return;\n\n const dataMin = Math.min(...values);\n const dataMax = Math.max(...values);\n\n // Bar-specific bounds: always include zero; soft bounds expand if data exceeds.\n // Hard crops (minValue/maxValue) win over both.\n const effectiveMin = (this.minValue !== undefined)\n ? this.minValue\n : Math.min(0, this.softMin ?? 0, dataMin);\n const effectiveMax = (this.maxValue !== undefined)\n ? this.maxValue\n : Math.max(0, this.softMax ?? 0, dataMax);\n\n // Degenerate range guard\n let lo = effectiveMin;\n let hi = effectiveMax;\n if (hi === lo) hi = lo + 1;\n\n const width = this.getActualWidth();\n const height = this.getActualHeight();\n const drawTop = this.padding;\n const drawBottom = height - this.padding;\n const drawHeight = drawBottom - drawTop;\n const yScale = drawHeight / (hi - lo);\n\n // Empty-state: all values are zero AND no caller bounds. Render a thin\n // dashed line at drawBottom so the card communicates \"alive, just zero\"\n // instead of looking broken.\n const allZero = dataMin === 0 && dataMax === 0;\n const callerBounds = this.minValue !== undefined || this.maxValue !== undefined\n || this.softMin !== undefined || this.softMax !== undefined;\n if (allZero && !callerBounds) {\n const baseline = this.createSVGElement('line', {\n x1: this.padding,\n y1: drawBottom,\n x2: width - this.padding,\n y2: drawBottom,\n stroke: this.color,\n 'stroke-width': 1,\n 'stroke-opacity': 0.4,\n 'stroke-dasharray': '2,2',\n class: 'mini-chart-empty-baseline'\n });\n this.svg.appendChild(baseline);\n return;\n }\n\n // y-coord of zero baseline, clamped to drawable area\n const yZeroRaw = drawBottom - ((0 - lo) * yScale);\n const yBase = Math.max(drawTop, Math.min(drawBottom, yZeroRaw));\n\n // Reuse calculatePoints with the line-style bounds purely for x-positions\n // so x-spacing stays identical to the previous behavior. We ignore point.y.\n const points = this.calculatePoints(values, min, max);\n\n const barWidth = (width - this.padding * 2 - (this.barGap * (values.length - 1))) / values.length;\n\n points.forEach((point, index) => {\n const value = values[index];\n const yValueRaw = drawBottom - ((value - lo) * yScale);\n const yValue = Math.max(drawTop, Math.min(drawBottom, yValueRaw));\n const topY = Math.min(yValue, yBase);\n const bottomY = Math.max(yValue, yBase);\n const barHeight = bottomY - topY;\n const x = point.x - barWidth / 2;\n\n const bar = this.createSVGElement('rect', {\n x: x,\n y: topY,\n width: barWidth,\n height: barHeight,\n fill: this.color,\n rx: 1, // Slight rounding\n 'data-bar-index': index,\n class: 'mini-chart-bar'\n });\n this.svg.appendChild(bar);\n });\n }\n\n calculatePoints(values, min, max) {\n const range = max - min;\n const width = this.getActualWidth();\n const height = this.getActualHeight();\n const xStep = (width - this.padding * 2) / (values.length - 1 || 1);\n const yScale = (height - this.padding * 2) / range;\n\n return values.map((value, index) => ({\n x: this.padding + (index * xStep),\n y: height - this.padding - ((value - min) * yScale)\n }));\n }\n\n createLinePath(points) {\n if (points.length === 0) return '';\n\n let path = `M ${points[0].x},${points[0].y}`;\n for (let i = 1; i < points.length; i++) {\n path += ` L ${points[i].x},${points[i].y}`;\n }\n return path;\n }\n\n createSmoothPath(points) {\n if (points.length < 2) return this.createLinePath(points);\n\n let path = `M ${points[0].x},${points[0].y}`;\n\n for (let i = 0; i < points.length - 1; i++) {\n const current = points[i];\n const next = points[i + 1];\n\n // Calculate control points for cubic bezier curve\n const cp1x = current.x + (next.x - current.x) * this.smoothing;\n const cp1y = current.y;\n const cp2x = next.x - (next.x - current.x) * this.smoothing;\n const cp2y = next.y;\n\n path += ` C ${cp1x},${cp1y} ${cp2x},${cp2y} ${next.x},${next.y}`;\n }\n\n return path;\n }\n\n createAreaPath(points) {\n if (points.length === 0) return '';\n\n const linePath = this.smoothing > 0\n ? this.createSmoothPath(points)\n : this.createLinePath(points);\n\n // Close the path along the bottom\n const lastPoint = points[points.length - 1];\n const firstPoint = points[0];\n const height = this.getActualHeight();\n\n return `${linePath} L ${lastPoint.x},${height - this.padding} L ${firstPoint.x},${height - this.padding} Z`;\n }\n\n createSVGElement(tag, attributes = {}) {\n const element = document.createElementNS('http://www.w3.org/2000/svg', tag);\n Object.entries(attributes).forEach(([key, value]) => {\n element.setAttribute(key, value);\n });\n return element;\n }\n\n applyAnimation() {\n const paths = this.svg.querySelectorAll('path');\n paths.forEach(path => {\n const length = path.getTotalLength();\n path.style.strokeDasharray = length;\n path.style.strokeDashoffset = length;\n path.style.animation = `mini-chart-draw ${this.animationDuration}ms ease-out forwards`;\n });\n\n const bars = this.svg.querySelectorAll('rect');\n bars.forEach((bar, index) => {\n bar.style.transformOrigin = 'bottom';\n bar.style.animation = `mini-chart-bar-grow ${this.animationDuration}ms ease-out ${index * 20}ms forwards`;\n bar.style.transform = 'scaleY(0)';\n });\n }\n\n setupTooltip() {\n if (!this.svg || !this.tooltip) return;\n\n // Create invisible overlay rects for hover detection\n const values = this.data.map(d => typeof d === 'object' ? d.value : d);\n const points = this.calculatePoints(values, ...Object.values(this.calculateBounds()));\n\n const width = this.getActualWidth();\n const height = this.getActualHeight();\n const barWidth = width / values.length;\n\n points.forEach((point, index) => {\n const hitArea = this.createSVGElement('rect', {\n x: index * barWidth,\n y: 0,\n width: barWidth,\n height: height,\n fill: 'transparent',\n style: 'cursor: pointer;'\n });\n\n hitArea.addEventListener('mouseenter', (e) => {\n this.showTooltipAtIndex(index, e);\n });\n\n hitArea.addEventListener('mousemove', (e) => {\n this.updateTooltipPosition(e);\n });\n\n hitArea.addEventListener('mouseleave', () => {\n this.hideTooltip();\n });\n\n this.svg.appendChild(hitArea);\n });\n }\n\n showTooltipAtIndex(index, event) {\n if (!this.tooltip) return;\n\n this.hoveredIndex = index;\n const value = typeof this.data[index] === 'object' ? this.data[index].value : this.data[index];\n const dataLabel = typeof this.data[index] === 'object' ? this.data[index].label : null;\n const label = this.labels ? this.labels[index] : dataLabel;\n\n // Build tooltip content using priority system\n let content;\n\n if (this.tooltipTemplate && typeof this.tooltipTemplate === 'function') {\n // 1. Custom template function (highest priority)\n content = this.tooltipTemplate({ value, label, index, data: this.data[index] });\n } else {\n // 2. Format value with DataFormatter or custom formatter\n let displayValue = value;\n\n if (this.valueFormat && this.dataFormatter) {\n // Use DataFormatter with format string\n displayValue = this.dataFormatter.pipe(value, this.valueFormat);\n } else if (this.tooltipFormatter && typeof this.tooltipFormatter === 'function') {\n // Use custom formatter function\n displayValue = this.tooltipFormatter(value, index);\n } else {\n // Default formatting\n displayValue = typeof value === 'number' ? value.toLocaleString() : value;\n }\n\n // Format label if formatter provided\n let displayLabel = label;\n if (label && this.labelFormat && this.dataFormatter) {\n displayLabel = this.dataFormatter.pipe(label, this.labelFormat);\n }\n\n // Build default tooltip HTML\n content = `<strong>${displayValue}</strong>`;\n if (displayLabel) {\n content = `<div class=\"mini-chart-tooltip-label\">${displayLabel}</div>${content}`;\n }\n }\n\n this.tooltip.innerHTML = content;\n this.tooltip.style.display = 'block';\n this.updateTooltipPosition(event);\n\n // Highlight bar if in bar chart mode\n if (this.chartType === 'bar') {\n this.highlightBar(index);\n }\n\n // Show crosshair at the hovered position\n if (this.crosshair && this.showCrosshair) {\n const width = this.getActualWidth();\n const barWidth = width / this.data.length;\n const x = (index * barWidth) + (barWidth / 2);\n this.crosshair.setAttribute('x1', x);\n this.crosshair.setAttribute('x2', x);\n this.crosshair.style.display = 'block';\n }\n }\n\n updateTooltipPosition(event) {\n if (!this.tooltip || this.tooltip.style.display === 'none') return;\n\n const rect = this.svg.getBoundingClientRect();\n const x = event.clientX - rect.left;\n const y = event.clientY - rect.top;\n\n // Position tooltip above cursor\n this.tooltip.style.left = `${x}px`;\n this.tooltip.style.top = `${y - 10}px`;\n this.tooltip.style.transform = 'translate(-50%, -100%)';\n }\n\n hideTooltip() {\n if (this.tooltip) {\n this.tooltip.style.display = 'none';\n this.hoveredIndex = -1;\n }\n\n // Remove bar highlight\n if (this.chartType === 'bar') {\n this.unhighlightBars();\n }\n\n // Hide crosshair\n if (this.crosshair) {\n this.crosshair.style.display = 'none';\n }\n }\n\n highlightBar(index) {\n if (!this.svg) return;\n\n // Remove previous highlights\n this.unhighlightBars();\n\n // Highlight the hovered bar\n const bar = this.svg.querySelector(`rect.mini-chart-bar[data-bar-index=\"${index}\"]`);\n if (bar) {\n bar.style.opacity = '0.7';\n }\n }\n\n unhighlightBars() {\n if (!this.svg) return;\n\n const bars = this.svg.querySelectorAll('rect.mini-chart-bar');\n bars.forEach(bar => {\n bar.style.opacity = '1';\n });\n }\n\n // Public API\n setData(data) {\n this.data = data;\n if (this.svg) {\n this.renderChart();\n }\n }\n\n setColor(color) {\n this.color = color;\n if (this.svg) {\n this.renderChart();\n }\n }\n\n setType(type) {\n if (['line', 'bar'].includes(type)) {\n this.chartType = type;\n if (this.svg) {\n this.renderChart();\n }\n }\n }\n\n resize(width, height) {\n this.width = width;\n this.height = height;\n this.updateDimensions();\n if (this.svg) {\n this.renderChart();\n }\n }\n\n async onBeforeDestroy() {\n // Clean up resize observer\n if (this.resizeObserver) {\n this.resizeObserver.disconnect();\n this.resizeObserver = null;\n }\n await super.onBeforeDestroy();\n }\n}\n","/**\n * MetricsMiniChart - MiniChart with API integration\n * Extends MiniChart to add /api/metrics/fetch support (same API as MetricsChart)\n */\n\nimport MiniChart from './MiniChart.js';\n\nexport default class MetricsMiniChart extends MiniChart {\n constructor(options = {}) {\n super(options);\n\n // API configuration (matching MetricsChart)\n this.endpoint = options.endpoint || '/api/metrics/fetch';\n this.account = options.account || 'global';\n this.granularity = options.granularity || 'hours';\n this.slugs = options.slugs || null; // Single slug or array of slugs\n this.category = options.category || null;\n this.dateStart = options.dateStart || null;\n this.dateEnd = options.dateEnd || null;\n this.defaultDateRange = options.defaultDateRange || null;\n\n // State\n this.isLoading = false;\n this.lastFetch = null;\n this.refreshInterval = options.refreshInterval;\n\n // ONLY initialize date range if defaultDateRange is explicitly provided\n if (this.defaultDateRange && !this.dateStart && !this.dateEnd) {\n this.setQuickRange(this.defaultDateRange);\n }\n\n // Normalize slugs to array\n if (this.slugs && !Array.isArray(this.slugs)) {\n this.slugs = [this.slugs];\n }\n }\n\n async onAfterRender() {\n await super.onAfterRender();\n\n // Fetch initial data if endpoint provided and no data\n if (this.endpoint && (!this.data || this.data.length === 0)) {\n this.fetchData();\n }\n\n // Setup auto-refresh if configured\n if (this.refreshInterval && this.endpoint) {\n this.startAutoRefresh();\n }\n }\n\n buildApiParams() {\n const params = {\n granularity: this.granularity,\n account: this.account,\n with_labels: true\n };\n\n // Add slugs\n if (this.slugs && this.slugs.length > 0) {\n this.slugs.forEach(slug => {\n if (!params['slugs[]']) params['slugs[]'] = [];\n params['slugs[]'].push(slug);\n });\n }\n\n if (this.category) {\n params.category = this.category;\n }\n\n // Date range\n if (this.dateStart) {\n params.dr_start = Math.floor(this.dateStart.getTime() / 1000);\n }\n if (this.dateEnd) {\n params.dr_end = Math.floor(this.dateEnd.getTime() / 1000);\n }\n\n // Cache buster\n params._ = Date.now();\n\n return params;\n }\n\n async fetchData() {\n if (!this.endpoint) return;\n\n this.isLoading = true;\n\n try {\n const rest = this.getApp()?.rest;\n if (!rest) {\n throw new Error('No REST client available');\n }\n\n const params = this.buildApiParams();\n const response = await rest.GET(this.endpoint, params);\n\n // Handle Rest standardized response\n if (!response.success) {\n throw new Error(response.message || 'Network error');\n }\n if (!response.data?.status) {\n throw new Error(response.data?.error || 'Server error');\n }\n\n const metricsData = response.data.data;\n this.processMetricsData(metricsData);\n this.lastFetch = new Date();\n\n // Re-render to show updated values\n await this.render();\n\n this.emit('metrics:loaded', { chart: this, data: metricsData, params });\n\n } catch (error) {\n console.error('Failed to fetch metrics:', error);\n this.emit('metrics:error', { chart: this, error });\n } finally {\n this.isLoading = false;\n }\n }\n\n processMetricsData(metricsData) {\n // Expecting: { labels: [...], data: { metric_slug: [values...] } }\n const { data: metrics, labels } = metricsData;\n\n if (!metrics) return;\n\n // Get the first (or only) metric's data\n const metricKeys = Object.keys(metrics);\n if (metricKeys.length === 0) return;\n\n const metricSlug = metricKeys[0];\n const values = metrics[metricSlug];\n\n // Sanitize values\n const sanitizedValues = values.map(val => {\n if (val === null || val === undefined || val === '') return 0;\n return typeof val === 'number' ? val : (parseFloat(val) || 0);\n });\n\n // Update labels (for tooltips)\n this.labels = labels || null;\n\n // Update chart data\n this.setData(sanitizedValues);\n }\n\n setQuickRange(range) {\n const now = new Date();\n let startDate;\n\n switch (range) {\n case '1h':\n startDate = new Date(now.getTime() - (60 * 60 * 1000));\n break;\n case '24h':\n startDate = new Date(now.getTime() - (24 * 60 * 60 * 1000));\n break;\n case '7d':\n startDate = new Date(now.getTime() - (7 * 24 * 60 * 60 * 1000));\n break;\n case '30d':\n startDate = new Date(now.getTime() - (30 * 24 * 60 * 60 * 1000));\n break;\n default:\n startDate = new Date(now.getTime() - (24 * 60 * 60 * 1000));\n }\n\n this.dateStart = startDate;\n this.dateEnd = now;\n }\n\n startAutoRefresh() {\n if (this.refreshTimer) {\n clearInterval(this.refreshTimer);\n }\n\n this.refreshTimer = setInterval(() => {\n this.fetchData();\n }, this.refreshInterval);\n }\n\n stopAutoRefresh() {\n if (this.refreshTimer) {\n clearInterval(this.refreshTimer);\n this.refreshTimer = null;\n }\n }\n\n // Public API\n setGranularity(granularity) {\n this.granularity = granularity;\n return this.fetchData();\n }\n\n setDateRange(startDate, endDate) {\n this.dateStart = new Date(startDate);\n this.dateEnd = new Date(endDate);\n return this.fetchData();\n }\n\n setMetrics(slugs) {\n this.slugs = Array.isArray(slugs) ? slugs : [slugs];\n return this.fetchData();\n }\n\n setAccount(account) {\n this.account = account;\n return this.fetchData();\n }\n\n refresh() {\n return this.fetchData();\n }\n\n async onBeforeDestroy() {\n this.stopAutoRefresh();\n await super.onBeforeDestroy();\n }\n}\n","/**\n * MetricsMiniChartWidget - Bootstrap card wrapper around MetricsMiniChart\n *\n * Renders a compact card with:\n * - icon (Bootstrap Icons class)\n * - title\n * - subtitle (inserted raw into the template so Mustache can render tokens like '{{total}}')\n * - optional trending indicator (up/down percent) under the subtitle\n * - embedded MetricsMiniChart\n * - optional settings dropdown (granularity, chartType, date range)\n *\n * Usage:\n * new MetricsMiniChartWidget({\n * icon: \"bi bi-credit-card-fill\",\n * title: 'Declined Transactions',\n * subtitle: '{{total}} Transactions', // will be rendered by Mustache at runtime\n * background: \"#F3465D\",\n * textColor: \"#FFFFFF\",\n * granularity: 'hours',\n * slugs: ['pos_tx_declined'],\n * account: 'global',\n * chartType: 'bar',\n * showTooltip: true,\n * showXAxis: true,\n * height: 80,\n * chartWidth: '100%',\n * color: 'rgba(245, 245, 255, 0.8)',\n * fill: true,\n * fillColor: 'rgba(245, 245, 255, 0.6)',\n * smoothing: 0.3,\n * showTrending: true, // optional\n * showSettings: true, // optional - show settings dropdown\n * settingsKey: 'myChart', // optional - localStorage key for persisting settings\n * showDateRange: true, // optional - include date range in settings\n * containerId: 'decline-24h-chart'\n * });\n */\n\nimport View from '@core/View.js';\nimport Modal from '@core/views/feedback/Modal.js';\nimport MetricsMiniChart from './MetricsMiniChart.js';\n\n// Format a Date / ISO / 'YYYY-MM-DD' string as a value suitable for an\n// HTML `<input type=\"date\">`. Used to seed the settings dialog.\nfunction formatDateForInput(date) {\n if (!date) return '';\n if (typeof date === 'string' && /^\\d{4}-\\d{2}-\\d{2}$/.test(date)) return date;\n const d = date instanceof Date ? date : new Date(date);\n if (isNaN(d.getTime())) return '';\n const year = d.getFullYear();\n const month = String(d.getMonth() + 1).padStart(2, '0');\n const day = String(d.getDate()).padStart(2, '0');\n return `${year}-${month}-${day}`;\n}\n\nexport default class MetricsMiniChartWidget extends View {\n constructor(options = {}) {\n super({\n ...options,\n tagName: 'div',\n className: `metrics-mini-chart-widget ${options.className || ''}`.trim()\n });\n\n // Display config\n this.icon = options.icon || null;\n this.title = options.title || '';\n this.subtitle = options.subtitle || '';\n this.background = options.background || null;\n this.textColor = options.textColor || null;\n\n // Settings config\n this.showSettings = options.showSettings || false;\n this.settingsKey = options.settingsKey || null;\n this.showDateRange = options.showDateRange || false;\n this.showRefresh = options.showRefresh !== false;\n\n // Trending options/state\n this.showTrending = !!options.showTrending;\n this.trendRange = options.trendRange ?? null;\n this.trendOffset = options.trendOffset ?? 0;\n this.prevTrendOffset = options.prevTrendOffset ?? 0;\n this.total = 0;\n this.lastValue = 0;\n this.prevValue = 0;\n this.trendingPercent = 0;\n this.trendingUp = null;\n this.hasTrending = false;\n this.trendingClass = 'metrics-mini-chart-trending-text';\n this.trendingIcon = '';\n this.trendingLabel = '';\n\n // Chart config\n this.chartOptions = {\n endpoint: options.endpoint,\n account: options.account,\n granularity: options.granularity,\n slugs: options.slugs,\n category: options.category,\n dateStart: options.dateStart,\n dateEnd: options.dateEnd,\n defaultDateRange: options.defaultDateRange,\n refreshInterval: options.refreshInterval,\n chartType: options.chartType || 'line',\n showTooltip: options.showTooltip !== undefined ? options.showTooltip : true,\n showXAxis: options.showXAxis || false,\n height: options.height || 80,\n width: options.chartWidth || options.width || '100%',\n color: options.color,\n fill: options.fill !== undefined ? options.fill : true,\n fillColor: options.fillColor,\n smoothing: options.smoothing ?? 0.3,\n strokeWidth: options.strokeWidth,\n barGap: options.barGap,\n valueFormat: options.valueFormat,\n labelFormat: options.labelFormat,\n tooltipFormatter: options.tooltipFormatter,\n tooltipTemplate: options.tooltipTemplate,\n showCrosshair: options.showCrosshair,\n crosshairColor: options.crosshairColor,\n crosshairWidth: options.crosshairWidth,\n xAxisColor: options.xAxisColor,\n xAxisWidth: options.xAxisWidth,\n xAxisDashed: options.xAxisDashed,\n padding: options.padding,\n minValue: options.minValue,\n maxValue: options.maxValue,\n softMin: options.softMin,\n softMax: options.softMax,\n showDots: options.showDots,\n dotRadius: options.dotRadius,\n animate: options.animate,\n animationDuration: options.animationDuration\n };\n }\n\n async onInit() {\n // Load saved settings if available\n if (this.showSettings && this.settingsKey) {\n this._loadSettings();\n }\n\n // Create and register the child chart\n this.chart = new MetricsMiniChart({\n ...this.chartOptions,\n containerId: 'chart'\n });\n this.addChild(this.chart);\n\n // Create header view\n this.header = new View({\n containerId: 'chart-header',\n title: this.title,\n icon: this.icon,\n template: `\n <div class=\"d-flex justify-content-between align-items-start mb-2\">\n <div class=\"flex-grow-1\">\n <h6 class=\"card-title mb-1\" style=\"${this.textColor ? `color: ${this.textColor}` : ''}\">${this.title}</h6>\n <div class=\"metrics-mini-chart-subtitle\" style=\"${this.textColor ? `color: ${this.textColor}` : ''}\">${this.subtitle}</div>\n {{#hasTrending}}\n <div class=\"{{trendingClass}}\" style=\"${this.textColor ? `color: ${this.textColor}` : ''}\">\n <i class=\"{{trendingIcon}} me-1\"></i>{{trendingLabel}}\n </div>\n {{/hasTrending}}\n </div>\n ${this.icon ? `<i class=\"${this.icon} fs-4 flex-shrink-0\" aria-hidden=\"true\" style=\"${this.textColor ? `color: ${this.textColor}` : ''}\"></i>` : ''}\n </div>`\n });\n this.addChild(this.header);\n\n // Settings now open as a Modal dialog on cog click (see\n // `onActionToggleSettings`). No SettingsView child is needed; this\n // sidesteps the popover-after-re-render bug where the cog stopped\n // working after navigating away and back.\n\n // Listen for data load events\n if (this.chart?.on) {\n this.chart.on('metrics:loaded', this.onChildMetricsLoaded, this);\n }\n\n this.updateFromChartData({ render: false });\n }\n\n async onAfterRender() {\n await super.onAfterRender();\n }\n\n onChildMetricsLoaded() {\n this.updateFromChartData({ render: true });\n }\n\n updateFromChartData({ render = true } = {}) {\n const values = Array.isArray(this.chart?.data) ? this.chart.data : null;\n if (!values || values.length === 0) {\n this.total = 0;\n this.hasTrending = false;\n this.header.title = this.title;\n if (render) this.render();\n return;\n }\n\n // Normalize values to numbers\n const nums = values.map((v) => {\n if (typeof v === 'number') return v;\n if (v && typeof v.value === 'number') return v.value;\n const n = parseFloat(v);\n return Number.isNaN(n) ? 0 : n;\n });\n\n // Compute total\n this.header.title = this.title;\n this.header.total = nums.reduce((a, b) => a + b, 0);\n const offset = Math.max(0, parseInt(this.trendOffset || 0, 10) || 0);\n const endIndex = Math.max(0, nums.length - 1 - offset);\n this.header.now_value = nums[endIndex];\n \n // Set dynamic labels based on granularity\n this._updateGranularityLabels();\n\n // Compute trending using windowed sums with optional offset\n let hasTrend = false;\n let lastSum = 0;\n let prevSum = 0;\n\n const k = (this.trendRange && this.trendRange >= 2) ? Math.max(1, Math.floor(this.trendRange / 2)) : 1;\n\n if (endIndex >= 0) {\n const lastEnd = endIndex;\n const lastStart = lastEnd - (k - 1);\n let prevStart, prevEnd;\n if (this.prevTrendOffset && this.prevTrendOffset > 0) {\n prevStart = lastStart - this.prevTrendOffset;\n prevEnd = lastEnd - this.prevTrendOffset;\n } else {\n prevEnd = lastStart - 1;\n prevStart = prevEnd - (k - 1);\n }\n\n if (lastStart >= 0 && prevStart >= 0) {\n const sumRange = (arr, s, e) => {\n let sum = 0;\n for (let i = s; i <= e; i++) sum += arr[i] || 0;\n return sum;\n };\n\n lastSum = sumRange(nums, lastStart, lastEnd);\n prevSum = sumRange(nums, prevStart, prevEnd);\n hasTrend = true;\n }\n }\n\n // Fallback to single-point comparison if not enough data for windows\n if (!hasTrend) {\n const prevIndex = endIndex - (this.prevTrendOffset && this.prevTrendOffset > 0 ? this.prevTrendOffset : 1);\n if (prevIndex >= 0) {\n lastSum = nums[endIndex];\n prevSum = nums[prevIndex];\n hasTrend = true;\n }\n }\n\n if (hasTrend) {\n this.header.lastValue = lastSum;\n this.header.prevValue = prevSum;\n\n let percent = 0;\n if (prevSum === 0) {\n percent = lastSum > 0 ? 100 : 0;\n } else {\n percent = ((lastSum - prevSum) / Math.abs(prevSum)) * 100;\n }\n\n this.header.trendingPercent = percent;\n this.header.trendingUp = percent >= 0;\n if (!this.textColor) {\n this.header.trendingClass = this.header.trendingUp ? 'text-success' : 'text-danger';\n } else {\n this.header.trendingClass = '';\n }\n\n this.header.trendingIcon = this.header.trendingUp ? 'bi bi-arrow-up' : 'bi bi-arrow-down';\n\n const sign = percent > 0 ? '+' : '';\n this.header.trendingLabel = `${sign}${percent.toFixed(1)}%`;\n this.header.hasTrending = this.showTrending;\n } else {\n this.header.hasTrending = false;\n }\n\n if (render) {\n this.header.render();\n }\n }\n\n _updateGranularityLabels() {\n const granularity = this.chartOptions.granularity || 'days';\n \n const nowLabels = {\n 'hours': 'This Hour',\n 'days': 'Today',\n 'weeks': 'This Week',\n 'months': 'This Month',\n 'years': 'This Year'\n };\n \n const totalLabels = {\n 'hours': 'Total (24h)',\n 'days': 'Total (Period)',\n 'weeks': 'Total (Period)',\n 'months': 'Total (Period)',\n 'years': 'Total (Period)'\n };\n \n this.header.now_label = nowLabels[granularity] || 'Current';\n this.header.total_label = totalLabels[granularity] || 'Total';\n }\n\n get cardStyle() {\n const styles = [];\n if (this.background) styles.push(`background: ${this.background}`);\n if (this.textColor) styles.push(`color: ${this.textColor}`);\n styles.push('border: 0');\n return styles.join('; ');\n }\n\n async getTemplate() {\n return `\n <div class=\"card h-100 shadow-sm\" style=\"${this.cardStyle}; position: relative;\">\n ${this.showRefresh || this.showSettings ? `\n <div class=\"metrics-chart-actions\">\n ${this.showRefresh ? `\n <button class=\"btn btn-link p-0 text-muted metrics-refresh-btn\" type=\"button\" data-action=\"refresh-chart\" style=\"${this.textColor ? `color: ${this.textColor} !important` : ''}\">\n <i class=\"bi bi-arrow-clockwise\"></i>\n </button>\n ` : ''}\n ${this.showSettings ? `\n <button class=\"btn btn-link p-0 text-muted metrics-settings-btn\" type=\"button\" data-action=\"toggle-settings\" style=\"${this.textColor ? `color: ${this.textColor} !important` : ''}\">\n <i class=\"bi bi-gear-fill\"></i>\n </button>\n ` : ''}\n </div>\n ` : ''}\n <div class=\"card-body p-3\">\n <div data-container=\"chart-header\"></div>\n <div data-container=\"chart\"></div>\n </div>\n </div>\n `;\n }\n\n async onBeforeDestroy() {\n if (this.chart?.off) {\n this.chart.off('metrics:loaded', this.onChildMetricsLoaded, this);\n }\n await super.onBeforeDestroy();\n }\n\n /**\n * Open the settings dialog. Uses `Modal.form` so the chart's settings\n * UI is a proper modal — easier to use, theme-consistent with the rest\n * of the framework, and immune to the popover-after-re-render bug.\n */\n async onActionToggleSettings(event, element) {\n const fields = [\n {\n name: 'granularity',\n type: 'select',\n label: 'Granularity',\n value: this.chartOptions.granularity || 'hours',\n options: [\n { value: 'hours', label: 'Hours' },\n { value: 'days', label: 'Days' },\n { value: 'weeks', label: 'Weeks' },\n { value: 'months', label: 'Months' },\n { value: 'years', label: 'Years' }\n ]\n },\n {\n name: 'chartType',\n type: 'select',\n label: 'Chart Type',\n value: this.chartOptions.chartType || 'line',\n options: [\n { value: 'line', label: 'Line' },\n { value: 'bar', label: 'Bar' }\n ]\n }\n ];\n\n if (this.showDateRange) {\n fields.push(\n {\n name: 'dateStart',\n type: 'date',\n label: 'Start date',\n value: formatDateForInput(this.chartOptions.dateStart)\n },\n {\n name: 'dateEnd',\n type: 'date',\n label: 'End date',\n value: formatDateForInput(this.chartOptions.dateEnd)\n }\n );\n }\n\n const data = await Modal.form({\n title: this.title ? `${this.title} — Settings` : 'Chart Settings',\n size: 'sm',\n submitText: 'Apply',\n cancelText: 'Cancel',\n fields\n });\n\n // Modal.form resolves with the form data on submit, or null on cancel.\n if (data) await this._handleSettingsApply(data);\n }\n\n /**\n * Handle settings apply\n * @private\n */\n async _handleSettingsApply(data) {\n let hasChanges = false;\n let granularityChanged = false;\n let datesExplicitlySet = false;\n\n // Check if dates were explicitly changed by user in the form\n if ((data.dateStart && data.dateStart !== this.chartOptions.dateStart) || \n (data.dateEnd && data.dateEnd !== this.chartOptions.dateEnd)) {\n datesExplicitlySet = true;\n }\n\n // Apply granularity\n if (data.granularity && data.granularity !== this.chartOptions.granularity) {\n this.chartOptions.granularity = data.granularity;\n this.chart.granularity = data.granularity;\n granularityChanged = true;\n hasChanges = true;\n }\n\n // Apply chart type\n if (data.chartType && data.chartType !== this.chartOptions.chartType) {\n this.chartOptions.chartType = data.chartType;\n this.chart.chartType = data.chartType;\n hasChanges = true;\n }\n\n // Apply dates or auto-adjust based on granularity\n if (datesExplicitlySet) {\n // User explicitly set dates in the form\n if (data.dateStart) {\n this.chartOptions.dateStart = new Date(data.dateStart);\n this.chart.dateStart = new Date(data.dateStart);\n }\n if (data.dateEnd) {\n this.chartOptions.dateEnd = new Date(data.dateEnd);\n this.chart.dateEnd = new Date(data.dateEnd);\n }\n hasChanges = true;\n } else if (granularityChanged && (this.chartOptions.dateStart || this.chartOptions.dateEnd)) {\n // Only auto-adjust if dates were already set (don't set them for the first time)\n const endDate = new Date();\n let startDate;\n \n switch (data.granularity) {\n case 'hours':\n startDate = new Date(endDate.getTime() - (24 * 60 * 60 * 1000));\n break;\n case 'days':\n startDate = new Date(endDate.getTime() - (30 * 24 * 60 * 60 * 1000));\n break;\n case 'weeks':\n startDate = new Date(endDate.getTime() - (12 * 7 * 24 * 60 * 60 * 1000));\n break;\n case 'months':\n startDate = new Date(endDate);\n startDate.setMonth(startDate.getMonth() - 12);\n break;\n case 'years':\n startDate = new Date(endDate);\n startDate.setFullYear(startDate.getFullYear() - 5);\n break;\n default:\n startDate = new Date(endDate.getTime() - (30 * 24 * 60 * 60 * 1000));\n }\n \n this.chartOptions.dateStart = startDate;\n this.chart.dateStart = startDate;\n this.chartOptions.dateEnd = endDate;\n this.chart.dateEnd = endDate;\n }\n\n // Save and refresh if changes were made\n if (hasChanges) {\n this._saveSettings();\n await this.chart.refresh();\n }\n }\n\n /**\n * Handle refresh button click\n */\n async onActionRefreshChart(event, element) {\n const icon = element.querySelector('i');\n if (icon) {\n icon.classList.add('spin');\n }\n\n if (this.chart) {\n if (this.chartOptions.account) this.chart.account = this.chartOptions.account;\n await this.chart.refresh();\n }\n\n if (icon) {\n icon.classList.remove('spin');\n }\n }\n\n refresh() {\n if (this.chart) {\n if (this.chartOptions.account) this.chart.account = this.chartOptions.account;\n this.chart.refresh();\n }\n }\n\n // Update account and trigger a refetch in one call. Returns the\n // fetch promise so callers can `await` completion.\n setAccount(account) {\n this.chartOptions.account = account;\n if (!this.chart) return Promise.resolve();\n return this.chart.setAccount(account);\n }\n\n _loadSettings() {\n if (!this.settingsKey) return;\n\n try {\n const stored = localStorage.getItem(`metrics-chart-${this.settingsKey}`);\n if (stored) {\n const settings = JSON.parse(stored);\n \n if (settings.granularity) {\n this.chartOptions.granularity = settings.granularity;\n }\n if (settings.chartType) {\n this.chartOptions.chartType = settings.chartType;\n }\n if (settings.dateStart !== undefined) {\n this.chartOptions.dateStart = settings.dateStart;\n }\n if (settings.dateEnd !== undefined) {\n this.chartOptions.dateEnd = settings.dateEnd;\n }\n }\n } catch (error) {\n console.error('Failed to load chart settings:', error);\n }\n }\n\n _saveSettings() {\n if (!this.settingsKey) return;\n\n try {\n const settings = {\n granularity: this.chartOptions.granularity,\n chartType: this.chartOptions.chartType,\n dateStart: this.chartOptions.dateStart,\n dateEnd: this.chartOptions.dateEnd\n };\n \n localStorage.setItem(`metrics-chart-${this.settingsKey}`, JSON.stringify(settings));\n } catch (error) {\n console.error('Failed to save chart settings:', error);\n }\n }\n}\n","/**\n * exportChartPng — serialise a native SVG chart to a PNG download.\n *\n * Generic SVG-to-PNG; not chart-specific. Pass any View instance whose root\n * contains an <svg>, or pass an <svg>/HTMLElement directly.\n *\n * Usage:\n * import { exportChartPng } from 'web-mojo/charts/exportChart';\n * exportChartPng(myChart); // default filename\n * exportChartPng(myChart, { filename: 'my.png' });\n *\n * ⚠️ Tainted-canvas note: if the SVG references cross-origin resources\n * (external `<image href>` or remote fonts via `<style>`), browsers will\n * taint the canvas and `canvas.toDataURL` will throw a SecurityError. The\n * native chart components in this extension don't reference external\n * resources, so this only matters if you extend the helper to handle SVGs\n * with external content — inline those resources before serializing.\n */\n\nexport function exportChartPng(viewOrElement, { filename } = {}) {\n const root = viewOrElement?.element || viewOrElement;\n if (!root) {\n console.warn('exportChartPng: no element provided');\n return;\n }\n const svg = (root.tagName && root.tagName.toLowerCase() === 'svg')\n ? root\n : root.querySelector?.('svg');\n if (!svg) {\n console.warn('exportChartPng: no <svg> found in target');\n return;\n }\n\n const rect = svg.getBoundingClientRect();\n const vb = svg.getAttribute('viewBox')?.split(/\\s+/).map(Number);\n const width = (vb && vb.length === 4) ? vb[2] : Math.round(rect.width || 600);\n const height = (vb && vb.length === 4) ? vb[3] : Math.round(rect.height || 400);\n\n // Inline as a data URL (avoid CORS for cross-origin font/image refs).\n const clone = svg.cloneNode(true);\n clone.setAttribute('xmlns', 'http://www.w3.org/2000/svg');\n if (!clone.getAttribute('width')) clone.setAttribute('width', width);\n if (!clone.getAttribute('height')) clone.setAttribute('height', height);\n\n const xml = new XMLSerializer().serializeToString(clone);\n const svg64 = typeof btoa === 'function'\n ? btoa(unescape(encodeURIComponent(xml)))\n : Buffer.from(xml, 'utf-8').toString('base64');\n const dataUrl = `data:image/svg+xml;base64,${svg64}`;\n\n const img = new Image();\n img.crossOrigin = 'anonymous';\n img.onload = () => {\n const canvas = document.createElement('canvas');\n canvas.width = width;\n canvas.height = height;\n const ctx = canvas.getContext('2d');\n // White backdrop so transparent SVGs render on light pages.\n ctx.fillStyle = '#ffffff';\n ctx.fillRect(0, 0, canvas.width, canvas.height);\n ctx.drawImage(img, 0, 0, width, height);\n\n const png = canvas.toDataURL('image/png');\n const a = document.createElement('a');\n a.href = png;\n a.download = filename || `chart-${Date.now()}.png`;\n document.body.appendChild(a);\n a.click();\n a.remove();\n };\n img.onerror = (err) => {\n console.error('exportChartPng: image load failed', err);\n };\n img.src = dataUrl;\n}\n\nexport default exportChartPng;\n"],"names":["SERIES_COLORS","defaultColorGenerator","i","toFixed","SeriesChart","View","constructor","options","super","className","this","chartType","grouped","stacked","width","height","showXLabels","showYLabels","padTop","padRight","padBottom","padLeft","_padBottomOverride","strokeWidth","smoothing","showDots","dotRadius","fill","barGap","groupGap","showGrid","gridLines","showLegend","legendPosition","legendJustify","_normalizeLegendJustify","showTooltip","highlightOnHover","colors","Array","isArray","length","colorGenerator","valueFormatter","xLabelFormat","xLabelFormatter","dataFormatter","animate","animationDuration","crosshairTracking","crosshairColor","crosshairWidth","_rawData","data","_labels","_datasets","_hidden","Set","_tweenId","_currentGeometry","_crosshairLayer","_crosshairLine","_ghostDots","_hitRect","getTemplate","widthStyle","heightStyle","onAfterRender","svg","element","querySelector","tooltipEl","legendEl","_updateDimensions","_setupResizeObserver","_parseData","_renderChart","_renderLegend","onBeforeDestroy","_resizeObserver","disconnect","setData","setChartType","newType","toggleSeries","index","has","delete","add","emit","chart","hidden","rect","getBoundingClientRect","_w","_h","setAttribute","ResizeObserver","observe","labels","datasets","map","_","String","label","ds","color","borderColor","fillColor","backgroundColor","series","s","name","_toRgba","size","filter","_isStacked","_visibleDatasets","_plotLeft","_plotTop","_plotRight","_plotBottom","_plotW","_plotH","_calcBounds","min","Infinity","max","visible","count","pos","neg","v","isFinite","range","Math","_yToPixel","value","_xToPixel","tweenId","_clearCrosshair","innerHTML","targetGeometry","_buildGeometry","previous","requestAnimationFrame","_paintFrame","start","performance","now","duration","step","t","k","pow","ease","interp","_interpolateGeometry","ticks","_niceTicks","niceMin","niceMax","tickStep","tickCount","formattedX","xLabelsRotated","maxXLabels","floor","stepX","ceil","raw","push","text","_truncateLabel","_formatXLabel","slotW","reduce","m","l","baseline","geom","grid","yLabels","xLabels","lines","bars","y","x1","y1","x2","y2","x","_formatAxisValue","_barSlotCenter","_buildBars","_buildLines","groupW","barW","posCum","negCum","dsIdx","yTop","yBottom","w","h","abs","dataIdx","numSeries","points","g","appendChild","_svgEl","stroke","textContent","attrs","transform","_paintBars","_paintLines","_attachHoverListeners","_setupCrosshairTracking","line","path","_buildLinePath","d","class","p","cx","cy","r","b","rx","layer","lineAttrs","style","xLine","ghosts","dot","hit","addEventListener","event","cursorX","clientX","left","colIdx","_findColumn","_hideTooltip","_paintCrosshair","_showTooltip","_clearFade","firstVisible","datasetIndex","ratio","idx","round","point","display","cur","nxt","cp1x","cp2x","join","a","lerp","out","tb","sb","find","tl","sl","tp","sp","querySelectorAll","forEach","el","col","parseInt","getAttribute","isNaN","e","_fadeOtherSeries","_moveTooltip","activeDsIdx","match","classList","remove","head","document","createElement","row","swatch","background","strong","_formatValue","area","areaRect","clientY","top","tw","offsetWidth","th","offsetHeight","aw","ah","console","warn","item","labelEl","pipe","toLocaleString","_niceNumber","exponent","log10","fraction","nice","target","Number","isInteger","decimals","substring","alpha","trim","startsWith","hex","slice","split","c","parts","tag","createElementNS","Object","entries","_esc","DEFAULT_COLORS","PieChart","cutout","centerLabel","centerSubLabel","showLabels","showPercentages","endpoint","_segments","_currentSegments","onInit","rest","getApp","resp","GET","success","err","error","_renderPie","refresh","next","values","perItemColors","bg","keys","total","pct","_buildSegmentGeometry","_paintPie","_interpolateSegments","segments","result","angle","PI","seg","startAngle","endAngle","prev","prevByLabel","Map","set","get","outerR","innerR","_setupHover","sliceAngle","largeArc","x1Outer","cos","y1Outer","sin","x2Outer","y2Outer","mid","labelR","lx","ly","ctx","main","sub","mainText","subText","toUpperCase","sliceIdx","hasAttribute","displayValue","valueEl","MetricsChart","title","chartTitle","yAxis","beginAtZero","tooltip","account","granularity","slugs","category","dateStart","dateEnd","defaultDateRange","showGranularity","showDateRange","showTypeSwitch","compactHeader","withDelta","granularityOptions","quickRanges","maxDatasets","groupRemainingLabel","isLoading","lastFetch","setQuickRange","containerId","_resolveXLabelFormat","addChild","X_LABEL_FORMAT_BY_GRANULARITY","fetchData","_renderGearMenuHtml","_renderTypeSwitchHtml","items","opt","sel","_escAttr","_escHtml","qr","replace","onActionGranularityChanged","dataset","GRANULARITY_DEFAULTS","_updateDropdownActive","onActionQuickRange","onActionShowDateRangeDialog","Modal","form","fields","type","formatDateTimeLocal","required","dt_start","dt_end","Date","onActionSetChartType","stopPropagation","btns","isActive","toggle","onActionRetryFetch","action","activeValue","dataKey","buildApiParams","params","with_labels","with_delta","dr_start","getTime","dr_end","_showLoading","Error","response","message","status","metrics","chartData","processMetricsData","_hideError","_showError","_hideLoading","ranked","metric","sanitized","parseFloat","sort","other","remaining","otherValues","entry","formatMetricLabel","Boolean","charAt","msg","static","minutes","hours","days","weeks","months","date","getFullYear","getMonth","padStart","getDate","getHours","getMinutes","setGranularity","setDateRange","startDate","endDate","setMetrics","getStats","dateRange","end","MiniChart","maintainAspectRatio","padding","minValue","maxValue","softMin","softMax","tooltipFormatter","tooltipTemplate","valueFormat","labelFormat","showCrosshair","showXAxis","xAxisColor","xAxisWidth","xAxisDashed","crosshair","hoveredIndex","preserveAspectRatio","updateDimensions","renderChart","setupTooltip","setupResizeObserver","actualWidth","actualHeight","resizeObserver","calculateBounds","renderXAxis","renderLine","renderBar","getActualHeight","createSVGElement","applyAnimation","getActualWidth","yPos","yScale","xAxis","calculatePoints","areaPath","createAreaPath","linePath","createSmoothPath","createLinePath","dataMin","dataMax","effectiveMin","effectiveMax","lo","hi","drawTop","drawBottom","allZero","callerBounds","yZeroRaw","yBase","barWidth","yValueRaw","yValue","topY","barHeight","bar","xStep","current","lastPoint","firstPoint","attributes","key","getTotalLength","strokeDasharray","strokeDashoffset","animation","transformOrigin","hitArea","showTooltipAtIndex","updateTooltipPosition","hideTooltip","dataLabel","content","displayLabel","highlightBar","unhighlightBars","opacity","setColor","setType","includes","resize","MetricsMiniChart","refreshInterval","startAutoRefresh","slug","metricsData","render","metricKeys","sanitizedValues","val","refreshTimer","clearInterval","setInterval","stopAutoRefresh","setAccount","formatDateForInput","test","MetricsMiniChartWidget","tagName","icon","subtitle","textColor","showSettings","settingsKey","showRefresh","showTrending","trendRange","trendOffset","prevTrendOffset","lastValue","prevValue","trendingPercent","trendingUp","hasTrending","trendingClass","trendingIcon","trendingLabel","chartOptions","chartWidth","_loadSettings","header","template","on","onChildMetricsLoaded","updateFromChartData","nums","n","offset","endIndex","now_value","_updateGranularityLabels","hasTrend","lastSum","prevSum","lastEnd","lastStart","prevStart","prevEnd","sumRange","arr","sum","prevIndex","percent","sign","now_label","years","total_label","cardStyle","styles","off","onActionToggleSettings","submitText","cancelText","_handleSettingsApply","hasChanges","granularityChanged","datesExplicitlySet","setMonth","setFullYear","_saveSettings","onActionRefreshChart","Promise","resolve","stored","localStorage","getItem","settings","JSON","parse","setItem","stringify","viewOrElement","filename","root","toLowerCase","vb","clone","cloneNode","xml","XMLSerializer","serializeToString","dataUrl","btoa","unescape","encodeURIComponent","Buffer","from","toString","img","Image","crossOrigin","onload","canvas","getContext","fillStyle","fillRect","drawImage","png","toDataURL","href","download","body","click","onerror","src"],"mappings":"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"}
|