mnfst 0.5.244 → 0.5.245
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/lib/manifest.charts.js
CHANGED
|
@@ -190,7 +190,7 @@
|
|
|
190
190
|
function normalize(raw, el, typeFromModifier) {
|
|
191
191
|
const cfg = Object.assign({}, raw || {});
|
|
192
192
|
cfg.type = (cfg.type || typeFromModifier || 'line').toLowerCase();
|
|
193
|
-
cfg.height = num(cfg.height || el.getAttribute('height'), 240);
|
|
193
|
+
cfg.height = num(cfg.height || el.getAttribute('height') || undefined, cfg.type === 'map' ? 0 : 240); // maps size from width
|
|
194
194
|
cfg.stacked = !!cfg.stacked;
|
|
195
195
|
cfg.legend = cfg.legend !== false;
|
|
196
196
|
cfg.axis = cfg.axis !== false;
|
|
@@ -507,9 +507,23 @@
|
|
|
507
507
|
function drawCartesian(state, root, width, height) {
|
|
508
508
|
const cfg = state.config, d3 = state.d3;
|
|
509
509
|
const m = { top: 10, right: 14, bottom: 26, left: 40 };
|
|
510
|
-
const iw = width - m.left - m.right;
|
|
511
|
-
const ih = height - m.top - m.bottom;
|
|
512
510
|
const labels = cfg.labels.length ? cfg.labels : cfg.series[0].data.map((_, i) => i + 1);
|
|
511
|
+
const marks = cfg.axis ? axisMarks(cfg, labels) : [];
|
|
512
|
+
let iw = width - m.left - m.right;
|
|
513
|
+
// Widen margins (each side capped at 20% of width) so end labels sit
|
|
514
|
+
// centred on their points; past the cap, ends clamp inside the frame.
|
|
515
|
+
if (marks.length) {
|
|
516
|
+
const f = marks[0], l = marks[marks.length - 1];
|
|
517
|
+
const hf = labelWidth(root, [f.label]) / 2, hl = labelWidth(root, [l.label]) / 2;
|
|
518
|
+
const base = { left: m.left, right: m.right }, cap = width * 0.2;
|
|
519
|
+
for (let pass = 0; pass < 2; pass++) {
|
|
520
|
+
const c = xScheme(cfg, d3, labels.length, iw).x;
|
|
521
|
+
m.left = Math.max(base.left, Math.min(cap, Math.ceil(hf - c(f.at)) + 1));
|
|
522
|
+
m.right = Math.max(base.right, Math.min(cap, Math.ceil(hl - (iw - c(l.at))) + 1));
|
|
523
|
+
iw = width - m.left - m.right;
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
const ih = height - m.top - m.bottom;
|
|
513
527
|
const locale = (() => { try { return Alpine.store('locale')?.current || document.documentElement.lang || 'en'; } catch (_) { return 'en'; } })();
|
|
514
528
|
const nf = (() => { try { return new Intl.NumberFormat(locale, { notation: 'compact', maximumFractionDigits: 1 }); } catch (_) { return { format: String }; } })();
|
|
515
529
|
|
|
@@ -551,41 +565,73 @@
|
|
|
551
565
|
else if (cfg.type === 'scatter') drawScatter(state, plot, labels, iw, ih, y);
|
|
552
566
|
else drawLines(state, plot, labels, iw, ih, y); // line + area
|
|
553
567
|
|
|
554
|
-
// x axis labels (banded), thinned so they never overlap
|
|
568
|
+
// x axis labels (banded), evenly thinned so they never overlap
|
|
555
569
|
if (cfg.axis) {
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
text(plot, labels[i], { x: cx, y: ih + 16, 'text-anchor': 'middle' });
|
|
570
|
+
xAxisTicks(root, marks, xScheme(cfg, d3, labels.length, iw).x, iw, m).forEach(([t, cx]) => {
|
|
571
|
+
text(plot, t.label, { x: cx, y: ih + 16, 'text-anchor': 'middle' });
|
|
559
572
|
});
|
|
560
573
|
}
|
|
561
574
|
if (cfg.legend && cfg.series.length > 1) drawLegend(state);
|
|
562
575
|
}
|
|
563
576
|
|
|
564
|
-
//
|
|
565
|
-
//
|
|
566
|
-
function
|
|
577
|
+
// One index-keyed x scheme per chart (duplicate labels stay distinct), shared
|
|
578
|
+
// by marks and axis. Bars (and combo lines over bars) use band centres.
|
|
579
|
+
function xScheme(cfg, d3, n, w) {
|
|
580
|
+
const idx = Array.from({ length: n }, (_, i) => i);
|
|
581
|
+
const candle = cfg.type === 'candlestick' || cfg.type === 'ohlc';
|
|
582
|
+
const banded = candle || cfg.type === 'bar' || (cfg.type === 'combo' && cfg.series.some(s => { const t = seriesType(cfg, s); return t !== 'line' && t !== 'area'; }));
|
|
583
|
+
if (banded) {
|
|
584
|
+
const band = d3.scaleBand().domain(idx).range([0, w]).padding(candle ? 0.3 : 0.2);
|
|
585
|
+
const bw = band.bandwidth();
|
|
586
|
+
return { band, step: band.step(), x: i => band(i) + bw / 2 };
|
|
587
|
+
}
|
|
588
|
+
const p = d3.scalePoint().domain(idx).range([0, w]).padding(0.5);
|
|
589
|
+
return { step: typeof p.step === 'function' ? p.step() : w / Math.max(1, n), x: i => p(i) };
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
// Axis label candidates: author `ticks` ([index] or [{ at, label }]) or every label.
|
|
593
|
+
function axisMarks(cfg, labels) {
|
|
567
594
|
const n = labels.length;
|
|
568
|
-
if (!
|
|
569
|
-
const
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
595
|
+
if (!Array.isArray(cfg.ticks)) return labels.map((l, i) => ({ at: i, label: l }));
|
|
596
|
+
const seen = new Set();
|
|
597
|
+
return cfg.ticks
|
|
598
|
+
.map(t => t && typeof t === 'object' && !Array.isArray(t) ? { at: tickIndex(t.at), label: t.label } : { at: tickIndex(t) })
|
|
599
|
+
.filter(t => t.at >= 0 && t.at < n && !seen.has(t.at) && seen.add(t.at))
|
|
600
|
+
.map(t => ({ at: t.at, label: t.label != null ? t.label : labels[t.at] }))
|
|
601
|
+
.sort((a, b) => a.at - b.at);
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
function tickIndex(v) {
|
|
605
|
+
const ok = (typeof v === 'number' && isFinite(v)) || (typeof v === 'string' && v.trim() !== '' && isFinite(+v));
|
|
606
|
+
return ok ? Math.round(+v) : -1;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
// Marks + x to draw: the most evenly spaced subset (first and last kept)
|
|
610
|
+
// whose measured labels don't overlap; ends clamped inside the svg.
|
|
611
|
+
function xAxisTicks(root, marks, xc, iw, m) {
|
|
612
|
+
const N = marks.length;
|
|
613
|
+
if (!N) return [];
|
|
614
|
+
const GAP = 6;
|
|
615
|
+
let half;
|
|
616
|
+
if (N <= 60) {
|
|
617
|
+
const ws = labelWidths(root, marks.map(t => t.label));
|
|
618
|
+
half = k => ws[k] / 2;
|
|
619
|
+
} else {
|
|
620
|
+
const sample = [marks[0], marks[N - 1]].concat(marks.slice().sort((a, b) => String(b.label).length - String(a.label).length).slice(0, 30));
|
|
621
|
+
const w = labelWidth(root, sample.map(t => t.label));
|
|
622
|
+
half = () => w / 2;
|
|
623
|
+
}
|
|
624
|
+
const center = k => xc(marks[k].at);
|
|
625
|
+
const xAt = k => Math.min(Math.max(center(k), -m.left + half(k)), iw + m.right - half(k));
|
|
626
|
+
const pick = c => Array.from({ length: c }, (_, j) => Math.round(j * (N - 1) / (c - 1)));
|
|
627
|
+
const fits = ks => ks.every((k, j) => !j || xAt(k) - xAt(ks[j - 1]) >= half(k) + half(ks[j - 1]) + GAP);
|
|
628
|
+
const span = center(N - 1) - center(0);
|
|
629
|
+
const minW = N <= 60 ? Math.min(...marks.map((_, k) => half(k) * 2)) : half(0) * 2;
|
|
630
|
+
for (let c = Math.min(N, Math.floor(span / (minW + GAP)) + 1); c > 1; c--) {
|
|
631
|
+
const ks = pick(c);
|
|
632
|
+
if (fits(ks)) return ks.map(k => [marks[k], xAt(k)]);
|
|
633
|
+
}
|
|
634
|
+
return [[marks[0], xAt(0)]];
|
|
589
635
|
}
|
|
590
636
|
|
|
591
637
|
// `list` lets combo pass a subset of series with their original indices
|
|
@@ -593,15 +639,14 @@
|
|
|
593
639
|
// bar rects per index, highlighted from the dense hover columns.
|
|
594
640
|
function drawLines(state, plot, labels, iw, ih, y, list, barsAt) {
|
|
595
641
|
const cfg = state.config, d3 = state.d3;
|
|
596
|
-
const
|
|
642
|
+
const X = xScheme(cfg, d3, labels.length, iw), x = X.x, step = X.step;
|
|
597
643
|
const curve = curveFor(d3, cfg.curve);
|
|
598
644
|
const items = list || cfg.series.map((s, i) => ({ s, i, area: cfg.type === 'area' }));
|
|
599
645
|
// Dense: no per-point dots; hover columns carry the tooltip instead.
|
|
600
|
-
const step = typeof x.step === 'function' ? x.step() : iw / Math.max(1, labels.length);
|
|
601
646
|
const dense = labels.length > 1 && step < 10;
|
|
602
647
|
items.forEach(({ s, i: si, area }) => {
|
|
603
648
|
const color = seriesColorVar(si, s.color);
|
|
604
|
-
const points = labels.map((l, i) => [x(
|
|
649
|
+
const points = labels.map((l, i) => [x(i), y(num(s.data[i], 0))]);
|
|
605
650
|
if (area) {
|
|
606
651
|
const areaGen = d3.area().x(p => p[0]).y0(ih).y1(p => p[1]).curve(curve);
|
|
607
652
|
const ap = svg('path', { class: 'area', d: areaGen(points), style: `--color-chart-color:${color}` }, plot);
|
|
@@ -623,7 +668,7 @@
|
|
|
623
668
|
const g = svg('g', { class: 'hover' }, plot);
|
|
624
669
|
const focus = items.map(({ s, i: si }) => svg('circle', { class: 'focus', r: 3, display: 'none', style: `--color-chart-color:${seriesColorVar(si, s.color)}` }, g));
|
|
625
670
|
labels.forEach((l, i) => {
|
|
626
|
-
const cx = x(
|
|
671
|
+
const cx = x(i);
|
|
627
672
|
const hit = svg('rect', { class: 'hit', x: cx - step / 2, y: 0, width: step, height: ih, style: 'fill:transparent' }, g);
|
|
628
673
|
applyTip(hit, cfg.series.map(s => (s.name ? s.name + ': ' : '') + num(s.data[i], 0)), cfg, tipHead(cfg, l));
|
|
629
674
|
const bars = (barsAt && barsAt[i]) || [];
|
|
@@ -643,17 +688,17 @@
|
|
|
643
688
|
// only applies to the full-series bar chart, not combo.
|
|
644
689
|
function drawBars(state, plot, labels, iw, ih, y, list) {
|
|
645
690
|
const cfg = state.config, d3 = state.d3;
|
|
646
|
-
const x0 = d3
|
|
691
|
+
const x0 = xScheme(cfg, d3, labels.length, iw).band;
|
|
647
692
|
if (cfg.stacked && !list) {
|
|
648
693
|
labels.forEach((l, i) => {
|
|
649
694
|
let acc = 0;
|
|
650
695
|
cfg.series.forEach((s, si) => {
|
|
651
696
|
const v = num(s.data[i], 0);
|
|
652
697
|
const yTop = y(acc + v), yBot = y(acc);
|
|
653
|
-
const rect = svg('rect', { x: x0(
|
|
698
|
+
const rect = svg('rect', { x: x0(i), y: yTop, width: x0.bandwidth(), height: Math.max(0, yBot - yTop), style: `--color-chart-color:${seriesColorVar(si, s.color)}` }, plot);
|
|
654
699
|
applyTip(rect, (s.name ? s.name + ': ' : '') + v, cfg, tipHead(cfg, l));
|
|
655
700
|
animateBar(rect, ih);
|
|
656
|
-
if (cfg.dataLabels && (yBot - yTop) > 14) dataLabel(plot, v, x0(
|
|
701
|
+
if (cfg.dataLabels && (yBot - yTop) > 14) dataLabel(plot, v, x0(i) + x0.bandwidth() / 2, (yTop + yBot) / 2, 'middle', 'central', 'inverse');
|
|
657
702
|
acc += v;
|
|
658
703
|
});
|
|
659
704
|
});
|
|
@@ -666,11 +711,11 @@
|
|
|
666
711
|
const s = o.s, si = o.i;
|
|
667
712
|
const v = num(s.data[i], 0);
|
|
668
713
|
const yy = y(Math.max(0, v));
|
|
669
|
-
const rect = svg('rect', { x: x0(
|
|
714
|
+
const rect = svg('rect', { x: x0(i) + x1(String(k)), y: yy, width: x1.bandwidth(), height: Math.abs(y(v) - y(0)), style: `--color-chart-color:${seriesColorVar(si, s.color)}` }, plot);
|
|
670
715
|
byIndex[i].push(rect);
|
|
671
716
|
applyTip(rect, (s.name ? s.name + ': ' : '') + v, cfg, tipHead(cfg, l));
|
|
672
717
|
animateBar(rect, ih);
|
|
673
|
-
if (cfg.dataLabels) dataLabel(plot, v, x0(
|
|
718
|
+
if (cfg.dataLabels) dataLabel(plot, v, x0(i) + x1(String(k)) + x1.bandwidth() / 2, yy - 4);
|
|
674
719
|
});
|
|
675
720
|
});
|
|
676
721
|
return byIndex;
|
|
@@ -694,10 +739,9 @@
|
|
|
694
739
|
function drawCandles(state, plot, labels, iw, ih, y) {
|
|
695
740
|
const cfg = state.config, d3 = state.d3;
|
|
696
741
|
const cs = candleData(cfg.series[0].data);
|
|
697
|
-
const
|
|
698
|
-
const bw = x0.bandwidth();
|
|
742
|
+
const X = xScheme(cfg, d3, labels.length, iw), bw = X.band.bandwidth();
|
|
699
743
|
cs.forEach((c, i) => {
|
|
700
|
-
const cx =
|
|
744
|
+
const cx = X.x(i);
|
|
701
745
|
const up = c.c >= c.o;
|
|
702
746
|
const g = svg('g', { class: up ? 'positive' : 'negative' }, plot);
|
|
703
747
|
svg('line', { x1: cx, x2: cx, y1: y(c.h), y2: y(c.l) }, g);
|
|
@@ -715,14 +759,14 @@
|
|
|
715
759
|
|
|
716
760
|
function drawScatter(state, plot, labels, iw, ih, y) {
|
|
717
761
|
const cfg = state.config, d3 = state.d3;
|
|
718
|
-
const x = d3
|
|
762
|
+
const x = xScheme(cfg, d3, labels.length, iw).x;
|
|
719
763
|
cfg.series.forEach((s, si) => {
|
|
720
764
|
labels.forEach((l, i) => {
|
|
721
765
|
const v = num(s.data[i], 0);
|
|
722
|
-
const dot = svg('circle', { class: 'scatter', cx: x(
|
|
766
|
+
const dot = svg('circle', { class: 'scatter', cx: x(i), cy: y(v), r: 5, style: `--color-chart-color:${seriesColorVar(si, s.color)}` }, plot);
|
|
723
767
|
applyTip(dot, (s.name ? s.name + ': ' : '') + v, cfg, tipHead(cfg, l));
|
|
724
768
|
animate(dot, [{ opacity: 0, transform: 'scale(0)' }, { opacity: 1, transform: 'scale(1)' }], { duration: 350, delay: i * 25 });
|
|
725
|
-
if (cfg.dataLabels) dataLabel(plot, v, x(
|
|
769
|
+
if (cfg.dataLabels) dataLabel(plot, v, x(i), y(v) - 9);
|
|
726
770
|
});
|
|
727
771
|
});
|
|
728
772
|
}
|
|
@@ -752,11 +796,13 @@
|
|
|
752
796
|
// fallback). Sizes axis gutters to their content so charts sit balanced.
|
|
753
797
|
function labelWidth(root, items, cls) {
|
|
754
798
|
if (!items || !items.length) return 0;
|
|
799
|
+
return Math.max(...labelWidths(root, items, cls));
|
|
800
|
+
}
|
|
801
|
+
function labelWidths(root, items, cls) {
|
|
755
802
|
const probe = svg('text', cls ? { class: cls, x: -9999, y: -9999 } : { x: -9999, y: -9999 }, root);
|
|
756
|
-
let
|
|
757
|
-
for (const s of items) { probe.textContent = String(s); let w = 0; try { w = probe.getComputedTextLength(); } catch (_) { } if (!w) w = String(s).length * 7; if (w > max) max = w; }
|
|
803
|
+
const out = items.map(s => { probe.textContent = String(s == null ? '' : s); let w = 0; try { w = probe.getComputedTextLength(); } catch (_) { } return Math.ceil(w || String(s == null ? '' : s).length * 7); });
|
|
758
804
|
root.removeChild(probe);
|
|
759
|
-
return
|
|
805
|
+
return out;
|
|
760
806
|
}
|
|
761
807
|
|
|
762
808
|
function drawGauge(state, root, width, height) {
|
package/lib/manifest.data.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"manifest.appwrite.auth.js": "sha384-dsIWnH0qCAGSzAXMGrd8fvOrVl4tOIE6j5tC35JPTrQXZ56qLD36ARyvhR7vi3Id",
|
|
3
|
-
"manifest.appwrite.data.js": "sha384-
|
|
3
|
+
"manifest.appwrite.data.js": "sha384-bg/IZDy3pRsvCsopmIJQ1g5uc3KjpL6O1X/waOZLwDw0KjXuHsG8dRMkKdTdviP4",
|
|
4
4
|
"manifest.appwrite.presences.js": "sha384-JyVDWFT69b7Svq8J8p9tNWe2v9PZNQBY5UyhtOl1vnuHFAX0CRQ3MA9SiKq5wzNh",
|
|
5
5
|
"manifest.bindings.js": "sha384-lPtMf8Ykaic9gNVZKq8Scia1881ZeMAyxer3WCIkUNwwrgzGBWto1OXADUwjvORF",
|
|
6
|
-
"manifest.charts.js": "sha384-
|
|
6
|
+
"manifest.charts.js": "sha384-FTLltd+0atALQQD5Wi9eASFnNYYzhxouH3HJlMkFrDfjTV9/8TZhEif7bMDqElq3",
|
|
7
7
|
"manifest.chat.js": "sha384-88DfMfJLoi2oxclVD2iIMDkIGAExMXq5k47mekUredlicLaP3oZY5bwtwqs+TqDF",
|
|
8
8
|
"manifest.code.js": "sha384-WGPlZE5Sp9GygUzJSmCdpLyYQTgvmEKc9BQS9Hmq1VTQwkqYJzPSWibHvPekcres",
|
|
9
9
|
"manifest.color.js": "sha384-6Rv3LxyTcZNjrhtayQfqRdCx0uSZ4BiEbgEI98I62eTvp8Aw7LBIoNJ0Je1oktwL",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"manifest.combobox.js": "sha384-MILTkrgsTzsYUjGo4ZuADqV85Xs4GmfB4xexfe9vbJMIoQTZ42W4zs+DTaVSPEsx",
|
|
12
12
|
"manifest.components.js": "sha384-BUFA8h+G5Plr82sV7bKzO42pPoiRZwRQcKj1lt2ROFiKjjlkayU/vmkAFqEsdBA+",
|
|
13
13
|
"manifest.computed.js": "sha384-GYML/e81gQfN+iDbqhPUgny8bINCyL+SrbTofoGk4hlCnLLjv51mCv42JMqq+ku5",
|
|
14
|
-
"manifest.data.js": "sha384-
|
|
14
|
+
"manifest.data.js": "sha384-Ie+YDjD9X8mUgLqbRdgt6KLXNSB6ysP++yBs3W7JdhLr19xIkY9d54RLVGvwY6v7",
|
|
15
15
|
"manifest.datepicker.js": "sha384-XnbeURni2X91ozVzatQcSjYYIS4MoW12dBRJnYAGBr0nCQ624heH5s+xtQSpLZX6",
|
|
16
16
|
"manifest.defer.js": "sha384-pMRGqQKiEoJhpUcD40QeM4jEHau7sz9Xn/YCpiUamT1T4xJBZDSiYX+xnVrSWoq+",
|
|
17
17
|
"manifest.device.js": "sha384-g+txmrEszYtuOvRelTp/c1wSNR2AtllVI9rx5NPPD7DzhVUnMNughonZykv2xlBW",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"manifest.slides.js": "sha384-3uRTkyK9XPLmnxI2+igZlpi4EyPlU/7IHj5j3BZJJ2KN455vXyk99fiXV3feO/XY",
|
|
29
29
|
"manifest.status.js": "sha384-MBO345ab7H6Uq1X2dZLt4Ge1Gcra+Z2qYApvlAeIV8CJhDDJrz2FPXpp+Kcp8zcM",
|
|
30
30
|
"manifest.svg.js": "sha384-qr/8H9+2cIhSXNbRWRtIdrDlTOxKlNJqwEefHvCYoiBNW/kKhPTFa109Orv/EBnb",
|
|
31
|
-
"manifest.sw.js": "sha384-
|
|
31
|
+
"manifest.sw.js": "sha384-rK22P7FyWRLX/DuW34gS9OIShs4Jo/s5+10o9Y23dbrbktHY3XYfzRygMlIgK4IB",
|
|
32
32
|
"manifest.tabs.js": "sha384-OIIcyaQnGS0eNYk4zgAFEDboNYect7THvUd9D0V6nqCeDOxQcoiqLrBEmmWVTTet",
|
|
33
33
|
"manifest.tailwind.js": "sha384-r/Jvqb+Piz21jUts10BbVAJoKkShOdJRVFpywyi4HPIi/OfOJq5CtPyWAPbdkMgt",
|
|
34
34
|
"manifest.toasts.js": "sha384-3zkWxzw693pxg3QDFsoYCA3CqYaLKmBaMArULXODD66Utolpewl0OAeTB92aWUVv",
|
package/lib/manifest.sw.js
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
// Build stamps the published version here; unstamped (dev) falls back to the
|
|
18
18
|
// registration URL's `v`, then 'dev'.
|
|
19
|
-
const BUILD_VERSION = '0.5.
|
|
19
|
+
const BUILD_VERSION = '0.5.245';
|
|
20
20
|
const CACHE_PREFIX = 'mnfst-sw:';
|
|
21
21
|
const META_CACHE = CACHE_PREFIX + 'meta';
|
|
22
22
|
// Sized to hold a full precache.json warm-up (PRECACHE_MAX_ENTRIES server-side)
|