@socketsecurity/lib 3.0.4 → 3.0.5

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 CHANGED
@@ -5,6 +5,45 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [3.0.5](https://github.com/SocketDev/socket-lib/releases/tag/v3.0.5) - 2025-11-01
9
+
10
+ ### Fixed
11
+
12
+ - **Critical: Prompts API breaking changes**: Restored working prompts implementation that was accidentally replaced with non-functional stub in v3.0.0
13
+ - Consolidated all prompts functionality into `src/stdio/prompts.ts`
14
+ - Removed unimplemented stub from `src/prompts/` that was throwing "not yet implemented" errors
15
+ - Removed `./prompts` package export (use `@socketsecurity/lib/stdio/prompts` instead)
16
+ - Restored missing exports: `password`, `search`, `Separator`, and added `createSeparator()` helper
17
+ - Fixed `Choice` type to use correct `name` property (matching `@inquirer` API, not erroneous `label`)
18
+
19
+ ### Added
20
+
21
+ - **Theme integration for prompts**: Prompts now automatically use the active theme colors
22
+ - Prompt messages styled with `colors.prompt`
23
+ - Descriptions and disabled items styled with `colors.textDim`
24
+ - Answers and highlights styled with `colors.primary`
25
+ - Error messages styled with `colors.error`
26
+ - Success indicators styled with `colors.success`
27
+ - Exported `createInquirerTheme()` function for converting Socket themes to @inquirer format
28
+ - Consistent visual experience with Logger and Spinner theme integration
29
+
30
+ - **Theme parameter support**: Logger, Prompts, and text effects now accept optional `theme` parameter
31
+ - Pass theme names (`'socket'`, `'sunset'`, `'terracotta'`, `'lush'`, `'ultra'`) or Theme objects
32
+ - **Logger**: `new Logger({ theme: 'sunset' })` - uses theme-specific symbol colors
33
+ - **Prompts**: `await input({ message: 'Name:', theme: 'ultra' })` - uses theme for prompt styling
34
+ - **Text effects**: `applyShimmer(text, state, { theme: 'terracotta' })` - uses theme for shimmer colors
35
+ - Instance-specific themes override global theme context when provided
36
+ - Falls back to global theme context when no instance theme specified
37
+ - **Note**: Spinner already had theme parameter support in v3.0.0
38
+
39
+ ### Removed
40
+
41
+ - **Unused index entrypoint**: Removed `src/index.ts` and package exports for `"."` and `"./index"`
42
+ - This was a leftover from socket-registry and not needed for this library
43
+ - Users should import specific modules directly (e.g., `@socketsecurity/lib/logger`)
44
+ - Breaking: `import { getDefaultLogger } from '@socketsecurity/lib'` no longer works
45
+ - Use: `import { getDefaultLogger } from '@socketsecurity/lib/logger'` instead
46
+
8
47
  ## [3.0.4](https://github.com/SocketDev/socket-lib/releases/tag/v3.0.4) - 2025-11-01
9
48
 
10
49
  ### Changed
@@ -6,6 +6,13 @@
6
6
  export type SocketFramesOptions = {
7
7
  readonly baseColor?: readonly [number, number, number] | undefined;
8
8
  readonly interval?: number | undefined;
9
+ /**
10
+ * Theme to use for pulse colors.
11
+ * Can be a theme name ('socket', 'sunset', etc.) or a Theme object.
12
+ * Note: Currently frames only contain brightness modifiers.
13
+ * Colors are applied by yocto-spinner based on spinner.color.
14
+ */
15
+ readonly theme?: import('../themes/types').Theme | import('../themes/themes').ThemeName | undefined;
9
16
  };
10
17
  /**
11
18
  * Generate Socket pulse animation frames.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/effects/pulse-frames.ts"],
4
- "sourcesContent": ["/**\n * @fileoverview Socket pulse animation frames generator.\n * Generates themeable pulsing animation frames using sparkles (\u2727 \u2726) and lightning (\u26A1).\n * Follows the cli-spinners format: https://github.com/sindresorhus/cli-spinners\n */\n\nexport type SocketFramesOptions = {\n readonly baseColor?: readonly [number, number, number] | undefined\n readonly interval?: number | undefined\n}\n\n/**\n * Generate Socket pulse animation frames.\n * Creates a pulsing throbber using Unicode sparkles and lightning symbols.\n * Frames use brightness modifiers (bold/dim) but no embedded colors.\n * Yocto-spinner applies the current spinner color to each frame.\n *\n * Returns a spinner definition compatible with cli-spinners format.\n *\n * @see https://github.com/sindresorhus/cli-spinners/blob/main/spinners.json\n */\nexport function generateSocketSpinnerFrames(\n options?: SocketFramesOptions | undefined,\n): {\n frames: string[]\n interval: number\n} {\n const opts = { __proto__: null, ...options } as SocketFramesOptions\n const interval = opts.interval ?? 50\n\n // ANSI codes for brightness modifiers only (no colors).\n // Yocto-spinner will apply the spinner's current color to each frame.\n const bold = '\\x1b[1m'\n const dim = '\\x1b[2m'\n const reset = '\\x1b[0m'\n\n // Using VS15 (\\uFE0E) to force text-style rendering.\n // Lightning bolt (\u26A1) is wider than stars. To keep consistent spacing:\n // - All frames have NO internal padding\n // - Yocto-spinner adds 1 space after each frame\n // - Success/fail symbols also get 1 space (consistent)\n const lightning = '\u26A1\\uFE0E'\n const starFilled = '\u2726\\uFE0E'\n const starOutline = '\u2727\\uFE0E'\n const starTiny = '\u22C6\\uFE0E'\n\n // Pulse frames with brightness modifiers only.\n // Each frame gets colored by yocto-spinner based on current spinner.color.\n // Yocto-spinner adds 1 space after the frame automatically.\n const frames = [\n // Build up from dim to bright\n `${dim}${starOutline}${reset}`,\n `${dim}${starOutline}${reset}`,\n `${dim}${starTiny}${reset}`,\n `${starFilled}${reset}`,\n `${starFilled}${reset}`,\n `${bold}${starFilled}${reset}`,\n `${bold}${starFilled}${reset}`,\n `${bold}${lightning}${reset}`,\n `${bold}${lightning}${reset}`,\n `${bold}${lightning}${reset}`,\n // Fade down\n `${bold}${lightning}${reset}`,\n `${bold}${lightning}${reset}`,\n `${bold}${starFilled}${reset}`,\n `${bold}${starFilled}${reset}`,\n `${starFilled}${reset}`,\n `${starFilled}${reset}`,\n `${dim}${starTiny}${reset}`,\n `${dim}${starOutline}${reset}`,\n ]\n\n return {\n __proto__: null,\n frames,\n interval,\n } as { frames: string[]; interval: number }\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAqBO,SAAS,4BACd,SAIA;AACA,QAAM,OAAO,EAAE,WAAW,MAAM,GAAG,QAAQ;AAC3C,QAAM,WAAW,KAAK,YAAY;AAIlC,QAAM,OAAO;AACb,QAAM,MAAM;AACZ,QAAM,QAAQ;AAOd,QAAM,YAAY;AAClB,QAAM,aAAa;AACnB,QAAM,cAAc;AACpB,QAAM,WAAW;AAKjB,QAAM,SAAS;AAAA;AAAA,IAEb,GAAG,GAAG,GAAG,WAAW,GAAG,KAAK;AAAA,IAC5B,GAAG,GAAG,GAAG,WAAW,GAAG,KAAK;AAAA,IAC5B,GAAG,GAAG,GAAG,QAAQ,GAAG,KAAK;AAAA,IACzB,GAAG,UAAU,GAAG,KAAK;AAAA,IACrB,GAAG,UAAU,GAAG,KAAK;AAAA,IACrB,GAAG,IAAI,GAAG,UAAU,GAAG,KAAK;AAAA,IAC5B,GAAG,IAAI,GAAG,UAAU,GAAG,KAAK;AAAA,IAC5B,GAAG,IAAI,GAAG,SAAS,GAAG,KAAK;AAAA,IAC3B,GAAG,IAAI,GAAG,SAAS,GAAG,KAAK;AAAA,IAC3B,GAAG,IAAI,GAAG,SAAS,GAAG,KAAK;AAAA;AAAA,IAE3B,GAAG,IAAI,GAAG,SAAS,GAAG,KAAK;AAAA,IAC3B,GAAG,IAAI,GAAG,SAAS,GAAG,KAAK;AAAA,IAC3B,GAAG,IAAI,GAAG,UAAU,GAAG,KAAK;AAAA,IAC5B,GAAG,IAAI,GAAG,UAAU,GAAG,KAAK;AAAA,IAC5B,GAAG,UAAU,GAAG,KAAK;AAAA,IACrB,GAAG,UAAU,GAAG,KAAK;AAAA,IACrB,GAAG,GAAG,GAAG,QAAQ,GAAG,KAAK;AAAA,IACzB,GAAG,GAAG,GAAG,WAAW,GAAG,KAAK;AAAA,EAC9B;AAEA,SAAO;AAAA,IACL,WAAW;AAAA,IACX;AAAA,IACA;AAAA,EACF;AACF;",
4
+ "sourcesContent": ["/**\n * @fileoverview Socket pulse animation frames generator.\n * Generates themeable pulsing animation frames using sparkles (\u2727 \u2726) and lightning (\u26A1).\n * Follows the cli-spinners format: https://github.com/sindresorhus/cli-spinners\n */\n\nexport type SocketFramesOptions = {\n readonly baseColor?: readonly [number, number, number] | undefined\n readonly interval?: number | undefined\n /**\n * Theme to use for pulse colors.\n * Can be a theme name ('socket', 'sunset', etc.) or a Theme object.\n * Note: Currently frames only contain brightness modifiers.\n * Colors are applied by yocto-spinner based on spinner.color.\n */\n readonly theme?:\n | import('../themes/types').Theme\n | import('../themes/themes').ThemeName\n | undefined\n}\n\n/**\n * Generate Socket pulse animation frames.\n * Creates a pulsing throbber using Unicode sparkles and lightning symbols.\n * Frames use brightness modifiers (bold/dim) but no embedded colors.\n * Yocto-spinner applies the current spinner color to each frame.\n *\n * Returns a spinner definition compatible with cli-spinners format.\n *\n * @see https://github.com/sindresorhus/cli-spinners/blob/main/spinners.json\n */\nexport function generateSocketSpinnerFrames(\n options?: SocketFramesOptions | undefined,\n): {\n frames: string[]\n interval: number\n} {\n const opts = { __proto__: null, ...options } as SocketFramesOptions\n const interval = opts.interval ?? 50\n\n // ANSI codes for brightness modifiers only (no colors).\n // Yocto-spinner will apply the spinner's current color to each frame.\n const bold = '\\x1b[1m'\n const dim = '\\x1b[2m'\n const reset = '\\x1b[0m'\n\n // Using VS15 (\\uFE0E) to force text-style rendering.\n // Lightning bolt (\u26A1) is wider than stars. To keep consistent spacing:\n // - All frames have NO internal padding\n // - Yocto-spinner adds 1 space after each frame\n // - Success/fail symbols also get 1 space (consistent)\n const lightning = '\u26A1\\uFE0E'\n const starFilled = '\u2726\\uFE0E'\n const starOutline = '\u2727\\uFE0E'\n const starTiny = '\u22C6\\uFE0E'\n\n // Pulse frames with brightness modifiers only.\n // Each frame gets colored by yocto-spinner based on current spinner.color.\n // Yocto-spinner adds 1 space after the frame automatically.\n const frames = [\n // Build up from dim to bright\n `${dim}${starOutline}${reset}`,\n `${dim}${starOutline}${reset}`,\n `${dim}${starTiny}${reset}`,\n `${starFilled}${reset}`,\n `${starFilled}${reset}`,\n `${bold}${starFilled}${reset}`,\n `${bold}${starFilled}${reset}`,\n `${bold}${lightning}${reset}`,\n `${bold}${lightning}${reset}`,\n `${bold}${lightning}${reset}`,\n // Fade down\n `${bold}${lightning}${reset}`,\n `${bold}${lightning}${reset}`,\n `${bold}${starFilled}${reset}`,\n `${bold}${starFilled}${reset}`,\n `${starFilled}${reset}`,\n `${starFilled}${reset}`,\n `${dim}${starTiny}${reset}`,\n `${dim}${starOutline}${reset}`,\n ]\n\n return {\n __proto__: null,\n frames,\n interval,\n } as { frames: string[]; interval: number }\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA+BO,SAAS,4BACd,SAIA;AACA,QAAM,OAAO,EAAE,WAAW,MAAM,GAAG,QAAQ;AAC3C,QAAM,WAAW,KAAK,YAAY;AAIlC,QAAM,OAAO;AACb,QAAM,MAAM;AACZ,QAAM,QAAQ;AAOd,QAAM,YAAY;AAClB,QAAM,aAAa;AACnB,QAAM,cAAc;AACpB,QAAM,WAAW;AAKjB,QAAM,SAAS;AAAA;AAAA,IAEb,GAAG,GAAG,GAAG,WAAW,GAAG,KAAK;AAAA,IAC5B,GAAG,GAAG,GAAG,WAAW,GAAG,KAAK;AAAA,IAC5B,GAAG,GAAG,GAAG,QAAQ,GAAG,KAAK;AAAA,IACzB,GAAG,UAAU,GAAG,KAAK;AAAA,IACrB,GAAG,UAAU,GAAG,KAAK;AAAA,IACrB,GAAG,IAAI,GAAG,UAAU,GAAG,KAAK;AAAA,IAC5B,GAAG,IAAI,GAAG,UAAU,GAAG,KAAK;AAAA,IAC5B,GAAG,IAAI,GAAG,SAAS,GAAG,KAAK;AAAA,IAC3B,GAAG,IAAI,GAAG,SAAS,GAAG,KAAK;AAAA,IAC3B,GAAG,IAAI,GAAG,SAAS,GAAG,KAAK;AAAA;AAAA,IAE3B,GAAG,IAAI,GAAG,SAAS,GAAG,KAAK;AAAA,IAC3B,GAAG,IAAI,GAAG,SAAS,GAAG,KAAK;AAAA,IAC3B,GAAG,IAAI,GAAG,UAAU,GAAG,KAAK;AAAA,IAC5B,GAAG,IAAI,GAAG,UAAU,GAAG,KAAK;AAAA,IAC5B,GAAG,UAAU,GAAG,KAAK;AAAA,IACrB,GAAG,UAAU,GAAG,KAAK;AAAA,IACrB,GAAG,GAAG,GAAG,QAAQ,GAAG,KAAK;AAAA,IACzB,GAAG,GAAG,GAAG,WAAW,GAAG,KAAK;AAAA,EAC9B;AAEA,SAAO;AAAA,IACL,WAAW;AAAA,IACX;AAAA,IACA;AAAA,EACF;AACF;",
6
6
  "names": []
7
7
  }
@@ -17,6 +17,7 @@ type ShimmerOptions = {
17
17
  readonly direction?: ShimmerDirection | undefined;
18
18
  readonly shimmerWidth?: number | undefined;
19
19
  readonly styles?: TextStyles | undefined;
20
+ readonly theme?: import('../themes/types').Theme | import('../themes/themes').ThemeName | undefined;
20
21
  };
21
22
  export declare const COLOR_INHERIT = "inherit";
22
23
  export declare const DIR_LTR = "ltr";
@@ -30,6 +30,8 @@ module.exports = __toCommonJS(text_shimmer_exports);
30
30
  var import_ansi = require("../ansi");
31
31
  var import_arrays = require("../arrays");
32
32
  var import_ci = require("#env/ci");
33
+ var import_utils = require("../themes/utils");
34
+ var import_themes = require("../themes/themes");
33
35
  function detectStyles(text) {
34
36
  return {
35
37
  __proto__: null,
@@ -121,7 +123,17 @@ function applyShimmer(text, state, options) {
121
123
  const opts = { __proto__: null, ...options };
122
124
  const direction = opts.direction ?? DIR_NONE;
123
125
  const shimmerWidth = opts.shimmerWidth ?? 2.5;
124
- const color = opts.color ?? [140, 82, 255];
126
+ let color;
127
+ if (opts.theme) {
128
+ const theme = typeof opts.theme === "string" ? import_themes.THEMES[opts.theme] : opts.theme;
129
+ const themeColor = (0, import_utils.resolveColor)(
130
+ theme.colors.primary,
131
+ theme.colors
132
+ );
133
+ color = typeof themeColor === "string" ? [140, 82, 255] : themeColor;
134
+ } else {
135
+ color = opts.color ?? [140, 82, 255];
136
+ }
125
137
  const styles = opts.styles ?? detectStyles(text);
126
138
  const plainText = (0, import_ansi.stripAnsi)(text);
127
139
  if ((0, import_ci.getCI)() || !plainText || direction === DIR_NONE) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/effects/text-shimmer.ts"],
4
- "sourcesContent": ["/**\n * @fileoverview Text shimmer animation utilities.\n * Provides animated highlight effects for spinner text with configurable directions:\n * - LTR (left-to-right): Shimmer wave moves from left to right\n * - RTL (right-to-left): Shimmer wave moves from right to left\n * - Bidirectional: Alternates between LTR and RTL each cycle\n * - Random: Picks a random direction each cycle\n * - None: No shimmer animation\n *\n * The shimmer effect creates a bright wave that travels across the text,\n * with characters near the wave appearing nearly white and fading to the\n * base color as they get further from the wave position.\n */\n\nimport { ANSI_RESET, stripAnsi } from '../ansi'\nimport { isArray } from '../arrays'\nimport { getCI } from '#env/ci'\n\nimport type {\n ShimmerColorGradient,\n ShimmerColorRgb,\n ShimmerDirection,\n ShimmerState,\n} from './types'\n\n// Re-export types for backward compatibility.\nexport type {\n ShimmerColor,\n ShimmerColorGradient,\n ShimmerColorInherit,\n ShimmerColorRgb,\n ShimmerConfig,\n ShimmerDirection,\n ShimmerState,\n} from './types'\n\n/**\n * Detected text formatting styles from ANSI codes.\n */\ntype TextStyles = {\n bold: boolean\n dim: boolean\n italic: boolean\n strikethrough: boolean\n underline: boolean\n}\n\n/**\n * Detect all text formatting styles present in ANSI-coded text.\n * Checks for bold, dim, italic, underline, and strikethrough.\n */\nfunction detectStyles(text: string): TextStyles {\n return {\n __proto__: null,\n // biome-ignore lint/suspicious/noControlCharactersInRegex: ANSI escape sequence detection.\n bold: /\\x1b\\[1m/.test(text),\n // biome-ignore lint/suspicious/noControlCharactersInRegex: ANSI escape sequence detection.\n dim: /\\x1b\\[2m/.test(text),\n // biome-ignore lint/suspicious/noControlCharactersInRegex: ANSI escape sequence detection.\n italic: /\\x1b\\[3m/.test(text),\n // biome-ignore lint/suspicious/noControlCharactersInRegex: ANSI escape sequence detection.\n strikethrough: /\\x1b\\[9m/.test(text),\n // biome-ignore lint/suspicious/noControlCharactersInRegex: ANSI escape sequence detection.\n underline: /\\x1b\\[4m/.test(text),\n } as TextStyles\n}\n\n/**\n * Build ANSI code string from text styles.\n * Returns the concatenated ANSI codes needed to apply the styles.\n */\nfunction stylesToAnsi(styles: TextStyles): string {\n let codes = ''\n if (styles.bold) {\n codes += '\\x1b[1m'\n }\n if (styles.dim) {\n codes += '\\x1b[2m'\n }\n if (styles.italic) {\n codes += '\\x1b[3m'\n }\n if (styles.underline) {\n codes += '\\x1b[4m'\n }\n if (styles.strikethrough) {\n codes += '\\x1b[9m'\n }\n return codes\n}\n\n// Internal options for applyShimmer function.\ntype ShimmerOptions = {\n readonly color?: ShimmerColorRgb | ShimmerColorGradient | undefined\n readonly direction?: ShimmerDirection | undefined\n readonly shimmerWidth?: number | undefined\n readonly styles?: TextStyles | undefined\n}\n\nexport const COLOR_INHERIT = 'inherit'\n\nexport const DIR_LTR = 'ltr'\n\nexport const DIR_NONE = 'none'\n\nexport const DIR_RANDOM = 'random'\n\nexport const DIR_RTL = 'rtl'\n\nexport const MODE_BI = 'bi'\n\n/**\n * Calculate shimmer intensity based on distance from shimmer wave position.\n * Uses a power curve for smooth falloff - characters close to the wave\n * get high intensity (bright white), while distant characters get 0.\n */\nfunction shimmerIntensity(\n distance: number,\n shimmerWidth: number = 2.5,\n): number {\n // Characters beyond shimmer width get no effect.\n if (distance > shimmerWidth) {\n return 0\n }\n // Smooth falloff using power curve.\n const normalized = distance / shimmerWidth\n return (1 - normalized) ** 2.5\n}\n\n/**\n * Blend two RGB colors based on a blend factor (0-1).\n * factor 0 = color1, factor 1 = color2, factor 0.5 = 50/50 blend.\n */\nfunction blendColors(\n color1: readonly [number, number, number],\n color2: readonly [number, number, number],\n factor: number,\n): readonly [number, number, number] {\n const r = Math.round(color1[0] + (color2[0] - color1[0]) * factor)\n const g = Math.round(color1[1] + (color2[1] - color1[1]) * factor)\n const b = Math.round(color1[2] + (color2[2] - color1[2]) * factor)\n return [r, g, b] as const\n}\n\n/**\n * Render character with shimmer effect based on distance from shimmer position.\n * Characters closer to the shimmer position get brighter (nearly white),\n * while characters further away use the base color.\n * Creates a smooth gradient by blending base color with white based on intensity.\n * Supports both single color and per-character color gradients.\n */\nfunction renderChar(\n char: string,\n index: number,\n shimmerPos: number,\n baseColor: readonly [number, number, number] | ShimmerColorGradient,\n styles: TextStyles,\n): string {\n // Calculate how far this character is from the shimmer wave.\n const distance = Math.abs(index - shimmerPos)\n const intensity = shimmerIntensity(distance)\n\n const styleCode = stylesToAnsi(styles)\n\n // Get base color for this character (single or per-character from gradient).\n const charColor: readonly [number, number, number] = isArray(baseColor[0])\n ? ((baseColor as ShimmerColorGradient)[index % baseColor.length] ?? [\n 140, 82, 255,\n ])\n : (baseColor as readonly [number, number, number])\n\n // If no shimmer intensity, use base color as-is.\n if (intensity === 0) {\n const base = `\\x1b[38;2;${charColor[0]};${charColor[1]};${charColor[2]}m`\n return `${styleCode}${base}${char}${ANSI_RESET}`\n }\n\n // Blend base color with white based on intensity to create smooth gradient.\n // Higher intensity = more white, creating the shimmer wave effect.\n const white: readonly [number, number, number] = [255, 255, 255] as const\n const blended = blendColors(charColor, white, intensity)\n\n const color = `\\x1b[38;2;${blended[0]};${blended[1]};${blended[2]}m`\n return `${styleCode}${color}${char}${ANSI_RESET}`\n}\n\n/**\n * Calculate shimmer wave position for current animation step.\n * The shimmer wave moves across the text length, with extra space\n * for the wave to fade in/out at the edges.\n */\nfunction getShimmerPos(\n textLength: number,\n step: number,\n currentDir: 'ltr' | 'rtl',\n shimmerWidth: number = 2.5,\n): number {\n // Total steps for one complete cycle (text length + fade in/out space).\n const totalSteps = textLength + shimmerWidth + 2\n\n // RTL: Shimmer moves from right to left.\n if (currentDir === DIR_RTL) {\n return textLength - (step % totalSteps)\n }\n\n // LTR: Shimmer moves from left to right.\n return step % totalSteps\n}\n\n/**\n * Resolve shimmer direction to a concrete 'ltr' or 'rtl' value.\n * Used for initializing shimmer state and picking random directions.\n */\nfunction pickDirection(direction: ShimmerDirection): 'ltr' | 'rtl' {\n // Random mode: 50/50 chance of LTR or RTL.\n if (direction === DIR_RANDOM) {\n return Math.random() < 0.5 ? DIR_LTR : DIR_RTL\n }\n // RTL mode: Use RTL direction.\n if (direction === DIR_RTL) {\n return DIR_RTL\n }\n // LTR mode (or any other): Default to LTR.\n return DIR_LTR\n}\n\n/**\n * Apply shimmer animation effect to text.\n * This is the main entry point for shimmer animations. It:\n * 1. Strips ANSI codes to get plain text for character positioning\n * 2. Detects any styling (bold, italic, underline, etc.) to preserve\n * 3. Calculates the current shimmer wave position based on animation step\n * 4. Renders each character with appropriate brightness based on distance from wave\n * 5. Updates the animation state for the next frame\n * 6. Handles direction changes for bidirectional and random modes\n */\nexport function applyShimmer(\n text: string,\n state: ShimmerState,\n options?: ShimmerOptions | undefined,\n): string {\n const opts = { __proto__: null, ...options } as ShimmerOptions\n const direction = opts.direction ?? DIR_NONE\n const shimmerWidth = opts.shimmerWidth ?? 2.5\n // Socket purple.\n const color = opts.color ?? ([140, 82, 255] as const)\n\n // Detect text formatting styles from original text.\n const styles = opts.styles ?? detectStyles(text)\n\n // Strip ANSI codes to get plain text.\n const plainText = stripAnsi(text)\n\n // No shimmer effect in CI or when direction is 'none'.\n if (getCI() || !plainText || direction === DIR_NONE) {\n const styleCode = stylesToAnsi(styles)\n\n // Support gradient colors (array of colors, one per character).\n const isGradient = isArray(color[0])\n\n return plainText\n .split('')\n .map((char, i) => {\n const charColor: readonly [number, number, number] = isGradient\n ? ((color as ShimmerColorGradient)[i % color.length] ?? [\n 140, 82, 255,\n ])\n : (color as readonly [number, number, number])\n const base = `\\x1b[38;2;${charColor[0]};${charColor[1]};${charColor[2]}m`\n return `${styleCode}${base}${char}${ANSI_RESET}`\n })\n .join('')\n }\n\n // Calculate shimmer position.\n const shimmerPos = getShimmerPos(\n plainText.length,\n state.step,\n state.currentDir,\n shimmerWidth,\n )\n\n // Render text with shimmer.\n const result = plainText\n .split('')\n .map((char, i) => renderChar(char, i, shimmerPos, color, styles))\n .join('')\n\n // Advance shimmer position by speed amount each frame.\n // Speed represents steps per frame (e.g., 0.33 = advance 0.33 steps per frame).\n // This creates smooth animation by moving in small increments every frame\n // instead of jumping larger distances every N frames.\n state.step += state.speed\n\n // Handle bidirectional direction changes.\n const totalSteps = plainText.length + shimmerWidth + 2\n if (state.mode === MODE_BI) {\n if (state.step >= totalSteps) {\n state.step = 0\n // Toggle direction every cycle.\n state.currentDir = state.currentDir === DIR_LTR ? DIR_RTL : DIR_LTR\n }\n } else if (state.mode === DIR_RANDOM) {\n // Change direction randomly at end of each cycle.\n if (state.step >= totalSteps) {\n state.step = 0\n state.currentDir = pickDirection(DIR_RANDOM)\n }\n } else {\n // Reset for continuous loops.\n if (state.step >= totalSteps) {\n state.step = 0\n }\n }\n\n return result\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * @fileoverview Text shimmer animation utilities.\n * Provides animated highlight effects for spinner text with configurable directions:\n * - LTR (left-to-right): Shimmer wave moves from left to right\n * - RTL (right-to-left): Shimmer wave moves from right to left\n * - Bidirectional: Alternates between LTR and RTL each cycle\n * - Random: Picks a random direction each cycle\n * - None: No shimmer animation\n *\n * The shimmer effect creates a bright wave that travels across the text,\n * with characters near the wave appearing nearly white and fading to the\n * base color as they get further from the wave position.\n */\n\nimport { ANSI_RESET, stripAnsi } from '../ansi'\nimport { isArray } from '../arrays'\nimport { getCI } from '#env/ci'\nimport { resolveColor } from '../themes/utils'\nimport { THEMES } from '../themes/themes'\nimport type { ColorValue } from '../spinner'\n\nimport type {\n ShimmerColorGradient,\n ShimmerColorRgb,\n ShimmerDirection,\n ShimmerState,\n} from './types'\n\n// Re-export types for backward compatibility.\nexport type {\n ShimmerColor,\n ShimmerColorGradient,\n ShimmerColorInherit,\n ShimmerColorRgb,\n ShimmerConfig,\n ShimmerDirection,\n ShimmerState,\n} from './types'\n\n/**\n * Detected text formatting styles from ANSI codes.\n */\ntype TextStyles = {\n bold: boolean\n dim: boolean\n italic: boolean\n strikethrough: boolean\n underline: boolean\n}\n\n/**\n * Detect all text formatting styles present in ANSI-coded text.\n * Checks for bold, dim, italic, underline, and strikethrough.\n */\nfunction detectStyles(text: string): TextStyles {\n return {\n __proto__: null,\n // biome-ignore lint/suspicious/noControlCharactersInRegex: ANSI escape sequence detection.\n bold: /\\x1b\\[1m/.test(text),\n // biome-ignore lint/suspicious/noControlCharactersInRegex: ANSI escape sequence detection.\n dim: /\\x1b\\[2m/.test(text),\n // biome-ignore lint/suspicious/noControlCharactersInRegex: ANSI escape sequence detection.\n italic: /\\x1b\\[3m/.test(text),\n // biome-ignore lint/suspicious/noControlCharactersInRegex: ANSI escape sequence detection.\n strikethrough: /\\x1b\\[9m/.test(text),\n // biome-ignore lint/suspicious/noControlCharactersInRegex: ANSI escape sequence detection.\n underline: /\\x1b\\[4m/.test(text),\n } as TextStyles\n}\n\n/**\n * Build ANSI code string from text styles.\n * Returns the concatenated ANSI codes needed to apply the styles.\n */\nfunction stylesToAnsi(styles: TextStyles): string {\n let codes = ''\n if (styles.bold) {\n codes += '\\x1b[1m'\n }\n if (styles.dim) {\n codes += '\\x1b[2m'\n }\n if (styles.italic) {\n codes += '\\x1b[3m'\n }\n if (styles.underline) {\n codes += '\\x1b[4m'\n }\n if (styles.strikethrough) {\n codes += '\\x1b[9m'\n }\n return codes\n}\n\n// Internal options for applyShimmer function.\ntype ShimmerOptions = {\n readonly color?: ShimmerColorRgb | ShimmerColorGradient | undefined\n readonly direction?: ShimmerDirection | undefined\n readonly shimmerWidth?: number | undefined\n readonly styles?: TextStyles | undefined\n readonly theme?:\n | import('../themes/types').Theme\n | import('../themes/themes').ThemeName\n | undefined\n}\n\nexport const COLOR_INHERIT = 'inherit'\n\nexport const DIR_LTR = 'ltr'\n\nexport const DIR_NONE = 'none'\n\nexport const DIR_RANDOM = 'random'\n\nexport const DIR_RTL = 'rtl'\n\nexport const MODE_BI = 'bi'\n\n/**\n * Calculate shimmer intensity based on distance from shimmer wave position.\n * Uses a power curve for smooth falloff - characters close to the wave\n * get high intensity (bright white), while distant characters get 0.\n */\nfunction shimmerIntensity(\n distance: number,\n shimmerWidth: number = 2.5,\n): number {\n // Characters beyond shimmer width get no effect.\n if (distance > shimmerWidth) {\n return 0\n }\n // Smooth falloff using power curve.\n const normalized = distance / shimmerWidth\n return (1 - normalized) ** 2.5\n}\n\n/**\n * Blend two RGB colors based on a blend factor (0-1).\n * factor 0 = color1, factor 1 = color2, factor 0.5 = 50/50 blend.\n */\nfunction blendColors(\n color1: readonly [number, number, number],\n color2: readonly [number, number, number],\n factor: number,\n): readonly [number, number, number] {\n const r = Math.round(color1[0] + (color2[0] - color1[0]) * factor)\n const g = Math.round(color1[1] + (color2[1] - color1[1]) * factor)\n const b = Math.round(color1[2] + (color2[2] - color1[2]) * factor)\n return [r, g, b] as const\n}\n\n/**\n * Render character with shimmer effect based on distance from shimmer position.\n * Characters closer to the shimmer position get brighter (nearly white),\n * while characters further away use the base color.\n * Creates a smooth gradient by blending base color with white based on intensity.\n * Supports both single color and per-character color gradients.\n */\nfunction renderChar(\n char: string,\n index: number,\n shimmerPos: number,\n baseColor: readonly [number, number, number] | ShimmerColorGradient,\n styles: TextStyles,\n): string {\n // Calculate how far this character is from the shimmer wave.\n const distance = Math.abs(index - shimmerPos)\n const intensity = shimmerIntensity(distance)\n\n const styleCode = stylesToAnsi(styles)\n\n // Get base color for this character (single or per-character from gradient).\n const charColor: readonly [number, number, number] = isArray(baseColor[0])\n ? ((baseColor as ShimmerColorGradient)[index % baseColor.length] ?? [\n 140, 82, 255,\n ])\n : (baseColor as readonly [number, number, number])\n\n // If no shimmer intensity, use base color as-is.\n if (intensity === 0) {\n const base = `\\x1b[38;2;${charColor[0]};${charColor[1]};${charColor[2]}m`\n return `${styleCode}${base}${char}${ANSI_RESET}`\n }\n\n // Blend base color with white based on intensity to create smooth gradient.\n // Higher intensity = more white, creating the shimmer wave effect.\n const white: readonly [number, number, number] = [255, 255, 255] as const\n const blended = blendColors(charColor, white, intensity)\n\n const color = `\\x1b[38;2;${blended[0]};${blended[1]};${blended[2]}m`\n return `${styleCode}${color}${char}${ANSI_RESET}`\n}\n\n/**\n * Calculate shimmer wave position for current animation step.\n * The shimmer wave moves across the text length, with extra space\n * for the wave to fade in/out at the edges.\n */\nfunction getShimmerPos(\n textLength: number,\n step: number,\n currentDir: 'ltr' | 'rtl',\n shimmerWidth: number = 2.5,\n): number {\n // Total steps for one complete cycle (text length + fade in/out space).\n const totalSteps = textLength + shimmerWidth + 2\n\n // RTL: Shimmer moves from right to left.\n if (currentDir === DIR_RTL) {\n return textLength - (step % totalSteps)\n }\n\n // LTR: Shimmer moves from left to right.\n return step % totalSteps\n}\n\n/**\n * Resolve shimmer direction to a concrete 'ltr' or 'rtl' value.\n * Used for initializing shimmer state and picking random directions.\n */\nfunction pickDirection(direction: ShimmerDirection): 'ltr' | 'rtl' {\n // Random mode: 50/50 chance of LTR or RTL.\n if (direction === DIR_RANDOM) {\n return Math.random() < 0.5 ? DIR_LTR : DIR_RTL\n }\n // RTL mode: Use RTL direction.\n if (direction === DIR_RTL) {\n return DIR_RTL\n }\n // LTR mode (or any other): Default to LTR.\n return DIR_LTR\n}\n\n/**\n * Apply shimmer animation effect to text.\n * This is the main entry point for shimmer animations. It:\n * 1. Strips ANSI codes to get plain text for character positioning\n * 2. Detects any styling (bold, italic, underline, etc.) to preserve\n * 3. Calculates the current shimmer wave position based on animation step\n * 4. Renders each character with appropriate brightness based on distance from wave\n * 5. Updates the animation state for the next frame\n * 6. Handles direction changes for bidirectional and random modes\n */\nexport function applyShimmer(\n text: string,\n state: ShimmerState,\n options?: ShimmerOptions | undefined,\n): string {\n const opts = { __proto__: null, ...options } as ShimmerOptions\n const direction = opts.direction ?? DIR_NONE\n const shimmerWidth = opts.shimmerWidth ?? 2.5\n\n // Resolve color from theme or use provided color or default Socket purple.\n let color: ShimmerColorRgb | ShimmerColorGradient\n if (opts.theme) {\n // Resolve theme to Theme object\n const theme =\n typeof opts.theme === 'string' ? THEMES[opts.theme] : opts.theme\n // Use theme's primary color\n const themeColor = resolveColor(\n theme.colors.primary,\n theme.colors,\n ) as ColorValue\n // Convert ColorValue to ShimmerColorRgb\n // Fallback to Socket purple if color is a string\n color =\n typeof themeColor === 'string' ? ([140, 82, 255] as const) : themeColor\n } else {\n color = opts.color ?? ([140, 82, 255] as const)\n }\n\n // Detect text formatting styles from original text.\n const styles = opts.styles ?? detectStyles(text)\n\n // Strip ANSI codes to get plain text.\n const plainText = stripAnsi(text)\n\n // No shimmer effect in CI or when direction is 'none'.\n if (getCI() || !plainText || direction === DIR_NONE) {\n const styleCode = stylesToAnsi(styles)\n\n // Support gradient colors (array of colors, one per character).\n const isGradient = isArray(color[0])\n\n return plainText\n .split('')\n .map((char, i) => {\n const charColor: readonly [number, number, number] = isGradient\n ? ((color as ShimmerColorGradient)[i % color.length] ?? [\n 140, 82, 255,\n ])\n : (color as readonly [number, number, number])\n const base = `\\x1b[38;2;${charColor[0]};${charColor[1]};${charColor[2]}m`\n return `${styleCode}${base}${char}${ANSI_RESET}`\n })\n .join('')\n }\n\n // Calculate shimmer position.\n const shimmerPos = getShimmerPos(\n plainText.length,\n state.step,\n state.currentDir,\n shimmerWidth,\n )\n\n // Render text with shimmer.\n const result = plainText\n .split('')\n .map((char, i) => renderChar(char, i, shimmerPos, color, styles))\n .join('')\n\n // Advance shimmer position by speed amount each frame.\n // Speed represents steps per frame (e.g., 0.33 = advance 0.33 steps per frame).\n // This creates smooth animation by moving in small increments every frame\n // instead of jumping larger distances every N frames.\n state.step += state.speed\n\n // Handle bidirectional direction changes.\n const totalSteps = plainText.length + shimmerWidth + 2\n if (state.mode === MODE_BI) {\n if (state.step >= totalSteps) {\n state.step = 0\n // Toggle direction every cycle.\n state.currentDir = state.currentDir === DIR_LTR ? DIR_RTL : DIR_LTR\n }\n } else if (state.mode === DIR_RANDOM) {\n // Change direction randomly at end of each cycle.\n if (state.step >= totalSteps) {\n state.step = 0\n state.currentDir = pickDirection(DIR_RANDOM)\n }\n } else {\n // Reset for continuous loops.\n if (state.step >= totalSteps) {\n state.step = 0\n }\n }\n\n return result\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -20,6 +20,12 @@ export type ShimmerConfig = {
20
20
  * Default: 1/3 (~0.33).
21
21
  */
22
22
  readonly speed?: number | undefined;
23
+ /**
24
+ * Theme to use for shimmer colors.
25
+ * Can be a theme name ('socket', 'sunset', etc.) or a Theme object.
26
+ * If provided, overrides the color option.
27
+ */
28
+ readonly theme?: import('../themes/types').Theme | import('../themes/themes').ThemeName | undefined;
23
29
  };
24
30
  /**
25
31
  * Internal shimmer animation state.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/effects/types.ts"],
4
- "sourcesContent": ["/**\n * @fileoverview Shared types for effects (shimmer, pulse, ultra, etc.).\n * Common type definitions used across multiple effect modules.\n */\n\nexport type ShimmerColorInherit = 'inherit'\n\nexport type ShimmerColorRgb = readonly [number, number, number]\n\nexport type ShimmerColor = ShimmerColorInherit | ShimmerColorRgb\n\nexport type ShimmerColorGradient = readonly ShimmerColorRgb[]\n\nexport type ShimmerDirection = 'ltr' | 'rtl' | 'bi' | 'random' | 'none'\n\n/**\n * Shimmer animation configuration.\n */\nexport type ShimmerConfig = {\n readonly color?: ShimmerColor | ShimmerColorGradient | undefined\n readonly dir?: ShimmerDirection | undefined\n /**\n * Animation speed in steps per frame.\n * Lower values = slower shimmer (e.g., 0.33 = ~150ms per step).\n * Higher values = faster shimmer (e.g., 1.0 = 50ms per step).\n * Default: 1/3 (~0.33).\n */\n readonly speed?: number | undefined\n}\n\n/**\n * Internal shimmer animation state.\n * Tracks current animation position and direction.\n */\nexport type ShimmerState = {\n currentDir: 'ltr' | 'rtl'\n mode: ShimmerDirection\n /**\n * Animation speed in steps per frame.\n * The shimmer position advances by this amount every frame.\n */\n speed: number\n /**\n * Current shimmer position.\n * Can be fractional for smooth sub-character movement.\n */\n step: number\n}\n"],
4
+ "sourcesContent": ["/**\n * @fileoverview Shared types for effects (shimmer, pulse, ultra, etc.).\n * Common type definitions used across multiple effect modules.\n */\n\nexport type ShimmerColorInherit = 'inherit'\n\nexport type ShimmerColorRgb = readonly [number, number, number]\n\nexport type ShimmerColor = ShimmerColorInherit | ShimmerColorRgb\n\nexport type ShimmerColorGradient = readonly ShimmerColorRgb[]\n\nexport type ShimmerDirection = 'ltr' | 'rtl' | 'bi' | 'random' | 'none'\n\n/**\n * Shimmer animation configuration.\n */\nexport type ShimmerConfig = {\n readonly color?: ShimmerColor | ShimmerColorGradient | undefined\n readonly dir?: ShimmerDirection | undefined\n /**\n * Animation speed in steps per frame.\n * Lower values = slower shimmer (e.g., 0.33 = ~150ms per step).\n * Higher values = faster shimmer (e.g., 1.0 = 50ms per step).\n * Default: 1/3 (~0.33).\n */\n readonly speed?: number | undefined\n /**\n * Theme to use for shimmer colors.\n * Can be a theme name ('socket', 'sunset', etc.) or a Theme object.\n * If provided, overrides the color option.\n */\n readonly theme?:\n | import('../themes/types').Theme\n | import('../themes/themes').ThemeName\n | undefined\n}\n\n/**\n * Internal shimmer animation state.\n * Tracks current animation position and direction.\n */\nexport type ShimmerState = {\n currentDir: 'ltr' | 'rtl'\n mode: ShimmerDirection\n /**\n * Animation speed in steps per frame.\n * The shimmer position advances by this amount every frame.\n */\n speed: number\n /**\n * Current shimmer position.\n * Can be fractional for smooth sub-character movement.\n */\n step: number\n}\n"],
5
5
  "mappings": ";;;;;;;;;;;;;;AAAA;AAAA;",
6
6
  "names": []
7
7
  }
@@ -34,10 +34,11 @@ __export(links_exports, {
34
34
  module.exports = __toCommonJS(links_exports);
35
35
  var import_yoctocolors_cjs = __toESM(require("../external/yoctocolors-cjs"));
36
36
  var import_context = require("../themes/context");
37
+ var import_themes = require("../themes/themes");
37
38
  var import_utils = require("../themes/utils");
38
39
  function link(text, url, options) {
39
40
  const opts = { __proto__: null, fallback: false, ...options };
40
- const theme = typeof opts.theme === "string" ? require("../themes/themes").THEMES[opts.theme] : opts.theme ?? (0, import_context.getTheme)();
41
+ const theme = typeof opts.theme === "string" ? import_themes.THEMES[opts.theme] : opts.theme ?? (0, import_context.getTheme)();
41
42
  const linkColor = (0, import_utils.resolveColor)(theme.colors.link, theme.colors);
42
43
  const colors = import_yoctocolors_cjs.default;
43
44
  let colored;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/links/index.ts"],
4
- "sourcesContent": ["/**\n * @fileoverview Themed hyperlink utilities for terminal output.\n * Provides colored hyperlinks using theme configuration.\n */\n\nimport yoctocolorsCjs from '../external/yoctocolors-cjs'\nimport type { ColorName } from '../spinner'\nimport { getTheme } from '../themes/context'\nimport { resolveColor } from '../themes/utils'\nimport type { Theme } from '../themes/types'\nimport type { ThemeName } from '../themes/themes'\n\n/**\n * Options for creating themed links.\n */\nexport type LinkOptions = {\n /** Theme to use (overrides global) */\n theme?: Theme | ThemeName | undefined\n /** Show URL as fallback if terminal doesn't support links */\n fallback?: boolean | undefined\n}\n\n/**\n * Create a themed hyperlink for terminal output.\n * The link text is colored using the theme's link color.\n *\n * Note: Most terminals support ANSI color codes but not clickable links.\n * This function colors the text but does not create clickable hyperlinks.\n * For clickable links, use a library like 'terminal-link' separately.\n *\n * @param text - Link text to display\n * @param url - URL (included in fallback mode)\n * @param options - Link configuration options\n * @returns Colored link text\n *\n * @example\n * ```ts\n * import { link } from '@socketsecurity/lib/links'\n *\n * // Use current theme\n * console.log(link('Documentation', 'https://socket.dev'))\n *\n * // Override theme\n * console.log(link('API Docs', 'https://api.socket.dev', {\n * theme: 'coana'\n * }))\n *\n * // Show URL as fallback\n * console.log(link('GitHub', 'https://github.com', {\n * fallback: true\n * }))\n * // Output: \"GitHub (https://github.com)\"\n * ```\n */\nexport function link(text: string, url: string, options?: LinkOptions): string {\n const opts = { __proto__: null, fallback: false, ...options } as LinkOptions\n\n // Resolve theme\n const theme =\n typeof opts.theme === 'string'\n ? require('../themes/themes').THEMES[opts.theme]\n : (opts.theme ?? getTheme())\n\n // Resolve link color\n const linkColor = resolveColor(theme.colors.link, theme.colors)\n\n // Apply color - for now just use cyan as a simple fallback\n // Note: RGB color support to be added in yoctocolors wrapper\n const colors = yoctocolorsCjs\n let colored: string\n if (typeof linkColor === 'string' && linkColor !== 'inherit') {\n // Use named color method if available\n const colorMethod = colors[linkColor as ColorName]\n colored = colorMethod ? colorMethod(text) : colors.cyan(text)\n } else if (Array.isArray(linkColor)) {\n // RGB color - for now fallback to cyan\n // Note: RGB color support to be implemented\n colored = colors.cyan(text)\n } else {\n colored = colors.cyan(text)\n }\n\n // Return with or without URL fallback\n return opts.fallback ? `${colored} (${url})` : colored\n}\n\n/**\n * Create multiple themed links from an array of link specifications.\n *\n * @param links - Array of [text, url] pairs\n * @param options - Link configuration options\n * @returns Array of colored link texts\n *\n * @example\n * ```ts\n * import { links } from '@socketsecurity/lib/links'\n *\n * const formatted = links([\n * ['Documentation', 'https://socket.dev'],\n * ['API Reference', 'https://api.socket.dev'],\n * ['GitHub', 'https://github.com/SocketDev']\n * ])\n *\n * formatted.forEach(link => console.log(link))\n * ```\n */\nexport function links(\n linkSpecs: Array<[text: string, url: string]>,\n options?: LinkOptions,\n): string[] {\n return linkSpecs.map(([text, url]) => link(text, url, options))\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAKA,6BAA2B;AAE3B,qBAAyB;AACzB,mBAA6B;AA8CtB,SAAS,KAAK,MAAc,KAAa,SAA+B;AAC7E,QAAM,OAAO,EAAE,WAAW,MAAM,UAAU,OAAO,GAAG,QAAQ;AAG5D,QAAM,QACJ,OAAO,KAAK,UAAU,WAClB,QAAQ,kBAAkB,EAAE,OAAO,KAAK,KAAK,IAC5C,KAAK,aAAS,yBAAS;AAG9B,QAAM,gBAAY,2BAAa,MAAM,OAAO,MAAM,MAAM,MAAM;AAI9D,QAAM,SAAS,uBAAAA;AACf,MAAI;AACJ,MAAI,OAAO,cAAc,YAAY,cAAc,WAAW;AAE5D,UAAM,cAAc,OAAO,SAAsB;AACjD,cAAU,cAAc,YAAY,IAAI,IAAI,OAAO,KAAK,IAAI;AAAA,EAC9D,WAAW,MAAM,QAAQ,SAAS,GAAG;AAGnC,cAAU,OAAO,KAAK,IAAI;AAAA,EAC5B,OAAO;AACL,cAAU,OAAO,KAAK,IAAI;AAAA,EAC5B;AAGA,SAAO,KAAK,WAAW,GAAG,OAAO,KAAK,GAAG,MAAM;AACjD;AAsBO,SAAS,MACd,WACA,SACU;AACV,SAAO,UAAU,IAAI,CAAC,CAAC,MAAM,GAAG,MAAM,KAAK,MAAM,KAAK,OAAO,CAAC;AAChE;",
4
+ "sourcesContent": ["/**\n * @fileoverview Themed hyperlink utilities for terminal output.\n * Provides colored hyperlinks using theme configuration.\n */\n\nimport yoctocolorsCjs from '../external/yoctocolors-cjs'\nimport type { ColorName } from '../spinner'\nimport { getTheme } from '../themes/context'\nimport { THEMES } from '../themes/themes'\nimport { resolveColor } from '../themes/utils'\nimport type { Theme } from '../themes/types'\nimport type { ThemeName } from '../themes/themes'\n\n/**\n * Options for creating themed links.\n */\nexport type LinkOptions = {\n /** Theme to use (overrides global) */\n theme?: Theme | ThemeName | undefined\n /** Show URL as fallback if terminal doesn't support links */\n fallback?: boolean | undefined\n}\n\n/**\n * Create a themed hyperlink for terminal output.\n * The link text is colored using the theme's link color.\n *\n * Note: Most terminals support ANSI color codes but not clickable links.\n * This function colors the text but does not create clickable hyperlinks.\n * For clickable links, use a library like 'terminal-link' separately.\n *\n * @param text - Link text to display\n * @param url - URL (included in fallback mode)\n * @param options - Link configuration options\n * @returns Colored link text\n *\n * @example\n * ```ts\n * import { link } from '@socketsecurity/lib/links'\n *\n * // Use current theme\n * console.log(link('Documentation', 'https://socket.dev'))\n *\n * // Override theme\n * console.log(link('API Docs', 'https://api.socket.dev', {\n * theme: 'coana'\n * }))\n *\n * // Show URL as fallback\n * console.log(link('GitHub', 'https://github.com', {\n * fallback: true\n * }))\n * // Output: \"GitHub (https://github.com)\"\n * ```\n */\nexport function link(text: string, url: string, options?: LinkOptions): string {\n const opts = { __proto__: null, fallback: false, ...options } as LinkOptions\n\n // Resolve theme\n const theme =\n typeof opts.theme === 'string'\n ? THEMES[opts.theme]\n : (opts.theme ?? getTheme())\n\n // Resolve link color\n const linkColor = resolveColor(theme.colors.link, theme.colors)\n\n // Apply color - for now just use cyan as a simple fallback\n // Note: RGB color support to be added in yoctocolors wrapper\n const colors = yoctocolorsCjs\n let colored: string\n if (typeof linkColor === 'string' && linkColor !== 'inherit') {\n // Use named color method if available\n const colorMethod = colors[linkColor as ColorName]\n colored = colorMethod ? colorMethod(text) : colors.cyan(text)\n } else if (Array.isArray(linkColor)) {\n // RGB color - for now fallback to cyan\n // Note: RGB color support to be implemented\n colored = colors.cyan(text)\n } else {\n colored = colors.cyan(text)\n }\n\n // Return with or without URL fallback\n return opts.fallback ? `${colored} (${url})` : colored\n}\n\n/**\n * Create multiple themed links from an array of link specifications.\n *\n * @param links - Array of [text, url] pairs\n * @param options - Link configuration options\n * @returns Array of colored link texts\n *\n * @example\n * ```ts\n * import { links } from '@socketsecurity/lib/links'\n *\n * const formatted = links([\n * ['Documentation', 'https://socket.dev'],\n * ['API Reference', 'https://api.socket.dev'],\n * ['GitHub', 'https://github.com/SocketDev']\n * ])\n *\n * formatted.forEach(link => console.log(link))\n * ```\n */\nexport function links(\n linkSpecs: Array<[text: string, url: string]>,\n options?: LinkOptions,\n): string[] {\n return linkSpecs.map(([text, url]) => link(text, url, options))\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAKA,6BAA2B;AAE3B,qBAAyB;AACzB,oBAAuB;AACvB,mBAA6B;AA8CtB,SAAS,KAAK,MAAc,KAAa,SAA+B;AAC7E,QAAM,OAAO,EAAE,WAAW,MAAM,UAAU,OAAO,GAAG,QAAQ;AAG5D,QAAM,QACJ,OAAO,KAAK,UAAU,WAClB,qBAAO,KAAK,KAAK,IAChB,KAAK,aAAS,yBAAS;AAG9B,QAAM,gBAAY,2BAAa,MAAM,OAAO,MAAM,MAAM,MAAM;AAI9D,QAAM,SAAS,uBAAAA;AACf,MAAI;AACJ,MAAI,OAAO,cAAc,YAAY,cAAc,WAAW;AAE5D,UAAM,cAAc,OAAO,SAAsB;AACjD,cAAU,cAAc,YAAY,IAAI,IAAI,OAAO,KAAK,IAAI;AAAA,EAC9D,WAAW,MAAM,QAAQ,SAAS,GAAG;AAGnC,cAAU,OAAO,KAAK,IAAI;AAAA,EAC5B,OAAO;AACL,cAAU,OAAO,KAAK,IAAI;AAAA,EAC5B;AAGA,SAAO,KAAK,WAAW,GAAG,OAAO,KAAK,GAAG,MAAM;AACjD;AAsBO,SAAS,MACd,WACA,SACU;AACV,SAAO,UAAU,IAAI,CAAC,CAAC,MAAM,GAAG,MAAM,KAAK,MAAM,KAAK,OAAO,CAAC;AAChE;",
6
6
  "names": ["yoctocolorsCjs"]
7
7
  }
package/dist/logger.js CHANGED
@@ -39,6 +39,7 @@ var import_is_unicode_supported = __toESM(require("./external/@socketregistry/is
39
39
  var import_yoctocolors_cjs = __toESM(require("./external/yoctocolors-cjs"));
40
40
  var import_strings = require("./strings");
41
41
  var import_context = require("./themes/context");
42
+ var import_themes = require("./themes/themes");
42
43
  const globalConsole = console;
43
44
  const ReflectApply = Reflect.apply;
44
45
  const ReflectConstruct = Reflect.construct;
@@ -196,6 +197,7 @@ class Logger {
196
197
  #logCallCount = 0;
197
198
  #options;
198
199
  #originalStdout;
200
+ #theme;
199
201
  /**
200
202
  * Creates a new Logger instance.
201
203
  *
@@ -223,6 +225,14 @@ class Logger {
223
225
  if (typeof options === "object" && options !== null) {
224
226
  this.#options = { __proto__: null, ...options };
225
227
  this.#originalStdout = options.stdout;
228
+ const themeOption = options.theme;
229
+ if (themeOption) {
230
+ if (typeof themeOption === "string") {
231
+ this.#theme = import_themes.THEMES[themeOption];
232
+ } else {
233
+ this.#theme = themeOption;
234
+ }
235
+ }
226
236
  } else {
227
237
  this.#options = { __proto__: null };
228
238
  }
@@ -285,6 +295,7 @@ class Logger {
285
295
  instance.#parent = this;
286
296
  instance.#boundStream = "stderr";
287
297
  instance.#options = { __proto__: null, ...this.#options };
298
+ instance.#theme = this.#theme;
288
299
  this.#stderrLogger = instance;
289
300
  }
290
301
  return this.#stderrLogger;
@@ -317,6 +328,7 @@ class Logger {
317
328
  instance.#parent = this;
318
329
  instance.#boundStream = "stdout";
319
330
  instance.#options = { __proto__: null, ...this.#options };
331
+ instance.#theme = this.#theme;
320
332
  this.#stdoutLogger = instance;
321
333
  }
322
334
  return this.#stdoutLogger;
@@ -328,6 +340,31 @@ class Logger {
328
340
  #getRoot() {
329
341
  return this.#parent || this;
330
342
  }
343
+ /**
344
+ * Get the resolved theme for this logger instance.
345
+ * Returns instance theme if set, otherwise falls back to context theme.
346
+ * @private
347
+ */
348
+ #getTheme() {
349
+ return this.#theme ?? (0, import_context.getTheme)();
350
+ }
351
+ /**
352
+ * Get logger-specific symbols using the resolved theme.
353
+ * @private
354
+ */
355
+ #getSymbols() {
356
+ const theme = this.#getTheme();
357
+ const supported = (0, import_is_unicode_supported.default)();
358
+ const colors = /* @__PURE__ */ getYoctocolors();
359
+ return {
360
+ __proto__: null,
361
+ fail: /* @__PURE__ */ applyColor(supported ? "\u2716" : "\xD7", theme.colors.error, colors),
362
+ info: /* @__PURE__ */ applyColor(supported ? "\u2139" : "i", theme.colors.info, colors),
363
+ step: /* @__PURE__ */ applyColor(supported ? "\u2192" : ">", theme.colors.step, colors),
364
+ success: /* @__PURE__ */ applyColor(supported ? "\u2714" : "\u221A", theme.colors.success, colors),
365
+ warn: /* @__PURE__ */ applyColor(supported ? "\u26A0" : "\u203C", theme.colors.warning, colors)
366
+ };
367
+ }
331
368
  /**
332
369
  * Get indentation for a specific stream.
333
370
  * @private
@@ -418,8 +455,9 @@ class Logger {
418
455
  text = "";
419
456
  }
420
457
  const indent = this.#getIndent("stderr");
458
+ const symbols = this.#getSymbols();
421
459
  con.error(
422
- (0, import_strings.applyLinePrefix)(`${LOG_SYMBOLS[symbolType]} ${text}`, {
460
+ (0, import_strings.applyLinePrefix)(`${symbols[symbolType]} ${text}`, {
423
461
  prefix: indent
424
462
  }),
425
463
  ...extras
@@ -984,9 +1022,10 @@ class Logger {
984
1022
  }
985
1023
  const text = this.#stripSymbols(msg);
986
1024
  const indent = this.#getIndent("stdout");
1025
+ const symbols = this.#getSymbols();
987
1026
  const con = this.#getConsole();
988
1027
  con.log(
989
- (0, import_strings.applyLinePrefix)(`${LOG_SYMBOLS.step} ${text}`, {
1028
+ (0, import_strings.applyLinePrefix)(`${symbols.step} ${text}`, {
990
1029
  prefix: indent
991
1030
  }),
992
1031
  ...extras