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/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
  _Colors • Gradients • Animations • ASCII Art • Pixel Art • Trees • Components • Themes_
8
8
 
9
9
  [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg?style=flat-square)](LICENSE)
10
- [![npm](https://img.shields.io/badge/npm-v1.1.1-cb3837.svg?style=flat-square)](https://www.npmjs.com/package/ansimax)
10
+ [![npm](https://img.shields.io/badge/npm-v1.2.0-cb3837.svg?style=flat-square)](https://www.npmjs.com/package/ansimax)
11
11
  [![TypeScript](https://img.shields.io/badge/TypeScript-strict-3178c6.svg?style=flat-square)](tsconfig.json)
12
12
  [![Coverage](https://img.shields.io/badge/coverage-98%25-brightgreen.svg?style=flat-square)](#testing)
13
13
  [![Tests](https://img.shields.io/badge/tests-1700%2B%20passing-brightgreen.svg?style=flat-square)](#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('hello', {
56
56
  colorFn: (t) => gradient(t, ['#ff79c6', '#bd93f9', '#8be9fd']),
57
57
  }));
58
58
 
59
59
  const stop = loader.spin('Building project', { color: '#bd93f9' });
60
- await someAsyncWork();
60
+ await sleep(1500);
61
61
  stop('Build complete', true);
62
62
  ```
63
63
 
@@ -123,14 +123,14 @@ yarn add ansimax
123
123
  ## ⚡ 30-second example
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('Building project', { color: '#bd93f9' });
133
- await someAsyncWork();
133
+ await sleep(1500); // simulate async work
134
134
  stop('Build complete', true); // ✓ + success color
135
135
 
136
136
  console.log(color.green('✓') + ' Ready in ' + color.bold('1.4s'));
@@ -187,12 +187,66 @@ console.log(themes.primary('cyberpunk primary'));
187
187
  <img src="media/colors.png" alt="Colors and gradients" />
188
188
 
189
189
  ```ts
190
- import { color, gradient } from 'ansimax';
190
+ import { color, gradient, rainbow } from 'ansimax';
191
191
 
192
- color.red('red'); color.green('green'); color.blue('blue');
193
- color.bold(text); color.italic(text); color.underline(text);
194
- gradient('fire to ocean', ['#ff6b6b', '#feca57', '#48dbfb']);
195
- color.rainbow('built-in rainbow preset');
192
+ // Basic colors
193
+ console.log(color.red('red'), color.green('green'), color.blue('blue'));
194
+
195
+ // Style modifiers
196
+ console.log(color.bold('bold'), color.italic('italic'), color.underline('underlined'));
197
+
198
+ // Multi-stop gradient
199
+ console.log(gradient('fire to ocean', ['#ff6b6b', '#feca57', '#48dbfb']));
200
+
201
+ // Built-in rainbow preset
202
+ console.log(rainbow('built-in rainbow preset'));
203
+ ```
204
+
205
+ ### Animated Gradients (v1.2.0)
206
+
207
+ ```ts
208
+ import { animateGradient, sleep } from 'ansimax';
209
+
210
+ // Color flow animation — runs until you call stop()
211
+ const ctrl = animateGradient('Loading...', ['#ff79c6', '#bd93f9', '#8be9fd'], {
212
+ duration: 2000, // ms per cycle
213
+ fps: 30,
214
+ direction: 'forward', // or 'reverse'
215
+ });
216
+
217
+ await sleep(3000);
218
+ ctrl.stop();
219
+ ```
220
+
221
+ ### Easing Curves (v1.2.0)
222
+
223
+ ```ts
224
+ import { gradient } from 'ansimax';
225
+
226
+ // Five built-in easings + custom function support
227
+ gradient('hello world', stops, { easing: 'linear' });
228
+ gradient('hello world', stops, { easing: 'ease-in' });
229
+ gradient('hello world', stops, { easing: 'ease-out' });
230
+ gradient('hello world', stops, { easing: 'ease-in-out' });
231
+ gradient('hello world', stops, { easing: 'cubic-bezier' });
232
+
233
+ // Or pass your own easing function (t → eased t, both in [0,1])
234
+ gradient('hello world', stops, { easing: (t) => t * t * t });
235
+ ```
236
+
237
+ ### Conic Gradients (v1.2.0)
238
+
239
+ ```ts
240
+ import { gradientRect } from 'ansimax';
241
+
242
+ // Radial sweep around center — rainbow wheel
243
+ console.log(gradientRect({
244
+ width: 30, height: 15,
245
+ colors: ['#ff0000', '#ffff00', '#00ff00', '#00ffff', '#0000ff', '#ff00ff', '#ff0000'],
246
+ style: 'conic',
247
+ startAngle: 0, // rotation angle in degrees
248
+ dither: 'bayer',
249
+ }));
196
250
  ```
197
251
 
198
252
  ### ASCII Art
@@ -202,13 +256,13 @@ color.rainbow('built-in rainbow preset');
202
256
  ```ts
203
257
  import { ascii, gradient } from 'ansimax';
204
258
 
205
- ascii.banner('HELLO', {
259
+ console.log(ascii.banner('HELLO', {
206
260
  font: 'big',
207
261
  align: 'center',
208
262
  colorFn: (t) => gradient(t, ['#ff79c6', '#bd93f9']),
209
- });
263
+ }));
210
264
 
211
- ascii.box('Rainbow box!', { padding: 1, borderStyle: 'rounded' });
265
+ console.log(ascii.box('Rainbow box!', { padding: 1, borderStyle: 'rounded' }));
212
266
  ```
213
267
 
214
268
  ### Trees
@@ -235,7 +289,7 @@ console.log(project.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
  // Built-in sprite
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
- c.drawSprite(2, 2, images.sprites.star!.pixels);
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
  ['Module', 'Status', 'Coverage'],
267
322
  ['colors', color.green('● ready'), '100%'],
268
323
  ['animations', color.green('● ready'), '100%'],
269
324
  ['loaders', color.green('● ready'), '100%'],
270
- ], { borderStyle: 'rounded' });
325
+ ], { borderStyle: 'rounded' }));
271
326
 
272
- components.badge('VERSION', 'v1.1.1');
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.timeline([
336
+ import { components } from 'ansimax';
337
+
338
+ console.log(components.timeline([
282
339
  { label: 'Project init', done: true, time: '10:00' },
283
340
  { label: 'Build pipeline', done: true, time: '10:15' },
284
341
  { label: 'Run tests', done: false, time: '10:32' },
285
342
  { label: 'Deploy to npm', done: false },
286
- ]);
343
+ ]));
287
344
  ```
288
345
 
289
346
  ### Loaders & Progress
290
347
 
291
348
  ```ts
292
- import { loader } from 'ansimax';
349
+ import { loader, sleep } from 'ansimax';
293
350
 
294
351
  // Spinner with success/failure
295
352
  const stop = loader.spin('Loading...', { color: '#bd93f9' });
296
- await work();
353
+ await sleep(1500);
297
354
  stop('Done!', true); // ✓ green icon
298
355
 
299
356
  // Animated progress bar
@@ -303,18 +360,22 @@ await loader.progressAnimate(100, 'Downloading', {
303
360
 
304
361
  // Hierarchical tasks with parallel execution
305
362
  await loader.tasks([
306
- { text: 'Build', fn: async () => build(), subtasks: [
307
- { text: 'TypeScript', fn: async () => tsc() },
308
- { text: 'Bundle', fn: async () => bundle() },
309
- ]},
310
- { text: 'Test', fn: async () => test() },
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
  ### Animations
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('Welcome to the deployment wizard...', {
320
381
  speed: 30,
@@ -325,9 +386,9 @@ await animate.fadeIn('Loading complete', { duration: 600 });
325
386
 
326
387
  // Race steps against a timeout — never hang
327
388
  await animate.parallel([
328
- async () => await checkNetwork(),
329
- async () => await checkDatabase(),
330
- async () => await checkAuth(),
389
+ async () => await sleep(500), // simulated network check
390
+ async () => await sleep(700), // simulated database check
391
+ async () => await sleep(400), // simulated auth check
331
392
  ], { timeout: 5000 });
332
393
  ```
333
394
 
@@ -340,7 +401,7 @@ import { themes, createTheme } from 'ansimax';
340
401
 
341
402
  // Built-in themes
342
403
  themes.use('dracula');
343
- themes.primary('hello');
404
+ console.log(themes.primary('hello'));
344
405
 
345
406
  // Listen for changes
346
407
  const off = themes.onChange((newTheme, oldTheme) => {
@@ -350,7 +411,27 @@ const off = themes.onChange((newTheme, oldTheme) => {
350
411
  // Multi-tenant: each instance fully isolated
351
412
  const tenantA = createTheme('nord');
352
413
  const tenantB = createTheme('matrix');
353
- tenantA.register('custom', myDef); // doesn't leak to tenantB
414
+
415
+ // Define a custom theme and register it ONLY in 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 themes include custom?', tenantA.list().includes('custom'));
433
+ console.log('tenantB themes include custom?', tenantB.list().includes('custom'));
434
+ // ↑ false — full isolation
354
435
  ```
355
436
 
356
437
  ---
@@ -421,11 +502,11 @@ const off = onConfigKeyChange('theme', (newTheme, oldTheme) => {
421
502
 
422
503
  // Temporary override + auto-restore on completion or throw
423
504
  await withConfig({ animationSpeed: 'fast' }, async () => {
424
- await runDemo();
505
+ // ...your fast-mode code here...
425
506
  });
426
507
 
427
508
  // Strict mode catches config typos
428
- configure({ unknwnKey: 'x' }, { strict: true }); // throws RangeError
509
+ // configure({ unknwnKey: 'x' }, { strict: true }); // throws RangeError
429
510
  ```
430
511
 
431
512
  ---
@@ -453,9 +534,9 @@ The roadmap intentionally targets — and aims to surpass — gaps that even mat
453
534
  - [x] Arbitrary-angle gradients
454
535
  - [x] Bayer 4×4 dithering for smooth tonal transitions
455
536
  - [x] Single-stop UX (CSS-style behavior)
456
- - [ ] **Animated gradients** (color flow over time, infinite loops)
457
- - [ ] **Gradient interpolation curves** (linear / ease-in / ease-out / cubic-bezier)
458
- - [ ] **Conic gradients** (radial sweep)
537
+ - [x] **Animated gradients** color flow over time with `animateGradient()` (v1.2.0)
538
+ - [x] **Gradient interpolation curves** — `linear` / `ease-in` / `ease-out` / `ease-in-out` / `cubic-bezier` / custom (v1.2.0)
539
+ - [x] **Conic gradients** radial sweep with `style: 'conic'` (v1.2.0)
459
540
 
460
541
  ### 🟡 Phase 3 — ASCII engine
461
542
  - [x] Block fonts (`big`, `small`)
@@ -645,6 +726,35 @@ ansimax/
645
726
 
646
727
  ## 📝 Changelog
647
728
 
729
+ ### v1.2.0 — Phase 2 complete: animated, eased & conic gradients
730
+
731
+ Minor release closing the gradient engine roadmap with three powerful features:
732
+
733
+ - 🌊 **`animateGradient()`** — color flow over time with proper lifecycle (Promise, signal, fps, direction)
734
+ - 📐 **Easing curves** — `linear` / `ease-in` / `ease-out` / `ease-in-out` / `cubic-bezier` / custom functions
735
+ - ⭕ **Conic gradients** — `gradientRect({ style: 'conic', startAngle })` for radial sweeps
736
+
737
+ ```ts
738
+ import { animateGradient } from 'ansimax';
739
+
740
+ const ctrl = animateGradient('Loading...', ['#ff79c6', '#bd93f9', '#8be9fd']);
741
+ await sleep(3000);
742
+ ctrl.stop();
743
+ ```
744
+
745
+ Fully backwards-compatible — every 1.1.x program runs identically.
746
+
747
+ ### v1.1.2 — Maturity & robustness
748
+
749
+ Patch release focused on quality refinements — no API changes.
750
+
751
+ - 🛡️ **`process.setMaxListeners` defensive bump** — prevents `MaxListenersExceededWarning` in HMR / nodemon / ts-node-dev setups where ansimax modules re-register cursor-restore handlers
752
+ - 🧪 **Uniform `TypeError` for theme validation** — `themes.register()` now consistently throws `TypeError` for structural / type errors (was a mix of `Error` and `TypeError`)
753
+ - 🎯 **`themes.use()` throws `RangeError`** for unknown theme names (was `Error`) — better semantic match for "value out of allowed set"
754
+ - 📝 **Cleaner barrel re-exports** — header comment now documents legacy aliases and recommends canonical names
755
+
756
+ Drop-in replacement for `1.1.1`.
757
+
648
758
  ### v1.1.1 — Bug fixes + cleaner examples
649
759
 
650
760
  Patch release fixing two bugs from real-world v1.1.0 testing, plus a refreshed examples folder.
@@ -750,4 +860,4 @@ Ansimax is licensed under the **Apache License, Version 2.0** — a permissive l
750
860
 
751
861
  If Ansimax helps you ship better CLIs, give it a ⭐ on [GitHub](https://github.com/Brashkie/ansimax)!
752
862
 
753
- </div>
863
+ </div>
package/dist/index.d.mts CHANGED
@@ -538,13 +538,84 @@ declare const colorLevel: () => ColorLevel;
538
538
  /** Clear adaptive escape caches. Call after a color level change. */
539
539
  declare const clearColorCache: () => void;
540
540
  declare const compose: (...fns: ColorFn[]) => ColorFn;
541
+ /**
542
+ * Built-in easing curves. Each takes a t in [0, 1] and returns an eased t
543
+ * in [0, 1]. Used for non-linear gradient progression.
544
+ */
545
+ type EasingName = 'linear' | 'ease-in' | 'ease-out' | 'ease-in-out' | 'cubic-bezier';
546
+ type EasingFn = (t: number) => number;
541
547
  declare const stripAnsi: (str: string) => string;
542
548
  interface GradientOptions {
543
549
  /** Skip ANSI escapes in the input instead of overwriting them. */
544
550
  preserveAnsi?: boolean;
551
+ /**
552
+ * Interpolation curve. Default `'linear'`.
553
+ * - `'linear'` — even color distribution
554
+ * - `'ease-in'` — slow start, fast end (concentrates colors at the right)
555
+ * - `'ease-out'` — fast start, slow end (concentrates colors at the left)
556
+ * - `'ease-in-out'` — slow at both ends, fast in middle
557
+ * - `'cubic-bezier'` — CSS-style ease (smooth S-curve)
558
+ * - Or pass a custom `EasingFn` that maps `[0,1] → [0,1]`.
559
+ */
560
+ easing?: EasingName | EasingFn;
561
+ /**
562
+ * Phase offset in `[0, 1)` — shifts the gradient along the text.
563
+ * Use with an animation loop to produce a flowing color effect:
564
+ * `gradient(text, colors, { phase: (Date.now() / 100) % 1 })`
565
+ */
566
+ phase?: number;
545
567
  }
546
568
  declare const gradient: (text: unknown, stops: string[] | null | undefined, opts?: GradientOptions) => string;
547
569
  declare const rainbow: ColorFn;
570
+ interface AnimateGradientOptions {
571
+ /** Total animation duration in ms. Default `2000`. */
572
+ duration?: number;
573
+ /** Frames per second. Default `30`. Capped to `60`. */
574
+ fps?: number;
575
+ /** Loop infinitely. Default `true`. Use `signal` to stop. */
576
+ infinite?: boolean;
577
+ /** Cycle count when `infinite: false`. Default `1`. */
578
+ cycles?: number;
579
+ /** Direction: `'forward'` (default) shifts colors right; `'reverse'` shifts left. */
580
+ direction?: 'forward' | 'reverse';
581
+ /** Easing curve for the gradient itself (not the time progression). */
582
+ easing?: EasingName | EasingFn;
583
+ /** Preserve embedded ANSI escapes. Default `false`. */
584
+ preserveAnsi?: boolean;
585
+ /** Abort signal — stops the animation cleanly. */
586
+ signal?: AbortSignal;
587
+ /**
588
+ * Callback fired on every frame with the new colored string.
589
+ * If omitted, frames are written to stdout via cursor-up redraw.
590
+ */
591
+ onFrame?: (frame: string, phase: number) => void;
592
+ }
593
+ /**
594
+ * Render a gradient that "flows" through the text over time. Returns a
595
+ * controller with a `.stop()` method. When `infinite: true` (default),
596
+ * the animation continues until `.stop()` is called or `signal` aborts.
597
+ *
598
+ * @example
599
+ * ```ts
600
+ * const ctrl = animateGradient('Loading...', ['#ff79c6', '#bd93f9', '#8be9fd']);
601
+ * await sleep(3000);
602
+ * ctrl.stop();
603
+ * ```
604
+ *
605
+ * @example with custom render callback
606
+ * ```ts
607
+ * animateGradient('hi', ['#f00', '#0f0'], {
608
+ * onFrame: (frame) => myCustomRender(frame),
609
+ * });
610
+ * ```
611
+ */
612
+ interface AnimateGradientController {
613
+ /** Stops the animation. Safe to call multiple times. */
614
+ stop: () => void;
615
+ /** Promise that resolves when animation finishes (stop / abort / cycle limit). */
616
+ done: Promise<void>;
617
+ }
618
+ declare const animateGradient: (text: string, stops: string[], opts?: AnimateGradientOptions) => AnimateGradientController;
548
619
  declare const PRESET_DEFS: {
549
620
  readonly sunset: readonly ["#ff6b6b", "#feca57", "#48dbfb"];
550
621
  readonly ocean: readonly ["#0575e6", "#021b79"];
@@ -1408,9 +1479,14 @@ interface GradientRectOptions {
1408
1479
  height?: number;
1409
1480
  colors?: string[];
1410
1481
  /** Built-in style. Use `angle` for arbitrary directions. */
1411
- style?: 'horizontal' | 'vertical' | 'diagonal' | 'radial';
1482
+ style?: 'horizontal' | 'vertical' | 'diagonal' | 'radial' | 'conic';
1412
1483
  /** Custom angle in degrees (0=right, 90=down). Overrides `style`. */
1413
1484
  angle?: number;
1485
+ /**
1486
+ * Starting angle (degrees) for conic gradients. Default `0` (= right of center).
1487
+ * Rotates the radial sweep around the center point.
1488
+ */
1489
+ startAngle?: number;
1414
1490
  /** Dithering algorithm. 'bayer' improves perceived smoothness. */
1415
1491
  dither?: 'none' | 'bayer';
1416
1492
  /** Render in braille mode for 2× horizontal × 4× vertical resolution. */
@@ -1625,4 +1701,4 @@ declare const ansimax: {
1625
1701
  configure: (opts?: AnsimaxConfig, meta?: ConfigureOptions) => void;
1626
1702
  };
1627
1703
 
1628
- export { type AnimationHooks, type AnimationSpeed, type AnsiCode, type AnsimaxConfig, BEL, BG, type BadgeOptions, type BallOptions, type BannerOptions, type BoxOptions, type BoxStyle, type BreatheOptions, DEFAULTS as CONFIG_DEFAULTS, CSI, type Canvas, type CanvasRenderOptions, type ColorChain, type ColorFn, type ColorLevel, type ColorMode, type ColorSupport, type ColumnsOptions, type ConfigChangeListener, type ConfigKey, type ConfigKeyListener, type ConfigureOptions, type CountdownOptions, type CustomOptions, DEFAULT_TERM_COLS, DEFAULT_TERM_ROWS, type DebounceOptions, type DiffType, type Dimensions, type DividerOptions, type DotsOptions, ESC, type EraseMode, FG, FRAME_MS, type FadeOptions, type FontMap, type FontName, type FrameCallback, type FrameHandle, type GlitchOptions, type Glyph, type GradientOptions, type GradientRectOptions, type LineDiff, type LiveController, type LiveOptions, type LoadingBarOptions, type LogoOptions, MENU_CANCELLED, type MemoizeOptions, type MenuInput, type MenuOptions, type MenuOutput, type MenuResult, type MultiLoader, type MultiLoaderItem, OSC, type OnResizeOptions, type OutputBuffer, type ParallelOptions, type ParallelStep, type Pixel, type PixelGrid, type PlayController, type PlayOptions, type PresetName, type ProgressAnimateOptions, type ProgressBarOptions, type ProgressOptions, type PulseOptions, type RGB, type RGBA, type RegisterFontOptions, type RenderOptions, type ResizeListener, type RevealOptions, SPINNERS, SPRITES, ST, STYLE, type SectionOptions, type SleepOptions, type SlideOptions, type SpinOptions, type SpinnerType, type StatusOptions, type StatusType, type StopFn, type StreamOptions, type TableBorderStyle, type TableOptions, type Task, type TaskResult, type TasksOptions, type Theme, type BannerOpts as ThemeBannerOpts, type ThemeChangeListener, type ThemeInstance, type ThemeStyleName, type TimelineEvent, type TimelineOptions, type TreeData, type TreeDimensions, type TreeNode, type RenderOptions$1 as TreeRenderOptions, type TreeStyle, type TypeDeleteOptions, type TypewriterOptions, type WalkVisitor, type WaveOptions, type WriteAsyncOptions, animate, ascii, bell, bg256, bgRgb, box, canAnimate, cancelTerminalFrame, center, chain, charWidth, clamp, clearAnsiCache, clearColorCache, clearRenderCache, clearThemeColorCache, color, colorLevel, presets as colorPresets, components, compose, configure, countNodes, createCanvas, createOutputBuffer, createTheme, cursor, debounce, ansimax as default, diffLines, escapeRegex, fg256, fgRgb, filterTree, findInTree, flipHorizontal, flipVertical, frames, getConfig, getConfigValue, getRenderCacheSize, getSpeedMultiplier, getTerminalHeight, getTerminalWidth, gradient, gradientColor, gradientRect, graphemes, hasFont, hexToRgb, hideCursor, images, isHexColor, isNoColor, lerp, lerpColor, link, listFonts, listPresets, loader, mapTree, measureTree, memoize, nextTick, onConfigChange, onConfigKeyChange, onResize, once, padBoth, padEnd, padStart, pauseListeners, presetNames, rainbow, registerFont, registerPreset, renderPixelArt, renderTree, renderTreeStream, repeatVisible, requestTerminalFrame, reset, resetColorSupportCache, resetConfig, resetCursorRefCount, resetFramesCursorCount, resetLoaderCursorCount, resetNoColor, resumeListeners, rgbTo256, rgbToHex, rotate90, safeJson, screen, setNoColor, setTitle, sgr, showCursor, sleep, sleepFrame, sliceAnsi, stripAnsi$1 as stripAnsi, stripAnsi$2 as stripAnsiCodes, stripAnsi as stripAnsiColors, supportsColor, supportsColorLevel, termSize, themes, throttle, tree, trees, truncateAnsi, visibleLen, walkTree, withConfig, wordWrap, wrapAnsi, write, writeAsync, writeErr, writeln, writelnErr };
1704
+ export { type AnimateGradientController, type AnimateGradientOptions, type AnimationHooks, type AnimationSpeed, type AnsiCode, type AnsimaxConfig, BEL, BG, type BadgeOptions, type BallOptions, type BannerOptions, type BoxOptions, type BoxStyle, type BreatheOptions, DEFAULTS as CONFIG_DEFAULTS, CSI, type Canvas, type CanvasRenderOptions, type ColorChain, type ColorFn, type ColorLevel, type ColorMode, type ColorSupport, type ColumnsOptions, type ConfigChangeListener, type ConfigKey, type ConfigKeyListener, type ConfigureOptions, type CountdownOptions, type CustomOptions, DEFAULT_TERM_COLS, DEFAULT_TERM_ROWS, type DebounceOptions, type DiffType, type Dimensions, type DividerOptions, type DotsOptions, ESC, type EasingFn, type EasingName, type EraseMode, FG, FRAME_MS, type FadeOptions, type FontMap, type FontName, type FrameCallback, type FrameHandle, type GlitchOptions, type Glyph, type GradientOptions, type GradientRectOptions, type LineDiff, type LiveController, type LiveOptions, type LoadingBarOptions, type LogoOptions, MENU_CANCELLED, type MemoizeOptions, type MenuInput, type MenuOptions, type MenuOutput, type MenuResult, type MultiLoader, type MultiLoaderItem, OSC, type OnResizeOptions, type OutputBuffer, type ParallelOptions, type ParallelStep, type Pixel, type PixelGrid, type PlayController, type PlayOptions, type PresetName, type ProgressAnimateOptions, type ProgressBarOptions, type ProgressOptions, type PulseOptions, type RGB, type RGBA, type RegisterFontOptions, type RenderOptions, type ResizeListener, type RevealOptions, SPINNERS, SPRITES, ST, STYLE, type SectionOptions, type SleepOptions, type SlideOptions, type SpinOptions, type SpinnerType, type StatusOptions, type StatusType, type StopFn, type StreamOptions, type TableBorderStyle, type TableOptions, type Task, type TaskResult, type TasksOptions, type Theme, type BannerOpts as ThemeBannerOpts, type ThemeChangeListener, type ThemeInstance, type ThemeStyleName, type TimelineEvent, type TimelineOptions, type TreeData, type TreeDimensions, type TreeNode, type RenderOptions$1 as TreeRenderOptions, type TreeStyle, type TypeDeleteOptions, type TypewriterOptions, type WalkVisitor, type WaveOptions, type WriteAsyncOptions, animate, animateGradient, ascii, bell, bg256, bgRgb, box, canAnimate, cancelTerminalFrame, center, chain, charWidth, clamp, clearAnsiCache, clearColorCache, clearRenderCache, clearThemeColorCache, color, colorLevel, presets as colorPresets, components, compose, configure, countNodes, createCanvas, createOutputBuffer, createTheme, cursor, debounce, ansimax as default, diffLines, escapeRegex, fg256, fgRgb, filterTree, findInTree, flipHorizontal, flipVertical, frames, getConfig, getConfigValue, getRenderCacheSize, getSpeedMultiplier, getTerminalHeight, getTerminalWidth, gradient, gradientColor, gradientRect, graphemes, hasFont, hexToRgb, hideCursor, images, isHexColor, isNoColor, lerp, lerpColor, link, listFonts, listPresets, loader, mapTree, measureTree, memoize, nextTick, onConfigChange, onConfigKeyChange, onResize, once, padBoth, padEnd, padStart, pauseListeners, presetNames, rainbow, registerFont, registerPreset, renderPixelArt, renderTree, renderTreeStream, repeatVisible, requestTerminalFrame, reset, resetColorSupportCache, resetConfig, resetCursorRefCount, resetFramesCursorCount, resetLoaderCursorCount, resetNoColor, resumeListeners, rgbTo256, rgbToHex, rotate90, safeJson, screen, setNoColor, setTitle, sgr, showCursor, sleep, sleepFrame, sliceAnsi, stripAnsi$1 as stripAnsi, stripAnsi$2 as stripAnsiCodes, stripAnsi as stripAnsiColors, supportsColor, supportsColorLevel, termSize, themes, throttle, tree, trees, truncateAnsi, visibleLen, walkTree, withConfig, wordWrap, wrapAnsi, write, writeAsync, writeErr, writeln, writelnErr };
package/dist/index.d.ts CHANGED
@@ -538,13 +538,84 @@ declare const colorLevel: () => ColorLevel;
538
538
  /** Clear adaptive escape caches. Call after a color level change. */
539
539
  declare const clearColorCache: () => void;
540
540
  declare const compose: (...fns: ColorFn[]) => ColorFn;
541
+ /**
542
+ * Built-in easing curves. Each takes a t in [0, 1] and returns an eased t
543
+ * in [0, 1]. Used for non-linear gradient progression.
544
+ */
545
+ type EasingName = 'linear' | 'ease-in' | 'ease-out' | 'ease-in-out' | 'cubic-bezier';
546
+ type EasingFn = (t: number) => number;
541
547
  declare const stripAnsi: (str: string) => string;
542
548
  interface GradientOptions {
543
549
  /** Skip ANSI escapes in the input instead of overwriting them. */
544
550
  preserveAnsi?: boolean;
551
+ /**
552
+ * Interpolation curve. Default `'linear'`.
553
+ * - `'linear'` — even color distribution
554
+ * - `'ease-in'` — slow start, fast end (concentrates colors at the right)
555
+ * - `'ease-out'` — fast start, slow end (concentrates colors at the left)
556
+ * - `'ease-in-out'` — slow at both ends, fast in middle
557
+ * - `'cubic-bezier'` — CSS-style ease (smooth S-curve)
558
+ * - Or pass a custom `EasingFn` that maps `[0,1] → [0,1]`.
559
+ */
560
+ easing?: EasingName | EasingFn;
561
+ /**
562
+ * Phase offset in `[0, 1)` — shifts the gradient along the text.
563
+ * Use with an animation loop to produce a flowing color effect:
564
+ * `gradient(text, colors, { phase: (Date.now() / 100) % 1 })`
565
+ */
566
+ phase?: number;
545
567
  }
546
568
  declare const gradient: (text: unknown, stops: string[] | null | undefined, opts?: GradientOptions) => string;
547
569
  declare const rainbow: ColorFn;
570
+ interface AnimateGradientOptions {
571
+ /** Total animation duration in ms. Default `2000`. */
572
+ duration?: number;
573
+ /** Frames per second. Default `30`. Capped to `60`. */
574
+ fps?: number;
575
+ /** Loop infinitely. Default `true`. Use `signal` to stop. */
576
+ infinite?: boolean;
577
+ /** Cycle count when `infinite: false`. Default `1`. */
578
+ cycles?: number;
579
+ /** Direction: `'forward'` (default) shifts colors right; `'reverse'` shifts left. */
580
+ direction?: 'forward' | 'reverse';
581
+ /** Easing curve for the gradient itself (not the time progression). */
582
+ easing?: EasingName | EasingFn;
583
+ /** Preserve embedded ANSI escapes. Default `false`. */
584
+ preserveAnsi?: boolean;
585
+ /** Abort signal — stops the animation cleanly. */
586
+ signal?: AbortSignal;
587
+ /**
588
+ * Callback fired on every frame with the new colored string.
589
+ * If omitted, frames are written to stdout via cursor-up redraw.
590
+ */
591
+ onFrame?: (frame: string, phase: number) => void;
592
+ }
593
+ /**
594
+ * Render a gradient that "flows" through the text over time. Returns a
595
+ * controller with a `.stop()` method. When `infinite: true` (default),
596
+ * the animation continues until `.stop()` is called or `signal` aborts.
597
+ *
598
+ * @example
599
+ * ```ts
600
+ * const ctrl = animateGradient('Loading...', ['#ff79c6', '#bd93f9', '#8be9fd']);
601
+ * await sleep(3000);
602
+ * ctrl.stop();
603
+ * ```
604
+ *
605
+ * @example with custom render callback
606
+ * ```ts
607
+ * animateGradient('hi', ['#f00', '#0f0'], {
608
+ * onFrame: (frame) => myCustomRender(frame),
609
+ * });
610
+ * ```
611
+ */
612
+ interface AnimateGradientController {
613
+ /** Stops the animation. Safe to call multiple times. */
614
+ stop: () => void;
615
+ /** Promise that resolves when animation finishes (stop / abort / cycle limit). */
616
+ done: Promise<void>;
617
+ }
618
+ declare const animateGradient: (text: string, stops: string[], opts?: AnimateGradientOptions) => AnimateGradientController;
548
619
  declare const PRESET_DEFS: {
549
620
  readonly sunset: readonly ["#ff6b6b", "#feca57", "#48dbfb"];
550
621
  readonly ocean: readonly ["#0575e6", "#021b79"];
@@ -1408,9 +1479,14 @@ interface GradientRectOptions {
1408
1479
  height?: number;
1409
1480
  colors?: string[];
1410
1481
  /** Built-in style. Use `angle` for arbitrary directions. */
1411
- style?: 'horizontal' | 'vertical' | 'diagonal' | 'radial';
1482
+ style?: 'horizontal' | 'vertical' | 'diagonal' | 'radial' | 'conic';
1412
1483
  /** Custom angle in degrees (0=right, 90=down). Overrides `style`. */
1413
1484
  angle?: number;
1485
+ /**
1486
+ * Starting angle (degrees) for conic gradients. Default `0` (= right of center).
1487
+ * Rotates the radial sweep around the center point.
1488
+ */
1489
+ startAngle?: number;
1414
1490
  /** Dithering algorithm. 'bayer' improves perceived smoothness. */
1415
1491
  dither?: 'none' | 'bayer';
1416
1492
  /** Render in braille mode for 2× horizontal × 4× vertical resolution. */
@@ -1625,4 +1701,4 @@ declare const ansimax: {
1625
1701
  configure: (opts?: AnsimaxConfig, meta?: ConfigureOptions) => void;
1626
1702
  };
1627
1703
 
1628
- export { type AnimationHooks, type AnimationSpeed, type AnsiCode, type AnsimaxConfig, BEL, BG, type BadgeOptions, type BallOptions, type BannerOptions, type BoxOptions, type BoxStyle, type BreatheOptions, DEFAULTS as CONFIG_DEFAULTS, CSI, type Canvas, type CanvasRenderOptions, type ColorChain, type ColorFn, type ColorLevel, type ColorMode, type ColorSupport, type ColumnsOptions, type ConfigChangeListener, type ConfigKey, type ConfigKeyListener, type ConfigureOptions, type CountdownOptions, type CustomOptions, DEFAULT_TERM_COLS, DEFAULT_TERM_ROWS, type DebounceOptions, type DiffType, type Dimensions, type DividerOptions, type DotsOptions, ESC, type EraseMode, FG, FRAME_MS, type FadeOptions, type FontMap, type FontName, type FrameCallback, type FrameHandle, type GlitchOptions, type Glyph, type GradientOptions, type GradientRectOptions, type LineDiff, type LiveController, type LiveOptions, type LoadingBarOptions, type LogoOptions, MENU_CANCELLED, type MemoizeOptions, type MenuInput, type MenuOptions, type MenuOutput, type MenuResult, type MultiLoader, type MultiLoaderItem, OSC, type OnResizeOptions, type OutputBuffer, type ParallelOptions, type ParallelStep, type Pixel, type PixelGrid, type PlayController, type PlayOptions, type PresetName, type ProgressAnimateOptions, type ProgressBarOptions, type ProgressOptions, type PulseOptions, type RGB, type RGBA, type RegisterFontOptions, type RenderOptions, type ResizeListener, type RevealOptions, SPINNERS, SPRITES, ST, STYLE, type SectionOptions, type SleepOptions, type SlideOptions, type SpinOptions, type SpinnerType, type StatusOptions, type StatusType, type StopFn, type StreamOptions, type TableBorderStyle, type TableOptions, type Task, type TaskResult, type TasksOptions, type Theme, type BannerOpts as ThemeBannerOpts, type ThemeChangeListener, type ThemeInstance, type ThemeStyleName, type TimelineEvent, type TimelineOptions, type TreeData, type TreeDimensions, type TreeNode, type RenderOptions$1 as TreeRenderOptions, type TreeStyle, type TypeDeleteOptions, type TypewriterOptions, type WalkVisitor, type WaveOptions, type WriteAsyncOptions, animate, ascii, bell, bg256, bgRgb, box, canAnimate, cancelTerminalFrame, center, chain, charWidth, clamp, clearAnsiCache, clearColorCache, clearRenderCache, clearThemeColorCache, color, colorLevel, presets as colorPresets, components, compose, configure, countNodes, createCanvas, createOutputBuffer, createTheme, cursor, debounce, ansimax as default, diffLines, escapeRegex, fg256, fgRgb, filterTree, findInTree, flipHorizontal, flipVertical, frames, getConfig, getConfigValue, getRenderCacheSize, getSpeedMultiplier, getTerminalHeight, getTerminalWidth, gradient, gradientColor, gradientRect, graphemes, hasFont, hexToRgb, hideCursor, images, isHexColor, isNoColor, lerp, lerpColor, link, listFonts, listPresets, loader, mapTree, measureTree, memoize, nextTick, onConfigChange, onConfigKeyChange, onResize, once, padBoth, padEnd, padStart, pauseListeners, presetNames, rainbow, registerFont, registerPreset, renderPixelArt, renderTree, renderTreeStream, repeatVisible, requestTerminalFrame, reset, resetColorSupportCache, resetConfig, resetCursorRefCount, resetFramesCursorCount, resetLoaderCursorCount, resetNoColor, resumeListeners, rgbTo256, rgbToHex, rotate90, safeJson, screen, setNoColor, setTitle, sgr, showCursor, sleep, sleepFrame, sliceAnsi, stripAnsi$1 as stripAnsi, stripAnsi$2 as stripAnsiCodes, stripAnsi as stripAnsiColors, supportsColor, supportsColorLevel, termSize, themes, throttle, tree, trees, truncateAnsi, visibleLen, walkTree, withConfig, wordWrap, wrapAnsi, write, writeAsync, writeErr, writeln, writelnErr };
1704
+ export { type AnimateGradientController, type AnimateGradientOptions, type AnimationHooks, type AnimationSpeed, type AnsiCode, type AnsimaxConfig, BEL, BG, type BadgeOptions, type BallOptions, type BannerOptions, type BoxOptions, type BoxStyle, type BreatheOptions, DEFAULTS as CONFIG_DEFAULTS, CSI, type Canvas, type CanvasRenderOptions, type ColorChain, type ColorFn, type ColorLevel, type ColorMode, type ColorSupport, type ColumnsOptions, type ConfigChangeListener, type ConfigKey, type ConfigKeyListener, type ConfigureOptions, type CountdownOptions, type CustomOptions, DEFAULT_TERM_COLS, DEFAULT_TERM_ROWS, type DebounceOptions, type DiffType, type Dimensions, type DividerOptions, type DotsOptions, ESC, type EasingFn, type EasingName, type EraseMode, FG, FRAME_MS, type FadeOptions, type FontMap, type FontName, type FrameCallback, type FrameHandle, type GlitchOptions, type Glyph, type GradientOptions, type GradientRectOptions, type LineDiff, type LiveController, type LiveOptions, type LoadingBarOptions, type LogoOptions, MENU_CANCELLED, type MemoizeOptions, type MenuInput, type MenuOptions, type MenuOutput, type MenuResult, type MultiLoader, type MultiLoaderItem, OSC, type OnResizeOptions, type OutputBuffer, type ParallelOptions, type ParallelStep, type Pixel, type PixelGrid, type PlayController, type PlayOptions, type PresetName, type ProgressAnimateOptions, type ProgressBarOptions, type ProgressOptions, type PulseOptions, type RGB, type RGBA, type RegisterFontOptions, type RenderOptions, type ResizeListener, type RevealOptions, SPINNERS, SPRITES, ST, STYLE, type SectionOptions, type SleepOptions, type SlideOptions, type SpinOptions, type SpinnerType, type StatusOptions, type StatusType, type StopFn, type StreamOptions, type TableBorderStyle, type TableOptions, type Task, type TaskResult, type TasksOptions, type Theme, type BannerOpts as ThemeBannerOpts, type ThemeChangeListener, type ThemeInstance, type ThemeStyleName, type TimelineEvent, type TimelineOptions, type TreeData, type TreeDimensions, type TreeNode, type RenderOptions$1 as TreeRenderOptions, type TreeStyle, type TypeDeleteOptions, type TypewriterOptions, type WalkVisitor, type WaveOptions, type WriteAsyncOptions, animate, animateGradient, ascii, bell, bg256, bgRgb, box, canAnimate, cancelTerminalFrame, center, chain, charWidth, clamp, clearAnsiCache, clearColorCache, clearRenderCache, clearThemeColorCache, color, colorLevel, presets as colorPresets, components, compose, configure, countNodes, createCanvas, createOutputBuffer, createTheme, cursor, debounce, ansimax as default, diffLines, escapeRegex, fg256, fgRgb, filterTree, findInTree, flipHorizontal, flipVertical, frames, getConfig, getConfigValue, getRenderCacheSize, getSpeedMultiplier, getTerminalHeight, getTerminalWidth, gradient, gradientColor, gradientRect, graphemes, hasFont, hexToRgb, hideCursor, images, isHexColor, isNoColor, lerp, lerpColor, link, listFonts, listPresets, loader, mapTree, measureTree, memoize, nextTick, onConfigChange, onConfigKeyChange, onResize, once, padBoth, padEnd, padStart, pauseListeners, presetNames, rainbow, registerFont, registerPreset, renderPixelArt, renderTree, renderTreeStream, repeatVisible, requestTerminalFrame, reset, resetColorSupportCache, resetConfig, resetCursorRefCount, resetFramesCursorCount, resetLoaderCursorCount, resetNoColor, resumeListeners, rgbTo256, rgbToHex, rotate90, safeJson, screen, setNoColor, setTitle, sgr, showCursor, sleep, sleepFrame, sliceAnsi, stripAnsi$1 as stripAnsi, stripAnsi$2 as stripAnsiCodes, stripAnsi as stripAnsiColors, supportsColor, supportsColorLevel, termSize, themes, throttle, tree, trees, truncateAnsi, visibleLen, walkTree, withConfig, wordWrap, wrapAnsi, write, writeAsync, writeErr, writeln, writelnErr };