asciify-engine 1.0.10 → 1.0.12

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/dist/index.d.cts CHANGED
@@ -251,6 +251,57 @@ declare function renderWaveBackground(ctx: CanvasRenderingContext2D, width: numb
251
251
  x: number;
252
252
  y: number;
253
253
  }, options?: WaveBackgroundOptions): void;
254
+ /**
255
+ * Drop-in helper that mounts an interactive ASCII wave background onto any
256
+ * element. Injects a canvas, wires DPR resize, mouse tracking, and the RAF
257
+ * loop — all internally. Auto-detects light/dark mode and stays in sync if
258
+ * the system theme changes.
259
+ *
260
+ * Returns a `destroy()` function to clean everything up.
261
+ *
262
+ * @example
263
+ * ```ts
264
+ * import { asciiBackground } from 'asciify-engine';
265
+ *
266
+ * // 1 line:
267
+ * const { destroy } = asciiBackground('#hero', { opacity: 0.2 });
268
+ *
269
+ * // Custom color:
270
+ * asciiBackground('#hero', { color: '#6b8700', accentColor: '#d4ff00' });
271
+ *
272
+ * // React — return destroy as cleanup:
273
+ * useEffect(() => asciiBackground(ref.current).destroy, []);
274
+ * ```
275
+ */
276
+ interface AsciiBackgroundOptions extends WaveBackgroundOptions {
277
+ /** CSS opacity applied to the canvas element (default: 0.2) */
278
+ opacity?: number;
279
+ /** Extra CSS class names added to the injected canvas */
280
+ className?: string;
281
+ /** z-index of the canvas (default: 0) */
282
+ zIndex?: number;
283
+ /**
284
+ * Colour scheme handling (default: 'auto').
285
+ * - 'auto' — follows the system prefers-color-scheme and updates live
286
+ * - 'dark' — always render dark-on-dark (bright chars on dark bg)
287
+ * - 'light' — always render dark chars on light background
288
+ */
289
+ colorScheme?: 'auto' | 'light' | 'dark';
290
+ /**
291
+ * Custom character colour. Accepts any CSS colour string: hex, rgb(), hsl().
292
+ * When set, overrides the default white/black colour for the ASCII chars.
293
+ * The accent colour remains separate — use `accentColor` to change it.
294
+ * @example '#6b8700'
295
+ */
296
+ color?: string;
297
+ }
298
+ declare function asciiBackground(target: string | HTMLElement | null, options?: AsciiBackgroundOptions): {
299
+ destroy: () => void;
300
+ };
301
+ /** @deprecated Use `asciiBackground` instead. */
302
+ declare const mountWaveBackground: typeof asciiBackground;
303
+ /** @deprecated Use `AsciiBackgroundOptions` instead. */
304
+ type MountWaveOptions = AsciiBackgroundOptions;
254
305
 
