/ src / components / AnimatedClaudeAsterisk.tsx
AnimatedClaudeAsterisk.tsx
 1  import React from 'react'
 2  import { Text } from 'ink'
 3  import {
 4    smallAnimatedArray,
 5    largeAnimatedAray,
 6  } from '../constants/claude-asterisk-ascii-art.js'
 7  import { getTheme } from '../utils/theme.js'
 8  
 9  export type ClaudeAsteriskSize = 'small' | 'medium' | 'large'
10  
11  interface AnimatedClaudeAsteriskProps {
12    size?: ClaudeAsteriskSize
13    cycles?: number
14    color?: string
15    intervalMs?: number
16  }
17  
18  export function AnimatedClaudeAsterisk({
19    size = 'small',
20    cycles,
21    color,
22    intervalMs,
23  }: AnimatedClaudeAsteriskProps): React.ReactNode {
24    const [currentAsciiArtIndex, setCurrentAsciiArtIndex] = React.useState(0)
25    const direction = React.useRef(1)
26    const animateLoopCount = React.useRef(0)
27    const theme = getTheme()
28  
29    // Determine which array to use based on size
30    const animatedArray =
31      size === 'large' ? largeAnimatedAray : smallAnimatedArray
32  
33    // Animation interval for ascii art
34    React.useEffect(() => {
35      const timer = setInterval(
36        () => {
37          setCurrentAsciiArtIndex(prevIndex => {
38            // Stop animating after specified number of cycles if provided
39            if (
40              cycles !== undefined &&
41              cycles !== null &&
42              animateLoopCount.current >= cycles
43            ) {
44              return 0
45            }
46  
47            // Cycle through array indices
48            if (prevIndex === animatedArray.length - 1) {
49              direction.current = -1
50              animateLoopCount.current += 1
51            }
52            if (prevIndex === 0) {
53              direction.current = 1
54            }
55            return prevIndex + direction.current
56          })
57        },
58        intervalMs || (size === 'large' ? 100 : 200),
59      ) // Default: 100ms for large, 200ms for small/medium
60  
61      return () => clearInterval(timer)
62    }, [animatedArray.length, cycles, intervalMs, size])
63  
64    return (
65      <Text color={color || theme.claude}>
66        {animatedArray[currentAsciiArtIndex]}
67      </Text>
68    )
69  }