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