bo-grid 0.7.0 → 0.8.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/README.md CHANGED
@@ -16,14 +16,16 @@ matrix, a **Leaderboard** with rank medals and score bars, a **Tree** file
16
16
  explorer, a drag-to-reorder **Tasks** list, and a **1M-row** trade tape windowed
17
17
  from a synthetic source — switch between them with the tabs.
18
18
 
19
- > **Status: v0.2.** Working: config-driven columns, virtual scroll, client
20
- > single/multi/controlled sort + global & per-column filters, multi-cell selection
21
- > + live range aggregation, row grouping (nested, collapsible, sticky headers,
22
- > live subtotals), pivot tables, tree data, master-detail, a server-side
23
- > `RowSource` for huge datasets, CSV/Excel export, drag-to-reorder and
24
- > drag-to-resize columns, pinned columns (left/right), row selection, pagination,
25
- > inline editing with validation, type-to-edit, clipboard copy/paste, sparklines,
26
- > realtime flash, heatmaps, theming, and full keyboard a11y. **SSR/SvelteKit-safe.**
19
+ > **Status: actively developed.** Working: config-driven columns, virtual scroll,
20
+ > sort (single / multi / controlled), filtering (global, per-column row, header
21
+ > filter menus with set / number / date filters, quick search, controlled +
22
+ > server-side), multi-cell selection + live aggregation, grouping (nested, sticky,
23
+ > subtotals), pivot, tree data, master-detail, a server-side `RowSource` for huge
24
+ > datasets, CSV/Excel export, column management (reorder, resize, pin L/R, hide,
25
+ > autosize, tool panel, column menu), spreadsheet editing (inline + typed editors,
26
+ > validation, copy/paste, fill handle, undo/redo), row selection, pagination,
27
+ > sparklines, realtime flash, heatmaps, theming, and full keyboard a11y.
28
+ > **SSR/SvelteKit-safe.**
27
29
  > Unit tests (Vitest), type-check, a headless mount smoke-test, an SSR render
28
30
  > check, and library + demo bundle-size budgets all run in CI. A formal WCAG audit
29
31
  > is the main thing left — see the roadmap.
@@ -290,6 +292,30 @@ these:
290
292
  }
