{"version":3,"file":"FloatingCursorComponent-BjCr6Ruj.cjs","sources":["../../lib/vowel/components/FloatingCursorComponent.tsx"],"sourcesContent":["/**\n * @fileoverview FloatingCursor React Component - Visual indicator for AI automation\n * \n * A React component that displays an animated cursor with a text badge to show where the AI\n * is interacting with the page during voice-controlled automation.\n * \n * Features:\n * - Smooth position transitions\n * - Typing animation for text labels\n * - Bounce animation when idle\n * - Smart badge positioning (flips to right edge if needed)\n * - Fully styled with Tailwind CSS\n * \n * @module @vowel.to/client/components\n * @author vowel.to\n * @license Proprietary\n */\n\nimport { useEffect, useState, useRef } from 'react';\nimport { cn, VOWEL_UI_SCOPE_CLASS } from '../utils';\n\n/**\n * FloatingCursor component props\n */\nexport interface FloatingCursorComponentProps {\n  /** X position as percentage (0-100) */\n  x?: number;\n  \n  /** Y position as percentage (0-100) */\n  y?: number;\n  \n  /** Text to display in badge */\n  text?: string;\n  \n  /** Whether cursor is idle (shows bounce animation) */\n  isIdle?: boolean;\n  \n  /** Whether cursor is visible */\n  visible?: boolean;\n  \n  /** Cursor color (hex) */\n  cursorColor?: string;\n  \n  /** Cursor size in pixels */\n  cursorSize?: number;\n  \n  /** Badge background color (hex) */\n  badgeBackground?: string;\n  \n  /** Badge text color (hex) */\n  badgeTextColor?: string;\n  \n  /** Enable typing animation */\n  enableTyping?: boolean;\n  \n  /** Typing speed in milliseconds */\n  typingSpeed?: number;\n  \n  /** Enable bounce animation when idle */\n  enableBounce?: boolean;\n  \n  /** Transition duration in milliseconds */\n  transitionDuration?: number;\n  \n  /** Z-index for positioning */\n  zIndex?: number;\n  \n  /** Callback when typing animation completes */\n  onTypingComplete?: () => void;\n}\n\n/**\n * FloatingCursor Component\n * \n * Displays an animated cursor with text badge to visualize AI automation actions.\n * \n * @example\n * ```tsx\n * <FloatingCursorComponent\n *   x={50}\n *   y={50}\n *   text=\"Clicking button\"\n *   visible={true}\n *   isIdle={false}\n * />\n * ```\n */\nexport function FloatingCursorComponent({\n  x = 50,\n  y = 50,\n  text = '',\n  isIdle = false,\n  visible = false,\n  cursorColor = '#000000',\n  cursorSize = 24,\n  badgeBackground = '#000000',\n  badgeTextColor = '#ffffff',\n  enableTyping = true,\n  typingSpeed = 50,\n  enableBounce = true,\n  transitionDuration = 1000,\n  zIndex = 9999,\n  onTypingComplete,\n}: FloatingCursorComponentProps) {\n  const [displayedText, setDisplayedText] = useState('');\n  const [showBadge, setShowBadge] = useState(false);\n  const [badgePosition, setBadgePosition] = useState<'left' | 'right'>('left');\n  const typingIntervalRef = useRef<number | null>(null);\n  const containerRef = useRef<HTMLDivElement>(null);\n\n  // Calculate if badge should be positioned on right (when cursor is near right edge)\n  useEffect(() => {\n    if (typeof window !== 'undefined') {\n      const cursorX = (x / 100) * window.innerWidth;\n      const viewportWidth = window.innerWidth;\n      const distanceFromRightEdge = viewportWidth - cursorX;\n      const edgeThreshold = 200; // Flip if within 200px of right edge\n      \n      setBadgePosition(distanceFromRightEdge < edgeThreshold ? 'right' : 'left');\n    }\n  }, [x]);\n\n  // Typing animation effect\n  useEffect(() => {\n    // Clear any existing interval\n    if (typingIntervalRef.current !== null) {\n      window.clearInterval(typingIntervalRef.current);\n      typingIntervalRef.current = null;\n    }\n\n    if (!text) {\n      setDisplayedText('');\n      setShowBadge(false);\n      return;\n    }\n\n    // Show badge\n    setShowBadge(true);\n\n    if (!enableTyping) {\n      // No typing animation - show text immediately\n      setDisplayedText(text);\n      onTypingComplete?.();\n      return;\n    }\n\n    // Reset displayed text and start typing\n    setDisplayedText('');\n    let currentIndex = 0;\n\n    const typeNextChar = () => {\n      if (currentIndex < text.length) {\n        setDisplayedText(text.slice(0, currentIndex + 1));\n        currentIndex++;\n      } else {\n        // Typing complete\n        if (typingIntervalRef.current !== null) {\n          window.clearInterval(typingIntervalRef.current);\n          typingIntervalRef.current = null;\n        }\n        onTypingComplete?.();\n      }\n    };\n\n    // Start typing\n    typeNextChar(); // Type first character immediately\n    typingIntervalRef.current = window.setInterval(typeNextChar, typingSpeed);\n\n    return () => {\n      if (typingIntervalRef.current !== null) {\n        window.clearInterval(typingIntervalRef.current);\n        typingIntervalRef.current = null;\n      }\n    };\n  }, [text, enableTyping, typingSpeed, onTypingComplete]);\n\n  // Cursor SVG\n  const cursorSvg = (\n    <svg \n      viewBox=\"0 0 24 24\" \n      fill={cursorColor} \n      width={cursorSize} \n      height={cursorSize}\n      className=\"drop-shadow-md\"\n    >\n      <path d=\"M7.4 2.5l-.9 15.9 3.9-4.2 3.7 6.8 2.5-1.3-3.7-6.8 5.4-1.6L7.4 2.5z\"/>\n    </svg>\n  );\n\n  return (\n    <div\n      ref={containerRef}\n      className={cn(\n        VOWEL_UI_SCOPE_CLASS,\n        \"fixed inset-0 w-full h-full pointer-events-none transition-opacity duration-300\",\n        visible ? \"opacity-100\" : \"opacity-0\"\n      )}\n      style={{ zIndex }}\n    >\n      <div\n        className=\"absolute transition-all ease-out\"\n        style={{\n          left: `${x}%`,\n          top: `${y}%`,\n          transform: 'translate(-50%, -50%)', // Center cursor on target point\n          transitionDuration: `${transitionDuration}ms`,\n        }}\n      >\n        {/* Cursor icon */}\n        <div\n          className={cn(\n            \"relative\",\n            enableBounce && isIdle && \"animate-bounce\"\n          )}\n          style={{\n            width: `${cursorSize}px`,\n            height: `${cursorSize}px`,\n          }}\n        >\n          {cursorSvg}\n          \n          {/* Badge (pill label below cursor) */}\n          <div\n            className={cn(\n              \"absolute top-full mt-1 px-3 py-1.5 rounded-xl shadow-lg\",\n              \"font-sans text-sm font-medium whitespace-nowrap\",\n              \"transition-all duration-200 backdrop-blur-sm\",\n              showBadge ? \"opacity-100\" : \"opacity-0\",\n              badgePosition === 'right' ? \"right-0\" : \"left-0\"\n            )}\n            style={{\n              backgroundColor: badgeBackground,\n              color: badgeTextColor,\n            }}\n          >\n            {displayedText}\n            {enableTyping && displayedText.length < text.length && (\n              <span className=\"inline-block ml-0.5 animate-pulse\">|</span>\n            )}\n          </div>\n        </div>\n      </div>\n    </div>\n  );\n}\n"],"names":["useState","useRef","useEffect","jsx","cn","VOWEL_UI_SCOPE_CLASS","jsxs"],"mappings":"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"}