ink-hud 0.1.2 โ†’ 0.1.4

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
@@ -1,52 +1,69 @@
1
- # ink-hud
1
+ <div align="center">
2
2
 
3
- > ๐Ÿ’Ž Retina-grade terminal data visualization dashboard - High-resolution chart library based on Braille characters
3
+ <h1>ink-hud</h1>
4
4
 
5
- [![npm version](https://badge.fury.io/js/ink-hud.svg)](https://www.npmjs.com/package/ink-hud)
6
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+ <p><strong>Retina-grade data visualization for the terminal โ€” built on React and Ink.</strong></p>
7
6
 
8
- **ink-hud** is a high-fidelity data visualization component library designed for the terminal, built on React and Ink. By utilizing Braille dot matrix characters (โฃฟ), it achieves 8x higher vertical resolution than standard block characters, delivering smooth and detailed charts and data visualizations right in your terminal.
7
+ <p>
8
+ <a href="https://github.com/zzf2333/ink-hud/stargazers"><img src="https://img.shields.io/github/stars/zzf2333/ink-hud?style=flat-square&color=2563eb" alt="GitHub Stars"/></a>
9
+ <a href="https://www.npmjs.com/package/ink-hud"><img src="https://img.shields.io/npm/v/ink-hud?style=flat-square&color=16a34a" alt="npm version"/></a>
10
+ <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-6b7280?style=flat-square" alt="License MIT"/></a>
11
+ <img src="https://img.shields.io/badge/node-18%2B-6b7280?style=flat-square" alt="Node 18+"/>
12
+ <img src="https://img.shields.io/badge/react-18%2B-6b7280?style=flat-square" alt="React 18+"/>
13
+ </p>
9
14
 
10
- ![Dashboard Demo](./docs/images/dashboard.png)
15
+ </div>
11
16
 
12
- ## โœจ Core Features
17
+ ---
18
+
19
+ ink-hud renders 13+ chart and layout components directly in the terminal. It uses Braille dot-matrix characters (โฃฟ) to achieve 8ร— higher vertical resolution than standard block characters, and falls back gracefully to block or ASCII mode on terminals that don't support Braille.
20
+
21
+ ![Dashboard Demo](./docs/images/all.png)
22
+
23
+ ---
24
+
25
+ ## Components
26
+
27
+ **Charts** โ€” LineChart ยท AreaChart ยท BarChart ยท PieChart ยท Sparkline ยท Heatmap
28
+
29
+ **Metrics** โ€” BigNumber ยท Gauge
30
+
31
+ **Data** โ€” Table ยท LogStream ยท PulseBar
13
32
 
14
- - **๐ŸŽฏ High-Resolution Rendering**: Uses Braille dot matrix characters (2ร—4 dots) for 8x vertical resolution
15
- - **๐ŸŽจ Multi-Renderer Architecture**: Auto-detects terminal capabilities, supports Braille, Block, and ASCII rendering modes
16
- - **๐Ÿ“Š Rich Component Library**: 13+ ready-to-use components covering charts, metrics, and layouts
17
- - **๐ŸŽญ VS Code Dark+ Theme**: Carefully designed default color scheme, beautiful and readable
18
- - **๐Ÿ“ Responsive Layout**: Built-in Grid and Panel system for easy adaptive terminal interfaces
19
- - **โšก Smooth Animations**: Built-in data smoothing Hooks with multiple easing functions
20
- - **๐Ÿ”ง TypeScript First**: Complete type definitions for excellent developer experience
21
- - **๐ŸŒˆ Compatibility Guaranteed**: Auto-degrades to block characters or ASCII for universal terminal support
33
+ **Layout** โ€” Panel ยท Grid
22
34
 
23
- ## ๐Ÿ“ฆ Installation
35
+ ---
36
+
37
+ ## Installation
24
38
 
25
39
  ```bash
26
40
  npm install ink-hud ink react
27
- # or with pnpm
41
+ # or
28
42
  pnpm add ink-hud ink react
29
43
  ```
30
44
 
31
- **Requirements:**
32
- - Node.js >= 18.0.0
33
- - React >= 18.0.0
34
- - Ink >= 4.0.0
45
+ Requires Node.js 18+, React 18+, Ink 4+.
35
46
 
36
- ## ๐Ÿš€ Quick Start
47
+ ---
48
+
49
+ ## Quick Start
37
50
 
38
51
  ```tsx
39
52
  import React from 'react';
40
53
  import { render } from 'ink';
41
- import { LineChart } from 'ink-hud';
54
+ import { InkHudProvider, LineChart } from 'ink-hud';
42
55
 
43
56
  const App = () => {
44
57
  const data = [
45
- { name: 'CPU', data: [12, 15, 45, 32, 60, 75, 20, 10], color: 'cyan' },
58
+ { name: 'CPU', data: [12, 15, 45, 32, 60, 75, 20, 10], color: 'cyan' },
46
59
  { name: 'Memory', data: [40, 42, 45, 48, 40, 38, 42, 45], color: 'magenta' },
47
60
  ];
48
61
 
49
- return <LineChart series={data} width={60} height={15} />;
62
+ return (
63
+ <InkHudProvider>
64
+ <LineChart series={data} width={60} height={15} showLegend />
65
+ </InkHudProvider>
66
+ );
50
67
  };
51
68
 
52
69
  render(<App />);
@@ -56,162 +73,147 @@ render(<App />);
56
73
  npx tsx app.tsx
57
74
  ```
58
75
 
59
- ## ๐Ÿ“Š Components
76
+ ---
60
77
 
61
- ### Chart Components
78
+ ## Component Reference
62
79
 
63
- #### LineChart
64
- Multi-series line chart for trend analysis and time series comparison.
80
+ ### LineChart
65
81
 
66
- ![LineChart](./docs/images/linechart.png)
82
+ Multi-series line chart for trend analysis and time-series comparison.
67
83
 
68
84
  ```tsx
69
- <LineChart
70
- series={[{ name: 'CPU', data: [12, 15, 45, 32], color: 'cyan' }]}
71
- width={60}
85
+ <LineChart
86
+ series={[{ name: 'CPU', data: [12, 15, 45, 32], color: 'cyan' }]}
87
+ width={60}
72
88
  height={15}
73
- showLegend={true}
89
+ showLegend
74
90
  />
75
91
  ```
76
92
 
77
- #### AreaChart
78
- Stacked area chart for cumulative data and proportion trends.
93
+ ### AreaChart
79
94
 
80
- ![AreaChart](./docs/images/areachart.png)
95
+ Filled area chart for cumulative data and proportion trends.
81
96
 
82
97
  ```tsx
83
- <AreaChart
84
- series={[{ name: 'Usage', data: [10, 20, 15, 25], color: 'green' }]}
85
- width={60}
98
+ <AreaChart
99
+ series={[{ name: 'Traffic', data: [10, 20, 15, 25], color: 'green' }]}
100
+ width={60}
86
101
  height={15}
87
102
  />
88
103
  ```
89
104
 
90
- #### BarChart
91
- Vertical and horizontal bar charts for category comparison.
105
+ ### BarChart
92
106
 
93
- ![BarChart](./docs/images/barchart.png)
94
- ![BarChart Horizontal](./docs/images/barchart-horizontal.png)
107
+ Vertical bar chart for category comparison. Uses BlockRenderer by default for clean rectangular fills.
95
108
 
96
109
  ```tsx
97
- <BarChart
98
- series={[{ name: 'Sales', data: [100, 200, 150], color: 'blue' }]}
99
- width={40}
110
+ <BarChart
111
+ series={[{ name: 'Requests', data: [100, 200, 150, 180], color: 'blue' }]}
112
+ width={40}
100
113
  height={15}
101
114
  orientation="vertical"
102
115
  />
103
116
  ```
104
117
 
105
- #### PieChart
106
- Pie chart for distribution and resource allocation visualization.
118
+ ### PieChart
107
119
 
108
- ![PieChart](./docs/images/piechart.png)
120
+ Circular sector chart for distribution and resource allocation. The canvas is constrained to a visual square so the circle always fills the container.
109
121
 
110
122
  ```tsx
111
- <PieChart
123
+ <PieChart
112
124
  data={[
113
- { name: 'System', value: 30, color: 'cyan' },
114
- { name: 'Apps', value: 50, color: 'green' },
115
- { name: 'Free', value: 20, color: 'yellow' },
116
- ]}
117
- width={30}
125
+ { name: 'API', value: 45, color: 'cyan' },
126
+ { name: 'DB', value: 25, color: 'blue' },
127
+ { name: 'Cache', value: 20, color: 'green' },
128
+ { name: 'Static', value: 10, color: 'yellow' },
129
+ ]}
130
+ width={30}
118
131
  height={15}
119
132
  />
120
133
  ```
121
134
 
122
- #### Sparkline
123
- Compact inline trend chart for embedded metrics.
135
+ ### Sparkline
124
136
 
125
- ![Sparkline](./docs/images/sparkline.png)
137
+ Compact inline trend chart for embedded metrics. Uses a static character table (`SPARK_LEVELS`) โ€” its `variant` prop (`'block' | 'braille'`) is independent of `InkHudProvider renderers`. Supports an `image` mode that renders via the Kitty/iTerm2 image protocol when available.
126
138
 
127
139
  ```tsx
128
140
  <Sparkline data={[1, 4, 2, 5, 3, 6]} width={20} color="cyan" />
141
+ <Sparkline data={[1, 4, 2, 5, 3, 6]} width={20} mode="auto" colors={['#00ff00', '#ff0000']} />
129
142
  ```
130
143
 
131
- #### Heatmap
132
- 2D grid visualization for matrix data and density distribution.
144
+ ### Heatmap
133
145
 
134
- ![Heatmap](./docs/images/heatmap.png)
146
+ 2D grid visualization for matrix data and density distribution. Uses the Kitty or iTerm2 image protocol for pixel-perfect rendering when available; falls back to `mode="character"` (chalk-colored block characters) on other terminals.
135
147
 
136
148
  ```tsx
137
- <Heatmap
138
- data={[[0.2, 0.5, 0.8], [0.1, 0.4, 0.7], [0.3, 0.6, 0.9]]}
149
+ <Heatmap
150
+ data={[[0.2, 0.5, 0.8], [0.1, 0.4, 0.7], [0.3, 0.6, 0.9]]}
139
151
  />
140
152
  ```
141
153
 
142
- ### Metric Components
143
-
144
- #### BigNumber
145
- Large number card for KPI display with trend indicators.
154
+ ### BigNumber
146
155
 
147
- ![BigNumber](./docs/images/bignumber.png)
156
+ Large-number KPI card with trend indicator.
148
157
 
149
158
  ```tsx
150
- <BigNumber value={125000} label="Revenue" trend={12.5} color="green" />
159
+ <BigNumber value={14328} label="Requests/s" trend={4.5} color="cyan" />
151
160
  ```
152
161
 
153
- #### Gauge
154
- Circular or linear progress indicator for percentages and load.
162
+ ### Gauge
155
163
 
156
- ![Gauge](./docs/images/gauge.png)
164
+ Progress bar for percentages and load metrics.
157
165
 
158
166
  ```tsx
159
- <Gauge value={75} label="CPU" max={100} color="yellow" />
167
+ <Gauge value={96} max={100} label="CPU" color="yellow" />
160
168
  ```
161
169
 
162
- ### Data Components
170
+ ### Table
163
171
 
164
- #### Table
165
- Interactive sortable data table with keyboard navigation.
166
-
167
- ![Table](./docs/images/table.png)
172
+ Sortable data table with keyboard navigation and optional zebra striping.
168
173
 
169
174
  ```tsx
170
- <Table
171
- data={[{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }]}
175
+ <Table
176
+ data={[
177
+ { pid: 1704, name: 'node', cpu: '12%', mem: '150 MB', status: 'Running' },
178
+ { pid: 2048, name: 'postgres', cpu: '5.2%', mem: '100 MB', status: 'Running' },
179
+ ]}
172
180
  columns={[
173
- { header: 'ID', accessor: 'id' },
174
- { header: 'Name', accessor: 'name' },
181
+ { header: 'PID', accessor: 'pid' },
182
+ { header: 'NAME', accessor: 'name' },
183
+ { header: 'CPU', accessor: 'cpu' },
184
+ { header: 'MEM', accessor: 'mem' },
185
+ { header: 'STATUS', accessor: 'status' },
175
186
  ]}
176
- zebra={true}
187
+ zebra
177
188
  />
178
189
  ```
179
190
 
180
- #### LogStream
181
- Real-time scrolling log display with syntax highlighting.
191
+ ### LogStream
182
192
 
183
- ![LogStream](./docs/images/logstream.png)
193
+ Real-time scrolling log display with per-level color coding.
184
194
 
185
195
  ```tsx
186
- <LogStream
187
- logs={['[INFO] Started', '[WARN] High CPU', '[ERROR] Failed']}
196
+ <LogStream
197
+ logs={['[INFO] Started', '[WARN] High CPU', '[ERROR] Connection failed']}
188
198
  maxLines={10}
189
199
  />
190
200
  ```
191
201
 
192
- #### PulseBar
193
- Heartbeat-style connection status history.
202
+ ### PulseBar
194
203
 
195
- ![PulseBar](./docs/images/pulsebar.png)
204
+ Heartbeat-style connection status history.
196
205
 
197
206
  ```tsx
198
- <PulseBar
199
- records={[
200
- { status: 'good' },
201
- { status: 'unstable' },
202
- { status: 'bad' },
203
- ]}
207
+ <PulseBar
208
+ records={[{ status: 'good' }, { status: 'unstable' }, { status: 'bad' }]}
204
209
  maxBars={30}
205
210
  variant="unicode"
206
211
  />
207
212
  ```
208
213
 
209
- ### Layout Components
210
-
211
- #### Panel
212
- Bordered container with optional title for content grouping.
214
+ ### Panel
213
215
 
214
- ![Panel](./docs/images/panel.png)
216
+ Bordered container with an optional title for content grouping.
215
217
 
216
218
  ```tsx
217
219
  <Panel title="System Status" borderColor="cyan">
@@ -219,84 +221,177 @@ Bordered container with optional title for content grouping.
219
221
  </Panel>
220
222
  ```
221
223
 
222
- #### Grid
223
- Responsive grid layout system for dashboard construction.
224
+ ### Grid
224
225
 
225
- ![Grid](./docs/images/grid.png)
226
+ Responsive grid layout system. Children are `<GridItem>` elements that can span multiple columns.
226
227
 
227
228
  ```tsx
228
229
  <Grid columns={3} width={120} rowHeight={10}>
229
230
  <GridItem><Panel title="A">Content</Panel></GridItem>
230
- <GridItem span={2}><Panel title="B">Wide</Panel></GridItem>
231
+ <GridItem span={2}><Panel title="B">Wide content</Panel></GridItem>
231
232
  </Grid>
232
233
  ```
233
234
 
234
- ## ๐ŸŽจ Renderer System
235
+ ---
236
+
237
+ ## Renderer System
238
+
239
+ ink-hud uses two independent rendering systems:
240
+
241
+ ![Rendering Architecture](./docs/images/rendering-architecture.png)
235
242
 
236
- ink-hud auto-detects terminal capabilities and selects the best renderer:
243
+ ### Pixel Canvas (charts)
237
244
 
238
- | Renderer | Resolution | Characters | Best For |
239
- |----------|------------|------------|----------|
240
- | **Braille** | 2ร—4 dots, 8x vertical | `โ €โ โ ‚...โฃฟ` | Modern terminals |
241
- | **Block** | 2ร—8 dots, 8x vertical | `โ–โ–‚โ–ƒโ–„โ–…โ–†โ–‡โ–ˆ` | UTF-8 terminals |
242
- | **ASCII** | 1ร—3, max compat | `_.-'"` | Legacy terminals |
245
+ LineChart, AreaChart, BarChart, and PieChart share a five-stage pipeline:
246
+
247
+ 1. `useChartCore` โ€” process series data, compute min/max, assign colors
248
+ 2. `useChartRenderer` โ€” resolve a `Renderer` instance from the `InkHudProvider` context
249
+ 3. `renderXxxChartCanvas` โ€” draw to a `Pixel[][]` grid via `renderer.setPixel()` / `drawLine()`
250
+ 4. `renderer.renderCanvas()` โ€” convert `Pixel[][]` to ANSI-colored text lines
251
+ 5. `ChartContainer` โ€” wrap with axes, legend, and border
252
+
253
+ Each chart ships with a pre-tuned default renderer:
254
+
255
+ | Chart kind | Default renderer | Reason |
256
+ |------------|-----------------|--------|
257
+ | `line` | Braille | 2ร—4 sub-pixel grid renders smooth diagonals |
258
+ | `area` | Braille | Fine-grained fill under curves |
259
+ | `bar` | Block | Clean rectangular bar edges |
260
+ | `pie` | Block | Solid fills create clean sector boundaries |
261
+
262
+ The three renderer implementations:
263
+
264
+ | Renderer | Characters | Resolution |
265
+ |----------|-----------|-----------|
266
+ | `BrailleRenderer` | `โ €โ โ ‚โ€ฆโฃฟ` | 2ร—4 dots per cell |
267
+ | `BlockRenderer` | `โ–โ–‚โ–ƒโ–„โ–…โ–†โ–‡โ–ˆ` | 2ร—2 dots per cell |
268
+ | `AsciiRenderer` | ASCII text | 1ร—1 per cell (fallback) |
269
+
270
+ ### Image Protocol (Heatmap, Sparkline image mode)
271
+
272
+ `capabilities.ts` detects terminal support from environment variables (`$TERM_PROGRAM`, `$TERM`). For Kitty terminals, components upload a PNG via `encodeKittyUpload()` and render `U+10EEEE` Unicode Placeholder characters โ€” this survives Ink re-renders without cursor flicker. For iTerm2, a cursor-up escape sequence fallback is used. On other terminals, `mode="character"` renders chalk-colored block characters.
273
+
274
+ ---
275
+
276
+ ## Configuration
277
+
278
+ ### InkHudProvider
279
+
280
+ Wrap your app in `<InkHudProvider>` to enable renderer selection and dependency injection. Without the provider, components use the global `TerminalDetector` singleton.
243
281
 
244
282
  ```tsx
245
- // Force specific renderer
246
- <LineChart series={data} renderer="braille" />
247
- <LineChart series={data} renderer="block" />
248
- <LineChart series={data} renderer="ascii" />
283
+ // Auto-detect terminal, use default renderer per chart kind
284
+ <InkHudProvider>
285
+ <MyApp />
286
+ </InkHudProvider>
287
+
288
+ // Override renderer for specific chart kinds
289
+ <InkHudProvider renderers={{ line: 'block', bar: 'braille' }}>
290
+ <MyApp />
291
+ </InkHudProvider>
292
+
293
+ // Inject a mock detector for testing (no env-var manipulation needed)
294
+ <InkHudProvider detector={mockDetector}>
295
+ <MyApp />
296
+ </InkHudProvider>
249
297
  ```
250
298
 
251
- ## ๐Ÿ–ฅ Terminal Compatibility
299
+ When the configured renderer is not supported by the terminal (e.g. Braille on a legacy console), `BlockRenderer` is used as a fallback. In development mode, a one-time `console.warn` is emitted per affected chart kind to help diagnose why the configured renderer is not active.
300
+
301
+ ### Smooth animations
302
+
303
+ ```tsx
304
+ import { useSmooth, useSmoothArray } from 'ink-hud';
305
+
306
+ // Animate a single number
307
+ const smoothValue = useSmooth(rawValue, { duration: 300, easing: 'easeOutCubic' });
308
+
309
+ // Animate a data series
310
+ const smoothSeries = useSmoothArray(rawSeries, { duration: 400 });
311
+ ```
312
+
313
+ ### Theme
314
+
315
+ ```tsx
316
+ import { ThemeProvider, ONE_DARK_THEME } from 'ink-hud';
317
+
318
+ <ThemeProvider theme={ONE_DARK_THEME}>
319
+ <MyApp />
320
+ </ThemeProvider>
321
+ ```
322
+
323
+ ---
324
+
325
+ ## Terminal Compatibility
326
+
327
+ | Support level | Terminals |
328
+ |--------------|-----------|
329
+ | Full (Braille + image protocol) | iTerm2, Warp, Alacritty, Kitty, Windows Terminal, VS Code |
330
+ | Partial (Block only) | macOS Terminal.app, some SSH sessions |
331
+ | Minimum (ASCII fallback) | Any ANSI-capable terminal |
252
332
 
253
- | Support Level | Terminals |
254
- |---------------|-----------|
255
- | โœ… **Full (Braille)** | iTerm2, Warp, Alacritty, Kitty, Windows Terminal, VS Code |
256
- | โš ๏ธ **Partial (Block)** | macOS Terminal.app, some SSH sessions |
257
- | ๐Ÿ“ **Minimum (ASCII)** | Legacy terminals, plain text environments |
333
+ ---
258
334
 
259
- ## ๐Ÿ“š Examples
335
+ ## Examples
336
+
337
+ Run the full dashboard:
260
338
 
261
339
  ```bash
262
340
  git clone https://github.com/zzf2333/ink-hud.git
263
341
  cd ink-hud
264
342
  pnpm install
343
+ pnpm demo
344
+ ```
265
345
 
266
- # Run complete dashboard
267
- npx tsx examples/dashboard.tsx
346
+ The `examples/` directory also contains individual page demos:
268
347
 
269
- # Run individual components
270
- npx tsx examples/basic/pulsebar.tsx
271
- npx tsx examples/basic/linechart.tsx
272
- npx tsx examples/basic/piechart.tsx
273
- npx tsx examples/basic/table.tsx
348
+ ```bash
349
+ node --import tsx examples/pages/charts.tsx
350
+ node --import tsx examples/pages/streams.tsx
351
+ node --import tsx examples/pages/layout.tsx
352
+ node --import tsx examples/pages/image.tsx
274
353
  ```
275
354
 
276
- ## ๐Ÿ›  Development
355
+ ---
356
+
357
+ ## Development
277
358
 
278
359
  ```bash
279
- pnpm install # Install dependencies
280
- pnpm build # Build library
281
- pnpm test # Run tests
282
- pnpm lint # Lint code
283
- pnpm typecheck # Type check
360
+ pnpm install # install dependencies
361
+ pnpm build # build (ESM + CJS + declarations)
362
+ pnpm test # run test suite
363
+ pnpm typecheck # tsc --noEmit
364
+ pnpm lint # biome check
365
+ pnpm demo # run examples/demo.tsx
284
366
  ```
285
367
 
286
- ## ๐Ÿ“– Documentation
368
+ Tests use `ink-testing-library`. The standard pattern for controlling renderer selection in tests:
287
369
 
288
- - [Component API Reference](./docs/api.md)
289
- - [Component Usage Guide](./docs/components.md)
290
- - [Getting Started Tutorial](./docs/getting-started.md)
370
+ ```tsx
371
+ // Inject a mock detector โ€” no env-var manipulation required
372
+ const detector = new TerminalDetector({ TERM_PROGRAM: 'iTerm.app' });
373
+
374
+ render(
375
+ <InkHudProvider detector={detector}>
376
+ <LineChart series={data} width={40} height={10} />
377
+ </InkHudProvider>
378
+ );
379
+ ```
380
+
381
+ Or bypass detection entirely with `forceRenderer`:
291
382
 
292
- ## ๐Ÿค Contributing
383
+ ```tsx
384
+ <LineChart series={data} width={40} height={10} forceRenderer="block" />
385
+ ```
293
386
 
294
- Contributions welcome! See [CONTRIBUTING.md](./CONTRIBUTING.md) for details.
387
+ ---
295
388
 
296
- ## ๐Ÿ“„ License
389
+ ## Contributing
297
390
 
298
- MIT ยฉ [saonian](https://github.com/zzf2333)
391
+ Contributions are welcome. See [CONTRIBUTING.md](./CONTRIBUTING.md) for details.
299
392
 
300
393
  ---
301
394
 
302
- **If this project helps you, please give it a โญ๏ธ!**
395
+ ## License
396
+
397
+ MIT ยฉ [saonian](https://github.com/zzf2333)