ansimax 1.0.0 → 1.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 +201 -21
- package/README.es.md +697 -629
- package/README.md +444 -376
- package/dist/index.d.mts +1256 -336
- package/dist/index.d.ts +1256 -336
- package/dist/index.js +4391 -683
- package/dist/index.mjs +4293 -682
- package/examples/01-cli-installer.ts +96 -0
- package/examples/02-live-dashboard.ts +152 -0
- package/examples/03-pixel-art-game.ts +170 -0
- package/examples/04-interactive-deploy.ts +163 -0
- package/examples/05-tree-visualizations.ts +183 -0
- package/examples/06-everything-together.ts +466 -0
- package/examples/animations.ts +172 -0
- package/examples/demo.js +213 -0
- package/examples/demo.ts +212 -0
- package/examples/loaders.ts +254 -0
- package/examples/showcase.ts +174 -0
- package/examples/trees-basic.ts +99 -0
- package/examples/tsconfig.json +18 -0
- package/examples/tsconfig.vscode.json +25 -0
- package/package.json +20 -8
package/README.md
CHANGED
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
|
|
3
|
-
<img src="media/ansimax.png" alt="Ansimax" width="
|
|
4
|
-
|
|
5
|
-
# Ansimax
|
|
3
|
+
<img src="media/ansimax.png" alt="Ansimax logo" width="380"/>
|
|
6
4
|
|
|
7
5
|
### The ultimate CLI rendering library for Node.js
|
|
8
6
|
|
|
9
|
-
|
|
7
|
+
_Colors • Gradients • Animations • ASCII Art • Pixel Art • Trees • Components • Themes_
|
|
10
8
|
|
|
11
|
-
[](LICENSE)
|
|
10
|
+
[](https://www.npmjs.com/package/ansimax)
|
|
11
|
+
[](tsconfig.json)
|
|
12
|
+
[](#testing)
|
|
13
|
+
[](#testing)
|
|
16
14
|
[](#)
|
|
15
|
+
[](#)
|
|
17
16
|
|
|
18
17
|
**English** · [Español](README.es.md)
|
|
19
18
|
|
|
@@ -21,60 +20,68 @@ Colors • Gradients • Animations • ASCII Art • Pixel Art • Components
|
|
|
21
20
|
|
|
22
21
|
---
|
|
23
22
|
|
|
24
|
-
##
|
|
25
|
-
|
|
26
|
-
See Ansimax in action — every animation and loader running live:
|
|
27
|
-
|
|
28
|
-
### Animations
|
|
29
|
-
|
|
30
|
-
https://github.com/Brashkie/ansimax/raw/main/media/animations.mp4
|
|
31
|
-
|
|
32
|
-
### Loaders
|
|
33
|
-
|
|
34
|
-
https://github.com/Brashkie/ansimax/raw/main/media/loaders.mp4
|
|
23
|
+
## 🌟 What is Ansimax?
|
|
35
24
|
|
|
36
|
-
|
|
25
|
+
Ansimax is a **batteries-included rendering library** for building beautiful terminal UIs in Node.js. One package replaces a stack of 8+ dependencies — colors, gradients, ASCII art, spinners, progress bars, tables, menus, trees, themes, pixel art — combined into a single coherent TypeScript API with **zero runtime dependencies**.
|
|
37
26
|
|
|
38
|
-
|
|
27
|
+
```bash
|
|
28
|
+
npm install ansimax
|
|
29
|
+
```
|
|
39
30
|
|
|
40
|
-
|
|
31
|
+
```ts
|
|
32
|
+
import { color, gradient, ascii, loader } from 'ansimax';
|
|
41
33
|
|
|
42
|
-
|
|
34
|
+
console.log(ascii.banner('hello', {
|
|
35
|
+
colorFn: (t) => gradient(t, ['#ff79c6', '#bd93f9', '#8be9fd']),
|
|
36
|
+
}));
|
|
43
37
|
|
|
44
|
-
|
|
38
|
+
const stop = loader.spin('Building project', { color: '#bd93f9' });
|
|
39
|
+
await someAsyncWork();
|
|
40
|
+
stop('Build complete', true);
|
|
41
|
+
```
|
|
45
42
|
|
|
46
43
|
---
|
|
47
44
|
|
|
48
45
|
## 💡 Why Ansimax?
|
|
49
46
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
47
|
+
| Without Ansimax | With Ansimax |
|
|
48
|
+
|---|---|
|
|
49
|
+
| Install 8+ packages: `chalk`, `gradient-string`, `figlet`, `ora`, `cli-progress`, `cli-table3`, `boxen`, `inquirer` | One install: `ansimax` |
|
|
50
|
+
| Mix incompatible APIs, different paradigms, conflicting types | Consistent functional API, single source of truth |
|
|
51
|
+
| No coherent theme system across packages | Built-in themes (Dracula, Nord, Matrix, Cyberpunk, +5) |
|
|
52
|
+
| Manual cursor cleanup, no crash safety | Reference-counted cursor + crash handlers built in |
|
|
53
|
+
| No `AbortSignal` support in most CLI libs | Every animation, loader, and prompt is abortable |
|
|
54
|
+
| Each lib brings its own runtime fallback logic | Unified `NO_COLOR` / `FORCE_COLOR` / TTY detection |
|
|
55
|
+
| No memory bounds on color caches | Bounded LRU caches everywhere (no leaks under load) |
|
|
56
56
|
|
|
57
57
|
---
|
|
58
58
|
|
|
59
|
-
## 🆚 Comparison
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
|
64
|
-
|
|
65
|
-
|
|
|
66
|
-
|
|
|
67
|
-
|
|
|
68
|
-
|
|
|
69
|
-
|
|
|
70
|
-
|
|
|
71
|
-
|
|
|
72
|
-
|
|
|
73
|
-
|
|
|
74
|
-
|
|
|
75
|
-
|
|
|
76
|
-
|
|
77
|
-
|
|
59
|
+
## 🆚 Comparison with the Node.js ecosystem
|
|
60
|
+
|
|
61
|
+
Ansimax replaces a dependency stack of popular Node.js libraries with one coherent, typed package:
|
|
62
|
+
|
|
63
|
+
| Feature | chalk | gradient-string | ora | cli-progress | figlet | boxen | inquirer | cli-table3 | **Ansimax** |
|
|
64
|
+
|---|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
|
|
65
|
+
| Basic + 256 colors | ✅ | — | — | — | — | — | — | — | ✅ |
|
|
66
|
+
| Truecolor with adaptive fallback | ✅ | ✅ | — | — | — | — | — | — | ✅ |
|
|
67
|
+
| Multi-stop gradients | — | ✅ | — | — | — | — | — | — | ✅ |
|
|
68
|
+
| **Animated gradients** | — | — | — | — | — | — | — | — | 🔜 |
|
|
69
|
+
| ASCII banners | — | — | — | — | ✅ | — | — | — | ✅ |
|
|
70
|
+
| Custom font registry | — | — | — | — | partial | — | — | — | ✅ |
|
|
71
|
+
| Boxes with multiple styles | — | — | — | — | — | ✅ | — | — | ✅ |
|
|
72
|
+
| Spinners (multiple styles) | — | — | ✅ | — | — | — | — | — | ✅ (11 styles) |
|
|
73
|
+
| Animated progress bars | — | — | — | ✅ | — | — | — | — | ✅ |
|
|
74
|
+
| **Hierarchical/parallel tasks** | — | — | — | — | — | — | — | — | ✅ |
|
|
75
|
+
| Tables (multi-line, ANSI-aware) | — | — | — | — | — | — | — | ✅ | ✅ |
|
|
76
|
+
| Interactive menus + multi-select | — | — | — | — | — | — | ✅ | — | ✅ |
|
|
77
|
+
| **Trees with cycle detection** | — | — | — | — | — | — | — | — | ✅ |
|
|
78
|
+
| **Pixel art + canvas + sprites** | — | — | — | — | — | — | — | — | ✅ |
|
|
79
|
+
| **Theme system + per-instance isolation** | — | — | — | — | — | — | — | — | ✅ |
|
|
80
|
+
| `AbortSignal` everywhere | — | — | partial | — | — | — | partial | — | ✅ |
|
|
81
|
+
| `NO_COLOR` env support | ✅ | partial | partial | — | — | — | — | — | ✅ |
|
|
82
|
+
| TypeScript-first | partial | partial | ✅ | partial | partial | ✅ | partial | partial | ✅ |
|
|
83
|
+
| Zero runtime dependencies | ✅ | — | — | — | — | — | — | — | ✅ |
|
|
84
|
+
| **Total install size** | small | small | medium | medium | medium | small | large | medium | **< 100 KB** |
|
|
78
85
|
|
|
79
86
|
---
|
|
80
87
|
|
|
@@ -82,441 +89,476 @@ Built for developers who want to ship CLIs that **feel** professional.
|
|
|
82
89
|
|
|
83
90
|
```bash
|
|
84
91
|
npm install ansimax
|
|
92
|
+
# or
|
|
93
|
+
pnpm add ansimax
|
|
94
|
+
# or
|
|
95
|
+
yarn add ansimax
|
|
85
96
|
```
|
|
86
97
|
|
|
87
|
-
|
|
88
|
-
yarn add ansimax # Yarn
|
|
89
|
-
pnpm add ansimax # PNPM
|
|
90
|
-
bun add ansimax # Bun
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
**Requires Node.js >= 18**
|
|
98
|
+
**Requirements:** Node.js ≥ 18. ESM and CJS both supported. Examples published with the package — see [`/examples`](./examples).
|
|
94
99
|
|
|
95
100
|
---
|
|
96
101
|
|
|
97
102
|
## ⚡ 30-second example
|
|
98
103
|
|
|
99
104
|
```ts
|
|
100
|
-
import { color } from 'ansimax';
|
|
105
|
+
import { color, gradient, loader, ascii } from 'ansimax';
|
|
101
106
|
|
|
102
|
-
console.log(
|
|
103
|
-
|
|
107
|
+
console.log(ascii.banner('deploy', {
|
|
108
|
+
colorFn: (t) => gradient(t, ['#ff6b6b', '#feca57', '#48dbfb']),
|
|
109
|
+
}));
|
|
104
110
|
|
|
105
|
-
|
|
111
|
+
const stop = loader.spin('Building project', { color: '#bd93f9' });
|
|
112
|
+
await someAsyncWork();
|
|
113
|
+
stop('Build complete', true); // ✓ + success color
|
|
114
|
+
|
|
115
|
+
console.log(color.green('✓') + ' Ready in ' + color.bold('1.4s'));
|
|
116
|
+
```
|
|
106
117
|
|
|
107
118
|
---
|
|
108
119
|
|
|
109
120
|
## 🚀 Quick Start
|
|
110
121
|
|
|
111
122
|
```ts
|
|
112
|
-
import {
|
|
113
|
-
|
|
114
|
-
// Colors with stacked styles (single ANSI reset, no nesting)
|
|
115
|
-
console.log(color.bold(color.cyan('Hello, terminal!')));
|
|
116
|
-
|
|
117
|
-
// Gradient text
|
|
118
|
-
console.log(gradient('Smooth color flow', ['#ff6b6b', '#feca57', '#48dbfb']));
|
|
123
|
+
import { configure, color, themes, gradient } from 'ansimax';
|
|
119
124
|
|
|
120
|
-
//
|
|
121
|
-
|
|
125
|
+
// Global configuration
|
|
126
|
+
configure({ theme: 'dracula', animationSpeed: 'normal' });
|
|
122
127
|
|
|
123
|
-
//
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
stop('Built successfully', true);
|
|
128
|
+
// Basic styling
|
|
129
|
+
console.log(color.red('error'));
|
|
130
|
+
console.log(color.bold(color.cyan('important')));
|
|
127
131
|
|
|
128
|
-
//
|
|
129
|
-
console.log(
|
|
132
|
+
// Multi-stop gradient
|
|
133
|
+
console.log(gradient('rainbow text', [
|
|
134
|
+
'#ff5555', '#ffaa00', '#ffff00',
|
|
135
|
+
'#00ff00', '#0099ff', '#cc44ff',
|
|
136
|
+
]));
|
|
130
137
|
|
|
131
|
-
//
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
['Build', '✓ ready'],
|
|
135
|
-
], { header: true, borderStyle: 'rounded' }));
|
|
138
|
+
// Switch theme — fires subscribers
|
|
139
|
+
themes.use('cyberpunk');
|
|
140
|
+
console.log(themes.primary('cyberpunk primary'));
|
|
136
141
|
```
|
|
137
142
|
|
|
138
143
|
---
|
|
139
144
|
|
|
140
145
|
## ✨ Features
|
|
141
146
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
147
|
+
- 🎨 **Colors** — Truecolor / 256 / basic with adaptive fallback. NO_COLOR / FORCE_COLOR / TTY detection
|
|
148
|
+
- 🌈 **Gradients** — Multi-stop linear, radial, diagonal, arbitrary-angle. Custom presets via `registerPreset`
|
|
149
|
+
- 🔠 **ASCII Art** — Banners (`big`/`small` fonts), boxes (6 styles), dividers, logos. Stream API + custom font registry
|
|
150
|
+
- 🖼️ **Pixel Art** — Sprites, alpha blending, dithered gradients, canvas with dirty-rect rendering, braille mode (2×4 sub-pixel)
|
|
151
|
+
- 🌳 **Trees** — Builder + plain-data API, 4 styles, per-node colors/icons, max-depth, cycle detection, walk/find/map/filter algorithms
|
|
152
|
+
- 🎞️ **Animations** — Typewriter, fade, slide, pulse, wave, glitch, reveal. AbortSignal-aware, reducedMotion mode
|
|
153
|
+
- ⏳ **Loaders** — 11 spinner styles, animated bars, hierarchical/parallel tasks, countdowns, multi-spinner manager
|
|
154
|
+
- 🎬 **Frames** — Sequenced playback with pause/resume/seek, live push-based renderer, drift-corrected timing, morph
|
|
155
|
+
- 🧱 **Components** — Tables (ANSI-aware, multi-line cells), badges, status lines, sections, columns, timelines, interactive menus
|
|
156
|
+
- 🎨 **Themes** — 8 built-ins (Dracula, Nord, Monokai, Cyberpunk, Pastel, Matrix, Ocean, Sunset). Per-instance isolation, `onChange` listeners, `bg*` helpers
|
|
157
|
+
- ⚙️ **Configure** — Centralized config with subscribers, batched updates, `withConfig()` temporary overrides, strict mode
|
|
158
|
+
- 🛠️ **Utils** — ANSI primitives, cursor control, terminal hyperlinks (OSC 8), `setTitle`, `safeJson`, `onResize`, debounce/throttle/memoize
|
|
154
159
|
|
|
155
160
|
---
|
|
156
161
|
|
|
157
162
|
## 📸 Showcase
|
|
158
163
|
|
|
159
164
|
### Colors & Gradients
|
|
160
|
-
<div align="center">
|
|
161
|
-
<img src="media/colors.png" alt="Colors and gradients" width="700"/>
|
|
162
|
-
</div>
|
|
163
|
-
|
|
164
|
-
```ts
|
|
165
|
-
import { color, gradient, rainbow, compose } from 'ansimax';
|
|
166
165
|
|
|
167
|
-
|
|
168
|
-
color.red('basic'); // 16-color
|
|
169
|
-
color.color256(196)('palette'); // 256-color
|
|
170
|
-
color.hex('#48dbfb')('truecolor'); // 24-bit
|
|
171
|
-
color.rgb(255, 100, 50)('custom'); // RGB
|
|
166
|
+
<img src="media/colors.png" alt="Colors and gradients" />
|
|
172
167
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
console.log(errorStyle('CRITICAL ERROR'));
|
|
168
|
+
```ts
|
|
169
|
+
import { color, gradient } from 'ansimax';
|
|
176
170
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
171
|
+
color.red('red'); color.green('green'); color.blue('blue');
|
|
172
|
+
color.bold(text); color.italic(text); color.underline(text);
|
|
173
|
+
gradient('fire to ocean', ['#ff6b6b', '#feca57', '#48dbfb']);
|
|
174
|
+
color.rainbow('built-in rainbow preset');
|
|
180
175
|
```
|
|
181
176
|
|
|
182
|
-
---
|
|
183
|
-
|
|
184
177
|
### ASCII Art
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
</div>
|
|
178
|
+
|
|
179
|
+
<img src="media/ascii_art.png" alt="ASCII art" />
|
|
188
180
|
|
|
189
181
|
```ts
|
|
190
|
-
import { ascii,
|
|
182
|
+
import { ascii, gradient } from 'ansimax';
|
|
191
183
|
|
|
192
|
-
ascii.
|
|
193
|
-
ascii.small('hello'); // 3-line compact font
|
|
194
|
-
ascii.banner('ANSIMAX', {
|
|
184
|
+
ascii.banner('HELLO', {
|
|
195
185
|
font: 'big',
|
|
196
|
-
colorFn: rainbow,
|
|
197
186
|
align: 'center',
|
|
187
|
+
colorFn: (t) => gradient(t, ['#ff79c6', '#bd93f9']),
|
|
198
188
|
});
|
|
199
189
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
borderStyle: 'double',
|
|
203
|
-
padding: 2,
|
|
204
|
-
});
|
|
190
|
+
ascii.box('Rainbow box!', { padding: 1, borderStyle: 'rounded' });
|
|
191
|
+
```
|
|
205
192
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
193
|
+
### Trees
|
|
194
|
+
|
|
195
|
+
<img src="media/trees.png" alt="Trees" />
|
|
196
|
+
|
|
197
|
+
```ts
|
|
198
|
+
import { tree, color } from 'ansimax';
|
|
199
|
+
|
|
200
|
+
const project = tree({ label: 'my-app', icon: '📦', color: color.bold });
|
|
201
|
+
const src = project.add({ label: 'src', icon: '📁' });
|
|
202
|
+
src.addLeaf({ label: 'index.ts', icon: '📄' });
|
|
203
|
+
src.addLeaf({ label: 'app.ts', icon: '📄' });
|
|
204
|
+
|
|
205
|
+
console.log(project.render({
|
|
206
|
+
style: 'rounded',
|
|
207
|
+
palette: [color.cyan, color.green, color.magenta],
|
|
208
|
+
guideColor: color.dim,
|
|
209
|
+
}));
|
|
211
210
|
```
|
|
212
211
|
|
|
213
|
-
|
|
212
|
+
### Pixel Art & Canvas
|
|
213
|
+
|
|
214
|
+
<img src="media/pixel_art.png" alt="Pixel art" />
|
|
215
|
+
|
|
216
|
+
```ts
|
|
217
|
+
import { images, createCanvas, gradientRect } from 'ansimax';
|
|
218
|
+
|
|
219
|
+
// Built-in sprite
|
|
220
|
+
console.log(images.sprite('heart'));
|
|
221
|
+
|
|
222
|
+
// Smooth gradient with Bayer dither
|
|
223
|
+
console.log(gradientRect({
|
|
224
|
+
width: 50, height: 4,
|
|
225
|
+
colors: ['#ff6b6b', '#feca57', '#48dbfb'],
|
|
226
|
+
dither: 'bayer',
|
|
227
|
+
}));
|
|
228
|
+
|
|
229
|
+
// Custom canvas
|
|
230
|
+
const c = createCanvas(40, 10);
|
|
231
|
+
c.fill({ r: 18, g: 18, b: 38 });
|
|
232
|
+
c.drawCircle(20, 5, 4, { r: 255, g: 200, b: 0 }, true);
|
|
233
|
+
c.drawSprite(2, 2, images.sprites.star!.pixels);
|
|
234
|
+
c.print();
|
|
235
|
+
```
|
|
214
236
|
|
|
215
237
|
### Components
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
</div>
|
|
238
|
+
|
|
239
|
+
<img src="media/components.png" alt="Components" />
|
|
219
240
|
|
|
220
241
|
```ts
|
|
221
|
-
import { components } from 'ansimax';
|
|
242
|
+
import { components, color } from 'ansimax';
|
|
222
243
|
|
|
223
|
-
// Tables with auto-sizing
|
|
224
244
|
components.table([
|
|
225
|
-
['
|
|
226
|
-
['
|
|
227
|
-
['
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
components.
|
|
232
|
-
components.
|
|
233
|
-
components.status('warn', 'Deprecation notice');
|
|
234
|
-
|
|
235
|
-
// Badges
|
|
236
|
-
components.badge('VERSION', 'v1.0.0');
|
|
237
|
-
components.badge('BUILD', 'passing');
|
|
238
|
-
|
|
239
|
-
// Interactive menus (with AbortSignal support)
|
|
240
|
-
const choice = await components.menu([
|
|
241
|
-
'Install dependencies',
|
|
242
|
-
'Run tests',
|
|
243
|
-
'Deploy',
|
|
244
|
-
'Cancel',
|
|
245
|
-
], { multiSelect: false });
|
|
245
|
+
['Module', 'Status', 'Coverage'],
|
|
246
|
+
['colors', color.green('● ready'), '100%'],
|
|
247
|
+
['animations', color.green('● ready'), '100%'],
|
|
248
|
+
['loaders', color.green('● ready'), '100%'],
|
|
249
|
+
], { borderStyle: 'rounded' });
|
|
250
|
+
|
|
251
|
+
components.badge('VERSION', 'v1.1.0');
|
|
252
|
+
components.badge('BUILD', 'passing');
|
|
246
253
|
```
|
|
247
254
|
|
|
248
|
-
---
|
|
249
|
-
|
|
250
255
|
### Timeline
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
</div>
|
|
256
|
+
|
|
257
|
+
<img src="media/timeline.png" alt="Timeline" />
|
|
254
258
|
|
|
255
259
|
```ts
|
|
256
260
|
components.timeline([
|
|
257
261
|
{ label: 'Project init', done: true, time: '10:00' },
|
|
258
262
|
{ label: 'Build pipeline', done: true, time: '10:15' },
|
|
259
|
-
{ label: 'Run tests', done:
|
|
260
|
-
{ label: 'Deploy to npm', done: false
|
|
263
|
+
{ label: 'Run tests', done: false, time: '10:32' },
|
|
264
|
+
{ label: 'Deploy to npm', done: false },
|
|
261
265
|
]);
|
|
262
266
|
```
|
|
263
267
|
|
|
264
|
-
---
|
|
265
|
-
|
|
266
268
|
### Loaders & Progress
|
|
267
|
-
<div align="center">
|
|
268
|
-
<img src="media/loaders.png" alt="Loaders and progress bars" width="700"/>
|
|
269
|
-
</div>
|
|
270
269
|
|
|
271
270
|
```ts
|
|
272
271
|
import { loader } from 'ansimax';
|
|
273
272
|
|
|
274
|
-
// Spinner
|
|
275
|
-
const stop = loader.spin('
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
signal: ctrl.signal, // AbortSignal aware
|
|
279
|
-
});
|
|
280
|
-
stop('Complete', true);
|
|
273
|
+
// Spinner with success/failure
|
|
274
|
+
const stop = loader.spin('Loading...', { color: '#bd93f9' });
|
|
275
|
+
await work();
|
|
276
|
+
stop('Done!', true); // ✓ green icon
|
|
281
277
|
|
|
282
278
|
// Animated progress bar
|
|
283
|
-
await loader.progressAnimate(
|
|
284
|
-
delay:
|
|
285
|
-
color: '#48dbfb',
|
|
279
|
+
await loader.progressAnimate(100, 'Downloading', {
|
|
280
|
+
color: '#50fa7b', delay: 25,
|
|
286
281
|
});
|
|
287
282
|
|
|
288
|
-
//
|
|
283
|
+
// Hierarchical tasks with parallel execution
|
|
289
284
|
await loader.tasks([
|
|
290
|
-
{ text: '
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
],
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
await loader.countdown(5, {
|
|
297
|
-
label: 'Launching in',
|
|
298
|
-
color: '#ffd700',
|
|
299
|
-
});
|
|
285
|
+
{ text: 'Build', fn: async () => build(), subtasks: [
|
|
286
|
+
{ text: 'TypeScript', fn: async () => tsc() },
|
|
287
|
+
{ text: 'Bundle', fn: async () => bundle() },
|
|
288
|
+
]},
|
|
289
|
+
{ text: 'Test', fn: async () => test() },
|
|
290
|
+
], { parallel: true });
|
|
300
291
|
```
|
|
301
292
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
### Pixel Art & Canvas
|
|
305
|
-
<div align="center">
|
|
306
|
-
<img src="media/pixel_art.png" alt="Pixel art and canvas drawing" width="700"/>
|
|
307
|
-
</div>
|
|
293
|
+
### Animations
|
|
308
294
|
|
|
309
295
|
```ts
|
|
310
|
-
import {
|
|
311
|
-
|
|
312
|
-
// Built-in sprites: heart, star, smiley, pacman
|
|
313
|
-
console.log(images.sprite('heart', { scale: 2 }));
|
|
314
|
-
|
|
315
|
-
// Sprite transforms
|
|
316
|
-
const flipped = images.flipHorizontal(images.sprites.heart.pixels);
|
|
317
|
-
const rotated = images.rotate90(images.sprites.star.pixels);
|
|
318
|
-
|
|
319
|
-
// Custom canvas drawing
|
|
320
|
-
const canvas = createCanvas(30, 10);
|
|
321
|
-
canvas.drawRect(0, 0, 30, 10, { r: 30, g: 30, b: 50 }, true);
|
|
322
|
-
canvas.drawCircle(15, 5, 4, { r: 255, g: 200, b: 0 }, true);
|
|
323
|
-
canvas.print();
|
|
324
|
-
|
|
325
|
-
// Gradient rectangles — horizontal, vertical, diagonal, radial
|
|
326
|
-
images.gradientRect({
|
|
327
|
-
width: 50, height: 8,
|
|
328
|
-
colors: ['#ff0080', '#7928ca', '#0070f3'],
|
|
329
|
-
style: 'radial',
|
|
330
|
-
});
|
|
331
|
-
```
|
|
296
|
+
import { animate, gradient } from 'ansimax';
|
|
332
297
|
|
|
333
|
-
|
|
298
|
+
await animate.typewriter('Welcome to the deployment wizard...', {
|
|
299
|
+
speed: 30,
|
|
300
|
+
colorFn: (t) => gradient(t, ['#bd93f9', '#ff79c6']),
|
|
301
|
+
});
|
|
334
302
|
|
|
335
|
-
|
|
336
|
-
<div align="center">
|
|
337
|
-
<img src="media/themes.png" alt="Built-in themes" width="700"/>
|
|
338
|
-
</div>
|
|
303
|
+
await animate.fadeIn('Loading complete', { duration: 600 });
|
|
339
304
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
const t = themes.current();
|
|
348
|
-
console.log(color.hex(t.primary)('Primary text'));
|
|
349
|
-
console.log(color.hex(t.error)('Error message'));
|
|
350
|
-
console.log(color.hex(t.success)('Success!'));
|
|
351
|
-
|
|
352
|
-
// Define your own theme
|
|
353
|
-
themes.define('mytheme', {
|
|
354
|
-
primary: '#00ff88',
|
|
355
|
-
secondary: '#0070f3',
|
|
356
|
-
accent: '#ffd700',
|
|
357
|
-
error: '#ff4757',
|
|
358
|
-
warning: '#ffa502',
|
|
359
|
-
success: '#2ed573',
|
|
360
|
-
});
|
|
305
|
+
// Race steps against a timeout — never hang
|
|
306
|
+
await animate.parallel([
|
|
307
|
+
async () => await checkNetwork(),
|
|
308
|
+
async () => await checkDatabase(),
|
|
309
|
+
async () => await checkAuth(),
|
|
310
|
+
], { timeout: 5000 });
|
|
361
311
|
```
|
|
362
312
|
|
|
363
|
-
|
|
313
|
+
### Themes
|
|
364
314
|
|
|
365
|
-
|
|
366
|
-
<div align="center">
|
|
367
|
-
<img src="media/get_started.png" alt="Get started" width="700"/>
|
|
368
|
-
</div>
|
|
315
|
+
<img src="media/themes.png" alt="Themes" />
|
|
369
316
|
|
|
370
|
-
|
|
317
|
+
```ts
|
|
318
|
+
import { themes, createTheme } from 'ansimax';
|
|
371
319
|
|
|
372
|
-
|
|
320
|
+
// Built-in themes
|
|
321
|
+
themes.use('dracula');
|
|
322
|
+
themes.primary('hello');
|
|
373
323
|
|
|
374
|
-
|
|
324
|
+
// Listen for changes
|
|
325
|
+
const off = themes.onChange((newTheme, oldTheme) => {
|
|
326
|
+
console.log(`Theme: ${oldTheme.name} → ${newTheme.name}`);
|
|
327
|
+
});
|
|
375
328
|
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
329
|
+
// Multi-tenant: each instance fully isolated
|
|
330
|
+
const tenantA = createTheme('nord');
|
|
331
|
+
const tenantB = createTheme('matrix');
|
|
332
|
+
tenantA.register('custom', myDef); // doesn't leak to tenantB
|
|
333
|
+
```
|
|
379
334
|
|
|
380
|
-
|
|
381
|
-
npm run build
|
|
382
|
-
node examples/demo.js
|
|
335
|
+
---
|
|
383
336
|
|
|
384
|
-
|
|
385
|
-
npx tsx examples/showcase.ts
|
|
337
|
+
## 📚 Examples
|
|
386
338
|
|
|
387
|
-
|
|
388
|
-
npx tsx examples/animations.ts
|
|
339
|
+
Seven production-grade examples ship in the npm package and are runnable directly. Find them in [`/examples`](./examples) once you install:
|
|
389
340
|
|
|
390
|
-
|
|
391
|
-
|
|
341
|
+
| File | What it demonstrates |
|
|
342
|
+
|---|---|
|
|
343
|
+
| `trees-basic.ts` | Minimal trees example — builder API + algorithms |
|
|
344
|
+
| `01-cli-installer.ts` | npm-create style installer — banner + hierarchical tasks + status icons + summary box |
|
|
345
|
+
| `02-live-dashboard.ts` | Real-time dashboard — `frames.live` + service table + gradient bars + `onResize` + SIGINT cleanup |
|
|
346
|
+
| `03-pixel-art-game.ts` | Bouncing rocket sprite — canvas + alpha blending + gradient + FPS counter + drift-corrected loop |
|
|
347
|
+
| `04-interactive-deploy.ts` | Menu + multi-select + `loader.multi` + `createTheme` + `onConfigChange` |
|
|
348
|
+
| `05-tree-visualizations.ts` | Filesystem + dependency + JSON + decision trees (`walk` + `measure` bonus) |
|
|
349
|
+
| `06-everything-together.ts` | Comprehensive showcase — every module exercised in one cohesive demo |
|
|
350
|
+
|
|
351
|
+
Run any example with:
|
|
352
|
+
```bash
|
|
353
|
+
npx tsx examples/06-everything-together.ts
|
|
392
354
|
```
|
|
393
355
|
|
|
394
356
|
---
|
|
395
357
|
|
|
396
358
|
## 🎯 Use Cases
|
|
397
359
|
|
|
398
|
-
- **
|
|
399
|
-
- **
|
|
400
|
-
- **
|
|
401
|
-
- **
|
|
402
|
-
- **
|
|
403
|
-
- **
|
|
404
|
-
- **
|
|
360
|
+
- **CLI installers & scaffolders** — beautiful first-run experience (create-react-app, create-next-app style)
|
|
361
|
+
- **DevOps tools** — deployment dashboards, build pipelines, health monitors
|
|
362
|
+
- **Dev experience** — better test runners, lint output, error formatting
|
|
363
|
+
- **Interactive prompts** — menus, confirmations, multi-select wizards
|
|
364
|
+
- **Data exploration** — tables, trees, charts for terminal-first workflows
|
|
365
|
+
- **Status reporters** — real-time progress, multi-task orchestration
|
|
366
|
+
- **ASCII intros** — game launchers, demo splash screens, login banners
|
|
405
367
|
|
|
406
368
|
---
|
|
407
369
|
|
|
408
370
|
## ⚙️ Configuration
|
|
409
371
|
|
|
372
|
+
Global config affects every module that respects it (colors, themes, animation speed, etc.):
|
|
373
|
+
|
|
410
374
|
```ts
|
|
411
|
-
import { configure } from 'ansimax';
|
|
375
|
+
import { configure, getConfig, withConfig, onConfigKeyChange } from 'ansimax';
|
|
412
376
|
|
|
413
377
|
configure({
|
|
414
|
-
colorMode:
|
|
415
|
-
animationSpeed: 'normal',
|
|
378
|
+
colorMode: 'auto', // 'none' | 'basic' | '256' | 'truecolor' | 'auto'
|
|
379
|
+
animationSpeed: 'normal', // 'slow' | 'normal' | 'fast' | 'instant'
|
|
380
|
+
theme: 'dracula', // any registered theme
|
|
381
|
+
reducedMotion: false,
|
|
416
382
|
});
|
|
417
383
|
|
|
418
|
-
//
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
384
|
+
// Listen for changes (per-key — avoids over-firing)
|
|
385
|
+
const off = onConfigKeyChange('theme', (newTheme, oldTheme) => {
|
|
386
|
+
console.log(`Theme: ${oldTheme} → ${newTheme}`);
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
// Temporary override + auto-restore on completion or throw
|
|
390
|
+
await withConfig({ animationSpeed: 'fast' }, async () => {
|
|
391
|
+
await runDemo();
|
|
392
|
+
});
|
|
422
393
|
|
|
423
|
-
|
|
394
|
+
// Strict mode catches config typos
|
|
395
|
+
configure({ unknwnKey: 'x' }, { strict: true }); // throws RangeError
|
|
396
|
+
```
|
|
424
397
|
|
|
425
398
|
---
|
|
426
399
|
|
|
427
400
|
## 🛣️ Roadmap
|
|
428
401
|
|
|
429
|
-
Ansimax is being built toward a full
|
|
402
|
+
Ansimax is being built toward a **full terminal rendering platform** — a Node-native answer to what Python developers get from `rich` + `textual` combined, with Node-specific improvements where it matters.
|
|
430
403
|
|
|
431
|
-
|
|
404
|
+
The roadmap intentionally targets — and aims to surpass — gaps that even mature Python TUI libraries haven't fully solved: live-diff renderers, animated gradients, terminal image protocols, and a true reactive layer.
|
|
432
405
|
|
|
433
|
-
|
|
434
|
-
- [x]
|
|
435
|
-
- [x]
|
|
436
|
-
- [x]
|
|
437
|
-
- [x]
|
|
406
|
+
### ✅ Phase 1 — Core foundation
|
|
407
|
+
- [x] Styling engine — ANSI 16 / 256 / truecolor with adaptive fallback
|
|
408
|
+
- [x] Hex + RGB helpers with clamping and validation
|
|
409
|
+
- [x] `NO_COLOR` / `FORCE_COLOR` env support + non-TTY auto-detection
|
|
410
|
+
- [x] `AbortSignal` integration across animations and loaders
|
|
411
|
+
- [x] `compose()` style stacking with single-reset emission
|
|
412
|
+
- [x] Bounded LRU escape cache (512 entries, packed-RGB keyed)
|
|
413
|
+
- [x] Custom preset registry (`registerPreset`, `listPresets`)
|
|
438
414
|
|
|
439
415
|
### ✅ Phase 2 — Gradient engine
|
|
440
|
-
|
|
441
416
|
- [x] Linear gradients (multi-stop)
|
|
442
|
-
- [x] Rainbow presets
|
|
417
|
+
- [x] Rainbow + 6 built-in presets
|
|
443
418
|
- [x] Radial gradients (in `gradientRect`)
|
|
444
419
|
- [x] Diagonal gradients
|
|
445
|
-
- [
|
|
420
|
+
- [x] Arbitrary-angle gradients
|
|
421
|
+
- [x] Bayer 4×4 dithering for smooth tonal transitions
|
|
422
|
+
- [x] Single-stop UX (CSS-style behavior)
|
|
423
|
+
- [ ] **Animated gradients** (color flow over time, infinite loops)
|
|
424
|
+
- [ ] **Gradient interpolation curves** (linear / ease-in / ease-out / cubic-bezier)
|
|
425
|
+
- [ ] **Conic gradients** (radial sweep)
|
|
446
426
|
|
|
447
427
|
### 🟡 Phase 3 — ASCII engine
|
|
448
|
-
|
|
449
428
|
- [x] Block fonts (`big`, `small`)
|
|
450
|
-
- [x] Banner with gradient + alignment
|
|
429
|
+
- [x] Banner with gradient + alignment + per-char coloring
|
|
451
430
|
- [x] Box drawing (6 border styles)
|
|
452
|
-
- [
|
|
431
|
+
- [x] Divider with style variants
|
|
432
|
+
- [x] Logo composer (gradient + box wrapping)
|
|
433
|
+
- [x] Custom font registry (`registerFont`, `hasFont`, `listFonts`)
|
|
434
|
+
- [x] Stream API (`ascii.stream()` with AbortSignal)
|
|
435
|
+
- [ ] **Image → ASCII** converter (with edge detection, Sobel/Canny)
|
|
453
436
|
- [ ] **Color ASCII** rendering (preserve image colors)
|
|
454
|
-
- [ ] **Image dithering** for better tonal range
|
|
437
|
+
- [ ] **Image dithering** for better tonal range (Floyd-Steinberg)
|
|
455
438
|
- [ ] **Face-optimized ASCII** (high-detail mode for portraits)
|
|
439
|
+
- [ ] **Figlet font support** (.flf file loader — 250+ community fonts)
|
|
456
440
|
|
|
457
441
|
### ✅ Phase 4 — Terminal UI primitives
|
|
458
|
-
|
|
459
|
-
- [x] Tables (irregular rows, jagged data)
|
|
442
|
+
- [x] Tables (irregular rows, multi-line cells, ANSI-aware)
|
|
460
443
|
- [x] Boxes with multiple styles
|
|
461
|
-
- [x] Status messages + badges
|
|
444
|
+
- [x] Status messages + badges (with border option)
|
|
462
445
|
- [x] Timelines with done/pending states
|
|
463
446
|
- [x] Interactive menus (single + multi-select)
|
|
464
|
-
- [
|
|
465
|
-
- [
|
|
447
|
+
- [x] Columns layout (truncate/wrap overflow)
|
|
448
|
+
- [x] Sections (gradient headers with auto-width)
|
|
449
|
+
- [x] Trees (collapsible, max-depth, cycle-safe)
|
|
450
|
+
- [ ] **Panels** (split layouts: hsplit, vsplit)
|
|
466
451
|
- [ ] **Layouts** (flexbox-style positioning)
|
|
452
|
+
- [ ] **Grid system** (CSS Grid-inspired column/row spans)
|
|
453
|
+
- [ ] **Markdown rendering** (headings, lists, code blocks, tables)
|
|
454
|
+
- [ ] **Syntax highlighting** (built-in language grammars)
|
|
455
|
+
- [ ] **JSON/YAML pretty-printing** (with depth limit + collapse)
|
|
456
|
+
- [ ] **Logging integration** (drop-in replacement for `console`/`pino`/`winston` transports)
|
|
467
457
|
|
|
468
458
|
### ✅ Phase 5 — Cursor & screen control
|
|
469
|
-
|
|
470
|
-
- [x] Cursor visibility, save/restore, positioning
|
|
459
|
+
- [x] Cursor visibility, save/restore, positioning, line navigation
|
|
471
460
|
- [x] Screen clearing (line, area, full)
|
|
472
|
-
- [x]
|
|
461
|
+
- [x] Reference-counted cursor (overlapping calls safe)
|
|
462
|
+
- [x] Crash-safe restore (exit/SIGINT/SIGTERM handlers)
|
|
463
|
+
- [x] Terminal hyperlinks (OSC 8)
|
|
464
|
+
- [x] Window title (OSC 2)
|
|
465
|
+
- [x] Bell (BEL)
|
|
473
466
|
|
|
474
467
|
### ✅ Phase 6 — Animation engine
|
|
475
|
-
|
|
476
468
|
- [x] Typewriter, fadeIn, fadeOut, slide, pulse, wave, glitch, reveal
|
|
477
469
|
- [x] All `AbortSignal`-aware
|
|
478
470
|
- [x] `reducedMotion` mode for accessibility
|
|
479
|
-
- [x]
|
|
471
|
+
- [x] Frame morph (text → text interpolation, cinematic decryption)
|
|
472
|
+
- [x] `parallel()` with timeout
|
|
473
|
+
- [x] Signal propagation to nested animations
|
|
474
|
+
- [ ] **Easing functions library** (24 standard easings: cubic, elastic, bounce, back)
|
|
475
|
+
- [ ] **Animation composition** (`parallel + sequence + delay` DSL)
|
|
476
|
+
- [ ] **Spring physics** animations (`react-spring` style)
|
|
477
|
+
- [ ] **Tween engine** (interpolate any value type)
|
|
480
478
|
|
|
481
479
|
### 🟡 Phase 7 — Progress ecosystem
|
|
482
|
-
|
|
483
480
|
- [x] Spinners (11 styles) with color + AbortSignal
|
|
484
481
|
- [x] Animated progress bars
|
|
485
482
|
- [x] Multi-task runners (sequential + parallel)
|
|
486
483
|
- [x] Countdown timers
|
|
487
|
-
- [
|
|
488
|
-
- [
|
|
489
|
-
- [ ] **Live
|
|
484
|
+
- [x] Multi-spinner manager (stacked concurrent spinners)
|
|
485
|
+
- [x] Hierarchical tasks (parent + subtasks rollup)
|
|
486
|
+
- [ ] **Live ETA estimation** (rolling average + Kalman filter projection)
|
|
487
|
+
- [ ] **Live refresh diff renderer** (no flicker, only redraw changed lines)
|
|
488
|
+
- [ ] **Progress groups** (named groups with shared theme)
|
|
489
|
+
- [ ] **Throughput meters** (bytes/sec, ops/sec with auto-scaling units)
|
|
490
490
|
|
|
491
491
|
### 🟡 Phase 8 — Capability detection
|
|
492
|
-
|
|
493
492
|
- [x] TTY detection (auto-disable in pipes/CI)
|
|
494
|
-
- [x] `NO_COLOR` env support
|
|
495
|
-
- [
|
|
496
|
-
- [
|
|
497
|
-
- [
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
- [ ] **
|
|
493
|
+
- [x] `NO_COLOR` / `FORCE_COLOR` env support
|
|
494
|
+
- [x] Color depth detection (16 / 256 / truecolor)
|
|
495
|
+
- [x] CI provider detection (GitHub Actions, CircleCI, GitLab, Buildkite, Drone, Travis)
|
|
496
|
+
- [x] Terminal program detection (iTerm, vscode, WezTerm, Hyper, Apple_Terminal)
|
|
497
|
+
- [x] Windows Terminal detection (`WT_SESSION`)
|
|
498
|
+
- [ ] **Unicode width detection** (CJK halfwidth/fullwidth, emoji clusters, ZWJ sequences)
|
|
499
|
+
- [ ] **Image protocol detection** (Sixel, iTerm inline images, Kitty graphics protocol)
|
|
500
|
+
- [ ] **Terminal capability database** (full xterm capability flags + version probes)
|
|
501
|
+
- [ ] **Font metrics detection** (cell width/height for pixel-accurate layouts)
|
|
502
|
+
|
|
503
|
+
### 🟡 Phase 9 — Advanced rendering
|
|
504
|
+
- [x] Dirty-rectangle canvas (only redraw changed pixels)
|
|
505
|
+
- [x] Bounded LRU caches (escape sequences, render cache, ANSI cache)
|
|
506
|
+
- [x] Drift-corrected timing (animations stay locked to wall-clock)
|
|
507
|
+
- [ ] **Diff renderer** (line-level damage tracking for full UIs)
|
|
502
508
|
- [ ] **Virtual buffer** (compose UI without writing to stdout)
|
|
503
|
-
- [ ] **Z-index / layering**
|
|
504
|
-
- [ ] **Mouse event support**
|
|
509
|
+
- [ ] **Z-index / layering** (overlap panels with priority)
|
|
510
|
+
- [ ] **Mouse event support** (click, hover, drag, scroll wheel)
|
|
511
|
+
- [ ] **Keyboard event abstraction** (arrow keys, modifiers, key sequences, dead keys)
|
|
512
|
+
- [ ] **Full TUI framework** (reactive components — Textual-equivalent for Node)
|
|
505
513
|
|
|
506
514
|
### 🔴 Phase 10 — Terminal charts
|
|
507
|
-
|
|
508
|
-
- [ ] Bar charts (horizontal + vertical)
|
|
515
|
+
- [ ] Bar charts (horizontal + vertical, grouped, stacked)
|
|
509
516
|
- [ ] Line charts (with braille for sub-character resolution)
|
|
510
|
-
- [ ] Sparklines
|
|
511
|
-
- [ ]
|
|
512
|
-
- [ ]
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
517
|
+
- [ ] Sparklines (inline mini-charts for status bars)
|
|
518
|
+
- [ ] Area charts (filled with gradients)
|
|
519
|
+
- [ ] Heatmaps (color-mapped 2D grids)
|
|
520
|
+
- [ ] Pie / donut charts (with percentage labels)
|
|
521
|
+
- [ ] Scatter plots
|
|
522
|
+
- [ ] Box plots / candlestick charts
|
|
523
|
+
- [ ] Real-time streaming charts (live data feed with rolling window)
|
|
524
|
+
- [ ] **Plot composer** (multi-chart dashboards with shared axes)
|
|
525
|
+
|
|
526
|
+
### 🔴 Phase 11 — Forms & Input
|
|
527
|
+
- [ ] Text input prompts (with autocomplete + history)
|
|
528
|
+
- [ ] Password prompts (masked, strength meter)
|
|
529
|
+
- [ ] Confirm dialogs (yes/no with default highlight)
|
|
530
|
+
- [ ] Numeric input (with min/max validation)
|
|
531
|
+
- [ ] Date/time pickers (calendar widget)
|
|
532
|
+
- [ ] File picker (filesystem navigator)
|
|
533
|
+
- [ ] Form composer (multi-field with validation + error display)
|
|
534
|
+
- [ ] **Wizard flows** (multi-step forms with back/forward, progress indicator)
|
|
535
|
+
|
|
536
|
+
### 🔴 Phase 12 — Image & media
|
|
537
|
+
- [ ] Sixel image rendering (xterm, mlterm, WezTerm)
|
|
538
|
+
- [ ] iTerm2 inline images (base64 protocol)
|
|
539
|
+
- [ ] Kitty graphics protocol
|
|
540
|
+
- [ ] PNG/JPEG → terminal image (auto-detect best protocol)
|
|
541
|
+
- [ ] Video preview (frame-by-frame at low FPS)
|
|
542
|
+
- [ ] QR code generation (with size + ECC level options)
|
|
543
|
+
- [ ] Bar code generation (Code 128, EAN-13)
|
|
544
|
+
|
|
545
|
+
### 🔴 Phase 13 — Plugin system
|
|
516
546
|
- [ ] Plugin API for custom components
|
|
517
547
|
- [ ] Theme marketplace
|
|
518
|
-
- [ ] Custom font registration
|
|
548
|
+
- [ ] Custom font registration via npm packages
|
|
519
549
|
- [ ] Community animations registry
|
|
550
|
+
- [ ] Capability provider interface (plug in custom detectors)
|
|
551
|
+
- [ ] Renderer plugins (swap stdout for any writable stream)
|
|
552
|
+
|
|
553
|
+
### 🔴 Phase 14 — Reactivity layer (TUI framework)
|
|
554
|
+
- [ ] **Component lifecycle** (mount/unmount/update hooks)
|
|
555
|
+
- [ ] **Reactive state** (auto re-render on data change, signals or hooks)
|
|
556
|
+
- [ ] **Virtual DOM diffing** (line-level updates)
|
|
557
|
+
- [ ] **Event bus** (component communication)
|
|
558
|
+
- [ ] **Application loop** (single render tree with full lifecycle)
|
|
559
|
+
- [ ] **Routing** (multi-screen apps with history)
|
|
560
|
+
- [ ] **DevTools integration** (inspect component tree, mark changed nodes)
|
|
561
|
+
- [ ] **CSS-in-TS styling** (scoped styles per component)
|
|
520
562
|
|
|
521
563
|
**Legend:** ✅ Complete · 🟡 Partial · 🔴 Planned
|
|
522
564
|
|
|
@@ -524,20 +566,25 @@ Ansimax is being built toward a full **terminal rendering platform**. Here's wha
|
|
|
524
566
|
|
|
525
567
|
## 🧪 Testing
|
|
526
568
|
|
|
527
|
-
Ansimax ships with **750+ tests** and **100% line coverage**:
|
|
528
|
-
|
|
529
569
|
```bash
|
|
530
|
-
npm test
|
|
531
|
-
npm run test:
|
|
532
|
-
npm run
|
|
570
|
+
npm test # Run all 1700+ tests
|
|
571
|
+
npm run test:watch # Watch mode
|
|
572
|
+
npm run test:coverage # Coverage report
|
|
533
573
|
```
|
|
534
574
|
|
|
575
|
+
Coverage targets:
|
|
576
|
+
- Statements: **98%**
|
|
577
|
+
- Branches: **95%**
|
|
578
|
+
- Functions: **99%**
|
|
579
|
+
- Lines: **99%**
|
|
580
|
+
|
|
535
581
|
---
|
|
536
582
|
|
|
537
583
|
## 🛠️ Requirements
|
|
538
584
|
|
|
539
|
-
- Node.js
|
|
540
|
-
-
|
|
585
|
+
- **Node.js** ≥ 18
|
|
586
|
+
- **TypeScript** ≥ 5.0 (for typed consumption — optional)
|
|
587
|
+
- **Terminal** with truecolor support recommended (Windows Terminal, iTerm2, WezTerm, Kitty, modern xterm). Gracefully degrades to 256 / 16 / no-color.
|
|
541
588
|
|
|
542
589
|
---
|
|
543
590
|
|
|
@@ -546,64 +593,80 @@ npm run typecheck # Strict TypeScript check
|
|
|
546
593
|
```
|
|
547
594
|
ansimax/
|
|
548
595
|
├── src/
|
|
549
|
-
│ ├── colors/
|
|
550
|
-
│ ├──
|
|
551
|
-
│ ├── ascii/
|
|
552
|
-
│ ├──
|
|
553
|
-
│ ├── loaders/
|
|
554
|
-
│ ├── frames/
|
|
555
|
-
│ ├──
|
|
556
|
-
│ ├──
|
|
557
|
-
│ ├──
|
|
558
|
-
│
|
|
559
|
-
|
|
560
|
-
├──
|
|
561
|
-
└──
|
|
596
|
+
│ ├── colors/ Color rendering + gradient engine
|
|
597
|
+
│ ├── themes/ Theme system + 8 built-ins
|
|
598
|
+
│ ├── ascii/ Banners, boxes, fonts
|
|
599
|
+
│ ├── animations/ Typewriter, fade, slide, pulse, wave, glitch, reveal
|
|
600
|
+
│ ├── loaders/ Spinners, progress, tasks, multi-loader
|
|
601
|
+
│ ├── frames/ Sequenced playback + live renderer + morph
|
|
602
|
+
│ ├── components/ Tables, badges, status, timelines, menus
|
|
603
|
+
│ ├── images/ Sprites, canvas, dithered gradients
|
|
604
|
+
│ ├── trees/ Tree builder + algorithms
|
|
605
|
+
│ ├── utils/ ANSI primitives + helpers
|
|
606
|
+
│ └── configure.ts Global config + subscribers
|
|
607
|
+
├── examples/ 7 production-grade examples
|
|
608
|
+
└── __tests__/ 16 test suites, 1700+ tests
|
|
562
609
|
```
|
|
563
610
|
|
|
564
611
|
---
|
|
565
612
|
|
|
566
|
-
##
|
|
613
|
+
## 📝 Changelog
|
|
567
614
|
|
|
568
|
-
|
|
615
|
+
### v1.1.0 — Comprehensive hardening + new features
|
|
569
616
|
|
|
570
|
-
|
|
571
|
-
2. Create a branch: `git checkout -b feature/amazing-thing`
|
|
572
|
-
3. Add tests for your changes (the bar is 100% coverage)
|
|
573
|
-
4. Commit: `git commit -m 'Add: amazing thing'`
|
|
574
|
-
5. Push: `git push origin feature/amazing-thing`
|
|
575
|
-
6. Open a Pull Request
|
|
617
|
+
A massive robustness pass across every module, plus a new `trees` module. **100% backward compatible** — every existing API works identically.
|
|
576
618
|
|
|
577
|
-
|
|
578
|
-
- All tests pass: `npm test`
|
|
579
|
-
- TypeScript is happy: `npm run typecheck`
|
|
580
|
-
- Code follows the existing style
|
|
619
|
+
**Highlights:**
|
|
581
620
|
|
|
582
|
-
|
|
621
|
+
- 🌳 **New `trees` module** — builder API + plain-data API, 4 styles, cycle detection, algorithms (`walk`, `find`, `count`, `map`, `filter`)
|
|
622
|
+
- ⚙️ **`configure.ts` upgrades** — `onConfigKeyChange`, `pauseListeners` / `resumeListeners`, `withConfig()`, strict mode
|
|
623
|
+
- 🎨 **Themes** — per-instance isolation (multi-tenant safe), `tryUse`, `onChange` listeners, `unregister`, `bg*` helpers, dynamic `style(name)` accessor
|
|
624
|
+
- 🌈 **Colors** — `registerPreset` / `listPresets`, bounded LRU escape cache, NaN/Infinity-safe RGB, single-stop gradient UX
|
|
625
|
+
- 🖼️ **Images** — `Pixel` / `PixelGrid` exported, deep-clone `canvas.pixels`, defensive coords, ANSI cache LRU bounded
|
|
626
|
+
- 🔠 **ASCII** — `hasFont`, `measure`, `stream` with AbortSignal, grapheme-aware
|
|
627
|
+
- 🎞️ **Frames** — ref-counted cursor, crash-safe restore, `repeat: 0` = infinite, fps cap at 60, drift correction
|
|
628
|
+
- 🧱 **Components** — `menu([])` returns `MENU_CANCELLED` (no throw), defensive numeric inputs everywhere
|
|
629
|
+
- 🛠️ **Utils** — `setTitle`, `link` (OSC 8 hyperlinks), `bell`, `safeJson` (BigInt + circular), `once`, `escapeRegex`, `padBoth`, `nextTick`, `memoize` with custom keyFn, `debounce` with `maxWait`, throttled `onResize`
|
|
630
|
+
- 🧪 **Tests** — ~1700+ tests across 16 suites, all green, ~98% coverage
|
|
583
631
|
|
|
584
|
-
|
|
632
|
+
See [CHANGELOG.md](CHANGELOG.md) for the complete version history with per-module breakdowns.
|
|
585
633
|
|
|
586
|
-
|
|
634
|
+
### v1.0.0 — Initial release
|
|
635
|
+
|
|
636
|
+
- Core modules: `color`, `animate`, `ascii`, `loader`, `frames`, `components`, `themes`, `images`, `configure`
|
|
637
|
+
- TypeScript types exported, ESM + CJS dual build
|
|
638
|
+
- Adaptive color rendering (NO_COLOR / FORCE_COLOR / TTY detection)
|
|
639
|
+
- `AbortSignal` support across all blocking APIs
|
|
640
|
+
- 750+ tests, 85%+ coverage
|
|
587
641
|
|
|
588
642
|
---
|
|
589
643
|
|
|
590
|
-
##
|
|
644
|
+
## 🤝 Contributing
|
|
591
645
|
|
|
592
|
-
|
|
646
|
+
Contributions welcome! Areas where help is especially appreciated:
|
|
593
647
|
|
|
594
|
-
-
|
|
595
|
-
-
|
|
596
|
-
-
|
|
597
|
-
-
|
|
598
|
-
-
|
|
648
|
+
- New animation presets (easing, spring physics)
|
|
649
|
+
- Additional ASCII fonts (figlet `.flf` parser)
|
|
650
|
+
- Terminal capability database entries
|
|
651
|
+
- Translations (es, fr, de, ja, ...)
|
|
652
|
+
- Real-world example apps
|
|
653
|
+
- Chart implementations (Phase 10)
|
|
599
654
|
|
|
600
|
-
|
|
655
|
+
Please read [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
|
|
601
656
|
|
|
602
657
|
---
|
|
603
658
|
|
|
604
|
-
##
|
|
659
|
+
## 🐛 Reporting Issues
|
|
660
|
+
|
|
661
|
+
Found a bug? Have a feature request? [Open an issue](https://github.com/Brashkie/ansimax/issues/new).
|
|
605
662
|
|
|
606
|
-
|
|
663
|
+
For security disclosures, please email [security@brashkie.dev](mailto:security@brashkie.dev) instead of opening a public issue.
|
|
664
|
+
|
|
665
|
+
---
|
|
666
|
+
|
|
667
|
+
## ⭐ Support
|
|
668
|
+
|
|
669
|
+
If Ansimax saves you time, please star the repo on [GitHub](https://github.com/Brashkie/ansimax) — it helps the project grow and accelerates the roadmap.
|
|
607
670
|
|
|
608
671
|
---
|
|
609
672
|
|
|
@@ -615,15 +678,20 @@ See [CHANGELOG.md](CHANGELOG.md) for the version history.
|
|
|
615
678
|
|
|
616
679
|
## 📜 License
|
|
617
680
|
|
|
618
|
-
[
|
|
681
|
+
[Apache License 2.0](LICENSE) © 2026 Brashkie
|
|
682
|
+
|
|
683
|
+
Ansimax is licensed under the **Apache License, Version 2.0** — a permissive license that allows commercial use, modification, distribution, and includes an explicit patent grant. See the [LICENSE](LICENSE) file for the full text.
|
|
619
684
|
|
|
620
685
|
---
|
|
621
686
|
|
|
622
|
-
**Keywords:** cli, terminal, ansi, colors, gradients, animation, spinner, ascii, ascii-art, pixel-art, progress-bar, loader, components, table, banner, theme, typescript, nodejs, zero-dependencies
|
|
687
|
+
**Keywords:** cli, terminal, ansi, colors, gradients, animation, spinner, ascii, ascii-art, pixel-art, progress-bar, loader, components, table, banner, theme, tree, trees, tui, typescript, nodejs, zero-dependencies, chalk, ora, boxen, figlet, inquirer
|
|
623
688
|
|
|
624
689
|
---
|
|
625
690
|
|
|
626
691
|
<div align="center">
|
|
627
|
-
|
|
628
|
-
|
|
692
|
+
|
|
693
|
+
**Built with ❤️ and TypeScript**
|
|
694
|
+
|
|
695
|
+
If Ansimax helps you ship better CLIs, give it a ⭐ on [GitHub](https://github.com/Brashkie/ansimax)!
|
|
696
|
+
|
|
629
697
|
</div>
|