291
293
  ```
292
294
 
295
+ Native form controls (checkboxes, date pickers, number spinners, search inputs,
296
+ scrollbars) follow the theme automatically via `color-scheme` + `accent-color`.
297
+ A custom theme defaults to dark; set `scheme: 'light'` (or `--bo-grid-scheme:
298
+ light`) for a light one.
299
+
300
+ **Tokens** cover colour, typography (`mono`/`sans`/`fontSize`), shape (`radius`),
301
+ and density (`cellPad`, plus the `rowHeight` prop) — so the whole look is yours.
302
+ Numeric columns use tabular figures so digits line up. A few looks:
303
+
304
+ ```svelte
305
+ <!-- Compact / dense -->
306
+ <Grid {rows} {columns} rowHeight={28}
307
+ theme={{ fontSize: '12px', cellPad: '6px' }} height={640} />
308
+
309
+ <!-- Roomy & rounded -->
310
+ <Grid {rows} {columns} rowHeight={44}
311
+ theme={{ radius: '16px', cellPad: '16px', fontSize: '14px' }} height={640} />
312
+
313
+ <!-- Branded -->
314
+ <Grid {rows} {columns}
315
+ theme={{ bg: '#0b1020', headerBg: '#0d1226', up: '#22d3ee', down: '#fb7185',
316
+ selBorder: '#22d3ee', radius: '12px' }} height={640} />
317
+ ```
318
+
293
319
  ## Server-side / large datasets
294
320
 
295
321
  Instead of an in-memory `rows` array, back the grid with a **`RowSource`** — the
@@ -251,9 +251,9 @@
251
251
  position: relative;
252
252
  display: flex;
253
253
  align-items: center;
254
- padding: 0 8px;
254
+ padding: 0 var(--bo-cell-pad, 8px);
255
255
  height: 100%;
256
- font-size: 13px;
256
+ font-size: var(--bo-font-size, 13px);
257
257
  line-height: 1.4;
258
258
  overflow: hidden;
259
259
  white-space: nowrap;
@@ -1803,6 +1803,15 @@
1803
1803
  --bo-header-h: var(--bo-grid-header-h, 28px);
1804
1804
  --bo-mono: var(--bo-grid-mono, "SF Mono", "JetBrains Mono", Menlo, Consolas, monospace);
1805
1805
  --bo-sans: var(--bo-grid-sans, Inter, "Segoe UI", system-ui, sans-serif);
1806
+ /* Layout/density tokens (override via --bo-grid-* for a custom look). */
1807
+ --bo-radius: var(--bo-grid-radius, 8px);
1808
+ --bo-font-size: var(--bo-grid-font-size, 13px);
1809
+ --bo-cell-pad: var(--bo-grid-cell-pad, 8px);
1810
+
1811
+ /* Theme native controls (checkboxes, date pickers, number spinners, search
1812
+ clear buttons, scrollbars) and accent fills to match the grid theme. */
1813
+ color-scheme: var(--bo-grid-scheme, dark);
1814
+ accent-color: var(--bo-up);
1806
1815
 
1807
1816
  display: flex;
1808
1817
  flex-direction: column;
@@ -1810,7 +1819,7 @@
1810
1819
  font-family: var(--bo-sans);
1811
1820
  background: var(--bo-bg);
1812
1821
  border: 0.5px solid var(--bo-border);
1813
- border-radius: 8px;
1822
+ border-radius: var(--bo-radius);
1814
1823
  overflow: hidden;
1815
1824
  outline: none;
1816
1825
  }
@@ -1893,7 +1902,7 @@
1893
1902
  display: flex;
1894
1903
  align-items: center;
1895
1904
  gap: 4px;
1896
- padding: 0 8px;
1905
+ padding: 0 var(--bo-cell-pad, 8px);
1897
1906
  min-width: 0;
1898
1907
  font: inherit;
1899
1908
  font-size: 11px;
@@ -2037,6 +2046,26 @@
2037
2046
  overflow-y: auto;
2038
2047
  overflow-x: hidden;
2039
2048
  user-select: none;
2049
+ /* Thin, themed scrollbars (Firefox) — Chromium/Safari below. */
2050
+ scrollbar-width: thin;
2051
+ scrollbar-color: color-mix(in srgb, var(--bo-text-dim) 55%, transparent) transparent;
2052
+ }
2053
+ .viewport::-webkit-scrollbar {
2054
+ width: 10px;
2055
+ height: 10px;
2056
+ }
2057
+ .viewport::-webkit-scrollbar-thumb {
2058
+ background: color-mix(in srgb, var(--bo-text-dim) 45%, transparent);
2059
+ border: 2px solid transparent;
2060
+ background-clip: padding-box;
2061
+ border-radius: 6px;
2062
+ }
2063
+ .viewport::-webkit-scrollbar-thumb:hover {
2064
+ background: color-mix(in srgb, var(--bo-text-dim) 70%, transparent);
2065
+ background-clip: padding-box;
2066
+ }
2067
+ .viewport::-webkit-scrollbar-corner {
2068
+ background: transparent;
2040
2069
  }
2041
2070
  .empty {
2042
2071
  position: absolute;
@@ -20,6 +20,16 @@ export interface GridTheme {
20
20
  headerH?: string;
21
21
  mono?: string;
22
22
  sans?: string;
23
+ /** Native-control color scheme: themes checkboxes, date pickers, number
24
+ spinners, search-clear buttons and scrollbars. Defaults to dark. */
25
+ scheme?: 'light' | 'dark';
26
+ /** Outer corner radius (e.g. '8px', '0', '14px'). Default 8px. */
27
+ radius?: string;
28
+ /** Cell/row font size (e.g. '13px', '12px'). Default 13px. */
29
+ fontSize?: string;
30
+ /** Horizontal cell padding — the main density lever (e.g. '8px', '12px').
31
+ Pair with `rowHeight` for a fully compact or roomy look. Default 8px. */
32
+ cellPad?: string;
23
33
  }
24
34
  /** Serialize a theme to a CSS `--bo-grid-*: …;` declaration string. */
25
35
  export declare function themeVars(theme: GridTheme): string;
@@ -15,6 +15,10 @@ const VARS = {
15
15
  headerH: '--bo-grid-header-h',
16
16
  mono: '--bo-grid-mono',
17
17
  sans: '--bo-grid-sans',
18
+ scheme: '--bo-grid-scheme',
19
+ radius: '--bo-grid-radius',
20
+ fontSize: '--bo-grid-font-size',
21
+ cellPad: '--bo-grid-cell-pad',
18
22
  };
19
23
  /** Serialize a theme to a CSS `--bo-grid-*: …;` declaration string. */
20
24
  export function themeVars(theme) {
@@ -40,6 +44,7 @@ export const darkTheme = {
40
44
  amber: '#f59e0b',
41
45
  selFill: 'rgba(99,102,241,0.16)',
42
46
  selBorder: '#6366f1',
47
+ scheme: 'dark',
43
48
  };
44
49
  // A deliberate light palette (not an inverted dark one): near-white surfaces,
45
50
  // stronger green/red for contrast on light, subtle borders.
@@ -57,4 +62,5 @@ export const lightTheme = {
57
62
  amber: '#d97706',
58
63
  selFill: 'rgba(99,102,241,0.12)',
59
64
  selBorder: '#6366f1',
65
+ scheme: 'light',
60
66
  };
@@ -16,7 +16,13 @@
16
16
  // sparklines run this, so the realtime feed never repaints off-screen charts.
17
17
  $effect(() => {
18
18
  const ctx = setupHiDpiCanvas(canvas, width, height);
19
- drawCandles(ctx, candles, width, height);
19
+ // Pull the grid's up/down colors so candles follow the active theme
20
+ // (inherited --bo-up/--bo-down; falls back to the built-in defaults).
21
+ const cs = getComputedStyle(canvas);
22
+ drawCandles(ctx, candles, width, height, {
23
+ up: cs.getPropertyValue('--bo-up').trim() || undefined,
24
+ down: cs.getPropertyValue('--bo-down').trim() || undefined,
25
+ });
20
26
  });
21
27
 
22
28
  const label = $derived(summarize(candles));
@@ -66,7 +72,7 @@
66
72
  font-family: var(--bo-mono, "SF Mono", "JetBrains Mono", Menlo, Consolas, monospace);
67
73
  font-size: 10px;
68
74
  color: var(--bo-text, #e5e5e5);
69
- background: #000;
75
+ background: var(--bo-header-bg, #0f0f0f);
70
76
  border: 0.5px solid var(--bo-border, rgba(255, 255, 255, 0.12));
71
77
  border-radius: 4px;
72
78
  pointer-events: none;
@@ -9,7 +9,10 @@ export declare function setupHiDpiCanvas(canvas: HTMLCanvasElement, cssW: number
9
9
  * Draw compact candlesticks. Body shows open→close, wick shows low→high.
10
10
  * Color by per-candle direction. Canvas (not SVG) so 100+ of these stay cheap.
11
11
  */
12
- export declare function drawCandles(ctx: CanvasRenderingContext2D, candles: Candle[], w: number, h: number): void;
12
+ export declare function drawCandles(ctx: CanvasRenderingContext2D, candles: Candle[], w: number, h: number, colors?: {
13
+ up?: string;
14
+ down?: string;
15
+ }): void;
13
16
  /** Screen-reader text — canvas alone is invisible to AT, so we narrate trend. */
14
17
  export declare function summarize(candles: Candle[]): string;
15
18
  /** Which candle index sits under an x offset (for hover tooltips). */
@@ -37,10 +37,12 @@ function yOf(price, ext, h, pad) {
37
37
  * Draw compact candlesticks. Body shows open→close, wick shows low→high.
38
38
  * Color by per-candle direction. Canvas (not SVG) so 100+ of these stay cheap.
39
39
  */
40
- export function drawCandles(ctx, candles, w, h) {
40
+ export function drawCandles(ctx, candles, w, h, colors = {}) {
41
41
  ctx.clearRect(0, 0, w, h);
42
42
  if (candles.length === 0)
43
43
  return;
44
+ const upColor = colors.up || UP;
45
+ const downColor = colors.down || DOWN;
44
46
  const ext = priceExtent(candles);
45
47
  const pad = 2;
46
48
  const n = candles.length;
@@ -50,8 +52,8 @@ export function drawCandles(ctx, candles, w, h) {
50
52
  const c = candles[i];
51
53
  const cx = i * slot + slot / 2;
52
54
  const up = c.close >= c.open;
53
- ctx.strokeStyle = up ? UP : DOWN;
54
- ctx.fillStyle = up ? UP : DOWN;
55
+ ctx.strokeStyle = up ? upColor : downColor;
56
+ ctx.fillStyle = up ? upColor : downColor;
55
57
  // wick
56
58
  ctx.beginPath();
57
59
  ctx.moveTo(Math.round(cx) + 0.5, yOf(c.high, ext, h, pad));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bo-grid",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
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.",