@bicharts/chart-host 0.6.62 → 0.6.63
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/{chunk-ZLJM3EIP.mjs → chunk-ZTTBWP3I.mjs} +211 -205
- package/dist/index.mjs +1 -1
- package/dist/react.mjs +1 -1
- package/dist/types/idScope.d.ts +1 -1
- package/package.json +1 -1
|
@@ -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(box, n = GLYPH_SAMPLE_N) {
|
|
571
|
+
const out = [];
|
|
572
|
+
if (!box || !(box.width > 0) || !(box.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: box.left + box.width * (i + 0.5) / k3,
|
|
578
|
+
y: box.top + box.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(box) {
|
|
590
|
+
const out = [];
|
|
591
|
+
if (!box || !(box.width > 0) || !(box.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: box.left + box.width * (i + 0.5) / STRADDLE_COLS,
|
|
596
|
+
y: box.top + box.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
|
|
@@ -3343,170 +3513,6 @@ function fitRenderedChart(container, opts = {}) {
|
|
|
3343
3513
|
return result;
|
|
3344
3514
|
}
|
|
3345
3515
|
|
|
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
3516
|
// src/labelContrastDom.ts
|
|
3511
3517
|
var LABEL_CONTRAST_DONE_ATTR = "data-lch-contrast";
|
|
3512
3518
|
var LABEL_CONTRAST_CAP = 2e3;
|
|
@@ -3837,12 +3843,12 @@ function newIdScope() {
|
|
|
3837
3843
|
return "h" + seq;
|
|
3838
3844
|
}
|
|
3839
3845
|
var URL_REF = /url\(\s*(['"]?)#([^'")\s]+)\1\s*\)/g;
|
|
3840
|
-
function scopeChartIds(
|
|
3841
|
-
const
|
|
3846
|
+
function scopeChartIds(c2, scope) {
|
|
3847
|
+
const r2 = { renamed: 0, collisions: [] };
|
|
3842
3848
|
try {
|
|
3843
|
-
const tag = "--" + scope, doc =
|
|
3849
|
+
const tag = "--" + scope, doc = c2.ownerDocument, map = /* @__PURE__ */ new Map();
|
|
3844
3850
|
const refs = [], used = /* @__PURE__ */ new Set();
|
|
3845
|
-
|
|
3851
|
+
c2.querySelectorAll("*").forEach((el) => {
|
|
3846
3852
|
for (const a3 of el.getAttributeNames()) {
|
|
3847
3853
|
const v = el.getAttribute(a3);
|
|
3848
3854
|
const href = (a3 === "href" || a3 === "xlink:href") && v[0] === "#";
|
|
@@ -3852,15 +3858,15 @@ function scopeChartIds(container, scope) {
|
|
|
3852
3858
|
for (const m4 of v.matchAll(URL_REF)) used.add(m4[2]);
|
|
3853
3859
|
}
|
|
3854
3860
|
});
|
|
3855
|
-
|
|
3861
|
+
c2.querySelectorAll("[id]").forEach((el) => {
|
|
3856
3862
|
const id = el.id;
|
|
3857
|
-
if (!used.has(id) || id.endsWith(tag)
|
|
3863
|
+
if (!used.has(id) || id.endsWith(tag)) return;
|
|
3858
3864
|
const q2 = id.replace(/["\\]/g, "\\$&");
|
|
3859
|
-
if (doc && Array.from(doc.querySelectorAll(`[id="${q2}"],[id^="${q2}--h"]`)).some((o4) => !
|
|
3860
|
-
|
|
3865
|
+
if (doc && Array.from(doc.querySelectorAll(`[id="${q2}"],[id^="${q2}--h"]`)).some((o4) => !c2.contains(o4))) {
|
|
3866
|
+
r2.collisions.push(id);
|
|
3861
3867
|
}
|
|
3862
3868
|
map.set(id, el.id = id + tag);
|
|
3863
|
-
|
|
3869
|
+
r2.renamed++;
|
|
3864
3870
|
});
|
|
3865
3871
|
for (const [el, a3, v] of refs) {
|
|
3866
3872
|
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 +3874,7 @@ function scopeChartIds(container, scope) {
|
|
|
3868
3874
|
}
|
|
3869
3875
|
} catch {
|
|
3870
3876
|
}
|
|
3871
|
-
return
|
|
3877
|
+
return r2;
|
|
3872
3878
|
}
|
|
3873
3879
|
|
|
3874
3880
|
// src/invalidSentinel.ts
|
|
@@ -4356,7 +4362,7 @@ function createChartHost(container, config) {
|
|
|
4356
4362
|
warnedIds = true;
|
|
4357
4363
|
try {
|
|
4358
4364
|
(win?.console ?? console)?.warn(
|
|
4359
|
-
`[@bicharts/chart-host]
|
|
4365
|
+
`[@bicharts/chart-host] ids shared with another chart, scoped: ${r2.collisions.slice(0, 5).join(", ")}`
|
|
4360
4366
|
);
|
|
4361
4367
|
} catch {
|
|
4362
4368
|
}
|
|
@@ -4726,6 +4732,35 @@ function createChartGroup(columns, rows, opts = {}) {
|
|
|
4726
4732
|
}
|
|
4727
4733
|
|
|
4728
4734
|
export {
|
|
4735
|
+
DARK_TEXT,
|
|
4736
|
+
LIGHT_TEXT,
|
|
4737
|
+
MIN_CONTRAST,
|
|
4738
|
+
WHITE_TEXT_BG_LUM,
|
|
4739
|
+
PILL_MIN_ALPHA,
|
|
4740
|
+
PILL_OPAQUE_ALPHA,
|
|
4741
|
+
PAGE_MATCH_TOLERANCE,
|
|
4742
|
+
isPillBackdropAlpha,
|
|
4743
|
+
PILL_MIN_COVERAGE,
|
|
4744
|
+
pillBacksGlyph,
|
|
4745
|
+
BACKING_MAJORITY,
|
|
4746
|
+
backingHoldsGlyph,
|
|
4747
|
+
cellSuppressesNormalize,
|
|
4748
|
+
toRGBA,
|
|
4749
|
+
compositeOver,
|
|
4750
|
+
relativeLuminance,
|
|
4751
|
+
contrastRatio,
|
|
4752
|
+
decideLabelColor,
|
|
4753
|
+
GLYPH_SAMPLE_N,
|
|
4754
|
+
glyphSampleGrid,
|
|
4755
|
+
STRADDLE_COLS,
|
|
4756
|
+
STRADDLE_ROWS,
|
|
4757
|
+
STRADDLE_MIN_SHARE,
|
|
4758
|
+
STRADDLE_TARGET_CONTRAST,
|
|
4759
|
+
STRADDLE_PILL_ALPHA,
|
|
4760
|
+
straddleSampleGrid,
|
|
4761
|
+
straddles,
|
|
4762
|
+
minContrastOver,
|
|
4763
|
+
pickColorOver,
|
|
4729
4764
|
deltaEHex,
|
|
4730
4765
|
SAME_SHADE_DELTA_E,
|
|
4731
4766
|
MIN_RAMP_FILLS,
|
|
@@ -4797,35 +4832,6 @@ export {
|
|
|
4797
4832
|
unpinScrolledAxis,
|
|
4798
4833
|
pinScrolledAxis,
|
|
4799
4834
|
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
4835
|
LABEL_CONTRAST_DONE_ATTR,
|
|
4830
4836
|
LABEL_CONTRAST_CAP,
|
|
4831
4837
|
LABEL_PILL_CLASS,
|
package/dist/index.mjs
CHANGED
package/dist/react.mjs
CHANGED
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.63",
|
|
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",
|