bo-grid 0.1.0
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/LICENSE +21 -0
- package/README.md +461 -0
- package/dist/format/format.d.ts +5 -0
- package/dist/format/format.js +25 -0
- package/dist/grid/AggregationBar.svelte +45 -0
- package/dist/grid/AggregationBar.svelte.d.ts +8 -0
- package/dist/grid/Cell.svelte +230 -0
- package/dist/grid/Cell.svelte.d.ts +32 -0
- package/dist/grid/Grid.svelte +1339 -0
- package/dist/grid/Grid.svelte.d.ts +76 -0
- package/dist/grid/GroupRow.svelte +110 -0
- package/dist/grid/GroupRow.svelte.d.ts +11 -0
- package/dist/grid/aggregate.d.ts +11 -0
- package/dist/grid/aggregate.js +23 -0
- package/dist/grid/clipboard.d.ts +9 -0
- package/dist/grid/clipboard.js +24 -0
- package/dist/grid/column.d.ts +95 -0
- package/dist/grid/column.js +62 -0
- package/dist/grid/export-xlsx.d.ts +8 -0
- package/dist/grid/export-xlsx.js +19 -0
- package/dist/grid/export.d.ts +19 -0
- package/dist/grid/export.js +48 -0
- package/dist/grid/grouping.d.ts +36 -0
- package/dist/grid/grouping.js +62 -0
- package/dist/grid/heatmap.d.ts +1 -0
- package/dist/grid/heatmap.js +12 -0
- package/dist/grid/pin.d.ts +23 -0
- package/dist/grid/pin.js +24 -0
- package/dist/grid/pivot.d.ts +27 -0
- package/dist/grid/pivot.js +0 -0
- package/dist/grid/reorder.d.ts +2 -0
- package/dist/grid/reorder.js +10 -0
- package/dist/grid/rowheight.d.ts +17 -0
- package/dist/grid/rowheight.js +41 -0
- package/dist/grid/selection.svelte.d.ts +30 -0
- package/dist/grid/selection.svelte.js +64 -0
- package/dist/grid/sizing.d.ts +17 -0
- package/dist/grid/sizing.js +28 -0
- package/dist/grid/source.d.ts +43 -0
- package/dist/grid/source.js +29 -0
- package/dist/grid/source.svelte.d.ts +21 -0
- package/dist/grid/source.svelte.js +53 -0
- package/dist/grid/theme.d.ts +27 -0
- package/dist/grid/theme.js +60 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +24 -0
- package/dist/sparkline/Sparkline.svelte +74 -0
- package/dist/sparkline/Sparkline.svelte.d.ts +9 -0
- package/dist/sparkline/sparkline-render.d.ts +16 -0
- package/dist/sparkline/sparkline-render.js +83 -0
- package/dist/types.d.ts +7 -0
- package/dist/types.js +1 -0
- package/package.json +82 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
const UP = '#34d399';
|
|
2
|
+
const DOWN = '#f87171';
|
|
3
|
+
/**
|
|
4
|
+
* Size a canvas for the current devicePixelRatio so 1px CSS strokes render
|
|
5
|
+
* crisp on HiDPI/Retina. Returns a context already scaled to CSS pixels —
|
|
6
|
+
* callers draw in CSS-pixel coordinates and forget dpr exists.
|
|
7
|
+
*/
|
|
8
|
+
export function setupHiDpiCanvas(canvas, cssW, cssH) {
|
|
9
|
+
const dpr = window.devicePixelRatio || 1;
|
|
10
|
+
canvas.width = Math.round(cssW * dpr);
|
|
11
|
+
canvas.height = Math.round(cssH * dpr);
|
|
12
|
+
canvas.style.width = `${cssW}px`;
|
|
13
|
+
canvas.style.height = `${cssH}px`;
|
|
14
|
+
const ctx = canvas.getContext('2d');
|
|
15
|
+
if (!ctx)
|
|
16
|
+
throw new Error('2d context unavailable');
|
|
17
|
+
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
|
18
|
+
return ctx;
|
|
19
|
+
}
|
|
20
|
+
function priceExtent(candles) {
|
|
21
|
+
let min = Infinity;
|
|
22
|
+
let max = -Infinity;
|
|
23
|
+
for (const c of candles) {
|
|
24
|
+
if (c.low < min)
|
|
25
|
+
min = c.low;
|
|
26
|
+
if (c.high > max)
|
|
27
|
+
max = c.high;
|
|
28
|
+
}
|
|
29
|
+
return { min, max };
|
|
30
|
+
}
|
|
31
|
+
/** Map a price to a y pixel (inverted: high price = small y). */
|
|
32
|
+
function yOf(price, ext, h, pad) {
|
|
33
|
+
const span = ext.max - ext.min || 1;
|
|
34
|
+
return pad + (1 - (price - ext.min) / span) * (h - pad * 2);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Draw compact candlesticks. Body shows open→close, wick shows low→high.
|
|
38
|
+
* Color by per-candle direction. Canvas (not SVG) so 100+ of these stay cheap.
|
|
39
|
+
*/
|
|
40
|
+
export function drawCandles(ctx, candles, w, h) {
|
|
41
|
+
ctx.clearRect(0, 0, w, h);
|
|
42
|
+
if (candles.length === 0)
|
|
43
|
+
return;
|
|
44
|
+
const ext = priceExtent(candles);
|
|
45
|
+
const pad = 2;
|
|
46
|
+
const n = candles.length;
|
|
47
|
+
const slot = w / n;
|
|
48
|
+
const bodyW = Math.max(1, Math.min(6, slot * 0.6));
|
|
49
|
+
for (let i = 0; i < n; i++) {
|
|
50
|
+
const c = candles[i];
|
|
51
|
+
const cx = i * slot + slot / 2;
|
|
52
|
+
const up = c.close >= c.open;
|
|
53
|
+
ctx.strokeStyle = up ? UP : DOWN;
|
|
54
|
+
ctx.fillStyle = up ? UP : DOWN;
|
|
55
|
+
// wick
|
|
56
|
+
ctx.beginPath();
|
|
57
|
+
ctx.moveTo(Math.round(cx) + 0.5, yOf(c.high, ext, h, pad));
|
|
58
|
+
ctx.lineTo(Math.round(cx) + 0.5, yOf(c.low, ext, h, pad));
|
|
59
|
+
ctx.stroke();
|
|
60
|
+
// body
|
|
61
|
+
const yo = yOf(c.open, ext, h, pad);
|
|
62
|
+
const yc = yOf(c.close, ext, h, pad);
|
|
63
|
+
const top = Math.min(yo, yc);
|
|
64
|
+
const bh = Math.max(1, Math.abs(yc - yo));
|
|
65
|
+
ctx.fillRect(cx - bodyW / 2, top, bodyW, bh);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/** Screen-reader text — canvas alone is invisible to AT, so we narrate trend. */
|
|
69
|
+
export function summarize(candles) {
|
|
70
|
+
if (candles.length === 0)
|
|
71
|
+
return 'no data';
|
|
72
|
+
const first = candles[0].open;
|
|
73
|
+
const last = candles[candles.length - 1].close;
|
|
74
|
+
const pct = ((last - first) / first) * 100;
|
|
75
|
+
const dir = pct >= 0 ? 'up' : 'down';
|
|
76
|
+
return `sparkline ${dir} ${Math.abs(pct).toFixed(1)}% over ${candles.length} periods`;
|
|
77
|
+
}
|
|
78
|
+
/** Which candle index sits under an x offset (for hover tooltips). */
|
|
79
|
+
export function candleAtX(x, w, n) {
|
|
80
|
+
if (n === 0)
|
|
81
|
+
return -1;
|
|
82
|
+
return Math.max(0, Math.min(n - 1, Math.floor((x / w) * n)));
|
|
83
|
+
}
|
package/dist/types.d.ts
ADDED
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "bo-grid",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"description": "Tiny, fast Svelte 5 data grid: canvas sparklines, batched realtime cell updates, and virtual scrolling. A free, fintech-focused alternative to heavyweight grids.",
|
|
7
|
+
"homepage": "https://bonguynvan.github.io/bo-grid/",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/bonguynvan/bo-grid.git"
|
|
11
|
+
},
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/bonguynvan/bo-grid/issues"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"svelte",
|
|
17
|
+
"svelte5",
|
|
18
|
+
"datagrid",
|
|
19
|
+
"grid",
|
|
20
|
+
"table",
|
|
21
|
+
"sparkline",
|
|
22
|
+
"candlestick",
|
|
23
|
+
"virtual-scroll",
|
|
24
|
+
"realtime",
|
|
25
|
+
"fintech",
|
|
26
|
+
"trading"
|
|
27
|
+
],
|
|
28
|
+
"svelte": "./dist/index.js",
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
30
|
+
"exports": {
|
|
31
|
+
".": {
|
|
32
|
+
"types": "./dist/index.d.ts",
|
|
33
|
+
"svelte": "./dist/index.js",
|
|
34
|
+
"default": "./dist/index.js"
|
|
35
|
+
},
|
|
36
|
+
"./package.json": "./package.json"
|
|
37
|
+
},
|
|
38
|
+
"files": [
|
|
39
|
+
"dist"
|
|
40
|
+
],
|
|
41
|
+
"sideEffects": false,
|
|
42
|
+
"peerDependencies": {
|
|
43
|
+
"svelte": "^5.0.0",
|
|
44
|
+
"xlsx": "*"
|
|
45
|
+
},
|
|
46
|
+
"peerDependenciesMeta": {
|
|
47
|
+
"xlsx": {
|
|
48
|
+
"optional": true
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
"scripts": {
|
|
52
|
+
"dev": "vite",
|
|
53
|
+
"demo:build": "vite build",
|
|
54
|
+
"pages:build": "vite build --base=/bo-grid/ --outDir demo-dist",
|
|
55
|
+
"preview": "vite preview",
|
|
56
|
+
"package": "svelte-package -i src/lib -o dist && node scripts/clean-dist.mjs",
|
|
57
|
+
"prepublishOnly": "pnpm run package",
|
|
58
|
+
"check": "svelte-check --tsconfig ./tsconfig.json",
|
|
59
|
+
"size": "vite build && node scripts/size-check.mjs",
|
|
60
|
+
"size:lib": "vite build --config vite.lib.config.ts && node scripts/size-lib.mjs",
|
|
61
|
+
"smoke": "vite build --base=./ --outDir demo-dist && node scripts/smoke.mjs",
|
|
62
|
+
"test": "vitest run",
|
|
63
|
+
"release": "node scripts/release.mjs",
|
|
64
|
+
"release:dry": "node scripts/release.mjs --dry-run"
|
|
65
|
+
},
|
|
66
|
+
"pnpm": {
|
|
67
|
+
"onlyBuiltDependencies": [
|
|
68
|
+
"esbuild"
|
|
69
|
+
]
|
|
70
|
+
},
|
|
71
|
+
"devDependencies": {
|
|
72
|
+
"@sveltejs/package": "^2.5.8",
|
|
73
|
+
"@sveltejs/vite-plugin-svelte": "^5.0.3",
|
|
74
|
+
"jsdom": "^29.1.1",
|
|
75
|
+
"svelte": "^5.19.0",
|
|
76
|
+
"svelte-check": "^4.1.4",
|
|
77
|
+
"typescript": "^5.7.3",
|
|
78
|
+
"vite": "^6.0.7",
|
|
79
|
+
"vitest": "^2.1.8",
|
|
80
|
+
"xlsx": "0.18.5"
|
|
81
|
+
}
|
|
82
|
+
}
|