ansimax 1.3.1 ā 1.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/CHANGELOG.md +37 -0
- package/README.es.md +57 -2
- package/README.md +57 -2
- package/dist/index.d.mts +202 -0
- package/dist/index.d.ts +202 -0
- package/docs/README.md +110 -0
- package/docs/examples-cjs.md +706 -0
- package/docs/examples-mjs.md +676 -0
- package/docs/examples-ts.md +715 -0
- package/docs/showcase.md +398 -0
- package/examples/all-in-one.cjs +1 -1
- package/examples/all-in-one.mjs +1 -1
- package/package.json +2 -1
|
@@ -0,0 +1,706 @@
|
|
|
1
|
+
# š ansimax ā JavaScript CommonJS examples
|
|
2
|
+
|
|
3
|
+
All examples use **CommonJS** (`require()` / `module.exports`). Save any snippet as `.cjs` (or `.js` in a classic Node project) and run with:
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
node example.cjs
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
> ā ļø **About top-level `await`**: CommonJS doesn't support top-level `await`. Examples that need async are wrapped in an `async function main()` + `main().catch(console.error)`.
|
|
10
|
+
|
|
11
|
+
For TypeScript, see [`examples-ts.md`](./examples-ts.md). For ESM, see [`examples-mjs.md`](./examples-mjs.md).
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## šØ 1. `color` ā Terminal colors & styles
|
|
16
|
+
|
|
17
|
+
### 1.1 ā Basic colored output
|
|
18
|
+
|
|
19
|
+
```js
|
|
20
|
+
const { color } = require('ansimax');
|
|
21
|
+
|
|
22
|
+
console.log(color.green('ā Build successful'));
|
|
23
|
+
console.log(color.red('ā Build failed'));
|
|
24
|
+
console.log(color.yellow('ā 3 warnings'));
|
|
25
|
+
console.log(color.cyan('ā¹ Check the logs above'));
|
|
26
|
+
|
|
27
|
+
// Composable styles
|
|
28
|
+
console.log(color.bold(color.magenta('Application started')));
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### 1.2 ā Status report with mixed colors
|
|
32
|
+
|
|
33
|
+
```js
|
|
34
|
+
const { color } = require('ansimax');
|
|
35
|
+
|
|
36
|
+
const services = [
|
|
37
|
+
{ name: 'api', status: 'up', latency: 45 },
|
|
38
|
+
{ name: 'database', status: 'up', latency: 12 },
|
|
39
|
+
{ name: 'cache', status: 'degraded', latency: 240 },
|
|
40
|
+
{ name: 'auth', status: 'down', latency: 0 },
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
console.log(color.bold('Service Health Report\n'));
|
|
44
|
+
|
|
45
|
+
for (const svc of services) {
|
|
46
|
+
const icon = svc.status === 'up' ? color.green('ā')
|
|
47
|
+
: svc.status === 'degraded' ? color.yellow('ā')
|
|
48
|
+
: color.red('ā');
|
|
49
|
+
const lat = svc.latency > 100 ? color.red(`${svc.latency}ms`)
|
|
50
|
+
: svc.latency > 50 ? color.yellow(`${svc.latency}ms`)
|
|
51
|
+
: color.green(`${svc.latency}ms`);
|
|
52
|
+
|
|
53
|
+
console.log(`${icon} ${svc.name.padEnd(10)} ${lat}`);
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### 1.3 ā Truecolor & hex colors
|
|
58
|
+
|
|
59
|
+
```js
|
|
60
|
+
const { color } = require('ansimax');
|
|
61
|
+
|
|
62
|
+
console.log(color.bgHex('#bd93f9')(' Dracula purple '));
|
|
63
|
+
console.log(color.bgHex('#ff79c6')(' Pink '));
|
|
64
|
+
console.log(color.bgHex('#50fa7b')(' Green '));
|
|
65
|
+
|
|
66
|
+
console.log(color.hex('#ff6b6b')('Bright red text'));
|
|
67
|
+
console.log(color.hex('#4ecdc4')('Turquoise text'));
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## š 2. `gradient` ā Multi-stop gradients
|
|
73
|
+
|
|
74
|
+
### 2.1 ā Simple two-color gradient
|
|
75
|
+
|
|
76
|
+
```js
|
|
77
|
+
const { gradient } = require('ansimax');
|
|
78
|
+
|
|
79
|
+
console.log(gradient('Hello, gradients!', ['#ff79c6', '#bd93f9']));
|
|
80
|
+
console.log(gradient('Pink to purple', ['#ff79c6', '#bd93f9']));
|
|
81
|
+
console.log(gradient('Sunset', ['#ff5e62', '#ff9966', '#ffd86f']));
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### 2.2 ā Reusable gradient with easing
|
|
85
|
+
|
|
86
|
+
```js
|
|
87
|
+
const { createGradient } = require('ansimax');
|
|
88
|
+
|
|
89
|
+
const easings = ['linear', 'ease-in', 'ease-out', 'ease-in-out'];
|
|
90
|
+
|
|
91
|
+
for (const ease of easings) {
|
|
92
|
+
const grad = createGradient(['#8be9fd', '#bd93f9', '#ff79c6'], { easing: ease });
|
|
93
|
+
console.log(`${ease.padEnd(15)} ${grad('āāāāāāāāāāāāāāāāāāāāāāāāāāāā')}`);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const cubic = createGradient(['#ff0000', '#0000ff'], {
|
|
97
|
+
easing: (t) => t * t * t,
|
|
98
|
+
});
|
|
99
|
+
console.log(cubic('Custom cubic easing across this whole line'));
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### 2.3 ā Animated gradient
|
|
103
|
+
|
|
104
|
+
```js
|
|
105
|
+
const { animateGradient } = require('ansimax');
|
|
106
|
+
|
|
107
|
+
async function main() {
|
|
108
|
+
const ctrl = animateGradient(
|
|
109
|
+
'āāāā Loading data... āāāā',
|
|
110
|
+
['#ff79c6', '#bd93f9', '#8be9fd', '#50fa7b'],
|
|
111
|
+
{
|
|
112
|
+
interval: 80,
|
|
113
|
+
cycles: 3,
|
|
114
|
+
duration: 800,
|
|
115
|
+
infinite: false,
|
|
116
|
+
},
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
await ctrl.promise;
|
|
120
|
+
console.log('\nā Done');
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
main().catch(console.error);
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## š¤ 3. `ascii` ā Boxes, banners, image-to-ASCII
|
|
129
|
+
|
|
130
|
+
### 3.1 ā Boxes with multiple styles
|
|
131
|
+
|
|
132
|
+
```js
|
|
133
|
+
const { ascii, gradient } = require('ansimax');
|
|
134
|
+
|
|
135
|
+
console.log(ascii.box('Hello world!', { borderStyle: 'rounded' }));
|
|
136
|
+
console.log(ascii.box('Important!', { borderStyle: 'double', padding: 2 }));
|
|
137
|
+
|
|
138
|
+
const colored = gradient('Rainbow inside', ['#ff79c6', '#bd93f9', '#8be9fd']);
|
|
139
|
+
console.log(ascii.box(colored, { borderStyle: 'heavy', padding: 1 }));
|
|
140
|
+
|
|
141
|
+
const multi = 'Line 1\nLine 2\nLine 3 longer\n\nWith blank line';
|
|
142
|
+
console.log(ascii.box(multi, { borderStyle: 'rounded', padding: 1 }));
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### 3.2 ā Banner with figlet font
|
|
146
|
+
|
|
147
|
+
```js
|
|
148
|
+
const { ascii, gradient } = require('ansimax');
|
|
149
|
+
|
|
150
|
+
const banner = ascii.figletText('ANSIMAX', { font: 'standard' });
|
|
151
|
+
console.log(gradient(banner, ['#ff79c6', '#bd93f9', '#8be9fd']));
|
|
152
|
+
|
|
153
|
+
const compact = ascii.figletText('v1.3.2', { font: 'small' });
|
|
154
|
+
console.log(ascii.box(compact, { borderStyle: 'rounded' }));
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### 3.3 ā Image-to-ASCII from a PixelGrid
|
|
158
|
+
|
|
159
|
+
```js
|
|
160
|
+
const { ascii } = require('ansimax');
|
|
161
|
+
|
|
162
|
+
const N = null;
|
|
163
|
+
const Y = { r: 255, g: 220, b: 0 };
|
|
164
|
+
const K = { r: 0, g: 0, b: 0 };
|
|
165
|
+
|
|
166
|
+
const smiley = [
|
|
167
|
+
[N, N, Y, Y, Y, Y, N, N],
|
|
168
|
+
[N, Y, Y, Y, Y, Y, Y, N],
|
|
169
|
+
[Y, Y, K, Y, Y, K, Y, Y],
|
|
170
|
+
[Y, Y, Y, Y, Y, Y, Y, Y],
|
|
171
|
+
[Y, K, Y, Y, Y, Y, K, Y],
|
|
172
|
+
[Y, Y, K, K, K, K, Y, Y],
|
|
173
|
+
[N, Y, Y, Y, Y, Y, Y, N],
|
|
174
|
+
[N, N, Y, Y, Y, Y, N, N],
|
|
175
|
+
];
|
|
176
|
+
|
|
177
|
+
console.log(ascii.fromImage(smiley, { width: 30, ramp: 'block' }));
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## ⨠4. `animations` ā Typewriter, fadeIn, fadeOut
|
|
183
|
+
|
|
184
|
+
### 4.1 ā Typewriter effect
|
|
185
|
+
|
|
186
|
+
```js
|
|
187
|
+
const { animate } = require('ansimax');
|
|
188
|
+
|
|
189
|
+
async function main() {
|
|
190
|
+
await animate.typewriter('Loading project configuration...', { speed: 40 });
|
|
191
|
+
console.log();
|
|
192
|
+
|
|
193
|
+
const ctrl = new AbortController();
|
|
194
|
+
setTimeout(() => ctrl.abort(), 500);
|
|
195
|
+
|
|
196
|
+
try {
|
|
197
|
+
await animate.typewriter(
|
|
198
|
+
'This is a very long sentence that will get cut off mid-print.',
|
|
199
|
+
{ speed: 30, signal: ctrl.signal },
|
|
200
|
+
);
|
|
201
|
+
} catch {
|
|
202
|
+
console.log('\n(aborted)');
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
main().catch(console.error);
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### 4.2 ā Fade in with custom color
|
|
210
|
+
|
|
211
|
+
```js
|
|
212
|
+
const { animate } = require('ansimax');
|
|
213
|
+
|
|
214
|
+
async function main() {
|
|
215
|
+
await animate.fadeIn('ā
Welcome to the demo ā
', {
|
|
216
|
+
duration: 1200,
|
|
217
|
+
color: '#bd93f9',
|
|
218
|
+
steps: 25,
|
|
219
|
+
});
|
|
220
|
+
console.log();
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
main().catch(console.error);
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### 4.3 ā Sequenced reveals for a fake intro
|
|
227
|
+
|
|
228
|
+
```js
|
|
229
|
+
const { animate, color } = require('ansimax');
|
|
230
|
+
|
|
231
|
+
async function main() {
|
|
232
|
+
const lines = [
|
|
233
|
+
'> Initializing system...',
|
|
234
|
+
'> Loading modules: 12/12 ā',
|
|
235
|
+
'> Connecting to mainframe...',
|
|
236
|
+
'> Access granted',
|
|
237
|
+
'> Welcome, operator.',
|
|
238
|
+
];
|
|
239
|
+
|
|
240
|
+
for (const line of lines) {
|
|
241
|
+
await animate.typewriter(color.green(line), { speed: 25 });
|
|
242
|
+
console.log();
|
|
243
|
+
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
main().catch(console.error);
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
252
|
+
## ā³ 5. `loaders` ā Spinners, tasks, progress
|
|
253
|
+
|
|
254
|
+
### 5.1 ā Spinner with success/error states
|
|
255
|
+
|
|
256
|
+
```js
|
|
257
|
+
const { loader } = require('ansimax');
|
|
258
|
+
|
|
259
|
+
async function main() {
|
|
260
|
+
const stop = loader.spin('Fetching data from API...', {
|
|
261
|
+
type: 'dots',
|
|
262
|
+
color: '#bd93f9',
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
try {
|
|
266
|
+
await new Promise((resolve) => setTimeout(resolve, 1500));
|
|
267
|
+
stop('Data loaded successfully!', true);
|
|
268
|
+
} catch {
|
|
269
|
+
stop('Request failed', false);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
main().catch(console.error);
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
### 5.2 ā Hierarchical task runner
|
|
277
|
+
|
|
278
|
+
```js
|
|
279
|
+
const { loader } = require('ansimax');
|
|
280
|
+
|
|
281
|
+
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
282
|
+
|
|
283
|
+
async function main() {
|
|
284
|
+
await loader.tasks([
|
|
285
|
+
{
|
|
286
|
+
text: 'Build pipeline',
|
|
287
|
+
fn: async () => sleep(200),
|
|
288
|
+
subtasks: [
|
|
289
|
+
{ text: 'Compile TypeScript', fn: async () => sleep(400) },
|
|
290
|
+
{ text: 'Bundle for production', fn: async () => sleep(300) },
|
|
291
|
+
{ text: 'Generate type defs', fn: async () => sleep(200) },
|
|
292
|
+
],
|
|
293
|
+
},
|
|
294
|
+
{
|
|
295
|
+
text: 'Quality checks',
|
|
296
|
+
fn: async () => sleep(150),
|
|
297
|
+
subtasks: [
|
|
298
|
+
{ text: 'Lint', fn: async () => sleep(250) },
|
|
299
|
+
{ text: 'Test', fn: async () => sleep(500) },
|
|
300
|
+
],
|
|
301
|
+
},
|
|
302
|
+
{ text: 'Publish to npm', fn: async () => sleep(300) },
|
|
303
|
+
]);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
main().catch(console.error);
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### 5.3 ā Parallel task execution
|
|
310
|
+
|
|
311
|
+
```js
|
|
312
|
+
const { loader } = require('ansimax');
|
|
313
|
+
|
|
314
|
+
async function main() {
|
|
315
|
+
const ping = async () => {
|
|
316
|
+
await new Promise((r) => setTimeout(r, 200 + Math.random() * 600));
|
|
317
|
+
return Math.random() > 0.2;
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
const results = await loader.tasks([
|
|
321
|
+
{ text: 'Check api.example.com', fn: ping },
|
|
322
|
+
{ text: 'Check db.example.com', fn: ping },
|
|
323
|
+
{ text: 'Check auth.example.com', fn: ping },
|
|
324
|
+
{ text: 'Check cdn.example.com', fn: ping },
|
|
325
|
+
], { parallel: true });
|
|
326
|
+
|
|
327
|
+
const failed = results.filter((r) => !r.success);
|
|
328
|
+
console.log(`\n${results.length - failed.length}/${results.length} services healthy`);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
main().catch(console.error);
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
---
|
|
335
|
+
|
|
336
|
+
## š§± 6. `components` ā Table, badge, status, timeline
|
|
337
|
+
|
|
338
|
+
### 6.1 ā Status report with badges
|
|
339
|
+
|
|
340
|
+
```js
|
|
341
|
+
const { components } = require('ansimax');
|
|
342
|
+
|
|
343
|
+
console.log(
|
|
344
|
+
components.badge('VERSION', 'v1.3.2'),
|
|
345
|
+
components.badge('BUILD', 'passing'),
|
|
346
|
+
components.badge('TESTS', '2000+ passing'),
|
|
347
|
+
components.badge('LICENSE', 'Apache 2.0'),
|
|
348
|
+
);
|
|
349
|
+
|
|
350
|
+
console.log();
|
|
351
|
+
console.log(components.status('success', 'Build completed in 4.2s'));
|
|
352
|
+
console.log(components.status('warn', '3 deprecation warnings'));
|
|
353
|
+
console.log(components.status('error', 'Type error in src/main.js:42'));
|
|
354
|
+
console.log(components.status('info', 'Documentation generated at docs/'));
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
### 6.2 ā Table with ANSI-aware cells
|
|
358
|
+
|
|
359
|
+
```js
|
|
360
|
+
const { components, color } = require('ansimax');
|
|
361
|
+
|
|
362
|
+
const rows = [
|
|
363
|
+
['Service', 'Status', 'Latency', 'Uptime'],
|
|
364
|
+
['api', color.green('ā healthy'), '45ms', '99.99%'],
|
|
365
|
+
['db', color.green('ā healthy'), '12ms', '99.95%'],
|
|
366
|
+
['cache', color.yellow('ā degraded'), '240ms', '98.20%'],
|
|
367
|
+
['auth', color.red('ā down'), 'ā', '95.10%'],
|
|
368
|
+
];
|
|
369
|
+
|
|
370
|
+
console.log(components.table(rows, {
|
|
371
|
+
borderStyle: 'rounded',
|
|
372
|
+
padding: 1,
|
|
373
|
+
}));
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
### 6.3 ā Project timeline with done/pending
|
|
377
|
+
|
|
378
|
+
```js
|
|
379
|
+
const { components } = require('ansimax');
|
|
380
|
+
|
|
381
|
+
const events = [
|
|
382
|
+
{ label: 'Project initialized', time: 'Mon', done: true },
|
|
383
|
+
{ label: 'Dependencies set up', time: 'Tue', done: true },
|
|
384
|
+
{ label: 'Core modules done', time: 'Wed', done: true },
|
|
385
|
+
{ label: 'Tests passing', time: 'Thu', done: true },
|
|
386
|
+
{ label: 'Documentation', time: 'Fri', done: false },
|
|
387
|
+
{ label: 'Publish to npm', done: false },
|
|
388
|
+
];
|
|
389
|
+
|
|
390
|
+
console.log(components.timeline(events, { node: 'ā', connector: 'ā' }));
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
---
|
|
394
|
+
|
|
395
|
+
## šØ 7. `themes` ā Built-in and custom themes
|
|
396
|
+
|
|
397
|
+
### 7.1 ā Switching active theme
|
|
398
|
+
|
|
399
|
+
```js
|
|
400
|
+
const { themes } = require('ansimax');
|
|
401
|
+
|
|
402
|
+
themes.use('dracula');
|
|
403
|
+
const active = themes.current();
|
|
404
|
+
|
|
405
|
+
console.log(`Active theme: ${active.name}`);
|
|
406
|
+
console.log(`Primary color: ${active.primary}`);
|
|
407
|
+
console.log(`Available themes: ${themes.list().join(', ')}`);
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
### 7.2 ā Registering a custom theme
|
|
411
|
+
|
|
412
|
+
```js
|
|
413
|
+
const { themes } = require('ansimax');
|
|
414
|
+
|
|
415
|
+
themes.register('synthwave', {
|
|
416
|
+
name: 'synthwave',
|
|
417
|
+
primary: '#ff6ec7',
|
|
418
|
+
secondary: '#36d6e7',
|
|
419
|
+
accent: '#ffd93d',
|
|
420
|
+
success: '#06d6a0',
|
|
421
|
+
warning: '#ffd93d',
|
|
422
|
+
error: '#ff5e5b',
|
|
423
|
+
info: '#36d6e7',
|
|
424
|
+
muted: '#6c757d',
|
|
425
|
+
bg: '#241734',
|
|
426
|
+
surface: '#34174f',
|
|
427
|
+
text: '#ffffff',
|
|
428
|
+
gradient: ['#ff6ec7', '#36d6e7'],
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
themes.use('synthwave');
|
|
432
|
+
console.log(`Now using: ${themes.current().name}`);
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
### 7.3 ā Subscribing to theme changes
|
|
436
|
+
|
|
437
|
+
```js
|
|
438
|
+
const { themes } = require('ansimax');
|
|
439
|
+
|
|
440
|
+
const unsubscribe = themes.onChange((newT, oldT) => {
|
|
441
|
+
console.log(`Theme changed: ${oldT.name} ā ${newT.name}`);
|
|
442
|
+
});
|
|
443
|
+
|
|
444
|
+
themes.use('dracula');
|
|
445
|
+
themes.use('nord');
|
|
446
|
+
themes.use('monokai');
|
|
447
|
+
|
|
448
|
+
unsubscribe();
|
|
449
|
+
themes.use('dracula'); // no log this time
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
---
|
|
453
|
+
|
|
454
|
+
## š³ 8. `trees` ā Hierarchical rendering
|
|
455
|
+
|
|
456
|
+
### 8.1 ā Simple file tree
|
|
457
|
+
|
|
458
|
+
```js
|
|
459
|
+
const { trees } = require('ansimax');
|
|
460
|
+
|
|
461
|
+
const projectTree = {
|
|
462
|
+
label: 'my-app/',
|
|
463
|
+
children: [
|
|
464
|
+
{
|
|
465
|
+
label: 'src/',
|
|
466
|
+
children: [
|
|
467
|
+
{ label: 'index.js' },
|
|
468
|
+
{ label: 'utils.js' },
|
|
469
|
+
{ label: 'config.js' },
|
|
470
|
+
],
|
|
471
|
+
},
|
|
472
|
+
{
|
|
473
|
+
label: 'tests/',
|
|
474
|
+
children: [
|
|
475
|
+
{ label: 'unit/' },
|
|
476
|
+
{ label: 'e2e/' },
|
|
477
|
+
],
|
|
478
|
+
},
|
|
479
|
+
{ label: 'package.json' },
|
|
480
|
+
{ label: 'README.md' },
|
|
481
|
+
],
|
|
482
|
+
};
|
|
483
|
+
|
|
484
|
+
console.log(trees.tree(projectTree, { style: 'unicode' }));
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
### 8.2 ā Limit depth for large trees
|
|
488
|
+
|
|
489
|
+
```js
|
|
490
|
+
const { trees } = require('ansimax');
|
|
491
|
+
|
|
492
|
+
const deep = {
|
|
493
|
+
label: 'root',
|
|
494
|
+
children: [
|
|
495
|
+
{ label: 'level-1', children: [
|
|
496
|
+
{ label: 'level-2', children: [
|
|
497
|
+
{ label: 'level-3', children: [
|
|
498
|
+
{ label: 'level-4 (hidden)' },
|
|
499
|
+
]},
|
|
500
|
+
]},
|
|
501
|
+
]},
|
|
502
|
+
],
|
|
503
|
+
};
|
|
504
|
+
|
|
505
|
+
console.log(trees.tree(deep, { maxDepth: 2 }));
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
### 8.3 ā Cycle-safe rendering
|
|
509
|
+
|
|
510
|
+
```js
|
|
511
|
+
const { trees } = require('ansimax');
|
|
512
|
+
|
|
513
|
+
const a = { label: 'Node A', children: [] };
|
|
514
|
+
const b = { label: 'Node B', children: [] };
|
|
515
|
+
a.children = [b];
|
|
516
|
+
b.children = [a]; // cycle!
|
|
517
|
+
|
|
518
|
+
console.log(trees.tree(a, { maxDepth: 5 }));
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
---
|
|
522
|
+
|
|
523
|
+
## š¬ 9. `frames` ā Frame-by-frame animation
|
|
524
|
+
|
|
525
|
+
### 9.1 ā Loading spinner with custom frames
|
|
526
|
+
|
|
527
|
+
```js
|
|
528
|
+
const { frames } = require('ansimax');
|
|
529
|
+
|
|
530
|
+
async function main() {
|
|
531
|
+
const spinner = ['ā ', 'ā ', 'ā ¹', 'ā ø', 'ā ¼', 'ā “', 'ā ¦', 'ā §', 'ā ', 'ā '];
|
|
532
|
+
|
|
533
|
+
const ctrl = frames.play(
|
|
534
|
+
spinner.map((f) => `${f} Loading...`),
|
|
535
|
+
{ interval: 80, loop: true },
|
|
536
|
+
);
|
|
537
|
+
|
|
538
|
+
setTimeout(() => ctrl.stop(), 3000);
|
|
539
|
+
await ctrl.promise;
|
|
540
|
+
console.log('Done!');
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
main().catch(console.error);
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
### 9.2 ā Procedural frame generation
|
|
547
|
+
|
|
548
|
+
```js
|
|
549
|
+
const { frames } = require('ansimax');
|
|
550
|
+
|
|
551
|
+
async function main() {
|
|
552
|
+
const pulse = frames.generate(20, (i, total) => {
|
|
553
|
+
const intensity = Math.sin((i / total) * Math.PI * 2);
|
|
554
|
+
const size = Math.round(Math.abs(intensity) * 5) + 1;
|
|
555
|
+
return 'ā'.repeat(size).padEnd(7);
|
|
556
|
+
});
|
|
557
|
+
|
|
558
|
+
await frames.play(pulse, {
|
|
559
|
+
interval: 80,
|
|
560
|
+
loop: true,
|
|
561
|
+
signal: AbortSignal.timeout(2000),
|
|
562
|
+
}).promise;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
main().catch(console.error);
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
### 9.3 ā Morph one text into another
|
|
569
|
+
|
|
570
|
+
```js
|
|
571
|
+
const { frames } = require('ansimax');
|
|
572
|
+
|
|
573
|
+
async function main() {
|
|
574
|
+
const morphed = frames.morph('HELLO', 'WORLD', 15, 'āāāāāāā');
|
|
575
|
+
await frames.play(morphed, { interval: 80, loop: false }).promise;
|
|
576
|
+
console.log('\nā Morph complete');
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
main().catch(console.error);
|
|
580
|
+
```
|
|
581
|
+
|
|
582
|
+
---
|
|
583
|
+
|
|
584
|
+
## š¼ļø 10. `images` ā Pixel art, canvas, gradients
|
|
585
|
+
|
|
586
|
+
### 10.1 ā Render a sprite from the built-in library
|
|
587
|
+
|
|
588
|
+
```js
|
|
589
|
+
const { renderPixelArt, SPRITES } = require('ansimax');
|
|
590
|
+
|
|
591
|
+
console.log('All sprites:', Object.keys(SPRITES).join(', '));
|
|
592
|
+
console.log();
|
|
593
|
+
console.log(renderPixelArt(SPRITES.heart.pixels, { scale: 2 }));
|
|
594
|
+
```
|
|
595
|
+
|
|
596
|
+
### 10.2 ā Gradient rectangle for visual demos
|
|
597
|
+
|
|
598
|
+
```js
|
|
599
|
+
const { gradientRect } = require('ansimax');
|
|
600
|
+
|
|
601
|
+
// Sunset
|
|
602
|
+
console.log(gradientRect({
|
|
603
|
+
width: 50, height: 8,
|
|
604
|
+
colors: ['#ff5e62', '#ff9966', '#ffd86f'],
|
|
605
|
+
style: 'horizontal',
|
|
606
|
+
}));
|
|
607
|
+
|
|
608
|
+
console.log();
|
|
609
|
+
|
|
610
|
+
// Conic (rainbow wheel)
|
|
611
|
+
console.log(gradientRect({
|
|
612
|
+
width: 30, height: 15,
|
|
613
|
+
colors: ['#ff0000', '#ffff00', '#00ff00', '#00ffff', '#0000ff', '#ff00ff', '#ff0000'],
|
|
614
|
+
style: 'conic',
|
|
615
|
+
dither: 'bayer',
|
|
616
|
+
}));
|
|
617
|
+
```
|
|
618
|
+
|
|
619
|
+
### 10.3 ā Canvas with drawing primitives
|
|
620
|
+
|
|
621
|
+
```js
|
|
622
|
+
const { createCanvas } = require('ansimax');
|
|
623
|
+
|
|
624
|
+
const canvas = createCanvas(40, 20, { r: 30, g: 30, b: 40 });
|
|
625
|
+
|
|
626
|
+
const orange = { r: 255, g: 165, b: 0 };
|
|
627
|
+
const cyan = { r: 0, g: 200, b: 255 };
|
|
628
|
+
const pink = { r: 255, g: 105, b: 180 };
|
|
629
|
+
|
|
630
|
+
canvas.drawRect(2, 2, 12, 6, cyan, true);
|
|
631
|
+
canvas.drawCircle(25, 8, 4, orange, true);
|
|
632
|
+
canvas.drawLine(0, 19, 39, 0, pink);
|
|
633
|
+
|
|
634
|
+
canvas.print();
|
|
635
|
+
```
|
|
636
|
+
|
|
637
|
+
---
|
|
638
|
+
|
|
639
|
+
## šŖ 11. `panels` + `json` ā Layouts and pretty-printing (v1.3.0+)
|
|
640
|
+
|
|
641
|
+
### 11.1 ā Side-by-side columns with nesting
|
|
642
|
+
|
|
643
|
+
```js
|
|
644
|
+
const { panels, ascii } = require('ansimax');
|
|
645
|
+
|
|
646
|
+
const sidebar = ascii.box('Sidebar\n⢠Item 1\n⢠Item 2\n⢠Item 3', { borderStyle: 'rounded' });
|
|
647
|
+
const main = ascii.box('Main content\n\nLorem ipsum dolor sit amet.', { borderStyle: 'rounded' });
|
|
648
|
+
|
|
649
|
+
console.log(panels.vsplit([sidebar, main], { gap: 2, align: 'start' }));
|
|
650
|
+
|
|
651
|
+
console.log();
|
|
652
|
+
|
|
653
|
+
console.log(panels.hsplit([
|
|
654
|
+
'āā Header āā',
|
|
655
|
+
ascii.box('Body content'),
|
|
656
|
+
'āā Footer āā',
|
|
657
|
+
], { align: 'center', gap: 1 }));
|
|
658
|
+
```
|
|
659
|
+
|
|
660
|
+
### 11.2 ā Centering and decorative frames
|
|
661
|
+
|
|
662
|
+
```js
|
|
663
|
+
const { panels, ascii } = require('ansimax');
|
|
664
|
+
|
|
665
|
+
const card = ascii.box('Welcome!', { borderStyle: 'rounded', padding: 2 });
|
|
666
|
+
console.log(panels.center(card, { width: 80 }));
|
|
667
|
+
|
|
668
|
+
console.log();
|
|
669
|
+
|
|
670
|
+
console.log(panels.frame('Important section content here', {
|
|
671
|
+
title: 'Section Header',
|
|
672
|
+
padding: 1,
|
|
673
|
+
topChar: 'ā',
|
|
674
|
+
}));
|
|
675
|
+
```
|
|
676
|
+
|
|
677
|
+
### 11.3 ā JSON pretty-print with all options
|
|
678
|
+
|
|
679
|
+
```js
|
|
680
|
+
const { json } = require('ansimax');
|
|
681
|
+
|
|
682
|
+
const data = {
|
|
683
|
+
name: 'ansimax',
|
|
684
|
+
version: '1.3.2',
|
|
685
|
+
features: ['colors', 'gradients', 'panels', 'json'],
|
|
686
|
+
stats: { tests: 2104, coverage: 0.98 },
|
|
687
|
+
meta: { active: true },
|
|
688
|
+
};
|
|
689
|
+
|
|
690
|
+
console.log(json.pretty(data));
|
|
691
|
+
|
|
692
|
+
console.log('\n--- With sortKeys (alphabetical) ---');
|
|
693
|
+
console.log(json.pretty(data, { sortKeys: true }));
|
|
694
|
+
|
|
695
|
+
console.log('\n--- With maxDepth: 1 (collapsed) ---');
|
|
696
|
+
console.log(json.pretty(data, { maxDepth: 1 }));
|
|
697
|
+
```
|
|
698
|
+
|
|
699
|
+
---
|
|
700
|
+
|
|
701
|
+
## šÆ Next steps
|
|
702
|
+
|
|
703
|
+
- **TypeScript?** ā [`examples-ts.md`](./examples-ts.md)
|
|
704
|
+
- **JavaScript ESM?** ā [`examples-mjs.md`](./examples-mjs.md)
|
|
705
|
+
- **Complete demo app combining everything?** ā [`showcase.md`](./showcase.md)
|
|
706
|
+
- **Back to docs index?** ā [`README.md`](./README.md)
|