@bicharts/chart-host 0.6.62 → 0.6.64
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.
|
@@ -475,6 +475,170 @@ var require_papaparse_min = __commonJS({
|
|
|
475
475
|
}
|
|
476
476
|
});
|
|
477
477
|
|
|
478
|
+
// src/labelContrast.ts
|
|
479
|
+
function parseRGBA(c2) {
|
|
480
|
+
if (typeof c2 !== "string") return null;
|
|
481
|
+
const s2 = c2.trim();
|
|
482
|
+
const m4 = s2.match(/^rgba?\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)\s*(?:,\s*([\d.]+)\s*)?\)$/i);
|
|
483
|
+
if (m4) return [parseFloat(m4[1]), parseFloat(m4[2]), parseFloat(m4[3]), m4[4] !== void 0 ? parseFloat(m4[4]) : 1];
|
|
484
|
+
let h4 = s2.replace(/^#/, "");
|
|
485
|
+
if (h4.length === 3) h4 = h4.split("").map((ch) => ch + ch).join("");
|
|
486
|
+
if (h4.length === 6 && /^[0-9a-fA-F]{6}$/.test(h4)) {
|
|
487
|
+
return [parseInt(h4.slice(0, 2), 16), parseInt(h4.slice(2, 4), 16), parseInt(h4.slice(4, 6), 16), 1];
|
|
488
|
+
}
|
|
489
|
+
return null;
|
|
490
|
+
}
|
|
491
|
+
var DARK_TEXT = "#111111";
|
|
492
|
+
var LIGHT_TEXT = "#ffffff";
|
|
493
|
+
var MIN_CONTRAST = 3;
|
|
494
|
+
var WHITE_TEXT_BG_LUM = 0.5;
|
|
495
|
+
var PILL_MIN_ALPHA = 0.05;
|
|
496
|
+
var PILL_OPAQUE_ALPHA = 0.85;
|
|
497
|
+
var PAGE_MATCH_TOLERANCE = 2;
|
|
498
|
+
function isPillBackdropAlpha(a3) {
|
|
499
|
+
return a3 >= PILL_MIN_ALPHA && a3 < PILL_OPAQUE_ALPHA;
|
|
500
|
+
}
|
|
501
|
+
var PILL_MIN_COVERAGE = 0.6;
|
|
502
|
+
function pillBacksGlyph(overlapArea, glyphArea) {
|
|
503
|
+
if (!(glyphArea > 0) || !isFinite(overlapArea) || overlapArea <= 0) return false;
|
|
504
|
+
return overlapArea / glyphArea >= PILL_MIN_COVERAGE;
|
|
505
|
+
}
|
|
506
|
+
var BACKING_MAJORITY = 0.5;
|
|
507
|
+
function backingHoldsGlyph(backedArea, glyphArea) {
|
|
508
|
+
if (!(glyphArea > 0) || !isFinite(backedArea) || backedArea <= 0) return false;
|
|
509
|
+
return backedArea / glyphArea >= BACKING_MAJORITY;
|
|
510
|
+
}
|
|
511
|
+
function cellSuppressesNormalize(cellClass) {
|
|
512
|
+
return typeof cellClass === "string" && /(^|\s)lch-deck-panel(\s|$)/.test(cellClass);
|
|
513
|
+
}
|
|
514
|
+
var NAMED = {
|
|
515
|
+
white: [255, 255, 255, 1],
|
|
516
|
+
black: [0, 0, 0, 1],
|
|
517
|
+
none: [0, 0, 0, 0],
|
|
518
|
+
transparent: [0, 0, 0, 0]
|
|
519
|
+
};
|
|
520
|
+
function toRGBA(c2) {
|
|
521
|
+
if (typeof c2 !== "string") return null;
|
|
522
|
+
const k3 = c2.trim().toLowerCase();
|
|
523
|
+
if (k3 in NAMED) return NAMED[k3];
|
|
524
|
+
return parseRGBA(c2);
|
|
525
|
+
}
|
|
526
|
+
function compositeOver(fg, bg) {
|
|
527
|
+
const a3 = Math.max(0, Math.min(1, fg[3]));
|
|
528
|
+
return [
|
|
529
|
+
Math.round(fg[0] * a3 + bg[0] * (1 - a3)),
|
|
530
|
+
Math.round(fg[1] * a3 + bg[1] * (1 - a3)),
|
|
531
|
+
Math.round(fg[2] * a3 + bg[2] * (1 - a3))
|
|
532
|
+
];
|
|
533
|
+
}
|
|
534
|
+
function relativeLuminance(rgb) {
|
|
535
|
+
const lin = rgb.map((v) => {
|
|
536
|
+
const s2 = v / 255;
|
|
537
|
+
return s2 <= 0.03928 ? s2 / 12.92 : Math.pow((s2 + 0.055) / 1.055, 2.4);
|
|
538
|
+
});
|
|
539
|
+
return 0.2126 * lin[0] + 0.7152 * lin[1] + 0.0722 * lin[2];
|
|
540
|
+
}
|
|
541
|
+
function contrastRatio(l1, l2) {
|
|
542
|
+
const hi = Math.max(l1, l2);
|
|
543
|
+
const lo = Math.min(l1, l2);
|
|
544
|
+
return (hi + 0.05) / (lo + 0.05);
|
|
545
|
+
}
|
|
546
|
+
function decideLabelColor(textColor, fill, fillOpacity, pageBg, minContrast = MIN_CONTRAST, normalize = false) {
|
|
547
|
+
const fillRGBA = toRGBA(fill);
|
|
548
|
+
if (!fillRGBA) return { fix: false, color: "", reason: "fill-unparsed" };
|
|
549
|
+
const pageRGBA = toRGBA(pageBg) || [255, 255, 255, 1];
|
|
550
|
+
const pageRGB = [pageRGBA[0], pageRGBA[1], pageRGBA[2]];
|
|
551
|
+
const effFill = [fillRGBA[0], fillRGBA[1], fillRGBA[2], fillRGBA[3] * clamp01(fillOpacity)];
|
|
552
|
+
const bgRGB = compositeOver(effFill, pageRGB);
|
|
553
|
+
const bgLum = relativeLuminance(bgRGB);
|
|
554
|
+
const bgIsPage = Math.abs(bgRGB[0] - pageRGB[0]) <= PAGE_MATCH_TOLERANCE && Math.abs(bgRGB[1] - pageRGB[1]) <= PAGE_MATCH_TOLERANCE && Math.abs(bgRGB[2] - pageRGB[2]) <= PAGE_MATCH_TOLERANCE;
|
|
555
|
+
const effNormalize = normalize && !bgIsPage;
|
|
556
|
+
const textRGBA = toRGBA(textColor);
|
|
557
|
+
if (!effNormalize && textRGBA) {
|
|
558
|
+
const txtRGB = compositeOver(textRGBA, bgRGB);
|
|
559
|
+
const cur = contrastRatio(relativeLuminance(txtRGB), bgLum);
|
|
560
|
+
if (cur >= minContrast) return { fix: false, color: "", reason: "ok" };
|
|
561
|
+
}
|
|
562
|
+
const darkC = contrastRatio(relativeLuminance(hexToRGB(DARK_TEXT)), bgLum);
|
|
563
|
+
const lightC = contrastRatio(relativeLuminance(hexToRGB(LIGHT_TEXT)), bgLum);
|
|
564
|
+
let useLight = bgLum <= WHITE_TEXT_BG_LUM;
|
|
565
|
+
if (useLight && lightC < minContrast && darkC >= minContrast) useLight = false;
|
|
566
|
+
if (!useLight && darkC < minContrast && lightC >= minContrast) useLight = true;
|
|
567
|
+
return useLight ? { fix: true, color: LIGHT_TEXT, reason: "fixed-light" } : { fix: true, color: DARK_TEXT, reason: "fixed-dark" };
|
|
568
|
+
}
|
|
569
|
+
var GLYPH_SAMPLE_N = 3;
|
|
570
|
+
function glyphSampleGrid(box2, n = GLYPH_SAMPLE_N) {
|
|
571
|
+
const out = [];
|
|
572
|
+
if (!box2 || !(box2.width > 0) || !(box2.height > 0) || !(n >= 1)) return out;
|
|
573
|
+
const k3 = Math.floor(n);
|
|
574
|
+
for (let i = 0; i < k3; i++) {
|
|
575
|
+
for (let j4 = 0; j4 < k3; j4++) {
|
|
576
|
+
out.push({
|
|
577
|
+
x: box2.left + box2.width * (i + 0.5) / k3,
|
|
578
|
+
y: box2.top + box2.height * (j4 + 0.5) / k3
|
|
579
|
+
});
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
return out;
|
|
583
|
+
}
|
|
584
|
+
var STRADDLE_COLS = 8;
|
|
585
|
+
var STRADDLE_ROWS = 2;
|
|
586
|
+
var STRADDLE_MIN_SHARE = 0.125;
|
|
587
|
+
var STRADDLE_TARGET_CONTRAST = 4.5;
|
|
588
|
+
var STRADDLE_PILL_ALPHA = 0.9;
|
|
589
|
+
function straddleSampleGrid(box2) {
|
|
590
|
+
const out = [];
|
|
591
|
+
if (!box2 || !(box2.width > 0) || !(box2.height > 0)) return out;
|
|
592
|
+
for (let i = 0; i < STRADDLE_COLS; i++) {
|
|
593
|
+
for (let j4 = 0; j4 < STRADDLE_ROWS; j4++) {
|
|
594
|
+
out.push({
|
|
595
|
+
x: box2.left + box2.width * (i + 0.5) / STRADDLE_COLS,
|
|
596
|
+
y: box2.top + box2.height * (j4 + 0.5) / STRADDLE_ROWS
|
|
597
|
+
});
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
return out;
|
|
601
|
+
}
|
|
602
|
+
function backgroundGroups(bgs, tol = 8) {
|
|
603
|
+
const groups = [];
|
|
604
|
+
for (const b4 of bgs || []) {
|
|
605
|
+
const g5 = groups.find((x3) => Math.abs(x3.rgb[0] - b4[0]) <= tol && Math.abs(x3.rgb[1] - b4[1]) <= tol && Math.abs(x3.rgb[2] - b4[2]) <= tol);
|
|
606
|
+
if (g5) g5.n++;
|
|
607
|
+
else groups.push({ rgb: [b4[0], b4[1], b4[2]], n: 1 });
|
|
608
|
+
}
|
|
609
|
+
return groups.sort((a3, b4) => b4.n - a3.n);
|
|
610
|
+
}
|
|
611
|
+
function straddles(bgs) {
|
|
612
|
+
if (!bgs || bgs.length < 2) return false;
|
|
613
|
+
const g5 = backgroundGroups(bgs);
|
|
614
|
+
return g5.length >= 2 && g5[1].n / bgs.length >= STRADDLE_MIN_SHARE;
|
|
615
|
+
}
|
|
616
|
+
function minContrastOver(textColor, bgs) {
|
|
617
|
+
const t = toRGBA(textColor);
|
|
618
|
+
if (!t || !bgs || !bgs.length) return 0;
|
|
619
|
+
let worst = Infinity;
|
|
620
|
+
for (const b4 of bgs) {
|
|
621
|
+
const tx = compositeOver(t, b4);
|
|
622
|
+
worst = Math.min(worst, contrastRatio(relativeLuminance(tx), relativeLuminance(b4)));
|
|
623
|
+
}
|
|
624
|
+
return worst;
|
|
625
|
+
}
|
|
626
|
+
function pickColorOver(textColor, bgs, target = STRADDLE_TARGET_CONTRAST) {
|
|
627
|
+
const cur = minContrastOver(textColor, bgs);
|
|
628
|
+
if (cur >= target) return { color: String(textColor), contrast: cur, keep: true };
|
|
629
|
+
const d2 = minContrastOver(DARK_TEXT, bgs), l2 = minContrastOver(LIGHT_TEXT, bgs);
|
|
630
|
+
const best = d2 >= l2 ? { color: DARK_TEXT, contrast: d2 } : { color: LIGHT_TEXT, contrast: l2 };
|
|
631
|
+
return best.contrast > cur ? { ...best, keep: false } : { color: String(textColor), contrast: cur, keep: true };
|
|
632
|
+
}
|
|
633
|
+
function clamp01(v) {
|
|
634
|
+
if (typeof v !== "number" || !isFinite(v)) return 1;
|
|
635
|
+
return Math.max(0, Math.min(1, v));
|
|
636
|
+
}
|
|
637
|
+
function hexToRGB(hex2) {
|
|
638
|
+
const p4 = toRGBA(hex2);
|
|
639
|
+
return [p4[0], p4[1], p4[2]];
|
|
640
|
+
}
|
|
641
|
+
|
|
478
642
|
// src/deltaE.ts
|
|
479
643
|
function linearise(c2) {
|
|
480
644
|
const v = c2 / 255;
|
|
@@ -776,6 +940,12 @@ function resolveAutoColorScale(p4) {
|
|
|
776
940
|
}
|
|
777
941
|
|
|
778
942
|
// src/defaults.ts
|
|
943
|
+
function themedLand(p4) {
|
|
944
|
+
const bg = p4.geoLandColor ? null : toRGBA(p4.backgroundColor);
|
|
945
|
+
if (!bg || bg[3] < 1 || relativeLuminance([bg[0], bg[1], bg[2]]) > 0.2) return void 0;
|
|
946
|
+
const fg = toRGBA(p4.themeFg) ?? [255, 255, 255, 1];
|
|
947
|
+
return "#" + compositeOver([fg[0], fg[1], fg[2], 0.18], [bg[0], bg[1], bg[2]]).map((v) => v.toString(16).padStart(2, "0")).join("");
|
|
948
|
+
}
|
|
779
949
|
var clamp = (n, lo, hi) => Math.max(lo, Math.min(hi, n));
|
|
780
950
|
var numberOr = (raw, dflt) => {
|
|
781
951
|
const n = raw == null || raw === "" ? NaN : Number(raw);
|
|
@@ -846,7 +1016,7 @@ function resolveOptions(p4) {
|
|
|
846
1016
|
// Map fills: `raw || undefined` like the colour-scale endpoints. The no-data ->
|
|
847
1017
|
// land cascade is left to the chart (so the fallback chain is visible in the
|
|
848
1018
|
// generated code); HC substitution has already happened in the caller.
|
|
849
|
-
geoLandColor: p4.geoLandColor || void 0,
|
|
1019
|
+
geoLandColor: p4.geoLandColor || themedLand(p4) || void 0,
|
|
850
1020
|
geoNoDataColor: p4.geoNoDataColor || void 0,
|
|
851
1021
|
aggregation: (p4.aggregation == null ? "" : String(p4.aggregation)) || void 0,
|
|
852
1022
|
// A recognised value wins, anything else falls to the default: an unknown string must
|
|
@@ -2281,9 +2451,9 @@ function createMarkResolver(env) {
|
|
|
2281
2451
|
const r2 = el.getBoundingClientRect ? el.getBoundingClientRect() : null;
|
|
2282
2452
|
if (!r2 || r2.width <= 0 || r2.height <= 0) continue;
|
|
2283
2453
|
if (x3 < r2.left || x3 > r2.right || y2 < r2.top || y2 > r2.bottom) continue;
|
|
2284
|
-
const
|
|
2285
|
-
if (
|
|
2286
|
-
bestArea =
|
|
2454
|
+
const area2 = r2.width * r2.height;
|
|
2455
|
+
if (area2 < bestArea) {
|
|
2456
|
+
bestArea = area2;
|
|
2287
2457
|
best = el;
|
|
2288
2458
|
}
|
|
2289
2459
|
}
|
|
@@ -2892,15 +3062,15 @@ function ctmScaleOf(m4) {
|
|
|
2892
3062
|
}
|
|
2893
3063
|
function svgInkReach(svg) {
|
|
2894
3064
|
try {
|
|
2895
|
-
const
|
|
2896
|
-
if (!(
|
|
3065
|
+
const box2 = svg.getBoundingClientRect();
|
|
3066
|
+
if (!(box2.width > 0) || !(box2.height > 0)) return null;
|
|
2897
3067
|
const els = svg.querySelectorAll(FIT_CONTENT_SELECTOR);
|
|
2898
3068
|
const clipOf = clipWindowReader(svg);
|
|
2899
3069
|
let right = -Infinity, bottom = -Infinity, seen = 0;
|
|
2900
3070
|
for (let i = 0; i < els.length && seen < FIT_WALK_CAP; i++) {
|
|
2901
3071
|
const r2 = els[i].getBoundingClientRect();
|
|
2902
3072
|
if (r2.width <= 0 && r2.height <= 0) continue;
|
|
2903
|
-
if (isPhantomBox(r2.width, r2.height,
|
|
3073
|
+
if (isPhantomBox(r2.width, r2.height, box2.width, box2.height)) continue;
|
|
2904
3074
|
let rr = r2.right, rb = r2.bottom;
|
|
2905
3075
|
const clip = clipOf(els[i]);
|
|
2906
3076
|
if (clip) {
|
|
@@ -2913,51 +3083,39 @@ function svgInkReach(svg) {
|
|
|
2913
3083
|
if (rb > bottom) bottom = rb;
|
|
2914
3084
|
}
|
|
2915
3085
|
if (seen === 0) return null;
|
|
2916
|
-
return { right: right -
|
|
3086
|
+
return { right: right - box2.left, bottom: bottom - box2.top };
|
|
3087
|
+
} catch {
|
|
3088
|
+
return null;
|
|
3089
|
+
}
|
|
3090
|
+
}
|
|
3091
|
+
function clipWindowOf(el) {
|
|
3092
|
+
try {
|
|
3093
|
+
const m4 = /url\(\s*['"]?#([^'")\s]+)['"]?\s*\)/.exec(el.getAttribute("clip-path") || "");
|
|
3094
|
+
const cp = m4 ? (el.closest("svg") ?? el.ownerDocument).querySelector(`clipPath[id="${m4[1].replace(/"/g, '\\"')}"]`) : null;
|
|
3095
|
+
const ctm = cp ? el.getScreenCTM?.() : null;
|
|
3096
|
+
if (!cp || !ctm || cp.getAttribute("clipPathUnits") === "objectBoundingBox") return null;
|
|
3097
|
+
let l2 = Infinity, t = Infinity, r2 = -Infinity, b4 = -Infinity;
|
|
3098
|
+
for (let i = 0; i < cp.children.length; i++) {
|
|
3099
|
+
const bb = cp.children[i].getBBox?.();
|
|
3100
|
+
if (!bb || !(bb.width > 0) || !(bb.height > 0)) continue;
|
|
3101
|
+
for (const [x3, y2] of [[bb.x, bb.y], [bb.x + bb.width, bb.y], [bb.x, bb.y + bb.height], [bb.x + bb.width, bb.y + bb.height]]) {
|
|
3102
|
+
const sx = ctm.a * x3 + ctm.c * y2 + ctm.e, sy = ctm.b * x3 + ctm.d * y2 + ctm.f;
|
|
3103
|
+
l2 = Math.min(l2, sx);
|
|
3104
|
+
t = Math.min(t, sy);
|
|
3105
|
+
r2 = Math.max(r2, sx);
|
|
3106
|
+
b4 = Math.max(b4, sy);
|
|
3107
|
+
}
|
|
3108
|
+
}
|
|
3109
|
+
return isFinite(r2) && isFinite(b4) ? { left: l2, top: t, right: r2, bottom: b4 } : null;
|
|
2917
3110
|
} catch {
|
|
2918
3111
|
return null;
|
|
2919
3112
|
}
|
|
2920
3113
|
}
|
|
2921
3114
|
function clipWindowReader(svg) {
|
|
2922
3115
|
const own = /* @__PURE__ */ new Map();
|
|
2923
|
-
const byId = (id) => {
|
|
2924
|
-
try {
|
|
2925
|
-
return svg.querySelector(`clipPath[id="${id.replace(/"/g, '\\"')}"]`);
|
|
2926
|
-
} catch {
|
|
2927
|
-
return null;
|
|
2928
|
-
}
|
|
2929
|
-
};
|
|
2930
3116
|
const windowOf = (el) => {
|
|
2931
|
-
if (own.has(el))
|
|
2932
|
-
|
|
2933
|
-
try {
|
|
2934
|
-
const ref = el.getAttribute("clip-path") || "";
|
|
2935
|
-
const m4 = /url\(\s*['"]?#([^'")\s]+)['"]?\s*\)/.exec(ref);
|
|
2936
|
-
const cp = m4 ? byId(m4[1]) : null;
|
|
2937
|
-
const ctm = cp ? el.getScreenCTM?.() : null;
|
|
2938
|
-
if (cp && ctm && cp.getAttribute("clipPathUnits") !== "objectBoundingBox") {
|
|
2939
|
-
let r2 = -Infinity, b4 = -Infinity;
|
|
2940
|
-
for (let i = 0; i < cp.children.length; i++) {
|
|
2941
|
-
const bb = cp.children[i].getBBox?.();
|
|
2942
|
-
if (!bb || !(bb.width > 0) || !(bb.height > 0)) continue;
|
|
2943
|
-
for (const [x3, y2] of [
|
|
2944
|
-
[bb.x, bb.y],
|
|
2945
|
-
[bb.x + bb.width, bb.y],
|
|
2946
|
-
[bb.x, bb.y + bb.height],
|
|
2947
|
-
[bb.x + bb.width, bb.y + bb.height]
|
|
2948
|
-
]) {
|
|
2949
|
-
const sx = ctm.a * x3 + ctm.c * y2 + ctm.e, sy = ctm.b * x3 + ctm.d * y2 + ctm.f;
|
|
2950
|
-
if (sx > r2) r2 = sx;
|
|
2951
|
-
if (sy > b4) b4 = sy;
|
|
2952
|
-
}
|
|
2953
|
-
}
|
|
2954
|
-
if (isFinite(r2) && isFinite(b4)) win = { right: r2, bottom: b4 };
|
|
2955
|
-
}
|
|
2956
|
-
} catch {
|
|
2957
|
-
win = null;
|
|
2958
|
-
}
|
|
2959
|
-
own.set(el, win);
|
|
2960
|
-
return win;
|
|
3117
|
+
if (!own.has(el)) own.set(el, clipWindowOf(el));
|
|
3118
|
+
return own.get(el);
|
|
2961
3119
|
};
|
|
2962
3120
|
return (el) => {
|
|
2963
3121
|
let acc = null;
|
|
@@ -3343,170 +3501,6 @@ function fitRenderedChart(container, opts = {}) {
|
|
|
3343
3501
|
return result;
|
|
3344
3502
|
}
|
|
3345
3503
|
|
|
3346
|
-
// src/labelContrast.ts
|
|
3347
|
-
function parseRGBA(c2) {
|
|
3348
|
-
if (typeof c2 !== "string") return null;
|
|
3349
|
-
const s2 = c2.trim();
|
|
3350
|
-
const m4 = s2.match(/^rgba?\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)\s*(?:,\s*([\d.]+)\s*)?\)$/i);
|
|
3351
|
-
if (m4) return [parseFloat(m4[1]), parseFloat(m4[2]), parseFloat(m4[3]), m4[4] !== void 0 ? parseFloat(m4[4]) : 1];
|
|
3352
|
-
let h4 = s2.replace(/^#/, "");
|
|
3353
|
-
if (h4.length === 3) h4 = h4.split("").map((ch) => ch + ch).join("");
|
|
3354
|
-
if (h4.length === 6 && /^[0-9a-fA-F]{6}$/.test(h4)) {
|
|
3355
|
-
return [parseInt(h4.slice(0, 2), 16), parseInt(h4.slice(2, 4), 16), parseInt(h4.slice(4, 6), 16), 1];
|
|
3356
|
-
}
|
|
3357
|
-
return null;
|
|
3358
|
-
}
|
|
3359
|
-
var DARK_TEXT = "#111111";
|
|
3360
|
-
var LIGHT_TEXT = "#ffffff";
|
|
3361
|
-
var MIN_CONTRAST = 3;
|
|
3362
|
-
var WHITE_TEXT_BG_LUM = 0.5;
|
|
3363
|
-
var PILL_MIN_ALPHA = 0.05;
|
|
3364
|
-
var PILL_OPAQUE_ALPHA = 0.85;
|
|
3365
|
-
var PAGE_MATCH_TOLERANCE = 2;
|
|
3366
|
-
function isPillBackdropAlpha(a3) {
|
|
3367
|
-
return a3 >= PILL_MIN_ALPHA && a3 < PILL_OPAQUE_ALPHA;
|
|
3368
|
-
}
|
|
3369
|
-
var PILL_MIN_COVERAGE = 0.6;
|
|
3370
|
-
function pillBacksGlyph(overlapArea, glyphArea) {
|
|
3371
|
-
if (!(glyphArea > 0) || !isFinite(overlapArea) || overlapArea <= 0) return false;
|
|
3372
|
-
return overlapArea / glyphArea >= PILL_MIN_COVERAGE;
|
|
3373
|
-
}
|
|
3374
|
-
var BACKING_MAJORITY = 0.5;
|
|
3375
|
-
function backingHoldsGlyph(backedArea, glyphArea) {
|
|
3376
|
-
if (!(glyphArea > 0) || !isFinite(backedArea) || backedArea <= 0) return false;
|
|
3377
|
-
return backedArea / glyphArea >= BACKING_MAJORITY;
|
|
3378
|
-
}
|
|
3379
|
-
function cellSuppressesNormalize(cellClass) {
|
|
3380
|
-
return typeof cellClass === "string" && /(^|\s)lch-deck-panel(\s|$)/.test(cellClass);
|
|
3381
|
-
}
|
|
3382
|
-
var NAMED = {
|
|
3383
|
-
white: [255, 255, 255, 1],
|
|
3384
|
-
black: [0, 0, 0, 1],
|
|
3385
|
-
none: [0, 0, 0, 0],
|
|
3386
|
-
transparent: [0, 0, 0, 0]
|
|
3387
|
-
};
|
|
3388
|
-
function toRGBA(c2) {
|
|
3389
|
-
if (typeof c2 !== "string") return null;
|
|
3390
|
-
const k3 = c2.trim().toLowerCase();
|
|
3391
|
-
if (k3 in NAMED) return NAMED[k3];
|
|
3392
|
-
return parseRGBA(c2);
|
|
3393
|
-
}
|
|
3394
|
-
function compositeOver(fg, bg) {
|
|
3395
|
-
const a3 = Math.max(0, Math.min(1, fg[3]));
|
|
3396
|
-
return [
|
|
3397
|
-
Math.round(fg[0] * a3 + bg[0] * (1 - a3)),
|
|
3398
|
-
Math.round(fg[1] * a3 + bg[1] * (1 - a3)),
|
|
3399
|
-
Math.round(fg[2] * a3 + bg[2] * (1 - a3))
|
|
3400
|
-
];
|
|
3401
|
-
}
|
|
3402
|
-
function relativeLuminance(rgb) {
|
|
3403
|
-
const lin = rgb.map((v) => {
|
|
3404
|
-
const s2 = v / 255;
|
|
3405
|
-
return s2 <= 0.03928 ? s2 / 12.92 : Math.pow((s2 + 0.055) / 1.055, 2.4);
|
|
3406
|
-
});
|
|
3407
|
-
return 0.2126 * lin[0] + 0.7152 * lin[1] + 0.0722 * lin[2];
|
|
3408
|
-
}
|
|
3409
|
-
function contrastRatio(l1, l2) {
|
|
3410
|
-
const hi = Math.max(l1, l2);
|
|
3411
|
-
const lo = Math.min(l1, l2);
|
|
3412
|
-
return (hi + 0.05) / (lo + 0.05);
|
|
3413
|
-
}
|
|
3414
|
-
function decideLabelColor(textColor, fill, fillOpacity, pageBg, minContrast = MIN_CONTRAST, normalize = false) {
|
|
3415
|
-
const fillRGBA = toRGBA(fill);
|
|
3416
|
-
if (!fillRGBA) return { fix: false, color: "", reason: "fill-unparsed" };
|
|
3417
|
-
const pageRGBA = toRGBA(pageBg) || [255, 255, 255, 1];
|
|
3418
|
-
const pageRGB = [pageRGBA[0], pageRGBA[1], pageRGBA[2]];
|
|
3419
|
-
const effFill = [fillRGBA[0], fillRGBA[1], fillRGBA[2], fillRGBA[3] * clamp01(fillOpacity)];
|
|
3420
|
-
const bgRGB = compositeOver(effFill, pageRGB);
|
|
3421
|
-
const bgLum = relativeLuminance(bgRGB);
|
|
3422
|
-
const bgIsPage = Math.abs(bgRGB[0] - pageRGB[0]) <= PAGE_MATCH_TOLERANCE && Math.abs(bgRGB[1] - pageRGB[1]) <= PAGE_MATCH_TOLERANCE && Math.abs(bgRGB[2] - pageRGB[2]) <= PAGE_MATCH_TOLERANCE;
|
|
3423
|
-
const effNormalize = normalize && !bgIsPage;
|
|
3424
|
-
const textRGBA = toRGBA(textColor);
|
|
3425
|
-
if (!effNormalize && textRGBA) {
|
|
3426
|
-
const txtRGB = compositeOver(textRGBA, bgRGB);
|
|
3427
|
-
const cur = contrastRatio(relativeLuminance(txtRGB), bgLum);
|
|
3428
|
-
if (cur >= minContrast) return { fix: false, color: "", reason: "ok" };
|
|
3429
|
-
}
|
|
3430
|
-
const darkC = contrastRatio(relativeLuminance(hexToRGB(DARK_TEXT)), bgLum);
|
|
3431
|
-
const lightC = contrastRatio(relativeLuminance(hexToRGB(LIGHT_TEXT)), bgLum);
|
|
3432
|
-
let useLight = bgLum <= WHITE_TEXT_BG_LUM;
|
|
3433
|
-
if (useLight && lightC < minContrast && darkC >= minContrast) useLight = false;
|
|
3434
|
-
if (!useLight && darkC < minContrast && lightC >= minContrast) useLight = true;
|
|
3435
|
-
return useLight ? { fix: true, color: LIGHT_TEXT, reason: "fixed-light" } : { fix: true, color: DARK_TEXT, reason: "fixed-dark" };
|
|
3436
|
-
}
|
|
3437
|
-
var GLYPH_SAMPLE_N = 3;
|
|
3438
|
-
function glyphSampleGrid(box, n = GLYPH_SAMPLE_N) {
|
|
3439
|
-
const out = [];
|
|
3440
|
-
if (!box || !(box.width > 0) || !(box.height > 0) || !(n >= 1)) return out;
|
|
3441
|
-
const k3 = Math.floor(n);
|
|
3442
|
-
for (let i = 0; i < k3; i++) {
|
|
3443
|
-
for (let j4 = 0; j4 < k3; j4++) {
|
|
3444
|
-
out.push({
|
|
3445
|
-
x: box.left + box.width * (i + 0.5) / k3,
|
|
3446
|
-
y: box.top + box.height * (j4 + 0.5) / k3
|
|
3447
|
-
});
|
|
3448
|
-
}
|
|
3449
|
-
}
|
|
3450
|
-
return out;
|
|
3451
|
-
}
|
|
3452
|
-
var STRADDLE_COLS = 8;
|
|
3453
|
-
var STRADDLE_ROWS = 2;
|
|
3454
|
-
var STRADDLE_MIN_SHARE = 0.125;
|
|
3455
|
-
var STRADDLE_TARGET_CONTRAST = 4.5;
|
|
3456
|
-
var STRADDLE_PILL_ALPHA = 0.9;
|
|
3457
|
-
function straddleSampleGrid(box) {
|
|
3458
|
-
const out = [];
|
|
3459
|
-
if (!box || !(box.width > 0) || !(box.height > 0)) return out;
|
|
3460
|
-
for (let i = 0; i < STRADDLE_COLS; i++) {
|
|
3461
|
-
for (let j4 = 0; j4 < STRADDLE_ROWS; j4++) {
|
|
3462
|
-
out.push({
|
|
3463
|
-
x: box.left + box.width * (i + 0.5) / STRADDLE_COLS,
|
|
3464
|
-
y: box.top + box.height * (j4 + 0.5) / STRADDLE_ROWS
|
|
3465
|
-
});
|
|
3466
|
-
}
|
|
3467
|
-
}
|
|
3468
|
-
return out;
|
|
3469
|
-
}
|
|
3470
|
-
function backgroundGroups(bgs, tol = 8) {
|
|
3471
|
-
const groups = [];
|
|
3472
|
-
for (const b4 of bgs || []) {
|
|
3473
|
-
const g5 = groups.find((x3) => Math.abs(x3.rgb[0] - b4[0]) <= tol && Math.abs(x3.rgb[1] - b4[1]) <= tol && Math.abs(x3.rgb[2] - b4[2]) <= tol);
|
|
3474
|
-
if (g5) g5.n++;
|
|
3475
|
-
else groups.push({ rgb: [b4[0], b4[1], b4[2]], n: 1 });
|
|
3476
|
-
}
|
|
3477
|
-
return groups.sort((a3, b4) => b4.n - a3.n);
|
|
3478
|
-
}
|
|
3479
|
-
function straddles(bgs) {
|
|
3480
|
-
if (!bgs || bgs.length < 2) return false;
|
|
3481
|
-
const g5 = backgroundGroups(bgs);
|
|
3482
|
-
return g5.length >= 2 && g5[1].n / bgs.length >= STRADDLE_MIN_SHARE;
|
|
3483
|
-
}
|
|
3484
|
-
function minContrastOver(textColor, bgs) {
|
|
3485
|
-
const t = toRGBA(textColor);
|
|
3486
|
-
if (!t || !bgs || !bgs.length) return 0;
|
|
3487
|
-
let worst = Infinity;
|
|
3488
|
-
for (const b4 of bgs) {
|
|
3489
|
-
const tx = compositeOver(t, b4);
|
|
3490
|
-
worst = Math.min(worst, contrastRatio(relativeLuminance(tx), relativeLuminance(b4)));
|
|
3491
|
-
}
|
|
3492
|
-
return worst;
|
|
3493
|
-
}
|
|
3494
|
-
function pickColorOver(textColor, bgs, target = STRADDLE_TARGET_CONTRAST) {
|
|
3495
|
-
const cur = minContrastOver(textColor, bgs);
|
|
3496
|
-
if (cur >= target) return { color: String(textColor), contrast: cur, keep: true };
|
|
3497
|
-
const d2 = minContrastOver(DARK_TEXT, bgs), l2 = minContrastOver(LIGHT_TEXT, bgs);
|
|
3498
|
-
const best = d2 >= l2 ? { color: DARK_TEXT, contrast: d2 } : { color: LIGHT_TEXT, contrast: l2 };
|
|
3499
|
-
return best.contrast > cur ? { ...best, keep: false } : { color: String(textColor), contrast: cur, keep: true };
|
|
3500
|
-
}
|
|
3501
|
-
function clamp01(v) {
|
|
3502
|
-
if (typeof v !== "number" || !isFinite(v)) return 1;
|
|
3503
|
-
return Math.max(0, Math.min(1, v));
|
|
3504
|
-
}
|
|
3505
|
-
function hexToRGB(hex2) {
|
|
3506
|
-
const p4 = toRGBA(hex2);
|
|
3507
|
-
return [p4[0], p4[1], p4[2]];
|
|
3508
|
-
}
|
|
3509
|
-
|
|
3510
3504
|
// src/labelContrastDom.ts
|
|
3511
3505
|
var LABEL_CONTRAST_DONE_ATTR = "data-lch-contrast";
|
|
3512
3506
|
var LABEL_CONTRAST_CAP = 2e3;
|
|
@@ -3837,12 +3831,12 @@ function newIdScope() {
|
|
|
3837
3831
|
return "h" + seq;
|
|
3838
3832
|
}
|
|
3839
3833
|
var URL_REF = /url\(\s*(['"]?)#([^'")\s]+)\1\s*\)/g;
|
|
3840
|
-
function scopeChartIds(
|
|
3841
|
-
const
|
|
3834
|
+
function scopeChartIds(c2, scope) {
|
|
3835
|
+
const r2 = { renamed: 0, collisions: [] };
|
|
3842
3836
|
try {
|
|
3843
|
-
const tag = "--" + scope, doc =
|
|
3837
|
+
const tag = "--" + scope, doc = c2.ownerDocument, map = /* @__PURE__ */ new Map();
|
|
3844
3838
|
const refs = [], used = /* @__PURE__ */ new Set();
|
|
3845
|
-
|
|
3839
|
+
c2.querySelectorAll("*").forEach((el) => {
|
|
3846
3840
|
for (const a3 of el.getAttributeNames()) {
|
|
3847
3841
|
const v = el.getAttribute(a3);
|
|
3848
3842
|
const href = (a3 === "href" || a3 === "xlink:href") && v[0] === "#";
|
|
@@ -3852,15 +3846,15 @@ function scopeChartIds(container, scope) {
|
|
|
3852
3846
|
for (const m4 of v.matchAll(URL_REF)) used.add(m4[2]);
|
|
3853
3847
|
}
|
|
3854
3848
|
});
|
|
3855
|
-
|
|
3849
|
+
c2.querySelectorAll("[id]").forEach((el) => {
|
|
3856
3850
|
const id = el.id;
|
|
3857
|
-
if (!used.has(id) || id.endsWith(tag)
|
|
3851
|
+
if (!used.has(id) || id.endsWith(tag)) return;
|
|
3858
3852
|
const q2 = id.replace(/["\\]/g, "\\$&");
|
|
3859
|
-
if (doc && Array.from(doc.querySelectorAll(`[id="${q2}"],[id^="${q2}--h"]`)).some((o4) => !
|
|
3860
|
-
|
|
3853
|
+
if (doc && Array.from(doc.querySelectorAll(`[id="${q2}"],[id^="${q2}--h"]`)).some((o4) => !c2.contains(o4))) {
|
|
3854
|
+
r2.collisions.push(id);
|
|
3861
3855
|
}
|
|
3862
3856
|
map.set(id, el.id = id + tag);
|
|
3863
|
-
|
|
3857
|
+
r2.renamed++;
|
|
3864
3858
|
});
|
|
3865
3859
|
for (const [el, a3, v] of refs) {
|
|
3866
3860
|
const nv = v[0] === "#" && map.has(v.slice(1)) ? "#" + map.get(v.slice(1)) : v.replace(URL_REF, (m4, q2, id) => map.has(id) ? `url(${q2}#${map.get(id)}${q2})` : m4);
|
|
@@ -3868,7 +3862,7 @@ function scopeChartIds(container, scope) {
|
|
|
3868
3862
|
}
|
|
3869
3863
|
} catch {
|
|
3870
3864
|
}
|
|
3871
|
-
return
|
|
3865
|
+
return r2;
|
|
3872
3866
|
}
|
|
3873
3867
|
|
|
3874
3868
|
// src/invalidSentinel.ts
|
|
@@ -3889,7 +3883,34 @@ function invalidSentinelReason(text2, max = 240) {
|
|
|
3889
3883
|
// src/annotations.ts
|
|
3890
3884
|
var ANNOTATION_LAYER_CLASS = "bic-annotations";
|
|
3891
3885
|
var ANNOTATION_CLASS = "bic-annotation";
|
|
3886
|
+
var ZOOM_PAD_CLASS = "llm-zoom-pad";
|
|
3892
3887
|
var text = (v) => v == null ? "" : String(v).trim();
|
|
3888
|
+
var FREE = { l: -Infinity, t: -Infinity, r: Infinity, b: Infinity };
|
|
3889
|
+
var box = (r2) => ({ l: r2.left, t: r2.top, r: r2.right, b: r2.bottom });
|
|
3890
|
+
var area = (b4) => (b4.r - b4.l) * (b4.b - b4.t);
|
|
3891
|
+
var cut = (a3, b4) => {
|
|
3892
|
+
if (!a3) return null;
|
|
3893
|
+
const c2 = { l: Math.max(a3.l, b4.l), t: Math.max(a3.t, b4.t), r: Math.min(a3.r, b4.r), b: Math.min(a3.b, b4.b) };
|
|
3894
|
+
return c2.r > c2.l && c2.b > c2.t ? c2 : null;
|
|
3895
|
+
};
|
|
3896
|
+
function shapeTest(mark) {
|
|
3897
|
+
const g5 = mark;
|
|
3898
|
+
let inv = null;
|
|
3899
|
+
try {
|
|
3900
|
+
inv = g5?.isPointInFill ? g5.getScreenCTM?.()?.inverse() ?? null : null;
|
|
3901
|
+
} catch {
|
|
3902
|
+
inv = null;
|
|
3903
|
+
}
|
|
3904
|
+
if (!g5 || !inv) return () => true;
|
|
3905
|
+
const m4 = inv;
|
|
3906
|
+
return (x3, y2) => {
|
|
3907
|
+
try {
|
|
3908
|
+
return g5.isPointInFill({ x: m4.a * x3 + m4.c * y2 + m4.e, y: m4.b * x3 + m4.d * y2 + m4.f });
|
|
3909
|
+
} catch {
|
|
3910
|
+
return true;
|
|
3911
|
+
}
|
|
3912
|
+
};
|
|
3913
|
+
}
|
|
3893
3914
|
var parseIdxs = (s2) => (s2 || "").split(",").map((x3) => parseInt(x3, 10)).filter((n) => Number.isFinite(n));
|
|
3894
3915
|
function createAnnotationLayer(container, onClick) {
|
|
3895
3916
|
let list = [];
|
|
@@ -3946,6 +3967,37 @@ function createAnnotationLayer(container, onClick) {
|
|
|
3946
3967
|
else marksByRow.set(r2, [m4]);
|
|
3947
3968
|
}
|
|
3948
3969
|
const origin = container.getBoundingClientRect();
|
|
3970
|
+
const open = origin.width > 0 && origin.height > 0 ? box(origin) : FREE;
|
|
3971
|
+
const clipOf = /* @__PURE__ */ new Map();
|
|
3972
|
+
const viewOf = (m4) => {
|
|
3973
|
+
let v = open;
|
|
3974
|
+
const svg = m4.closest("svg");
|
|
3975
|
+
if (svg) {
|
|
3976
|
+
const s2 = svg.getBoundingClientRect();
|
|
3977
|
+
if (s2.width > 0 && s2.height > 0) v = cut(v, box(s2));
|
|
3978
|
+
}
|
|
3979
|
+
for (let el = m4.parentElement; v && el && el !== svg && el !== container; el = el.parentElement) {
|
|
3980
|
+
if (!clipOf.has(el)) {
|
|
3981
|
+
const w4 = clipWindowOf(el);
|
|
3982
|
+
clipOf.set(el, w4 && box(w4));
|
|
3983
|
+
}
|
|
3984
|
+
const w3 = clipOf.get(el);
|
|
3985
|
+
if (w3) v = cut(v, w3);
|
|
3986
|
+
}
|
|
3987
|
+
return v;
|
|
3988
|
+
};
|
|
3989
|
+
const controls = Array.from(container.querySelectorAll(`.${CONTROL_CLASS}, .${ZOOM_PAD_CLASS}`)).map((c2) => c2.getBoundingClientRect()).filter((r2) => r2.width > 0 && r2.height > 0).map(box);
|
|
3990
|
+
const clear = (v, len, mark) => {
|
|
3991
|
+
const hw = Math.max(16, len * 6 + 8) / 2, hh = 8, g5 = 2;
|
|
3992
|
+
const cx = (v.l + v.r) / 2, cy = (v.t + v.b) / 2;
|
|
3993
|
+
const free = (x3, y2) => x3 >= v.l && x3 <= v.r && y2 >= v.t && y2 <= v.b && controls.every((c2) => x3 + hw <= c2.l || x3 - hw >= c2.r || y2 + hh <= c2.t || y2 - hh >= c2.b);
|
|
3994
|
+
const onShape = shapeTest(mark);
|
|
3995
|
+
const tries = [[cx, cy]];
|
|
3996
|
+
for (let i = 0; i <= 8; i++) for (let j4 = 0; j4 <= 6; j4++) tries.push([v.l + (v.r - v.l) * i / 8, v.t + (v.b - v.t) * j4 / 6]);
|
|
3997
|
+
tries.sort((p4, q2) => Math.hypot(p4[0] - cx, p4[1] - cy) - Math.hypot(q2[0] - cx, q2[1] - cy));
|
|
3998
|
+
for (const c2 of controls) tries.push([cx, c2.b + hh + g5], [cx, c2.t - hh - g5], [c2.l - hw - g5, cy], [c2.r + hw + g5, cy]);
|
|
3999
|
+
return tries.find(([x3, y2]) => free(x3, y2) && onShape(x3, y2)) ?? tries.find(([x3, y2]) => free(x3, y2)) ?? null;
|
|
4000
|
+
};
|
|
3949
4001
|
let shown = 0;
|
|
3950
4002
|
for (const a3 of list) {
|
|
3951
4003
|
const pairs = (a3.where ? Object.entries(a3.where) : a3.column != null ? [[a3.column, a3.value]] : []).map(([c2, v]) => [names.indexOf(c2), text(v)]);
|
|
@@ -3955,23 +4007,30 @@ function createAnnotationLayer(container, onClick) {
|
|
|
3955
4007
|
if (pairs.every(([ci, v]) => text(row?.[ci]) === v)) for (const m4 of marksByRow.get(r2) ?? []) hits.add(m4);
|
|
3956
4008
|
});
|
|
3957
4009
|
if (!hits.size) continue;
|
|
3958
|
-
|
|
3959
|
-
let best = null;
|
|
4010
|
+
let best = null, bestMark = null, laidOut = false;
|
|
3960
4011
|
for (const m4 of hits) {
|
|
3961
4012
|
const b4 = m4.getBoundingClientRect();
|
|
3962
|
-
if (!
|
|
4013
|
+
if (!(b4.width > 0 && b4.height > 0)) continue;
|
|
4014
|
+
laidOut = true;
|
|
4015
|
+
const v = cut(box(b4), viewOf(m4));
|
|
4016
|
+
if (v && (!best || area(v) > area(best))) {
|
|
4017
|
+
best = v;
|
|
4018
|
+
bestMark = m4;
|
|
4019
|
+
}
|
|
3963
4020
|
}
|
|
4021
|
+
const pt2 = best ? clear(best, (a3.label ?? "\u2022").length, bestMark) : null;
|
|
4022
|
+
if (laidOut && !pt2) continue;
|
|
4023
|
+
shown++;
|
|
3964
4024
|
const badge = doc.createElement("div");
|
|
3965
4025
|
badge.className = ANNOTATION_CLASS;
|
|
3966
4026
|
badge.textContent = a3.label ?? "\u2022";
|
|
3967
4027
|
if (a3.title) badge.setAttribute("title", a3.title);
|
|
3968
4028
|
badge.setAttribute("role", "button");
|
|
3969
4029
|
badge.setAttribute("aria-label", a3.title ? `Note: ${a3.title}` : `Note on ${want}`);
|
|
3970
|
-
const laidOut = !!best && best.width > 0 && best.height > 0;
|
|
3971
4030
|
Object.assign(badge.style, {
|
|
3972
4031
|
position: "absolute",
|
|
3973
|
-
left: `${Math.round(
|
|
3974
|
-
top: `${Math.round(
|
|
4032
|
+
left: `${Math.round(pt2 ? pt2[0] - origin.left : 0)}px`,
|
|
4033
|
+
top: `${Math.round(pt2 ? pt2[1] - origin.top : 0)}px`,
|
|
3975
4034
|
transform: "translate(-50%, -50%)",
|
|
3976
4035
|
minWidth: "16px",
|
|
3977
4036
|
height: "16px",
|
|
@@ -4356,7 +4415,7 @@ function createChartHost(container, config) {
|
|
|
4356
4415
|
warnedIds = true;
|
|
4357
4416
|
try {
|
|
4358
4417
|
(win?.console ?? console)?.warn(
|
|
4359
|
-
`[@bicharts/chart-host]
|
|
4418
|
+
`[@bicharts/chart-host] ids shared with another chart, scoped: ${r2.collisions.slice(0, 5).join(", ")}`
|
|
4360
4419
|
);
|
|
4361
4420
|
} catch {
|
|
4362
4421
|
}
|
|
@@ -4726,6 +4785,35 @@ function createChartGroup(columns, rows, opts = {}) {
|
|
|
4726
4785
|
}
|
|
4727
4786
|
|
|
4728
4787
|
export {
|
|
4788
|
+
DARK_TEXT,
|
|
4789
|
+
LIGHT_TEXT,
|
|
4790
|
+
MIN_CONTRAST,
|
|
4791
|
+
WHITE_TEXT_BG_LUM,
|
|
4792
|
+
PILL_MIN_ALPHA,
|
|
4793
|
+
PILL_OPAQUE_ALPHA,
|
|
4794
|
+
PAGE_MATCH_TOLERANCE,
|
|
4795
|
+
isPillBackdropAlpha,
|
|
4796
|
+
PILL_MIN_COVERAGE,
|
|
4797
|
+
pillBacksGlyph,
|
|
4798
|
+
BACKING_MAJORITY,
|
|
4799
|
+
backingHoldsGlyph,
|
|
4800
|
+
cellSuppressesNormalize,
|
|
4801
|
+
toRGBA,
|
|
4802
|
+
compositeOver,
|
|
4803
|
+
relativeLuminance,
|
|
4804
|
+
contrastRatio,
|
|
4805
|
+
decideLabelColor,
|
|
4806
|
+
GLYPH_SAMPLE_N,
|
|
4807
|
+
glyphSampleGrid,
|
|
4808
|
+
STRADDLE_COLS,
|
|
4809
|
+
STRADDLE_ROWS,
|
|
4810
|
+
STRADDLE_MIN_SHARE,
|
|
4811
|
+
STRADDLE_TARGET_CONTRAST,
|
|
4812
|
+
STRADDLE_PILL_ALPHA,
|
|
4813
|
+
straddleSampleGrid,
|
|
4814
|
+
straddles,
|
|
4815
|
+
minContrastOver,
|
|
4816
|
+
pickColorOver,
|
|
4729
4817
|
deltaEHex,
|
|
4730
4818
|
SAME_SHADE_DELTA_E,
|
|
4731
4819
|
MIN_RAMP_FILLS,
|
|
@@ -4797,35 +4885,6 @@ export {
|
|
|
4797
4885
|
unpinScrolledAxis,
|
|
4798
4886
|
pinScrolledAxis,
|
|
4799
4887
|
fitRenderedChart,
|
|
4800
|
-
DARK_TEXT,
|
|
4801
|
-
LIGHT_TEXT,
|
|
4802
|
-
MIN_CONTRAST,
|
|
4803
|
-
WHITE_TEXT_BG_LUM,
|
|
4804
|
-
PILL_MIN_ALPHA,
|
|
4805
|
-
PILL_OPAQUE_ALPHA,
|
|
4806
|
-
PAGE_MATCH_TOLERANCE,
|
|
4807
|
-
isPillBackdropAlpha,
|
|
4808
|
-
PILL_MIN_COVERAGE,
|
|
4809
|
-
pillBacksGlyph,
|
|
4810
|
-
BACKING_MAJORITY,
|
|
4811
|
-
backingHoldsGlyph,
|
|
4812
|
-
cellSuppressesNormalize,
|
|
4813
|
-
toRGBA,
|
|
4814
|
-
compositeOver,
|
|
4815
|
-
relativeLuminance,
|
|
4816
|
-
contrastRatio,
|
|
4817
|
-
decideLabelColor,
|
|
4818
|
-
GLYPH_SAMPLE_N,
|
|
4819
|
-
glyphSampleGrid,
|
|
4820
|
-
STRADDLE_COLS,
|
|
4821
|
-
STRADDLE_ROWS,
|
|
4822
|
-
STRADDLE_MIN_SHARE,
|
|
4823
|
-
STRADDLE_TARGET_CONTRAST,
|
|
4824
|
-
STRADDLE_PILL_ALPHA,
|
|
4825
|
-
straddleSampleGrid,
|
|
4826
|
-
straddles,
|
|
4827
|
-
minContrastOver,
|
|
4828
|
-
pickColorOver,
|
|
4829
4888
|
LABEL_CONTRAST_DONE_ATTR,
|
|
4830
4889
|
LABEL_CONTRAST_CAP,
|
|
4831
4890
|
LABEL_PILL_CLASS,
|
package/dist/index.mjs
CHANGED
package/dist/react.mjs
CHANGED
|
@@ -23,6 +23,9 @@ export interface AnnotationReport {
|
|
|
23
23
|
}
|
|
24
24
|
export declare const ANNOTATION_LAYER_CLASS = "bic-annotations";
|
|
25
25
|
export declare const ANNOTATION_CLASS = "bic-annotation";
|
|
26
|
+
/** The class the d3.llmGeoZoom helper gives its button pad - a control drawn by a generated chart without the
|
|
27
|
+
* contract's CONTROL_CLASS, so the badge layer names it too. */
|
|
28
|
+
export declare const ZOOM_PAD_CLASS = "llm-zoom-pad";
|
|
26
29
|
export interface AnnotationLayer {
|
|
27
30
|
set(list: MarkAnnotation[]): void;
|
|
28
31
|
/** Redraw against the container's current marks and the given data. */
|
package/dist/types/fitDom.d.ts
CHANGED
|
@@ -7,6 +7,15 @@ export declare function svgInkReach(svg: SVGSVGElement): {
|
|
|
7
7
|
right: number;
|
|
8
8
|
bottom: number;
|
|
9
9
|
} | null;
|
|
10
|
+
/** The window ONE element's own clip-path attribute opens, in screen coordinates - or null: no clip, a clip in
|
|
11
|
+
* objectBoundingBox units, or one that won't measure. Shared by the frame fit (right/bottom) and the note badges
|
|
12
|
+
* (the whole window). The clipPath is looked up within the element's own svg. */
|
|
13
|
+
export declare function clipWindowOf(el: Element): {
|
|
14
|
+
left: number;
|
|
15
|
+
top: number;
|
|
16
|
+
right: number;
|
|
17
|
+
bottom: number;
|
|
18
|
+
} | null;
|
|
10
19
|
export type InkReach = (el: Element) => {
|
|
11
20
|
right: number;
|
|
12
21
|
bottom: number;
|
package/dist/types/idScope.d.ts
CHANGED
|
@@ -6,4 +6,4 @@ export interface IdScopeReport {
|
|
|
6
6
|
/** Ids that also existed outside this chart when the pass ran - each one a clash this pass prevented. */
|
|
7
7
|
collisions: string[];
|
|
8
8
|
}
|
|
9
|
-
export declare function scopeChartIds(
|
|
9
|
+
export declare function scopeChartIds(c: Element, scope: string): IdScopeReport;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bicharts/chart-host",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.64",
|
|
4
4
|
"description": "Run a BIC-generated D3 chart in any web host: compiles the generated render() function, applies the shared option defaults, resolves mark clicks (through tooltip overlays), owns the selection affordance, and translates row indices between cross-filtered charts. The same contract the BIC Power BI visual implements, minus Power BI. React bindings at @bicharts/chart-host/react.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|