@aquera/nile-visualization 2.9.7 → 2.9.9
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/dist/src/nile-chart/nile-chart-config.d.ts +1 -2
- package/dist/src/nile-chart/nile-chart.css.js +45 -399
- package/dist/src/nile-chart/nile-chart.d.ts +2 -0
- package/dist/src/nile-chart/nile-chart.js +38 -3
- package/dist/src/nile-filter-chart/nile-filter-chart.css.js +184 -107
- package/dist/src/nile-filter-chart/nile-filter-chart.d.ts +20 -3
- package/dist/src/nile-filter-chart/nile-filter-chart.js +97 -25
- package/dist/src/nile-filter-chart/utils/prompt.js +210 -60
- package/dist/src/nile-filter-chart/utils/types.d.ts +59 -25
- package/dist/src/nile-kpi-chart/nile-kpi-chart.css.js +18 -314
- package/dist/src/nile-kpi-chart/nile-kpi-chart.d.ts +2 -4
- package/dist/src/nile-kpi-chart/nile-kpi-chart.js +26 -145
- package/package.json +1 -1
- package/dist/src/nile-chart/nile-chart-skeleton.d.ts +0 -2
- package/dist/src/nile-chart/nile-chart-skeleton.js +0 -188
|
@@ -169,6 +169,7 @@ let NileKpiChart = class NileKpiChart extends NileElement {
|
|
|
169
169
|
this._onSparklineMouseLeave = () => {
|
|
170
170
|
this._hideTip();
|
|
171
171
|
};
|
|
172
|
+
// ── Value / Gauge hover handlers ─────────────────────────────────────────
|
|
172
173
|
this._onValueEnter = (e) => {
|
|
173
174
|
const rect = e.currentTarget.getBoundingClientRect();
|
|
174
175
|
const rawNum = this.parseNumericValue(this.value);
|
|
@@ -195,21 +196,6 @@ let NileKpiChart = class NileKpiChart extends NileElement {
|
|
|
195
196
|
const rect = e.currentTarget.getBoundingClientRect();
|
|
196
197
|
this._showTip(this.getTooltipContent(), rect.left + rect.width / 2, rect.top + rect.height / 2);
|
|
197
198
|
};
|
|
198
|
-
this._onTrendEnter = (e) => {
|
|
199
|
-
const el = e.currentTarget;
|
|
200
|
-
if (this.trendValue === null)
|
|
201
|
-
return;
|
|
202
|
-
const textEl = el.querySelector('.kpi-trend-text');
|
|
203
|
-
const overflowing = textEl
|
|
204
|
-
? textEl.scrollWidth > textEl.clientWidth
|
|
205
|
-
: el.scrollWidth > el.clientWidth;
|
|
206
|
-
if (!overflowing)
|
|
207
|
-
return;
|
|
208
|
-
const percent = Math.abs(this.trendValue).toFixed(1) + '%';
|
|
209
|
-
const text = this.trendLabel ? `${percent} ${this.trendLabel}` : percent;
|
|
210
|
-
const rect = el.getBoundingClientRect();
|
|
211
|
-
this._showTip(text, rect.left + rect.width / 2, rect.top);
|
|
212
|
-
};
|
|
213
199
|
this._onTipLeave = () => {
|
|
214
200
|
this._hideTip();
|
|
215
201
|
};
|
|
@@ -648,32 +634,14 @@ let NileKpiChart = class NileKpiChart extends NileElement {
|
|
|
648
634
|
if (!this.sparklineChart || !this.sparklineContainer)
|
|
649
635
|
return;
|
|
650
636
|
const rect = this.sparklineContainer.getBoundingClientRect();
|
|
651
|
-
const
|
|
652
|
-
|
|
653
|
-
if (w > 0 && h > 0) {
|
|
654
|
-
this.sparklineChart.setSize(w, h, false);
|
|
655
|
-
}
|
|
656
|
-
this.sparklineChart.reflow();
|
|
657
|
-
}
|
|
658
|
-
syncGaugeChartSize() {
|
|
659
|
-
if (!this.gaugeChart || !this.gaugeContainer)
|
|
660
|
-
return;
|
|
661
|
-
const rect = this.gaugeContainer.getBoundingClientRect();
|
|
662
|
-
const w = Math.max(72, Math.round(rect.width));
|
|
663
|
-
const h = Math.max(72, Math.round(rect.height));
|
|
664
|
-
const side = Math.min(w, h);
|
|
665
|
-
const scaledY = Math.round((this.gaugeLabelYOffset * side) / 160);
|
|
666
|
-
this.gaugeChart.update({
|
|
667
|
-
plotOptions: { solidgauge: { dataLabels: { y: scaledY } } },
|
|
668
|
-
}, false, false);
|
|
669
|
-
this.gaugeChart.setSize(w, h, false);
|
|
637
|
+
const h = Math.max(22, Math.round(rect.height));
|
|
638
|
+
this.sparklineChart.setSize(null, h, false);
|
|
670
639
|
}
|
|
671
640
|
setupResizeObserver() {
|
|
672
641
|
this.resizeObserver = new ResizeObserver(() => {
|
|
673
642
|
this.syncSparklineChartSize();
|
|
674
|
-
this.
|
|
643
|
+
this.gaugeChart?.reflow();
|
|
675
644
|
});
|
|
676
|
-
this.resizeObserver.observe(this);
|
|
677
645
|
if (this.sparklineContainer)
|
|
678
646
|
this.resizeObserver.observe(this.sparklineContainer);
|
|
679
647
|
if (this.gaugeContainer)
|
|
@@ -685,8 +653,8 @@ let NileKpiChart = class NileKpiChart extends NileElement {
|
|
|
685
653
|
const lineWidth = this.sparklineLineWidth;
|
|
686
654
|
const seriesType = this.sparklineType;
|
|
687
655
|
const topAlpha = Math.round(Math.min(1, Math.max(0, this.sparklineFillOpacity)) * 255).toString(16).padStart(2, '0');
|
|
688
|
-
const
|
|
689
|
-
const fillColor = seriesType === 'area'
|
|
656
|
+
const plotKey = seriesType;
|
|
657
|
+
const fillColor = seriesType === 'area'
|
|
690
658
|
? {
|
|
691
659
|
fillColor: {
|
|
692
660
|
linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 },
|
|
@@ -697,70 +665,24 @@ let NileKpiChart = class NileKpiChart extends NileElement {
|
|
|
697
665
|
},
|
|
698
666
|
}
|
|
699
667
|
: {};
|
|
700
|
-
let pieData = [];
|
|
701
|
-
if (isPie && this.sparkline.length) {
|
|
702
|
-
const n = this.sparkline.length;
|
|
703
|
-
const picks = [
|
|
704
|
-
this.sparkline[0],
|
|
705
|
-
this.sparkline[Math.floor(n / 3)],
|
|
706
|
-
this.sparkline[Math.floor((2 * n) / 3)],
|
|
707
|
-
this.sparkline[n - 1],
|
|
708
|
-
];
|
|
709
|
-
pieData = picks.map(y => ({ y }));
|
|
710
|
-
}
|
|
711
|
-
const plotOptions = isPie
|
|
712
|
-
? {
|
|
713
|
-
pie: {
|
|
714
|
-
dataLabels: { enabled: false, connectorWidth: 0 },
|
|
715
|
-
showInLegend: false,
|
|
716
|
-
borderWidth: 0,
|
|
717
|
-
borderRadius: 0,
|
|
718
|
-
size: '100%',
|
|
719
|
-
center: ['50%', '50%'],
|
|
720
|
-
slicedOffset: 0,
|
|
721
|
-
allowPointSelect: false,
|
|
722
|
-
states: { hover: { halo: null } },
|
|
723
|
-
colors: [
|
|
724
|
-
brandColor + 'ff',
|
|
725
|
-
brandColor + 'cc',
|
|
726
|
-
brandColor + '99',
|
|
727
|
-
brandColor + '66',
|
|
728
|
-
],
|
|
729
|
-
},
|
|
730
|
-
}
|
|
731
|
-
: {
|
|
732
|
-
[seriesType]: {
|
|
733
|
-
marker: { enabled: this.sparklineMarkers },
|
|
734
|
-
lineWidth,
|
|
735
|
-
lineColor: brandColor,
|
|
736
|
-
color: brandColor,
|
|
737
|
-
...fillColor,
|
|
738
|
-
states: { hover: { lineWidth } },
|
|
739
|
-
},
|
|
740
|
-
};
|
|
741
|
-
// Let the chart inherit the container's height by default. An explicit
|
|
742
|
-
// height in options would freeze the chart at that size until setSize() is
|
|
743
|
-
// called, which made the initial render appear as a thin sliver.
|
|
744
|
-
const initialHeight = this.sparklineContainer?.clientHeight || null;
|
|
745
668
|
const defaults = {
|
|
746
|
-
chart: {
|
|
747
|
-
type: seriesType,
|
|
748
|
-
height: initialHeight && initialHeight > 0 ? initialHeight : null,
|
|
749
|
-
margin: isPie ? [0, 0, 0, 0] : [2, 0, 2, 0],
|
|
750
|
-
backgroundColor: 'transparent',
|
|
751
|
-
},
|
|
669
|
+
chart: { type: seriesType, height: this.sparklineHeight, margin: [2, 0, 2, 0], backgroundColor: 'transparent' },
|
|
752
670
|
title: { text: undefined },
|
|
753
671
|
subtitle: { text: undefined },
|
|
754
672
|
xAxis: { visible: false },
|
|
755
673
|
yAxis: { visible: false },
|
|
756
674
|
legend: { enabled: false },
|
|
757
675
|
tooltip: { enabled: false },
|
|
758
|
-
plotOptions
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
676
|
+
plotOptions: {
|
|
677
|
+
[plotKey]: {
|
|
678
|
+
marker: { enabled: this.sparklineMarkers },
|
|
679
|
+
lineWidth,
|
|
680
|
+
lineColor: brandColor,
|
|
681
|
+
...fillColor,
|
|
682
|
+
states: { hover: { lineWidth } },
|
|
683
|
+
},
|
|
684
|
+
},
|
|
685
|
+
series: [{ type: seriesType, data: this.sparkline }],
|
|
764
686
|
credits: { enabled: false },
|
|
765
687
|
};
|
|
766
688
|
return { ...defaults, ...this.options };
|
|
@@ -779,8 +701,7 @@ let NileKpiChart = class NileKpiChart extends NileElement {
|
|
|
779
701
|
return {
|
|
780
702
|
chart: {
|
|
781
703
|
type: 'solidgauge',
|
|
782
|
-
height:
|
|
783
|
-
width: null,
|
|
704
|
+
height: this.gaugeHeight,
|
|
784
705
|
margin: [0, 0, 0, 0],
|
|
785
706
|
backgroundColor: 'transparent',
|
|
786
707
|
},
|
|
@@ -818,18 +739,9 @@ let NileKpiChart = class NileKpiChart extends NileElement {
|
|
|
818
739
|
useHTML: true,
|
|
819
740
|
formatter: (() => {
|
|
820
741
|
const self = this;
|
|
821
|
-
const basePx = (() => {
|
|
822
|
-
const m = /^(-?\d*\.?\d+)px$/.exec(labelFontSize);
|
|
823
|
-
return m ? parseFloat(m[1]) : 28;
|
|
824
|
-
})();
|
|
825
742
|
return function () {
|
|
826
743
|
const fmtResult = self.formatValue(this.y ?? 0);
|
|
827
|
-
|
|
828
|
-
const side = chart
|
|
829
|
-
? Math.min(chart.plotWidth ?? 160, chart.plotHeight ?? 160)
|
|
830
|
-
: 160;
|
|
831
|
-
const scaledPx = Math.max(8, Math.round((basePx * side) / 160));
|
|
832
|
-
return `<div style="text-align:center"><span style="font-size:${scaledPx}px;font-weight:${labelFontWeight};color:${labelColor}">${self.prefix}${fmtResult.display}${self.suffix}</span></div>`;
|
|
744
|
+
return `<div style="text-align:center"><span style="font-size:${labelFontSize};font-weight:${labelFontWeight};color:${labelColor}">${self.prefix}${fmtResult.display}${self.suffix}</span></div>`;
|
|
833
745
|
};
|
|
834
746
|
})(),
|
|
835
747
|
},
|
|
@@ -859,31 +771,7 @@ let NileKpiChart = class NileKpiChart extends NileElement {
|
|
|
859
771
|
this._hc = await getHighcharts();
|
|
860
772
|
this.destroySparkline();
|
|
861
773
|
this.sparklineChart = this._hc.chart(this.sparklineContainer, this.buildSparklineOptions());
|
|
862
|
-
|
|
863
|
-
// Initial chart creation may run before parent flex layout settles, so the
|
|
864
|
-
// first measure can be too small; we keep syncing until we see two
|
|
865
|
-
// consecutive identical sizes.
|
|
866
|
-
let lastW = -1, lastH = -1, stable = 0, frames = 0;
|
|
867
|
-
const tick = () => {
|
|
868
|
-
if (!this.sparklineChart || !this.sparklineContainer)
|
|
869
|
-
return;
|
|
870
|
-
const rect = this.sparklineContainer.getBoundingClientRect();
|
|
871
|
-
const w = Math.round(rect.width);
|
|
872
|
-
const h = Math.round(rect.height);
|
|
873
|
-
if (w > 0 && h > 0)
|
|
874
|
-
this.sparklineChart.setSize(w, h, false);
|
|
875
|
-
this.sparklineChart.reflow();
|
|
876
|
-
if (w === lastW && h === lastH)
|
|
877
|
-
stable++;
|
|
878
|
-
else
|
|
879
|
-
stable = 0;
|
|
880
|
-
lastW = w;
|
|
881
|
-
lastH = h;
|
|
882
|
-
frames++;
|
|
883
|
-
if (stable < 2 && frames < 30)
|
|
884
|
-
requestAnimationFrame(tick);
|
|
885
|
-
};
|
|
886
|
-
requestAnimationFrame(tick);
|
|
774
|
+
requestAnimationFrame(() => this.syncSparklineChartSize());
|
|
887
775
|
this.sparklineContainer.addEventListener('mousemove', this._onSparklineMouseMove);
|
|
888
776
|
this.sparklineContainer.addEventListener('mouseleave', this._onSparklineMouseLeave);
|
|
889
777
|
this.emit('nile-chart-ready', { chart: this.sparklineChart });
|
|
@@ -895,7 +783,6 @@ let NileKpiChart = class NileKpiChart extends NileElement {
|
|
|
895
783
|
this._hc = await getHighcharts();
|
|
896
784
|
this.destroyGauge();
|
|
897
785
|
this.gaugeChart = this._hc.chart(this.gaugeContainer, this.buildGaugeOptions());
|
|
898
|
-
requestAnimationFrame(() => this.syncGaugeChartSize());
|
|
899
786
|
this.emit('nile-chart-ready', { chart: this.gaugeChart });
|
|
900
787
|
}
|
|
901
788
|
destroySparkline() {
|
|
@@ -924,14 +811,8 @@ let NileKpiChart = class NileKpiChart extends NileElement {
|
|
|
924
811
|
return undefined;
|
|
925
812
|
const dir = this.trendDirection;
|
|
926
813
|
const formatted = Math.abs(this.trendValue).toFixed(1) + '%';
|
|
927
|
-
const fullText = this.trendLabel ? `${formatted} ${this.trendLabel}` : formatted;
|
|
928
814
|
return html `
|
|
929
|
-
<span
|
|
930
|
-
class="kpi-trend kpi-trend--${dir}"
|
|
931
|
-
data-full-text=${fullText}
|
|
932
|
-
@mouseenter=${this._onTrendEnter}
|
|
933
|
-
@mouseleave=${this._onTipLeave}
|
|
934
|
-
>
|
|
815
|
+
<span class="kpi-trend kpi-trend--${dir}">
|
|
935
816
|
<span class="kpi-trend-arrow">
|
|
936
817
|
${dir === 'up'
|
|
937
818
|
? html `<svg viewBox="0 0 12 12"><path d="M6 2.5l4 5H2z"/></svg>`
|
|
@@ -939,7 +820,7 @@ let NileKpiChart = class NileKpiChart extends NileElement {
|
|
|
939
820
|
? html `<svg viewBox="0 0 12 12"><path d="M6 9.5l4-5H2z"/></svg>`
|
|
940
821
|
: html `<svg viewBox="0 0 12 12"><path d="M2 6.5h8" stroke="currentColor" stroke-width="1.5" fill="none"/></svg>`}
|
|
941
822
|
</span>
|
|
942
|
-
|
|
823
|
+
${formatted}${this.trendLabel ? html ` <span>${this.trendLabel}</span>` : nothing}
|
|
943
824
|
</span>
|
|
944
825
|
`;
|
|
945
826
|
}
|
|
@@ -951,9 +832,9 @@ let NileKpiChart = class NileKpiChart extends NileElement {
|
|
|
951
832
|
const rawNum = this.parseNumericValue(this.value);
|
|
952
833
|
const fmt = rawNum != null ? this.formatValue(rawNum) : null;
|
|
953
834
|
const displayValue = fmt ? fmt.display : String(this.value ?? '');
|
|
954
|
-
const
|
|
835
|
+
const showTooltip = !!fmt && fmt.display !== fmt.full;
|
|
955
836
|
return html `
|
|
956
|
-
<div class="kpi ${isGauge ? 'kpi--gauge' : ''}
|
|
837
|
+
<div class="kpi ${isGauge ? 'kpi--gauge' : ''}">
|
|
957
838
|
${this.label ? html `<p
|
|
958
839
|
class="kpi-label"
|
|
959
840
|
@mouseenter=${this._onLabelEnter}
|
|
@@ -972,8 +853,8 @@ let NileKpiChart = class NileKpiChart extends NileElement {
|
|
|
972
853
|
${!isGauge ? html `
|
|
973
854
|
<h2
|
|
974
855
|
class="kpi-value"
|
|
975
|
-
@mouseenter=${
|
|
976
|
-
@mouseleave=${
|
|
856
|
+
@mouseenter=${showTooltip ? this._onValueEnter : nothing}
|
|
857
|
+
@mouseleave=${showTooltip ? this._onTipLeave : nothing}
|
|
977
858
|
>
|
|
978
859
|
${this.prefix ? html `<span class="kpi-prefix">${this.prefix}</span>` : nothing}${displayValue}${this.suffix ? html `<span class="kpi-suffix">${this.suffix}</span>` : nothing}
|
|
979
860
|
</h2>
|
package/package.json
CHANGED
|
@@ -1,188 +0,0 @@
|
|
|
1
|
-
import { html } from 'lit';
|
|
2
|
-
const SKELETON_TYPE_MAP = {
|
|
3
|
-
column: 'columns', stacked: 'columns', cluster: 'columns', histogram: 'columns',
|
|
4
|
-
waterfall: 'columns', funnel: 'columns', columnPyramid: 'columns',
|
|
5
|
-
columnRange: 'columns', columnDrilldown: 'columns', lollipop: 'columns',
|
|
6
|
-
line: 'line', area: 'line', spline: 'line', areaSpline: 'line',
|
|
7
|
-
invertedArea: 'line', areaNegative: 'line', areaRange: 'line',
|
|
8
|
-
fan: 'line', bellcurve: 'line',
|
|
9
|
-
trendline: 'trendline', anomaly: 'anomaly',
|
|
10
|
-
pie: 'pie', donut: 'pie', variablePie: 'pie', radialBar: 'pie', gauge: 'pie', euler: 'pie',
|
|
11
|
-
scatter: 'scatter', bubble: 'scatter', dumbbell: 'scatter', boxplot: 'scatter',
|
|
12
|
-
heatmap: 'heatmap', flame: 'heatmap',
|
|
13
|
-
radar: 'radar', spiderweb: 'radar',
|
|
14
|
-
timeline: 'timeline', xrange: 'timeline',
|
|
15
|
-
kpi: 'kpi', grid: 'grid', filter: 'filter',
|
|
16
|
-
};
|
|
17
|
-
const SCATTER_DOTS = [
|
|
18
|
-
[12, 70, 8], [22, 45, 10], [28, 78, 6], [38, 30, 12], [46, 58, 7],
|
|
19
|
-
[54, 22, 9], [62, 65, 11], [70, 40, 7], [78, 75, 10], [88, 35, 8],
|
|
20
|
-
[18, 30, 6], [50, 80, 8],
|
|
21
|
-
];
|
|
22
|
-
const TIMELINE_BARS = [
|
|
23
|
-
[5, 38], [22, 28], [12, 55], [40, 22], [30, 40], [55, 30],
|
|
24
|
-
];
|
|
25
|
-
const sk = (variant, width, height, borderRadius) => borderRadius
|
|
26
|
-
? html `<nile-skeleton-loader variant=${variant} width=${width} height=${height} border-radius=${borderRadius}></nile-skeleton-loader>`
|
|
27
|
-
: html `<nile-skeleton-loader variant=${variant} width=${width} height=${height}></nile-skeleton-loader>`;
|
|
28
|
-
const repeat = (n, fn) => Array.from({ length: n }, (_, i) => fn(i));
|
|
29
|
-
const xaxis = (n = 5, w = 30) => html `
|
|
30
|
-
<div class="nile-chart-skeleton-xaxis-row">
|
|
31
|
-
${repeat(n, () => sk('rounded', w, 10))}
|
|
32
|
-
</div>
|
|
33
|
-
`;
|
|
34
|
-
function variantFor(type) {
|
|
35
|
-
return (type && SKELETON_TYPE_MAP[type]) || 'bars';
|
|
36
|
-
}
|
|
37
|
-
function renderBody(v) {
|
|
38
|
-
switch (v) {
|
|
39
|
-
case 'columns':
|
|
40
|
-
return html `
|
|
41
|
-
<div class="nile-chart-skeleton-columns">
|
|
42
|
-
${[58, 82, 44, 91, 67, 35, 76, 50].map(h => html `<div class="nile-chart-skeleton-col-cell" style="height:${h}%">${sk('rectangular', '100%', '100%')}</div>`)}
|
|
43
|
-
</div>
|
|
44
|
-
<div class="nile-chart-skeleton-xaxis-row nile-chart-skeleton-xaxis-row--columns">
|
|
45
|
-
${repeat(8, () => sk('rounded', 24, 10))}
|
|
46
|
-
</div>
|
|
47
|
-
`;
|
|
48
|
-
case 'line':
|
|
49
|
-
return html `
|
|
50
|
-
<div class="nile-chart-skeleton-line">
|
|
51
|
-
<svg viewBox="0 0 100 40" preserveAspectRatio="none" aria-hidden="true">
|
|
52
|
-
<path class="nile-chart-skeleton-line-area" d="M0,30 C10,20 18,32 28,22 C38,12 48,28 60,18 C72,8 82,24 92,14 L100,16 L100,40 L0,40 Z"></path>
|
|
53
|
-
<path class="nile-chart-skeleton-line-stroke" d="M0,30 C10,20 18,32 28,22 C38,12 48,28 60,18 C72,8 82,24 92,14 L100,16"></path>
|
|
54
|
-
</svg>
|
|
55
|
-
</div>
|
|
56
|
-
${xaxis()}
|
|
57
|
-
`;
|
|
58
|
-
case 'trendline':
|
|
59
|
-
// Solid actuals (0–60%) + a dashed straight forecast continuation (60–100%)
|
|
60
|
-
// along the trend, plus a faint trend line through it.
|
|
61
|
-
return html `
|
|
62
|
-
<div class="nile-chart-skeleton-line">
|
|
63
|
-
<svg viewBox="0 0 100 40" preserveAspectRatio="none" aria-hidden="true">
|
|
64
|
-
<line class="nile-chart-skeleton-trend-line" x1="0" y1="28" x2="100" y2="10"></line>
|
|
65
|
-
<path class="nile-chart-skeleton-line-stroke" d="M0,30 C8,24 14,30 22,22 C30,16 38,24 46,18 C52,14 56,20 60,16"></path>
|
|
66
|
-
<path class="nile-chart-skeleton-trend-forecast" d="M60,16 L72,13 L84,11 L100,8"></path>
|
|
67
|
-
<line class="nile-chart-skeleton-trend-divider" x1="60" y1="0" x2="60" y2="40"></line>
|
|
68
|
-
</svg>
|
|
69
|
-
</div>
|
|
70
|
-
${xaxis()}
|
|
71
|
-
`;
|
|
72
|
-
case 'anomaly':
|
|
73
|
-
// Smooth line with a few highlighted anomaly markers off-trend.
|
|
74
|
-
return html `
|
|
75
|
-
<div class="nile-chart-skeleton-line">
|
|
76
|
-
<svg viewBox="0 0 100 40" preserveAspectRatio="none" aria-hidden="true">
|
|
77
|
-
<path class="nile-chart-skeleton-line-stroke" d="M0,26 C10,22 18,24 26,20 C34,16 42,22 50,18 C58,14 66,18 74,16 C82,14 90,16 100,14"></path>
|
|
78
|
-
${[[18, 6], [50, 32], [74, 4]].map(([x, y]) => html `<circle class="nile-chart-skeleton-anomaly-dot" cx=${x} cy=${y} r="2.5"></circle>`)}
|
|
79
|
-
${[[18, 6], [50, 32], [74, 4]].map(([x, y]) => html `<circle class="nile-chart-skeleton-anomaly-halo" cx=${x} cy=${y} r="5"></circle>`)}
|
|
80
|
-
</svg>
|
|
81
|
-
</div>
|
|
82
|
-
${xaxis()}
|
|
83
|
-
`;
|
|
84
|
-
case 'pie':
|
|
85
|
-
return html `
|
|
86
|
-
<div class="nile-chart-skeleton-pie-wrap">
|
|
87
|
-
<div class="nile-chart-skeleton-pie"></div>
|
|
88
|
-
<div class="nile-chart-skeleton-legend">
|
|
89
|
-
${repeat(4, () => html `<div class="nile-chart-skeleton-legend-row">${sk('circular', 10, 10)}${sk('rounded', 70, 8)}</div>`)}
|
|
90
|
-
</div>
|
|
91
|
-
</div>
|
|
92
|
-
`;
|
|
93
|
-
case 'scatter':
|
|
94
|
-
return html `
|
|
95
|
-
<div class="nile-chart-skeleton-scatter">
|
|
96
|
-
${SCATTER_DOTS.map(([x, y, r]) => html `<span class="nile-chart-skeleton-dot-pos" style="left:${x}%;top:${y}%;">${sk('circular', r, r)}</span>`)}
|
|
97
|
-
</div>
|
|
98
|
-
${xaxis()}
|
|
99
|
-
`;
|
|
100
|
-
case 'heatmap':
|
|
101
|
-
return html `
|
|
102
|
-
<div class="nile-chart-skeleton-heatmap">
|
|
103
|
-
${repeat(4, () => html `<div class="nile-chart-skeleton-heatmap-row">${repeat(7, () => html `<div class="nile-chart-skeleton-heatmap-cell">${sk('rounded', '100%', '100%')}</div>`)}</div>`)}
|
|
104
|
-
</div>
|
|
105
|
-
`;
|
|
106
|
-
case 'radar': {
|
|
107
|
-
// Pentagon vertices (5-sided radar) at radii 40/27/14 around center (50,50).
|
|
108
|
-
const ring = (r) => [-90, -18, 54, 126, 198]
|
|
109
|
-
.map(deg => {
|
|
110
|
-
const rad = (deg * Math.PI) / 180;
|
|
111
|
-
return `${(50 + r * Math.cos(rad)).toFixed(2)},${(50 + r * Math.sin(rad)).toFixed(2)}`;
|
|
112
|
-
})
|
|
113
|
-
.join(' ');
|
|
114
|
-
const outer = ring(40);
|
|
115
|
-
const data = [35, 22, 30, 18, 28]
|
|
116
|
-
.map((r, i) => {
|
|
117
|
-
const deg = [-90, -18, 54, 126, 198][i];
|
|
118
|
-
const rad = (deg * Math.PI) / 180;
|
|
119
|
-
return `${(50 + r * Math.cos(rad)).toFixed(2)},${(50 + r * Math.sin(rad)).toFixed(2)}`;
|
|
120
|
-
})
|
|
121
|
-
.join(' ');
|
|
122
|
-
const spokes = [-90, -18, 54, 126, 198].map(deg => {
|
|
123
|
-
const rad = (deg * Math.PI) / 180;
|
|
124
|
-
return [50 + 40 * Math.cos(rad), 50 + 40 * Math.sin(rad)];
|
|
125
|
-
});
|
|
126
|
-
return html `
|
|
127
|
-
<div class="nile-chart-skeleton-radar-wrap">
|
|
128
|
-
<svg class="nile-chart-skeleton-radar-svg" viewBox="0 0 100 100" aria-hidden="true">
|
|
129
|
-
<polygon class="nile-chart-skeleton-radar-grid" points=${outer}></polygon>
|
|
130
|
-
<polygon class="nile-chart-skeleton-radar-grid" points=${ring(27)}></polygon>
|
|
131
|
-
<polygon class="nile-chart-skeleton-radar-grid" points=${ring(14)}></polygon>
|
|
132
|
-
${spokes.map(([x, y]) => html `<line class="nile-chart-skeleton-radar-spoke" x1="50" y1="50" x2=${x.toFixed(2)} y2=${y.toFixed(2)}></line>`)}
|
|
133
|
-
<polygon class="nile-chart-skeleton-radar-data" points=${data}></polygon>
|
|
134
|
-
${spokes.map(([x, y]) => html `<circle class="nile-chart-skeleton-radar-dot" cx=${x.toFixed(2)} cy=${y.toFixed(2)} r="1.6"></circle>`)}
|
|
135
|
-
</svg>
|
|
136
|
-
</div>
|
|
137
|
-
`;
|
|
138
|
-
}
|
|
139
|
-
case 'timeline':
|
|
140
|
-
return html `
|
|
141
|
-
<div class="nile-chart-skeleton-timeline">
|
|
142
|
-
${TIMELINE_BARS.map(([x, w]) => html `<div class="nile-chart-skeleton-tl-row"><span class="nile-chart-skeleton-tl-bar-pos" style="left:${x}%;width:${w}%;">${sk('rounded', '100%', 12, '999px')}</span></div>`)}
|
|
143
|
-
</div>
|
|
144
|
-
${xaxis()}
|
|
145
|
-
`;
|
|
146
|
-
case 'kpi':
|
|
147
|
-
return html `
|
|
148
|
-
<div class="nile-chart-skeleton-kpi">
|
|
149
|
-
${sk('rounded', '40%', 10)}${sk('rounded', '60%', 28)}${sk('rounded', '30%', 10)}
|
|
150
|
-
<svg class="nile-chart-skeleton-kpi-spark" viewBox="0 0 100 20" preserveAspectRatio="none" aria-hidden="true">
|
|
151
|
-
<path d="M0,14 L14,10 L28,12 L42,6 L56,9 L70,4 L84,7 L100,2"></path>
|
|
152
|
-
</svg>
|
|
153
|
-
</div>
|
|
154
|
-
`;
|
|
155
|
-
case 'grid':
|
|
156
|
-
return html `
|
|
157
|
-
<div class="nile-chart-skeleton-grid">
|
|
158
|
-
<div class="nile-chart-skeleton-grid-head">${repeat(4, () => sk('rounded', '100%', 12))}</div>
|
|
159
|
-
${repeat(5, () => html `<div class="nile-chart-skeleton-grid-row">${repeat(4, () => sk('text', '100%', 10))}</div>`)}
|
|
160
|
-
</div>
|
|
161
|
-
`;
|
|
162
|
-
case 'filter':
|
|
163
|
-
return html `
|
|
164
|
-
<div class="nile-chart-skeleton-filter">
|
|
165
|
-
${sk('rounded', '100%', 36)}
|
|
166
|
-
<div class="nile-chart-skeleton-filter-chips">
|
|
167
|
-
${[60, 80, 50, 90, 70].map(w => sk('rounded', w, 22, '999px'))}
|
|
168
|
-
</div>
|
|
169
|
-
</div>
|
|
170
|
-
`;
|
|
171
|
-
case 'bars':
|
|
172
|
-
default:
|
|
173
|
-
return html `
|
|
174
|
-
<div class="nile-chart-skeleton-body">
|
|
175
|
-
${[96, 88, 94, 84, 92].map(w => html `<div class="nile-chart-skeleton-row">
|
|
176
|
-
<nile-skeleton-loader class="nile-chart-skeleton-ylabel-sk" variant="rounded" width="100%" height="10"></nile-skeleton-loader>
|
|
177
|
-
<nile-skeleton-loader class="nile-chart-skeleton-bar-sk" variant="rounded" width="100%" height="18" style="flex:0 1 ${w}%;min-width:0;"></nile-skeleton-loader>
|
|
178
|
-
</div>`)}
|
|
179
|
-
</div>
|
|
180
|
-
${xaxis()}
|
|
181
|
-
`;
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
export function renderChartSkeleton(chartType) {
|
|
185
|
-
const v = variantFor(chartType);
|
|
186
|
-
return html `<div class="nile-chart-skeleton nile-chart-skeleton--${v}" aria-busy="true" aria-label="Loading chart">${renderBody(v)}</div>`;
|
|
187
|
-
}
|
|
188
|
-
//# sourceMappingURL=nile-chart-skeleton.js.map
|