255
306
  interface WebGLRenderer {
256
307
  render(frame: AsciiFrame, options: AsciiOptions, displayW: number, displayH: number, time: number, hoverPos?: {
@@ -269,4 +320,4 @@ interface WebGLRenderer {
269
320
  */
270
321
  declare function tryCreateWebGLRenderer(canvas: HTMLCanvasElement): WebGLRenderer | null;
271
322
 
272
- export { ART_STYLE_PRESETS, type AnimationStyle, type ArtStyle, type AsciiCell, type AsciiFrame, type AsciiOptions, type AsciiResult, type AsciifySimpleOptions, CHARSETS, type CharsetKey, type ColorMode, DEFAULT_OPTIONS, HOVER_PRESETS, type HoverEffect, type HoverPreset, type RenderMode, type SourceType, type WaveBackgroundOptions, type WebGLRenderer, asciify, asciifyGif, asciifyVideo, generateAnimatedEmbedCode, generateEmbedCode, gifToAsciiFrames, imageToAsciiFrame, renderFrameToCanvas, renderWaveBackground, tryCreateWebGLRenderer, videoToAsciiFrames };
323
+ export { ART_STYLE_PRESETS, type AnimationStyle, type ArtStyle, type AsciiBackgroundOptions, type AsciiCell, type AsciiFrame, type AsciiOptions, type AsciiResult, type AsciifySimpleOptions, CHARSETS, type CharsetKey, type ColorMode, DEFAULT_OPTIONS, HOVER_PRESETS, type HoverEffect, type HoverPreset, type MountWaveOptions, type RenderMode, type SourceType, type WaveBackgroundOptions, type WebGLRenderer, asciiBackground, asciify, asciifyGif, asciifyVideo, generateAnimatedEmbedCode, generateEmbedCode, gifToAsciiFrames, imageToAsciiFrame, mountWaveBackground, renderFrameToCanvas, renderWaveBackground, tryCreateWebGLRenderer, videoToAsciiFrames };
package/dist/index.d.ts CHANGED
@@ -251,6 +251,57 @@ declare function renderWaveBackground(ctx: CanvasRenderingContext2D, width: numb
251
251
  x: number;
252
252
  y: number;
253
253
  }, options?: WaveBackgroundOptions): void;
254
+ /**
255
+ * Drop-in helper that mounts an interactive ASCII wave background onto any
256
+ * element. Injects a canvas, wires DPR resize, mouse tracking, and the RAF
257
+ * loop — all internally. Auto-detects light/dark mode and stays in sync if
258
+ * the system theme changes.
259
+ *
260
+ * Returns a `destroy()` function to clean everything up.
261
+ *
262
+ * @example
263
+ * ```ts
264
+ * import { asciiBackground } from 'asciify-engine';
265
+ *
266
+ * // 1 line:
267
+ * const { destroy } = asciiBackground('#hero', { opacity: 0.2 });
268
+ *
269
+ * // Custom color:
270
+ * asciiBackground('#hero', { color: '#6b8700', accentColor: '#d4ff00' });
271
+ *
272
+ * // React — return destroy as cleanup:
273
+ * useEffect(() => asciiBackground(ref.current).destroy, []);
274
+ * ```
275
+ */
276
+ interface AsciiBackgroundOptions extends WaveBackgroundOptions {
277
+ /** CSS opacity applied to the canvas element (default: 0.2) */
278
+ opacity?: number;
279
+ /** Extra CSS class names added to the injected canvas */
280
+ className?: string;
281
+ /** z-index of the canvas (default: 0) */
282
+ zIndex?: number;
283
+ /**
284
+ * Colour scheme handling (default: 'auto').
285
+ * - 'auto' — follows the system prefers-color-scheme and updates live
286
+ * - 'dark' — always render dark-on-dark (bright chars on dark bg)
287
+ * - 'light' — always render dark chars on light background
288
+ */
289
+ colorScheme?: 'auto' | 'light' | 'dark';
290
+ /**
291
+ * Custom character colour. Accepts any CSS colour string: hex, rgb(), hsl().
292
+ * When set, overrides the default white/black colour for the ASCII chars.
293
+ * The accent colour remains separate — use `accentColor` to change it.
294
+ * @example '#6b8700'
295
+ */
296
+ color?: string;
297
+ }
298
+ declare function asciiBackground(target: string | HTMLElement | null, options?: AsciiBackgroundOptions): {
299
+ destroy: () => void;
300
+ };
301
+ /** @deprecated Use `asciiBackground` instead. */
302
+ declare const mountWaveBackground: typeof asciiBackground;
303
+ /** @deprecated Use `AsciiBackgroundOptions` instead. */
304
+ type MountWaveOptions = AsciiBackgroundOptions;
254
305
 
255
306
  interface WebGLRenderer {
256
307
  render(frame: AsciiFrame, options: AsciiOptions, displayW: number, displayH: number, time: number, hoverPos?: {
@@ -269,4 +320,4 @@ interface WebGLRenderer {
269
320
  */
270
321
  declare function tryCreateWebGLRenderer(canvas: HTMLCanvasElement): WebGLRenderer | null;
271
322
 
272
- export { ART_STYLE_PRESETS, type AnimationStyle, type ArtStyle, type AsciiCell, type AsciiFrame, type AsciiOptions, type AsciiResult, type AsciifySimpleOptions, CHARSETS, type CharsetKey, type ColorMode, DEFAULT_OPTIONS, HOVER_PRESETS, type HoverEffect, type HoverPreset, type RenderMode, type SourceType, type WaveBackgroundOptions, type WebGLRenderer, asciify, asciifyGif, asciifyVideo, generateAnimatedEmbedCode, generateEmbedCode, gifToAsciiFrames, imageToAsciiFrame, renderFrameToCanvas, renderWaveBackground, tryCreateWebGLRenderer, videoToAsciiFrames };
323
+ export { ART_STYLE_PRESETS, type AnimationStyle, type ArtStyle, type AsciiBackgroundOptions, type AsciiCell, type AsciiFrame, type AsciiOptions, type AsciiResult, type AsciifySimpleOptions, CHARSETS, type CharsetKey, type ColorMode, DEFAULT_OPTIONS, HOVER_PRESETS, type HoverEffect, type HoverPreset, type MountWaveOptions, type RenderMode, type SourceType, type WaveBackgroundOptions, type WebGLRenderer, asciiBackground, asciify, asciifyGif, asciifyVideo, generateAnimatedEmbedCode, generateEmbedCode, gifToAsciiFrames, imageToAsciiFrame, mountWaveBackground, renderFrameToCanvas, renderWaveBackground, tryCreateWebGLRenderer, videoToAsciiFrames };
package/dist/index.js CHANGED
@@ -830,7 +830,7 @@ async function asciifyVideo(source, canvas, { fontSize = 10, style = "classic",
830
830
  cancelAnimationFrame(animId);
831
831
  };
832
832
  }
833
- var EMBED_CDN_VERSION = "1.0.10";
833
+ var EMBED_CDN_VERSION = "1.0.12";
834
834
  function buildEmbedOpts(options, rows, cols, width, height, fps, animated) {
835
835
  const o = {
836
836
  r: rows,
@@ -997,6 +997,107 @@ function renderWaveBackground(ctx, width, height, time, mousePos = { x: 0.5, y:
997
997
  }
998
998
  }
999
999
  }
1000
+ function _parseColor(c) {
1001
+ const hex = c.match(/^#([0-9a-f]{3,8})$/i)?.[1];
1002
+ if (hex) {
1003
+ const h = hex.length <= 4 ? hex.split("").map((x) => parseInt(x + x, 16)) : [parseInt(hex.slice(0, 2), 16), parseInt(hex.slice(2, 4), 16), parseInt(hex.slice(4, 6), 16)];
1004
+ return { r: h[0], g: h[1], b: h[2] };
1005
+ }
1006
+ const rgb = c.match(/rgba?\(\s*(\d+)[,\s]+(\d+)[,\s]+(\d+)/i);
1007
+ if (rgb) return { r: +rgb[1], g: +rgb[2], b: +rgb[3] };
1008
+ return null;
1009
+ }
1010
+ function asciiBackground(target, options = {}) {
1011
+ const {
1012
+ opacity = 0.2,
1013
+ className,
1014
+ zIndex = 0,
1015
+ colorScheme = "auto",
1016
+ color,
1017
+ ...renderOpts
1018
+ } = options;
1019
+ const container = typeof target === "string" ? document.querySelector(target) : target;
1020
+ if (!container) {
1021
+ console.warn("[asciify] asciiBackground: target not found", target);
1022
+ return { destroy: () => {
1023
+ } };
1024
+ }
1025
+ const prevPosition = container.style.position;
1026
+ if (getComputedStyle(container).position === "static") {
1027
+ container.style.position = "relative";
1028
+ }
1029
+ const canvas = document.createElement("canvas");
1030
+ canvas.style.cssText = [
1031
+ "position:absolute",
1032
+ "inset:0",
1033
+ "width:100%",
1034
+ "height:100%",
1035
+ `opacity:${opacity}`,
1036
+ "pointer-events:none",
1037
+ `z-index:${zIndex}`
1038
+ ].join(";");
1039
+ if (className) canvas.className = className;
1040
+ container.prepend(canvas);
1041
+ const ctx = canvas.getContext("2d");
1042
+ const dpr = window.devicePixelRatio || 1;
1043
+ const mouse = { x: 0.5, y: 0.5 };
1044
+ const smoothMouse = { x: 0.5, y: 0.5 };
1045
+ const mq = window.matchMedia("(prefers-color-scheme: light)");
1046
+ const isLight = () => {
1047
+ if (colorScheme === "light") return true;
1048
+ if (colorScheme === "dark") return false;
1049
+ return mq.matches;
1050
+ };
1051
+ let parsedColor = null;
1052
+ if (color) parsedColor = _parseColor(color);
1053
+ const buildOpts = () => ({
1054
+ ...renderOpts,
1055
+ lightMode: renderOpts.lightMode !== void 0 ? renderOpts.lightMode : isLight(),
1056
+ baseColor: parsedColor ? `rgba(${parsedColor.r},${parsedColor.g},${parsedColor.b},{a})` : renderOpts.baseColor
1057
+ });
1058
+ const optsRef = { current: buildOpts() };
1059
+ const onSchemeChange = () => {
1060
+ optsRef.current = buildOpts();
1061
+ };
1062
+ if (colorScheme === "auto") mq.addEventListener("change", onSchemeChange);
1063
+ const resize = () => {
1064
+ const r = container.getBoundingClientRect();
1065
+ canvas.width = r.width * dpr;
1066
+ canvas.height = r.height * dpr;
1067
+ ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
1068
+ };
1069
+ resize();
1070
+ const onMouseMove = (e) => {
1071
+ const r = container.getBoundingClientRect();
1072
+ mouse.x = (e.clientX - r.left) / r.width;
1073
+ mouse.y = (e.clientY - r.top) / r.height;
1074
+ };
1075
+ const ro = new ResizeObserver(resize);
1076
+ ro.observe(container);
1077
+ window.addEventListener("mousemove", onMouseMove);
1078
+ let time = 0;
1079
+ let raf = 0;
1080
+ const tick = () => {
1081
+ smoothMouse.x += (mouse.x - smoothMouse.x) * 0.07;
1082
+ smoothMouse.y += (mouse.y - smoothMouse.y) * 0.07;
1083
+ const r = container.getBoundingClientRect();
1084
+ renderWaveBackground(ctx, r.width, r.height, time, smoothMouse, optsRef.current);
1085
+ time += 0.016;
1086
+ raf = requestAnimationFrame(tick);
1087
+ };
1088
+ raf = requestAnimationFrame(tick);
1089
+ return {
1090
+ destroy: () => {
1091
+ cancelAnimationFrame(raf);
1092
+ ro.disconnect();
1093
+ if (colorScheme === "auto") mq.removeEventListener("change", onSchemeChange);
1094
+ window.removeEventListener("mousemove", onMouseMove);
1095
+ canvas.remove();
1096
+ container.style.position = prevPosition;
1097
+ }
1098
+ };
1099
+ }
1100
+ var mountWaveBackground = asciiBackground;
1000
1101
 
1001
1102
  // src/webgl-engine.ts
1002
1103
  var VERT_SRC = (
@@ -1446,6 +1547,6 @@ function tryCreateWebGLRenderer(canvas) {
1446
1547
  }
1447
1548
  }
1448
1549
 
1449
- export { ART_STYLE_PRESETS, CHARSETS, DEFAULT_OPTIONS, HOVER_PRESETS, asciify, asciifyGif, asciifyVideo, generateAnimatedEmbedCode, generateEmbedCode, gifToAsciiFrames, imageToAsciiFrame, renderFrameToCanvas, renderWaveBackground, tryCreateWebGLRenderer, videoToAsciiFrames };
1550
+ export { ART_STYLE_PRESETS, CHARSETS, DEFAULT_OPTIONS, HOVER_PRESETS, asciiBackground, asciify, asciifyGif, asciifyVideo, generateAnimatedEmbedCode, generateEmbedCode, gifToAsciiFrames, imageToAsciiFrame, mountWaveBackground, renderFrameToCanvas, renderWaveBackground, tryCreateWebGLRenderer, videoToAsciiFrames };
1450
1551
  //# sourceMappingURL=index.js.map
1451
1552
  //# sourceMappingURL=index.js.map