ansimax 1.1.1 → 1.2.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/CHANGELOG.md +152 -0
- package/README.es.md +150 -40
- package/README.md +150 -40
- package/dist/index.d.mts +78 -2
- package/dist/index.d.ts +78 -2
- package/dist/index.js +140 -15
- package/dist/index.mjs +139 -15
- package/examples/all-in-one.cjs +1 -1
- package/examples/all-in-one.mjs +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,158 @@
|
|
|
3
3
|
All notable changes to **ansimax** are documented in this file.
|
|
4
4
|
This project follows [Semantic Versioning](https://semver.org/).
|
|
5
5
|
|
|
6
|
+
## [1.2.0] — Phase 2 complete: animated, eased & conic gradients
|
|
7
|
+
|
|
8
|
+
Minor release closing the **gradient engine roadmap (Phase 2)** with three
|
|
9
|
+
long-awaited capabilities. All additions are fully backwards-compatible —
|
|
10
|
+
existing `gradient()` calls work identically.
|
|
11
|
+
|
|
12
|
+
### Added — Easing curves
|
|
13
|
+
|
|
14
|
+
`gradient()` now accepts an `easing` option to control how colors are
|
|
15
|
+
distributed along the text. Five built-in curves plus custom functions:
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
gradient('hello world', ['#ff0000', '#0000ff'], { easing: 'ease-in' });
|
|
19
|
+
gradient('hello world', ['#ff0000', '#0000ff'], { easing: 'ease-out' });
|
|
20
|
+
gradient('hello world', ['#ff0000', '#0000ff'], { easing: 'ease-in-out' });
|
|
21
|
+
gradient('hello world', ['#ff0000', '#0000ff'], { easing: 'cubic-bezier' });
|
|
22
|
+
|
|
23
|
+
// Or pass a custom EasingFn (t → eased t, both in [0,1])
|
|
24
|
+
gradient('hello world', ['#ff0000', '#0000ff'], { easing: (t) => t * t * t });
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
- `linear` — even distribution (default, identical to pre-1.2.0 behavior)
|
|
28
|
+
- `ease-in` — concentrates colors at the end (quadratic)
|
|
29
|
+
- `ease-out` — concentrates colors at the start (quadratic)
|
|
30
|
+
- `ease-in-out` — slow at both ends, fast in middle
|
|
31
|
+
- `cubic-bezier` — CSS-style `ease` curve (Newton-Raphson approximated)
|
|
32
|
+
- Out-of-range custom easings are clamped to `[0, 1]` automatically
|
|
33
|
+
|
|
34
|
+
### Added — Phase offset (flowing colors)
|
|
35
|
+
|
|
36
|
+
`gradient()` now accepts a `phase` parameter `[0, 1)` that shifts the
|
|
37
|
+
gradient along the text. Combined with an animation loop, this produces
|
|
38
|
+
a flowing color effect:
|
|
39
|
+
|
|
40
|
+
```ts
|
|
41
|
+
gradient('hello', ['#ff0000', '#0000ff'], { phase: 0.5 });
|
|
42
|
+
// negative values wrap forward; NaN/Infinity falls back to 0
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Added — `animateGradient()` API
|
|
46
|
+
|
|
47
|
+
High-level API for animated gradients with proper lifecycle management:
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
import { animateGradient } from 'ansimax';
|
|
51
|
+
|
|
52
|
+
const ctrl = animateGradient('Loading...', ['#ff79c6', '#bd93f9', '#8be9fd'], {
|
|
53
|
+
duration: 2000,
|
|
54
|
+
fps: 30,
|
|
55
|
+
direction: 'forward', // or 'reverse'
|
|
56
|
+
infinite: true,
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
// Later
|
|
60
|
+
ctrl.stop();
|
|
61
|
+
// Or via AbortController
|
|
62
|
+
const abort = new AbortController();
|
|
63
|
+
animateGradient('hi', stops, { signal: abort.signal });
|
|
64
|
+
abort.abort();
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Returns an `AnimateGradientController` with `.stop()` and `.done` (Promise).
|
|
68
|
+
Supports `AbortSignal`, custom render via `onFrame`, fps cap at 60,
|
|
69
|
+
and direction reversal.
|
|
70
|
+
|
|
71
|
+
### Added — Conic gradients
|
|
72
|
+
|
|
73
|
+
`gradientRect()` now supports `style: 'conic'` for radial sweeps around
|
|
74
|
+
the center point:
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
import { gradientRect } from 'ansimax';
|
|
78
|
+
|
|
79
|
+
console.log(gradientRect({
|
|
80
|
+
width: 30, height: 15,
|
|
81
|
+
colors: ['#ff0000', '#00ff00', '#0000ff', '#ff0000'],
|
|
82
|
+
style: 'conic',
|
|
83
|
+
startAngle: 0, // rotation in degrees
|
|
84
|
+
dither: 'bayer',
|
|
85
|
+
}));
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
- `startAngle` (degrees) rotates the sweep
|
|
89
|
+
- Non-finite `startAngle` falls back to `0`
|
|
90
|
+
- Compatible with all existing options (`dither`, `braille`, `width`, `height`)
|
|
91
|
+
|
|
92
|
+
### Added — New exports
|
|
93
|
+
|
|
94
|
+
- `animateGradient` — function
|
|
95
|
+
- `AnimateGradientOptions` / `AnimateGradientController` — types
|
|
96
|
+
- `EasingName` — union type of built-in curve names
|
|
97
|
+
- `EasingFn` — `(t: number) => number` curve type
|
|
98
|
+
|
|
99
|
+
### Notes
|
|
100
|
+
|
|
101
|
+
- All 1848 + 30 new tests pass.
|
|
102
|
+
- Backwards-compatible: existing `gradient()` calls work identically.
|
|
103
|
+
- No new runtime dependencies.
|
|
104
|
+
- Phase 2 of the [roadmap](README.md#%EF%B8%8F-roadmap) is now **fully complete**.
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## [1.1.2] — maturity & robustness
|
|
109
|
+
|
|
110
|
+
Patch release focused on maturity: better error semantics, defensive
|
|
111
|
+
defaults, and cleaner type re-exports. No API breaking changes — every
|
|
112
|
+
1.1.1 program runs identically.
|
|
113
|
+
|
|
114
|
+
### Fixed
|
|
115
|
+
|
|
116
|
+
- **CI: `jest.config.js` syntax error.** The config file used `export default {}`
|
|
117
|
+
(ESM syntax), which crashed in Node CommonJS context — including in
|
|
118
|
+
GitHub Actions runners. Fixed by switching to `module.exports = {}` to
|
|
119
|
+
match `useESM: false` in the ts-jest configuration. Tests now run
|
|
120
|
+
correctly across Linux, macOS, and Windows runners.
|
|
121
|
+
|
|
122
|
+
### Improved
|
|
123
|
+
|
|
124
|
+
- **`process.setMaxListeners` defensive bump.** Ansimax modules
|
|
125
|
+
(`animations`, `frames`, `loaders`, `utils/ansi`) each register
|
|
126
|
+
`SIGINT` / `SIGTERM` / `exit` handlers for crash-safe cursor
|
|
127
|
+
restoration. With Node's default cap of 10, hot-reload setups
|
|
128
|
+
(Vite HMR, nodemon, ts-node-dev) could occasionally emit
|
|
129
|
+
`MaxListenersExceededWarning`. We now bump the cap to 20 on first
|
|
130
|
+
install — silently and safely, only if the current limit is lower.
|
|
131
|
+
Production apps unaffected.
|
|
132
|
+
- **Uniform `TypeError` for theme validation.** `themes.register()`
|
|
133
|
+
now throws `TypeError` for any structural / type issue (missing
|
|
134
|
+
fields, non-string `name`, invalid hex), matching the rest of the
|
|
135
|
+
validation surface. Previously it threw a mix of `Error` and
|
|
136
|
+
`TypeError`, which made `try / catch` filtering inconsistent.
|
|
137
|
+
- **`themes.use()` throws `RangeError`** for unknown theme names
|
|
138
|
+
(was `Error`). `RangeError` better reflects "value out of allowed
|
|
139
|
+
set" semantics — same standard library convention as `Array(-1)`.
|
|
140
|
+
Error message now also says "Available themes:" instead of
|
|
141
|
+
"Available:" for clarity.
|
|
142
|
+
- **Cleaner type re-exports in the barrel.** Added a header comment
|
|
143
|
+
explaining the legacy aliases (`stripAnsiColors`, `stripAnsiCodes`)
|
|
144
|
+
and recommending `stripAnsi` for new code. Version string in the
|
|
145
|
+
barrel header updated from the stale `v1.0.0` to `v1.1.2`.
|
|
146
|
+
|
|
147
|
+
### Notes
|
|
148
|
+
|
|
149
|
+
- All 1848 tests pass; 4 new tests cover the error-type guarantees.
|
|
150
|
+
- The error-type changes are technically observable via `instanceof`
|
|
151
|
+
checks, but `RangeError` and `TypeError` both extend `Error`, so any
|
|
152
|
+
`catch (e: Error)` block keeps working. We classify this as a
|
|
153
|
+
non-breaking quality-of-life improvement.
|
|
154
|
+
- No new dependencies — still zero runtime deps.
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
6
158
|
## [1.1.1] — bug fixes + improved examples
|
|
7
159
|
|
|
8
160
|
Patch release with two bug fixes from real-world testing of v1.1.0, plus
|
package/README.es.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
_Colores • Gradientes • Animaciones • ASCII Art • Pixel Art • Árboles • Componentes • Temas_
|
|
8
8
|
|
|
9
9
|
[](LICENSE)
|
|
10
|
-
[](https://www.npmjs.com/package/ansimax)
|
|
11
11
|
[](tsconfig.json)
|
|
12
12
|
[](#testing)
|
|
13
13
|
[](#testing)
|
|
@@ -50,14 +50,14 @@ npm install ansimax
|
|
|
50
50
|
```
|
|
51
51
|
|
|
52
52
|
```ts
|
|
53
|
-
import { color, gradient, ascii, loader } from 'ansimax';
|
|
53
|
+
import { color, gradient, ascii, loader, sleep } from 'ansimax';
|
|
54
54
|
|
|
55
55
|
console.log(ascii.banner('hola', {
|
|
56
56
|
colorFn: (t) => gradient(t, ['#ff79c6', '#bd93f9', '#8be9fd']),
|
|
57
57
|
}));
|
|
58
58
|
|
|
59
59
|
const stop = loader.spin('Construyendo proyecto', { color: '#bd93f9' });
|
|
60
|
-
await
|
|
60
|
+
await sleep(1500);
|
|
61
61
|
stop('Build completado', true);
|
|
62
62
|
```
|
|
63
63
|
|
|
@@ -123,14 +123,14 @@ yarn add ansimax
|
|
|
123
123
|
## ⚡ Ejemplo en 30 segundos
|
|
124
124
|
|
|
125
125
|
```ts
|
|
126
|
-
import { color, gradient, loader, ascii } from 'ansimax';
|
|
126
|
+
import { color, gradient, loader, ascii, sleep } from 'ansimax';
|
|
127
127
|
|
|
128
128
|
console.log(ascii.banner('deploy', {
|
|
129
129
|
colorFn: (t) => gradient(t, ['#ff6b6b', '#feca57', '#48dbfb']),
|
|
130
130
|
}));
|
|
131
131
|
|
|
132
132
|
const stop = loader.spin('Construyendo proyecto', { color: '#bd93f9' });
|
|
133
|
-
await
|
|
133
|
+
await sleep(1500); // simula trabajo asíncrono
|
|
134
134
|
stop('Build completado', true); // ✓ + color de éxito
|
|
135
135
|
|
|
136
136
|
console.log(color.green('✓') + ' Listo en ' + color.bold('1.4s'));
|
|
@@ -187,12 +187,66 @@ console.log(themes.primary('primary de cyberpunk'));
|
|
|
187
187
|
<img src="media/colors.png" alt="Colores y gradientes" />
|
|
188
188
|
|
|
189
189
|
```ts
|
|
190
|
-
import { color, gradient } from 'ansimax';
|
|
190
|
+
import { color, gradient, rainbow } from 'ansimax';
|
|
191
191
|
|
|
192
|
-
|
|
193
|
-
color.
|
|
194
|
-
|
|
195
|
-
|
|
192
|
+
// Colores básicos
|
|
193
|
+
console.log(color.red('rojo'), color.green('verde'), color.blue('azul'));
|
|
194
|
+
|
|
195
|
+
// Modificadores de estilo
|
|
196
|
+
console.log(color.bold('negrita'), color.italic('itálica'), color.underline('subrayado'));
|
|
197
|
+
|
|
198
|
+
// Gradiente multi-stop
|
|
199
|
+
console.log(gradient('fuego a océano', ['#ff6b6b', '#feca57', '#48dbfb']));
|
|
200
|
+
|
|
201
|
+
// Preset rainbow integrado
|
|
202
|
+
console.log(rainbow('preset rainbow integrado'));
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### Gradientes animados (v1.2.0)
|
|
206
|
+
|
|
207
|
+
```ts
|
|
208
|
+
import { animateGradient, sleep } from 'ansimax';
|
|
209
|
+
|
|
210
|
+
// Animación de flujo de color — corre hasta llamar stop()
|
|
211
|
+
const ctrl = animateGradient('Cargando...', ['#ff79c6', '#bd93f9', '#8be9fd'], {
|
|
212
|
+
duration: 2000, // ms por ciclo
|
|
213
|
+
fps: 30,
|
|
214
|
+
direction: 'forward', // o 'reverse'
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
await sleep(3000);
|
|
218
|
+
ctrl.stop();
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### Curvas de interpolación (v1.2.0)
|
|
222
|
+
|
|
223
|
+
```ts
|
|
224
|
+
import { gradient } from 'ansimax';
|
|
225
|
+
|
|
226
|
+
// Cinco easings built-in + soporte para funciones personalizadas
|
|
227
|
+
gradient('hola mundo', stops, { easing: 'linear' });
|
|
228
|
+
gradient('hola mundo', stops, { easing: 'ease-in' });
|
|
229
|
+
gradient('hola mundo', stops, { easing: 'ease-out' });
|
|
230
|
+
gradient('hola mundo', stops, { easing: 'ease-in-out' });
|
|
231
|
+
gradient('hola mundo', stops, { easing: 'cubic-bezier' });
|
|
232
|
+
|
|
233
|
+
// O tu propia función de easing (t → t suavizado, ambos en [0,1])
|
|
234
|
+
gradient('hola mundo', stops, { easing: (t) => t * t * t });
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### Gradientes cónicos (v1.2.0)
|
|
238
|
+
|
|
239
|
+
```ts
|
|
240
|
+
import { gradientRect } from 'ansimax';
|
|
241
|
+
|
|
242
|
+
// Barrido radial alrededor del centro — rueda arcoíris
|
|
243
|
+
console.log(gradientRect({
|
|
244
|
+
width: 30, height: 15,
|
|
245
|
+
colors: ['#ff0000', '#ffff00', '#00ff00', '#00ffff', '#0000ff', '#ff00ff', '#ff0000'],
|
|
246
|
+
style: 'conic',
|
|
247
|
+
startAngle: 0, // ángulo de rotación en grados
|
|
248
|
+
dither: 'bayer',
|
|
249
|
+
}));
|
|
196
250
|
```
|
|
197
251
|
|
|
198
252
|
### ASCII Art
|
|
@@ -202,13 +256,13 @@ color.rainbow('preset rainbow integrado');
|
|
|
202
256
|
```ts
|
|
203
257
|
import { ascii, gradient } from 'ansimax';
|
|
204
258
|
|
|
205
|
-
ascii.banner('HOLA', {
|
|
259
|
+
console.log(ascii.banner('HOLA', {
|
|
206
260
|
font: 'big',
|
|
207
261
|
align: 'center',
|
|
208
262
|
colorFn: (t) => gradient(t, ['#ff79c6', '#bd93f9']),
|
|
209
|
-
});
|
|
263
|
+
}));
|
|
210
264
|
|
|
211
|
-
ascii.box('¡Caja arcoiris!', { padding: 1, borderStyle: 'rounded' });
|
|
265
|
+
console.log(ascii.box('¡Caja arcoiris!', { padding: 1, borderStyle: 'rounded' }));
|
|
212
266
|
```
|
|
213
267
|
|
|
214
268
|
### Árboles
|
|
@@ -235,7 +289,7 @@ console.log(proyecto.render({
|
|
|
235
289
|
<img src="media/pixel_art.png" alt="Pixel art" />
|
|
236
290
|
|
|
237
291
|
```ts
|
|
238
|
-
import { images, createCanvas, gradientRect } from 'ansimax';
|
|
292
|
+
import { images, createCanvas, gradientRect, SPRITES } from 'ansimax';
|
|
239
293
|
|
|
240
294
|
// Sprite integrado
|
|
241
295
|
console.log(images.sprite('heart'));
|
|
@@ -251,7 +305,8 @@ console.log(gradientRect({
|
|
|
251
305
|
const c = createCanvas(40, 10);
|
|
252
306
|
c.fill({ r: 18, g: 18, b: 38 });
|
|
253
307
|
c.drawCircle(20, 5, 4, { r: 255, g: 200, b: 0 }, true);
|
|
254
|
-
|
|
308
|
+
const starSprite = SPRITES.star;
|
|
309
|
+
if (starSprite) c.drawSprite(2, 2, starSprite.pixels);
|
|
255
310
|
c.print();
|
|
256
311
|
```
|
|
257
312
|
|
|
@@ -262,15 +317,15 @@ c.print();
|
|
|
262
317
|
```ts
|
|
263
318
|
import { components, color } from 'ansimax';
|
|
264
319
|
|
|
265
|
-
components.table([
|
|
320
|
+
console.log(components.table([
|
|
266
321
|
['Módulo', 'Estado', 'Cobertura'],
|
|
267
322
|
['colors', color.green('● listo'), '100%'],
|
|
268
323
|
['animations', color.green('● listo'), '100%'],
|
|
269
324
|
['loaders', color.green('● listo'), '100%'],
|
|
270
|
-
], { borderStyle: 'rounded' });
|
|
325
|
+
], { borderStyle: 'rounded' }));
|
|
271
326
|
|
|
272
|
-
components.badge('VERSION', 'v1.
|
|
273
|
-
components.badge('BUILD', 'passing');
|
|
327
|
+
console.log(components.badge('VERSION', 'v1.2.0'));
|
|
328
|
+
console.log(components.badge('BUILD', 'passing'));
|
|
274
329
|
```
|
|
275
330
|
|
|
276
331
|
### Timeline
|
|
@@ -278,22 +333,24 @@ components.badge('BUILD', 'passing');
|
|
|
278
333
|
<img src="media/timeline.png" alt="Timeline" />
|
|
279
334
|
|
|
280
335
|
```ts
|
|
281
|
-
components
|
|
336
|
+
import { components } from 'ansimax';
|
|
337
|
+
|
|
338
|
+
console.log(components.timeline([
|
|
282
339
|
{ label: 'Init del proyecto', done: true, time: '10:00' },
|
|
283
340
|
{ label: 'Pipeline de build', done: true, time: '10:15' },
|
|
284
341
|
{ label: 'Correr tests', done: false, time: '10:32' },
|
|
285
342
|
{ label: 'Deploy a npm', done: false },
|
|
286
|
-
]);
|
|
343
|
+
]));
|
|
287
344
|
```
|
|
288
345
|
|
|
289
346
|
### Loaders y Progreso
|
|
290
347
|
|
|
291
348
|
```ts
|
|
292
|
-
import { loader } from 'ansimax';
|
|
349
|
+
import { loader, sleep } from 'ansimax';
|
|
293
350
|
|
|
294
351
|
// Spinner con éxito/fallo
|
|
295
352
|
const stop = loader.spin('Cargando...', { color: '#bd93f9' });
|
|
296
|
-
await
|
|
353
|
+
await sleep(1500);
|
|
297
354
|
stop('¡Listo!', true); // ✓ ícono verde
|
|
298
355
|
|
|
299
356
|
// Barra de progreso animada
|
|
@@ -303,18 +360,22 @@ await loader.progressAnimate(100, 'Descargando', {
|
|
|
303
360
|
|
|
304
361
|
// Tareas jerárquicas con ejecución paralela
|
|
305
362
|
await loader.tasks([
|
|
306
|
-
{
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
363
|
+
{
|
|
364
|
+
text: 'Build',
|
|
365
|
+
fn: async () => await sleep(500),
|
|
366
|
+
subtasks: [
|
|
367
|
+
{ text: 'TypeScript', fn: async () => await sleep(800) },
|
|
368
|
+
{ text: 'Bundle', fn: async () => await sleep(600) },
|
|
369
|
+
],
|
|
370
|
+
},
|
|
371
|
+
{ text: 'Test', fn: async () => await sleep(700) },
|
|
311
372
|
], { parallel: true });
|
|
312
373
|
```
|
|
313
374
|
|
|
314
375
|
### Animaciones
|
|
315
376
|
|
|
316
377
|
```ts
|
|
317
|
-
import { animate, gradient } from 'ansimax';
|
|
378
|
+
import { animate, gradient, sleep } from 'ansimax';
|
|
318
379
|
|
|
319
380
|
await animate.typewriter('Bienvenido al wizard de deployment...', {
|
|
320
381
|
speed: 30,
|
|
@@ -325,9 +386,9 @@ await animate.fadeIn('Carga completa', { duration: 600 });
|
|
|
325
386
|
|
|
326
387
|
// Carrera de pasos contra timeout — nunca se cuelga
|
|
327
388
|
await animate.parallel([
|
|
328
|
-
async () => await
|
|
329
|
-
async () => await
|
|
330
|
-
async () => await
|
|
389
|
+
async () => await sleep(500), // simulación de chequeo de red
|
|
390
|
+
async () => await sleep(700), // simulación de chequeo de base de datos
|
|
391
|
+
async () => await sleep(400), // simulación de chequeo de auth
|
|
331
392
|
], { timeout: 5000 });
|
|
332
393
|
```
|
|
333
394
|
|
|
@@ -340,7 +401,7 @@ import { themes, createTheme } from 'ansimax';
|
|
|
340
401
|
|
|
341
402
|
// Temas built-in
|
|
342
403
|
themes.use('dracula');
|
|
343
|
-
themes.primary('hola');
|
|
404
|
+
console.log(themes.primary('hola'));
|
|
344
405
|
|
|
345
406
|
// Escuchar cambios
|
|
346
407
|
const off = themes.onChange((nuevo, anterior) => {
|
|
@@ -350,7 +411,27 @@ const off = themes.onChange((nuevo, anterior) => {
|
|
|
350
411
|
// Multi-tenant: cada instancia totalmente aislada
|
|
351
412
|
const tenantA = createTheme('nord');
|
|
352
413
|
const tenantB = createTheme('matrix');
|
|
353
|
-
|
|
414
|
+
|
|
415
|
+
// Definir un tema personalizado y registrarlo SÓLO en tenantA
|
|
416
|
+
tenantA.register('custom', {
|
|
417
|
+
name: 'Custom',
|
|
418
|
+
primary: '#ff5e5e',
|
|
419
|
+
secondary: '#5e5eff',
|
|
420
|
+
accent: '#5eff5e',
|
|
421
|
+
success: '#10b981',
|
|
422
|
+
warning: '#fbbf24',
|
|
423
|
+
error: '#ef4444',
|
|
424
|
+
info: '#06b6d4',
|
|
425
|
+
muted: '#6b7280',
|
|
426
|
+
bg: '#1e293b',
|
|
427
|
+
surface: '#334155',
|
|
428
|
+
text: '#f1f5f9',
|
|
429
|
+
gradient: ['#ff5e5e', '#5eff5e', '#5e5eff'],
|
|
430
|
+
});
|
|
431
|
+
|
|
432
|
+
console.log('tenantA incluye custom?', tenantA.list().includes('custom'));
|
|
433
|
+
console.log('tenantB incluye custom?', tenantB.list().includes('custom'));
|
|
434
|
+
// ↑ false — aislamiento total
|
|
354
435
|
```
|
|
355
436
|
|
|
356
437
|
---
|
|
@@ -421,11 +502,11 @@ const off = onConfigKeyChange('theme', (nuevo, anterior) => {
|
|
|
421
502
|
|
|
422
503
|
// Override temporal + restauración automática al completar o lanzar
|
|
423
504
|
await withConfig({ animationSpeed: 'fast' }, async () => {
|
|
424
|
-
|
|
505
|
+
// ...tu código en modo fast aquí...
|
|
425
506
|
});
|
|
426
507
|
|
|
427
508
|
// Modo strict captura typos en config
|
|
428
|
-
configure({ unknwnKey: 'x' }, { strict: true }); // lanza RangeError
|
|
509
|
+
// configure({ unknwnKey: 'x' }, { strict: true }); // lanza RangeError
|
|
429
510
|
```
|
|
430
511
|
|
|
431
512
|
---
|
|
@@ -453,9 +534,9 @@ El roadmap apunta intencionalmente — y busca superar — gaps que ni siquiera
|
|
|
453
534
|
- [x] Gradientes a ángulo arbitrario
|
|
454
535
|
- [x] Dithering Bayer 4×4 para transiciones tonales suaves
|
|
455
536
|
- [x] UX single-stop (comportamiento estilo CSS)
|
|
456
|
-
- [
|
|
457
|
-
- [
|
|
458
|
-
- [
|
|
537
|
+
- [x] **Gradientes animados** — flujo de color en el tiempo con `animateGradient()` (v1.2.0)
|
|
538
|
+
- [x] **Curvas de interpolación** — `linear` / `ease-in` / `ease-out` / `ease-in-out` / `cubic-bezier` / personalizado (v1.2.0)
|
|
539
|
+
- [x] **Gradientes cónicos** — barrido radial con `style: 'conic'` (v1.2.0)
|
|
459
540
|
|
|
460
541
|
### 🟡 Fase 3 — Motor ASCII
|
|
461
542
|
- [x] Fuentes de bloque (`big`, `small`)
|
|
@@ -645,6 +726,35 @@ ansimax/
|
|
|
645
726
|
|
|
646
727
|
## 📝 Changelog
|
|
647
728
|
|
|
729
|
+
### v1.2.0 — Fase 2 completa: gradientes animados, easing y cónicos
|
|
730
|
+
|
|
731
|
+
Release minor que cierra el roadmap del motor de gradientes con tres features potentes:
|
|
732
|
+
|
|
733
|
+
- 🌊 **`animateGradient()`** — flujo de color en el tiempo con ciclo de vida apropiado (Promise, signal, fps, direction)
|
|
734
|
+
- 📐 **Curvas de interpolación** — `linear` / `ease-in` / `ease-out` / `ease-in-out` / `cubic-bezier` / funciones personalizadas
|
|
735
|
+
- ⭕ **Gradientes cónicos** — `gradientRect({ style: 'conic', startAngle })` para barridos radiales
|
|
736
|
+
|
|
737
|
+
```ts
|
|
738
|
+
import { animateGradient } from 'ansimax';
|
|
739
|
+
|
|
740
|
+
const ctrl = animateGradient('Cargando...', ['#ff79c6', '#bd93f9', '#8be9fd']);
|
|
741
|
+
await sleep(3000);
|
|
742
|
+
ctrl.stop();
|
|
743
|
+
```
|
|
744
|
+
|
|
745
|
+
Totalmente retrocompatible — todo programa 1.1.x corre idénticamente.
|
|
746
|
+
|
|
747
|
+
### v1.1.2 — Madurez y robustez
|
|
748
|
+
|
|
749
|
+
Release patch enfocado en refinamientos de calidad — sin cambios en la API.
|
|
750
|
+
|
|
751
|
+
- 🛡️ **Bump defensivo de `process.setMaxListeners`** — previene `MaxListenersExceededWarning` en setups con HMR / nodemon / ts-node-dev donde los módulos de ansimax re-registran handlers de restauración de cursor
|
|
752
|
+
- 🧪 **`TypeError` uniforme para validación de themes** — `themes.register()` ahora arroja consistentemente `TypeError` para errores estructurales / de tipo (antes era mezcla de `Error` y `TypeError`)
|
|
753
|
+
- 🎯 **`themes.use()` arroja `RangeError`** para nombres de tema desconocidos (antes `Error`) — mejor match semántico con "valor fuera del set permitido"
|
|
754
|
+
- 📝 **Re-exports más limpios en el barrel** — comentario de header ahora documenta aliases legacy y recomienda nombres canónicos
|
|
755
|
+
|
|
756
|
+
Drop-in replacement para `1.1.1`.
|
|
757
|
+
|
|
648
758
|
### v1.1.1 — Fixes de bugs + ejemplos limpios
|
|
649
759
|
|
|
650
760
|
Release patch que arregla dos bugs encontrados en testing real de v1.1.0, más una carpeta de ejemplos refrescada.
|
|
@@ -750,4 +860,4 @@ Ansimax está licenciada bajo **Apache License, Version 2.0** — una licencia p
|
|
|
750
860
|
|
|
751
861
|
Si Ansimax te ayuda a hacer mejores CLIs, ¡dale ⭐ en [GitHub](https://github.com/Brashkie/ansimax)!
|
|
752
862
|
|
|
753
|
-
</div>
|
|
863
|
+
</div>
|