@opendata-ai/openchart-vanilla 2.3.0 → 2.3.2
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/index.js +18 -3
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/graph/canvas-renderer.ts +34 -5
- package/src/table-renderer.ts +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opendata-ai/openchart-vanilla",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.2",
|
|
4
4
|
"description": "Vanilla JS renderer for openchart: SVG charts, HTML tables, force-directed graphs",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Riley Hilliard",
|
|
@@ -46,8 +46,8 @@
|
|
|
46
46
|
"typecheck": "tsc --noEmit"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@opendata-ai/openchart-core": "2.3.
|
|
50
|
-
"@opendata-ai/openchart-engine": "2.3.
|
|
49
|
+
"@opendata-ai/openchart-core": "2.3.2",
|
|
50
|
+
"@opendata-ai/openchart-engine": "2.3.2",
|
|
51
51
|
"d3-force": "^3.0.0",
|
|
52
52
|
"d3-quadtree": "^3.0.1"
|
|
53
53
|
},
|
|
@@ -247,7 +247,7 @@ export class GraphCanvasRenderer {
|
|
|
247
247
|
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
|
248
248
|
const padding = theme.spacing.padding;
|
|
249
249
|
const x = w - padding;
|
|
250
|
-
const y = h -
|
|
250
|
+
const y = h - padding;
|
|
251
251
|
ctx.font = `600 20px ${theme.fonts.family}`;
|
|
252
252
|
ctx.fillStyle = theme.colors.axis;
|
|
253
253
|
ctx.globalAlpha = 0.5;
|
|
@@ -662,14 +662,22 @@ export class GraphCanvasRenderer {
|
|
|
662
662
|
|
|
663
663
|
const labelY = node.y + node.radius + 3;
|
|
664
664
|
|
|
665
|
-
//
|
|
666
|
-
|
|
667
|
-
|
|
665
|
+
// Halo for readability: stroke behind text in the background color
|
|
666
|
+
// so labels stay legible over edges and other nodes.
|
|
667
|
+
if (theme.colors.background !== 'transparent') {
|
|
668
|
+
ctx.strokeStyle = theme.colors.background;
|
|
669
|
+
} else {
|
|
670
|
+
// Transparent bg: infer page background from text luminance.
|
|
671
|
+
// Light text = dark page, dark text = light page.
|
|
672
|
+
ctx.strokeStyle = isLightColor(theme.colors.text)
|
|
673
|
+
? 'rgba(0, 0, 0, 0.7)'
|
|
674
|
+
: 'rgba(255, 255, 255, 0.85)';
|
|
675
|
+
}
|
|
668
676
|
ctx.lineWidth = 3;
|
|
669
677
|
ctx.lineJoin = 'round';
|
|
678
|
+
ctx.miterLimit = 2;
|
|
670
679
|
ctx.strokeText(node.label, node.x, labelY);
|
|
671
680
|
|
|
672
|
-
// White/light text
|
|
673
681
|
ctx.fillStyle = theme.colors.text;
|
|
674
682
|
ctx.fillText(node.label, node.x, labelY);
|
|
675
683
|
}
|
|
@@ -715,3 +723,24 @@ function brighten(color: string): string {
|
|
|
715
723
|
|
|
716
724
|
return color;
|
|
717
725
|
}
|
|
726
|
+
|
|
727
|
+
/**
|
|
728
|
+
* Returns true if a color is perceptually light (luminance > 0.5).
|
|
729
|
+
* Used to pick a contrasting halo color for labels on transparent backgrounds.
|
|
730
|
+
*/
|
|
731
|
+
function isLightColor(color: string): boolean {
|
|
732
|
+
const hex = color.replace('#', '');
|
|
733
|
+
const full =
|
|
734
|
+
hex.length === 3
|
|
735
|
+
? hex
|
|
736
|
+
.split('')
|
|
737
|
+
.map((c) => c + c)
|
|
738
|
+
.join('')
|
|
739
|
+
: hex;
|
|
740
|
+
if (full.length !== 6) return false;
|
|
741
|
+
const r = parseInt(full.slice(0, 2), 16) / 255;
|
|
742
|
+
const g = parseInt(full.slice(2, 4), 16) / 255;
|
|
743
|
+
const b = parseInt(full.slice(4, 6), 16) / 255;
|
|
744
|
+
const toLinear = (c: number) => (c <= 0.03928 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4);
|
|
745
|
+
return 0.2126 * toLinear(r) + 0.7152 * toLinear(g) + 0.0722 * toLinear(b) > 0.5;
|
|
746
|
+
}
|
package/src/table-renderer.ts
CHANGED
|
@@ -354,7 +354,7 @@ export function renderTable(layout: TableLayout, container: HTMLElement): HTMLEl
|
|
|
354
354
|
brandLink.href = 'https://tryopendata.ai';
|
|
355
355
|
brandLink.target = '_blank';
|
|
356
356
|
brandLink.rel = 'noopener';
|
|
357
|
-
brandLink.style.cssText = `font-size: 20px; color: ${brandColor}; opacity: 0.55; text-decoration: none; font-family: ${theme ? theme.fonts.family : 'sans-serif'};`;
|
|
357
|
+
brandLink.style.cssText = `font-size: 20px; font-weight: 600; color: ${brandColor}; opacity: 0.55; text-decoration: none; font-family: ${theme ? theme.fonts.family : 'sans-serif'};`;
|
|
358
358
|
brandLink.textContent = 'OpenData';
|
|
359
359
|
brand.appendChild(brandLink);
|
|
360
360
|
wrapper.appendChild(brand);
|