{"version":3,"file":"index.cjs","sources":["../src/types/index.ts","../src/utils/emojiData.ts","../src/utils/categories.ts","../src/utils/search.ts","../src/hooks/useEmojiSearch.ts","../src/utils/storage.ts","../src/hooks/useEmojiStorage.ts","../src/hooks/useRecentlyUsed.ts","../src/hooks/useFrequentlyUsed.ts","../src/hooks/useSkinTone.ts","../src/components/SearchBar.tsx","../src/components/CategoryTabs.tsx","../src/components/EmojiButton.tsx","../src/components/EmojiGrid.tsx","../src/components/Preview.tsx","../src/components/SkinTonePicker.tsx","../src/components/EmojiPicker.tsx"],"sourcesContent":["import { CSSProperties } from 'react';\n\n/**\n * Represents a single emoji with all its metadata\n */\nexport interface EmojiData {\n  /** The actual emoji character(s) */\n  emoji: string;\n  /** Display name (e.g., \"Smiling Face\") */\n  name: string;\n  /** Shortcode format (e.g., \":smile:\") */\n  shortcode: string;\n  /** Unicode codepoint(s) (e.g., \"1F600\") */\n  unicode: string;\n  /** Category this emoji belongs to */\n  category: string;\n  /** Search keywords and aliases */\n  keywords: string[];\n  /** Skin tone variant if applicable (0 = default, 1-5 = variants) */\n  skinTone?: number;\n  /** Whether this emoji supports skin tone variants */\n  supportsSkinTone?: boolean;\n  /** Base emoji code (without skin tone modifier) */\n  baseEmoji?: string;\n}\n\n/**\n * Category configuration\n */\nexport interface CategoryConfig {\n  /** Unique category identifier */\n  id: string;\n  /** Display name */\n  name: string;\n  /** Representative emoji icon */\n  icon: string;\n  /** Emojis in this category */\n  emojis: EmojiData[];\n}\n\n/**\n * Theme options\n */\nexport type Theme = 'light' | 'dark' | 'auto';\n\n/**\n * Popup position options\n */\nexport type Position = 'top' | 'bottom' | 'left' | 'right' | 'auto';\n\n/**\n * Style overrides for different parts of the picker\n */\nexport interface EmojiPickerStyles {\n  /** Overall picker container */\n  picker?: CSSProperties;\n  /** Search bar */\n  search?: CSSProperties;\n  /** Category tabs container */\n  categories?: CSSProperties;\n  /** Individual category tab */\n  categoryTab?: CSSProperties;\n  /** Emoji grid container */\n  emojiGrid?: CSSProperties;\n  /** Individual emoji button */\n  emoji?: CSSProperties;\n  /** Preview area */\n  preview?: CSSProperties;\n  /** Skin tone picker */\n  skinTonePicker?: CSSProperties;\n  /** Frequently/Recently used section */\n  frequentSection?: CSSProperties;\n}\n\n/**\n * Storage adapter interface for custom storage implementations\n * Note: All methods must be synchronous. For async storage, consider\n * implementing a sync wrapper or caching layer.\n */\nexport interface StorageAdapter {\n  /** Get item from storage (synchronous) */\n  getItem: (key: string) => string | null;\n  /** Set item in storage (synchronous) */\n  setItem: (key: string, value: string) => void;\n  /** Remove item from storage (synchronous) */\n  removeItem: (key: string) => void;\n  /** Clear all items (synchronous) */\n  clear?: () => void;\n}\n\n/**\n * Main EmojiPicker component props\n */\nexport interface EmojiPickerProps {\n  // Required\n  /** Callback when an emoji is selected */\n  onEmojiSelect: (emoji: EmojiData) => void;\n\n  // Optional - Display\n  /** Initial/preset emoji to highlight */\n  presetEmoji?: string | EmojiData;\n  /** Color theme */\n  theme?: Theme;\n  /** Picker width (default: 338px) */\n  width?: number | string;\n  /** Picker height (default: 435px) */\n  height?: number | string;\n\n  // Customization\n  /** Custom CSS class */\n  className?: string;\n  /** Style overrides */\n  styles?: EmojiPickerStyles;\n  /** Popup position */\n  position?: Position;\n\n  // Behavior\n  /** Auto-focus search on open (default: true) */\n  autoFocus?: boolean;\n  /** Auto-close after selection (default: false) */\n  closeOnSelect?: boolean;\n  /** Show preview on hover (default: true) */\n  showPreview?: boolean;\n  /** Enable skin tone picker (default: true) */\n  showSkinTones?: boolean;\n  /** Show frequently used section (default: true) */\n  enableFrequentlyUsed?: boolean;\n  /** Max rows for frequent emojis (default: 2) */\n  maxFrequentRows?: number;\n\n  // Storage\n  /** localStorage key prefix (default: \"mm-emoji\") */\n  storageKey?: string;\n  /** Custom storage implementation */\n  customStorage?: StorageAdapter;\n\n  // Search\n  /** Search input placeholder (default: \"Search emojis...\") */\n  searchPlaceholder?: string;\n  /** Search debounce delay in ms (default: 300) */\n  searchDebounce?: number;\n\n  // Advanced\n  /** Localization (future) */\n  locale?: string;\n  /** Custom emojis (future) */\n  customEmojis?: CustomEmoji[];\n  /** Disable specific emojis */\n  disabledEmojis?: string[];\n  /** Custom category configuration */\n  categories?: CategoryConfig[];\n}\n\n/**\n * Custom emoji support (future feature)\n */\nexport interface CustomEmoji {\n  /** Unique identifier */\n  id: string;\n  /** Display name */\n  name: string;\n  /** Shortcode */\n  shortcode: string;\n  /** Image URL */\n  imageUrl: string;\n  /** Search keywords */\n  keywords: string[];\n}\n\n/**\n * Storage data structure for emoji usage\n */\nexport interface EmojiUsageData {\n  /** Recently used emojis (in order) */\n  recent: string[];\n  /** Frequently used emojis with counts */\n  frequent: Record<string, number>;\n  /** Skin tone preferences per emoji base */\n  skinTones: Record<string, number>;\n}\n\n/**\n * Skin tone options\n */\nexport enum SkinTone {\n  Default = 0,\n  Light = 1,\n  MediumLight = 2,\n  Medium = 3,\n  MediumDark = 4,\n  Dark = 5,\n}\n\n/**\n * Skin tone modifiers (Unicode)\n */\nexport const SKIN_TONE_MODIFIERS: Record<SkinTone, string> = {\n  [SkinTone.Default]: '',\n  [SkinTone.Light]: '\\u{1F3FB}',\n  [SkinTone.MediumLight]: '\\u{1F3FC}',\n  [SkinTone.Medium]: '\\u{1F3FD}',\n  [SkinTone.MediumDark]: '\\u{1F3FE}',\n  [SkinTone.Dark]: '\\u{1F3FF}',\n};\n\n/**\n * Category IDs\n */\nexport enum CategoryId {\n  Frequent = 'frequent',\n  SmileysAndPeople = 'smileys-people',\n  AnimalsAndNature = 'animals-nature',\n  FoodAndDrink = 'food-drink',\n  Activities = 'activities',\n  TravelAndPlaces = 'travel-places',\n  Objects = 'objects',\n  Symbols = 'symbols',\n  Flags = 'flags',\n}\n","import dataByGroup from 'unicode-emoji-json/data-by-group.json';\nimport { EmojiData, CategoryId } from '../types';\n\n/**\n * Type definitions for unicode-emoji-json data structure\n */\ninterface UnicodeEmojiData {\n  emoji: string;\n  name: string;\n  slug: string;\n  skin_tone_support?: boolean;\n}\n\ninterface UnicodeEmojiGroup {\n  name: string;\n  slug: string;\n  emojis: UnicodeEmojiData[];\n}\n\n/**\n * Map unicode-emoji-json group names to our category IDs\n */\nconst GROUP_TO_CATEGORY: Record<string, CategoryId> = {\n  'Smileys & Emotion': CategoryId.SmileysAndPeople,\n  'People & Body': CategoryId.SmileysAndPeople,\n  'Animals & Nature': CategoryId.AnimalsAndNature,\n  'Food & Drink': CategoryId.FoodAndDrink,\n  'Activities': CategoryId.Activities,\n  'Travel & Places': CategoryId.TravelAndPlaces,\n  'Objects': CategoryId.Objects,\n  'Symbols': CategoryId.Symbols,\n  'Flags': CategoryId.Flags,\n  'Component': CategoryId.Symbols, // Fallback for component emojis\n};\n\n\n/**\n * Generate a shortcode from an emoji name\n */\nfunction generateShortcode(name: string): string {\n  return `:${name\n    .toLowerCase()\n    .replace(/[^\\w\\s]/g, '')\n    .replace(/\\s+/g, '_')}:`;\n}\n\n/**\n * Generate search keywords from emoji name and slug\n */\nfunction generateKeywords(name: string, slug: string): string[] {\n  const keywords = new Set<string>();\n\n  // Add the name\n  keywords.add(name.toLowerCase());\n\n  // Add individual words from the name\n  name\n    .toLowerCase()\n    .split(/[\\s-]+/)\n    .forEach((word) => {\n      if (word.length > 2) {\n        keywords.add(word);\n      }\n    });\n\n  // Add slug variations\n  slug\n    .split('_')\n    .forEach((word) => {\n      if (word.length > 2) {\n        keywords.add(word);\n      }\n    });\n\n  return Array.from(keywords);\n}\n\n/**\n * Cache for processed emoji data to avoid reprocessing on every call\n */\nlet cachedEmojiData: EmojiData[] | null = null;\n\n/**\n * Process raw emoji data from unicode-emoji-json\n */\nexport function processEmojiData(): EmojiData[] {\n  // Return cached data if available\n  if (cachedEmojiData) {\n    return cachedEmojiData;\n  }\n\n  const allEmojis: EmojiData[] = [];\n\n  // dataByGroup is actually an array of groups in the JSON file\n  (dataByGroup as unknown as UnicodeEmojiGroup[]).forEach((group) => {\n    const groupName = group.name;\n    const category = GROUP_TO_CATEGORY[groupName] || CategoryId.Symbols;\n    const emojiList = group.emojis || [];\n\n    emojiList.forEach((emojiObj: UnicodeEmojiData) => {\n      const emoji = emojiObj.emoji;\n      const name = emojiObj.name || emoji;\n      const slug = emojiObj.slug || generateShortcode(name);\n\n      const emojiData: EmojiData = {\n        emoji,\n        name,\n        shortcode: slug.startsWith(':') ? slug : `:${slug}:`,\n        unicode: (Array.from(emoji) as string[])\n          .map((char) => char.codePointAt(0)?.toString(16).toUpperCase() || '')\n          .join('-'),\n        category,\n        keywords: generateKeywords(name, slug),\n        supportsSkinTone: emojiObj.skin_tone_support || false,\n      };\n\n      allEmojis.push(emojiData);\n    });\n  });\n\n  // Cache the processed data\n  cachedEmojiData = allEmojis;\n\n  return allEmojis;\n}\n\n/**\n * Get all emojis\n */\nexport function getAllEmojis(): EmojiData[] {\n  return processEmojiData();\n}\n\n/**\n * Get emojis by category\n */\nexport function getEmojisByCategory(categoryId: CategoryId): EmojiData[] {\n  return processEmojiData().filter((emoji) => emoji.category === categoryId);\n}\n\n/**\n * Get emoji by shortcode\n */\nexport function getEmojiByShortcode(shortcode: string): EmojiData | undefined {\n  return processEmojiData().find((emoji) => emoji.shortcode === shortcode);\n}\n\n/**\n * Get emoji by unicode\n */\nexport function getEmojiByUnicode(unicode: string): EmojiData | undefined {\n  return processEmojiData().find((emoji) => emoji.unicode === unicode);\n}\n\n/**\n * Apply skin tone to an emoji\n */\nexport function applySkinTone(emoji: string, skinToneModifier: string): string {\n  if (!skinToneModifier) return emoji;\n\n  // Remove existing skin tone if present\n  const withoutSkinTone = emoji.replace(/[\\u{1F3FB}-\\u{1F3FF}]/gu, '');\n\n  // Add new skin tone after the base emoji\n  return withoutSkinTone + skinToneModifier;\n}\n\n/**\n * Get base emoji (without skin tone)\n */\nexport function getBaseEmoji(emoji: string): string {\n  return emoji.replace(/[\\u{1F3FB}-\\u{1F3FF}]/gu, '');\n}\n\n/**\n * Compute unicode codepoints from an emoji string\n */\nexport function getUnicodeFromEmoji(emoji: string): string {\n  return (Array.from(emoji) as string[])\n    .map((char) => char.codePointAt(0)?.toString(16).toUpperCase() || '')\n    .join('-');\n}\n\n/**\n * Detect skin tone from an emoji string\n */\nexport function detectSkinTone(emoji: string): number {\n  const skinToneMap: Record<string, number> = {\n    '\\u{1F3FB}': 1, // Light\n    '\\u{1F3FC}': 2, // Medium-Light\n    '\\u{1F3FD}': 3, // Medium\n    '\\u{1F3FE}': 4, // Medium-Dark\n    '\\u{1F3FF}': 5, // Dark\n  };\n\n  for (const [modifier, tone] of Object.entries(skinToneMap)) {\n    if (emoji.includes(modifier)) {\n      return tone;\n    }\n  }\n\n  return 0; // Default (no skin tone)\n}\n","import { CategoryConfig, CategoryId, EmojiData } from '../types';\nimport { getEmojisByCategory } from './emojiData';\n\n/**\n * Category definitions with icons and display names\n */\nexport const CATEGORIES: Omit<CategoryConfig, 'emojis'>[] = [\n  {\n    id: CategoryId.Frequent,\n    name: 'Frequently Used',\n    icon: '🕒',\n  },\n  {\n    id: CategoryId.SmileysAndPeople,\n    name: 'Smileys & People',\n    icon: '😀',\n  },\n  {\n    id: CategoryId.AnimalsAndNature,\n    name: 'Animals & Nature',\n    icon: '🐶',\n  },\n  {\n    id: CategoryId.FoodAndDrink,\n    name: 'Food & Drink',\n    icon: '🍕',\n  },\n  {\n    id: CategoryId.Activities,\n    name: 'Activities',\n    icon: '⚽',\n  },\n  {\n    id: CategoryId.TravelAndPlaces,\n    name: 'Travel & Places',\n    icon: '🚗',\n  },\n  {\n    id: CategoryId.Objects,\n    name: 'Objects',\n    icon: '💡',\n  },\n  {\n    id: CategoryId.Symbols,\n    name: 'Symbols',\n    icon: '❤️',\n  },\n  {\n    id: CategoryId.Flags,\n    name: 'Flags',\n    icon: '🏁',\n  },\n];\n\n/**\n * Get all categories with their emojis\n */\nexport function getAllCategories(includeFrequent = true): CategoryConfig[] {\n  const categories = CATEGORIES.filter((cat) => includeFrequent || cat.id !== CategoryId.Frequent)\n    .map((cat) => {\n      // Skip loading emojis for frequent category, it will be populated dynamically\n      if (cat.id === CategoryId.Frequent) {\n        return {\n          ...cat,\n          emojis: [],\n        };\n      }\n\n      return {\n        ...cat,\n        emojis: getEmojisByCategory(cat.id as CategoryId),\n      };\n    });\n\n  return categories;\n}\n\n/**\n * Get category by ID\n */\nexport function getCategoryById(id: CategoryId): CategoryConfig | undefined {\n  const categoryDef = CATEGORIES.find((cat) => cat.id === id);\n  if (!categoryDef) return undefined;\n\n  if (id === CategoryId.Frequent) {\n    return {\n      ...categoryDef,\n      emojis: [],\n    };\n  }\n\n  return {\n    ...categoryDef,\n    emojis: getEmojisByCategory(id),\n  };\n}\n\n/**\n * Group emojis by category\n */\nexport function groupEmojisByCategory(emojis: EmojiData[]): Record<CategoryId, EmojiData[]> {\n  const grouped: Record<string, EmojiData[]> = {};\n\n  emojis.forEach((emoji) => {\n    if (!grouped[emoji.category]) {\n      grouped[emoji.category] = [];\n    }\n    grouped[emoji.category].push(emoji);\n  });\n\n  return grouped as Record<CategoryId, EmojiData[]>;\n}\n\n/**\n * Get category display name\n */\nexport function getCategoryName(id: CategoryId): string {\n  return CATEGORIES.find((cat) => cat.id === id)?.name || id;\n}\n\n/**\n * Get category icon\n */\nexport function getCategoryIcon(id: CategoryId): string {\n  return CATEGORIES.find((cat) => cat.id === id)?.icon || '📁';\n}\n","import { EmojiData } from '../types';\n\n/**\n * Search emojis by query\n * @param emojis - List of emojis to search\n * @param query - Search query\n * @returns Filtered and sorted emojis\n */\nexport function searchEmojis(emojis: EmojiData[], query: string): EmojiData[] {\n  if (!query || query.trim() === '') {\n    return emojis;\n  }\n\n  const normalizedQuery = query.toLowerCase().trim();\n\n  // Score each emoji based on relevance\n  const scored = emojis\n    .map((emoji) => {\n      let score = 0;\n\n      // Exact match on name (highest priority)\n      if (emoji.name.toLowerCase() === normalizedQuery) {\n        score += 100;\n      }\n      // Name starts with query\n      else if (emoji.name.toLowerCase().startsWith(normalizedQuery)) {\n        score += 50;\n      }\n      // Name contains query\n      else if (emoji.name.toLowerCase().includes(normalizedQuery)) {\n        score += 25;\n      }\n\n      // Exact match on shortcode\n      if (emoji.shortcode.toLowerCase().includes(normalizedQuery)) {\n        score += 40;\n      }\n\n      // Match in keywords\n      const keywordMatches = emoji.keywords.filter((keyword) =>\n        keyword.toLowerCase().includes(normalizedQuery)\n      );\n      score += keywordMatches.length * 10;\n\n      // Exact keyword match\n      if (emoji.keywords.some((keyword) => keyword.toLowerCase() === normalizedQuery)) {\n        score += 30;\n      }\n\n      return { emoji, score };\n    })\n    .filter(({ score }) => score > 0);\n\n  // Sort by score (descending), then alphabetically\n  scored.sort((a, b) => {\n    if (b.score !== a.score) {\n      return b.score - a.score;\n    }\n    return a.emoji.name.localeCompare(b.emoji.name);\n  });\n\n  return scored.map(({ emoji }) => emoji);\n}\n\n/**\n * Debounce function for search input with cancellation support\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function debounce<T extends (...args: any[]) => any>(\n  func: T,\n  wait: number\n): ((...args: Parameters<T>) => void) & { cancel: () => void } {\n  let timeout: ReturnType<typeof setTimeout> | null = null;\n\n  const debouncedFunction = function executedFunction(...args: Parameters<T>) {\n    const later = () => {\n      timeout = null;\n      func(...args);\n    };\n\n    if (timeout) {\n      clearTimeout(timeout);\n    }\n    timeout = setTimeout(later, wait);\n  };\n\n  // Add cancel method to clear pending timeout\n  debouncedFunction.cancel = () => {\n    if (timeout) {\n      clearTimeout(timeout);\n      timeout = null;\n    }\n  };\n\n  return debouncedFunction as typeof debouncedFunction & { cancel: () => void };\n}\n","import { useState, useCallback, useEffect, useMemo } from 'react';\nimport { EmojiData } from '../types';\nimport { searchEmojis, debounce } from '../utils/search';\n\n/**\n * Hook for searching emojis with debouncing\n */\nexport function useEmojiSearch(allEmojis: EmojiData[], debounceMs = 300) {\n  const [query, setQuery] = useState('');\n  const [debouncedQuery, setDebouncedQuery] = useState('');\n\n  // Create debounced function\n  const debouncedSetQuery = useMemo(\n    () =>\n      debounce((value: string) => {\n        setDebouncedQuery(value);\n      }, debounceMs),\n    [debounceMs]\n  );\n\n  // Update debounced query when query changes\n  useEffect(() => {\n    debouncedSetQuery(query);\n  }, [query, debouncedSetQuery]);\n\n  // Cleanup: cancel pending debounced calls on unmount\n  useEffect(() => {\n    return () => {\n      debouncedSetQuery.cancel();\n    };\n  }, [debouncedSetQuery]);\n\n  // Search results\n  const results = useMemo(() => {\n    return searchEmojis(allEmojis, debouncedQuery);\n  }, [allEmojis, debouncedQuery]);\n\n  // Update query\n  const updateQuery = useCallback((value: string) => {\n    setQuery(value);\n  }, []);\n\n  // Clear query\n  const clearQuery = useCallback(() => {\n    setQuery('');\n    setDebouncedQuery('');\n  }, []);\n\n  return {\n    query,\n    results,\n    isSearching: query.trim() !== '',\n    updateQuery,\n    clearQuery,\n  };\n}\n","import { StorageAdapter, EmojiUsageData } from '../types';\n\n/**\n * Default localStorage implementation of StorageAdapter\n */\nexport class LocalStorageAdapter implements StorageAdapter {\n  private prefix: string;\n\n  constructor(prefix = 'mm-emoji') {\n    this.prefix = prefix;\n  }\n\n  private getKey(key: string): string {\n    return `${this.prefix}:${key}`;\n  }\n\n  getItem(key: string): string | null {\n    try {\n      return localStorage.getItem(this.getKey(key));\n    } catch (error) {\n      console.error('Error reading from localStorage:', error);\n      return null;\n    }\n  }\n\n  setItem(key: string, value: string): void {\n    try {\n      localStorage.setItem(this.getKey(key), value);\n    } catch (error) {\n      console.error('Error writing to localStorage:', error);\n    }\n  }\n\n  removeItem(key: string): void {\n    try {\n      localStorage.removeItem(this.getKey(key));\n    } catch (error) {\n      console.error('Error removing from localStorage:', error);\n    }\n  }\n\n  clear(): void {\n    try {\n      // Only clear keys with our prefix\n      const keys = Object.keys(localStorage);\n      keys.forEach((key) => {\n        if (key.startsWith(`${this.prefix}:`)) {\n          localStorage.removeItem(key);\n        }\n      });\n    } catch (error) {\n      console.error('Error clearing localStorage:', error);\n    }\n  }\n}\n\n/**\n * Get emoji usage data from storage\n */\nexport function getEmojiUsageData(storage: StorageAdapter): EmojiUsageData {\n  const defaultData: EmojiUsageData = {\n    recent: [],\n    frequent: {},\n    skinTones: {},\n  };\n\n  try {\n    const stored = storage.getItem('usage');\n    if (!stored) return defaultData;\n\n    const parsed = JSON.parse(stored);\n    return {\n      recent: parsed.recent || [],\n      frequent: parsed.frequent || {},\n      skinTones: parsed.skinTones || {},\n    };\n  } catch (error) {\n    console.error('Error parsing emoji usage data:', error);\n    return defaultData;\n  }\n}\n\n/**\n * Save emoji usage data to storage\n */\nexport function saveEmojiUsageData(storage: StorageAdapter, data: EmojiUsageData): void {\n  try {\n    storage.setItem('usage', JSON.stringify(data));\n  } catch (error) {\n    console.error('Error saving emoji usage data:', error);\n  }\n}\n\n/**\n * Add emoji to recent list\n */\nexport function addToRecent(storage: StorageAdapter, emoji: string, maxRecent = 40): void {\n  const data = getEmojiUsageData(storage);\n\n  // Remove emoji if it already exists\n  data.recent = data.recent.filter((e) => e !== emoji);\n\n  // Add to front\n  data.recent.unshift(emoji);\n\n  // Limit size\n  if (data.recent.length > maxRecent) {\n    data.recent = data.recent.slice(0, maxRecent);\n  }\n\n  saveEmojiUsageData(storage, data);\n}\n\n/**\n * Increment emoji frequency count\n */\nexport function incrementFrequency(storage: StorageAdapter, emoji: string): void {\n  const data = getEmojiUsageData(storage);\n\n  if (!data.frequent[emoji]) {\n    data.frequent[emoji] = 0;\n  }\n  data.frequent[emoji]++;\n\n  saveEmojiUsageData(storage, data);\n}\n\n/**\n * Get frequently used emojis (sorted by count)\n */\nexport function getFrequentEmojis(storage: StorageAdapter, limit = 40): string[] {\n  const data = getEmojiUsageData(storage);\n\n  const sorted = Object.entries(data.frequent).sort((a, b) => b[1] - a[1]);\n\n  return sorted.slice(0, limit).map(([emoji]) => emoji);\n}\n\n/**\n * Save skin tone preference for an emoji base\n */\nexport function saveSkinTonePreference(\n  storage: StorageAdapter,\n  baseEmoji: string,\n  skinTone: number\n): void {\n  const data = getEmojiUsageData(storage);\n  data.skinTones[baseEmoji] = skinTone;\n  saveEmojiUsageData(storage, data);\n}\n\n/**\n * Get skin tone preference for an emoji base\n */\nexport function getSkinTonePreference(storage: StorageAdapter, baseEmoji: string): number | null {\n  const data = getEmojiUsageData(storage);\n  return data.skinTones[baseEmoji] ?? null;\n}\n","import { useMemo } from 'react';\nimport { StorageAdapter } from '../types';\nimport { LocalStorageAdapter } from '../utils/storage';\n\n/**\n * Hook to get storage adapter\n */\nexport function useEmojiStorage(\n  customStorage?: StorageAdapter,\n  storageKey = 'mm-emoji'\n): StorageAdapter {\n  return useMemo(() => {\n    if (customStorage) {\n      return customStorage;\n    }\n\n    // Default to localStorage\n    return new LocalStorageAdapter(storageKey);\n  }, [customStorage, storageKey]);\n}\n","import { useState, useEffect, useCallback } from 'react';\nimport { StorageAdapter } from '../types';\nimport { getEmojiUsageData, addToRecent } from '../utils/storage';\n\n/**\n * Hook for tracking recently used emojis\n */\nexport function useRecentlyUsed(storage: StorageAdapter, maxRecent = 40) {\n  const [recentEmojis, setRecentEmojis] = useState<string[]>([]);\n\n  // Load recent emojis on mount\n  useEffect(() => {\n    const data = getEmojiUsageData(storage);\n    setRecentEmojis(data.recent);\n  }, [storage]);\n\n  // Add emoji to recent\n  const addRecent = useCallback(\n    (emoji: string) => {\n      addToRecent(storage, emoji, maxRecent);\n      const data = getEmojiUsageData(storage);\n      setRecentEmojis(data.recent);\n    },\n    [storage, maxRecent]\n  );\n\n  return {\n    recentEmojis,\n    addRecent,\n  };\n}\n","import { useState, useEffect, useCallback } from 'react';\nimport { StorageAdapter } from '../types';\nimport { incrementFrequency, getFrequentEmojis } from '../utils/storage';\n\n/**\n * Hook for tracking frequently used emojis\n */\nexport function useFrequentlyUsed(storage: StorageAdapter, maxFrequent = 40) {\n  const [frequentEmojis, setFrequentEmojis] = useState<string[]>([]);\n\n  // Load frequent emojis on mount\n  useEffect(() => {\n    const emojis = getFrequentEmojis(storage, maxFrequent);\n    setFrequentEmojis(emojis);\n  }, [storage, maxFrequent]);\n\n  // Add emoji to frequent\n  const addFrequent = useCallback(\n    (emoji: string) => {\n      incrementFrequency(storage, emoji);\n      const emojis = getFrequentEmojis(storage, maxFrequent);\n      setFrequentEmojis(emojis);\n    },\n    [storage, maxFrequent]\n  );\n\n  return {\n    frequentEmojis,\n    addFrequent,\n  };\n}\n","import { useState, useEffect, useCallback } from 'react';\nimport { StorageAdapter, SkinTone, SKIN_TONE_MODIFIERS } from '../types';\nimport { saveSkinTonePreference, getSkinTonePreference } from '../utils/storage';\nimport { applySkinTone, getBaseEmoji } from '../utils/emojiData';\n\n/**\n * Hook for managing skin tone preferences\n */\nexport function useSkinTone(storage: StorageAdapter) {\n  const [skinTonePreferences, setSkinTonePreferences] = useState<Record<string, number>>({});\n\n  // Load preferences on mount\n  useEffect(() => {\n    // Preferences are loaded on-demand when needed\n  }, [storage]);\n\n  // Get preferred skin tone for an emoji\n  const getPreferredSkinTone = useCallback(\n    (emoji: string): SkinTone => {\n      const baseEmoji = getBaseEmoji(emoji);\n      if (skinTonePreferences[baseEmoji] !== undefined) {\n        return skinTonePreferences[baseEmoji];\n      }\n\n      const stored = getSkinTonePreference(storage, baseEmoji);\n      if (stored !== null) {\n        setSkinTonePreferences((prev) => ({ ...prev, [baseEmoji]: stored }));\n        return stored as SkinTone;\n      }\n\n      return SkinTone.Default;\n    },\n    [storage, skinTonePreferences]\n  );\n\n  // Set preferred skin tone for an emoji\n  const setPreferredSkinTone = useCallback(\n    (emoji: string, skinTone: SkinTone) => {\n      const baseEmoji = getBaseEmoji(emoji);\n      saveSkinTonePreference(storage, baseEmoji, skinTone);\n      setSkinTonePreferences((prev) => ({ ...prev, [baseEmoji]: skinTone }));\n    },\n    [storage]\n  );\n\n  // Apply skin tone to emoji\n  const applyTone = useCallback((emoji: string, skinTone: SkinTone): string => {\n    const modifier = SKIN_TONE_MODIFIERS[skinTone];\n    return applySkinTone(emoji, modifier);\n  }, []);\n\n  return {\n    getPreferredSkinTone,\n    setPreferredSkinTone,\n    applyTone,\n  };\n}\n","import React, { useRef, useEffect, CSSProperties } from 'react';\n\ninterface SearchBarProps {\n  value: string;\n  onChange: (value: string) => void;\n  onClear: () => void;\n  placeholder?: string;\n  autoFocus?: boolean;\n  style?: CSSProperties;\n  className?: string;\n}\n\nexport const SearchBar: React.FC<SearchBarProps> = ({\n  value,\n  onChange,\n  onClear,\n  placeholder = 'Search emojis...',\n  autoFocus = true,\n  style,\n  className,\n}) => {\n  const inputRef = useRef<HTMLInputElement>(null);\n\n  useEffect(() => {\n    if (autoFocus && inputRef.current) {\n      inputRef.current.focus();\n    }\n  }, [autoFocus]);\n\n  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n    onChange(e.target.value);\n  };\n\n  const handleClear = () => {\n    onClear();\n    if (inputRef.current) {\n      inputRef.current.focus();\n    }\n  };\n\n  return (\n    <div className={`search-bar ${className || ''}`} style={style}>\n      <div className=\"search-input-wrapper\">\n        <span className=\"search-icon\" aria-hidden=\"true\">\n          🔍\n        </span>\n        <input\n          ref={inputRef}\n          type=\"text\"\n          className=\"search-input\"\n          value={value}\n          onChange={handleChange}\n          placeholder={placeholder}\n          role=\"searchbox\"\n          aria-label=\"Search emojis\"\n        />\n        {value && (\n          <button\n            type=\"button\"\n            className=\"search-clear\"\n            onClick={handleClear}\n            aria-label=\"Clear search\"\n          >\n            ✕\n          </button>\n        )}\n      </div>\n    </div>\n  );\n};\n","import React, { CSSProperties } from 'react';\nimport { CategoryConfig } from '../types';\n\ninterface CategoryTabsProps {\n  categories: CategoryConfig[];\n  activeCategory: string;\n  onCategoryClick: (categoryId: string) => void;\n  style?: CSSProperties;\n  className?: string;\n}\n\nexport const CategoryTabs: React.FC<CategoryTabsProps> = ({\n  categories,\n  activeCategory,\n  onCategoryClick,\n  style,\n  className,\n}) => {\n  return (\n    <div className={`category-tabs ${className || ''}`} style={style} role=\"tablist\">\n      {categories.map((category) => (\n        <button\n          key={category.id}\n          type=\"button\"\n          className={`category-tab ${activeCategory === category.id ? 'active' : ''}`}\n          onClick={() => onCategoryClick(category.id)}\n          aria-label={category.name}\n          aria-selected={activeCategory === category.id}\n          title={category.name}\n          role=\"tab\"\n        >\n          <span className=\"category-icon\">{category.icon}</span>\n        </button>\n      ))}\n    </div>\n  );\n};\n","import React, { CSSProperties } from 'react';\nimport { EmojiData } from '../types';\n\ninterface EmojiButtonProps {\n  emoji: EmojiData;\n  onClick: (emoji: EmojiData) => void;\n  onMouseEnter?: (emoji: EmojiData) => void;\n  onMouseLeave?: () => void;\n  onLongPress?: (emoji: EmojiData) => void;\n  isSelected?: boolean;\n  style?: CSSProperties;\n  className?: string;\n}\n\nexport const EmojiButton: React.FC<EmojiButtonProps> = ({\n  emoji,\n  onClick,\n  onMouseEnter,\n  onMouseLeave,\n  onLongPress,\n  isSelected,\n  style,\n  className,\n}) => {\n  const [longPressTimer, setLongPressTimer] = React.useState<ReturnType<\n    typeof setTimeout\n  > | null>(null);\n  const [longPressFired, setLongPressFired] = React.useState(false);\n\n  const clearTimer = React.useCallback(() => {\n    if (longPressTimer) {\n      clearTimeout(longPressTimer);\n      setLongPressTimer(null);\n    }\n  }, [longPressTimer]);\n\n  const handleMouseDown = () => {\n    if (onLongPress && emoji.supportsSkinTone) {\n      setLongPressFired(false);\n      const timer = setTimeout(() => {\n        setLongPressFired(true);\n        onLongPress(emoji);\n      }, 500);\n      setLongPressTimer(timer);\n    }\n  };\n\n  const handleMouseUp = () => {\n    clearTimer();\n  };\n\n  const handleClick = () => {\n    handleMouseUp();\n    // Don't trigger onClick if long press already fired\n    if (!longPressFired) {\n      onClick(emoji);\n    }\n    setLongPressFired(false);\n  };\n\n  const handleMouseEnterInternal = () => {\n    if (onMouseEnter) {\n      onMouseEnter(emoji);\n    }\n  };\n\n  const handleMouseLeaveInternal = () => {\n    // Clear timer when pointer leaves the button\n    clearTimer();\n    if (onMouseLeave) {\n      onMouseLeave();\n    }\n  };\n\n  return (\n    <button\n      type=\"button\"\n      className={`emoji-button ${isSelected ? 'selected' : ''} ${className || ''}`}\n      onClick={handleClick}\n      onMouseDown={handleMouseDown}\n      onMouseUp={handleMouseUp}\n      onMouseEnter={handleMouseEnterInternal}\n      onMouseLeave={handleMouseLeaveInternal}\n      onTouchStart={handleMouseDown}\n      onTouchEnd={handleMouseUp}\n      onTouchCancel={clearTimer}\n      aria-label={emoji.name}\n      title={emoji.name}\n      style={style}\n    >\n      <span className=\"emoji-char\">{emoji.emoji}</span>\n    </button>\n  );\n};\n","import React, { useRef, useCallback, CSSProperties, forwardRef } from 'react';\nimport { CategoryConfig, EmojiData } from '../types';\nimport { EmojiButton } from './EmojiButton';\n\ninterface EmojiGridProps {\n  categories: CategoryConfig[];\n  onEmojiSelect: (emoji: EmojiData) => void;\n  onEmojiHover?: (emoji: EmojiData) => void;\n  onEmojiHoverEnd?: () => void;\n  onLongPress?: (emoji: EmojiData) => void;\n  presetEmoji?: string;\n  onCategoryChange?: (categoryId: string) => void;\n  style?: CSSProperties;\n  className?: string;\n}\n\nexport const EmojiGrid = forwardRef<HTMLDivElement, EmojiGridProps>(({\n  categories,\n  onEmojiSelect,\n  onEmojiHover,\n  onEmojiHoverEnd,\n  onLongPress,\n  presetEmoji,\n  onCategoryChange,\n  style,\n  className,\n}, ref) => {\n  const internalRef = useRef<HTMLDivElement>(null);\n  const categoryRefs = useRef<Record<string, HTMLDivElement | null>>({});\n\n  // Use the passed ref or internal ref\n  const gridRef = ref || internalRef;\n\n  // Handle scroll to update active category\n  const handleScroll = useCallback(() => {\n    // Helper to get the current element (inline to avoid dependencies)\n    const getGridElement = () => {\n      if (typeof gridRef === 'function') return null;\n      return gridRef.current;\n    };\n\n    const gridElement = getGridElement();\n    if (!gridElement || !onCategoryChange) return;\n\n    const scrollTop = gridElement.scrollTop;\n    const gridHeight = gridElement.clientHeight;\n\n    // Find the category that's most visible\n    let activeCategory = categories[0]?.id;\n    categories.forEach((category) => {\n      const element = categoryRefs.current[category.id];\n      if (!element) return;\n\n      const elementTop = element.offsetTop;\n      const elementBottom = elementTop + element.clientHeight;\n\n      // Check if element is in viewport\n      if (elementTop <= scrollTop + gridHeight / 2 && elementBottom >= scrollTop) {\n        activeCategory = category.id;\n      }\n    });\n\n    onCategoryChange(activeCategory);\n  }, [categories, onCategoryChange, gridRef]);\n\n  return (\n    <div\n      ref={gridRef as React.RefObject<HTMLDivElement>}\n      className={`emoji-grid ${className || ''}`}\n      style={style}\n      onScroll={handleScroll}\n      role=\"tabpanel\"\n    >\n      {categories.map((category) => {\n        // Skip empty categories\n        if (category.emojis.length === 0) {\n          return null;\n        }\n\n        return (\n          <div\n            key={category.id}\n            ref={(el) => {\n              categoryRefs.current[category.id] = el;\n            }}\n            className=\"emoji-category\"\n            data-category-id={category.id}\n          >\n            <h3 className=\"category-title\">{category.name}</h3>\n            <div className=\"emoji-list\">\n              {category.emojis.map((emoji) => (\n                <EmojiButton\n                  key={emoji.emoji}\n                  emoji={emoji}\n                  onClick={onEmojiSelect}\n                  onMouseEnter={onEmojiHover}\n                  onMouseLeave={onEmojiHoverEnd}\n                  onLongPress={onLongPress}\n                  isSelected={presetEmoji === emoji.emoji}\n                />\n              ))}\n            </div>\n          </div>\n        );\n      })}\n    </div>\n  );\n});\n\nEmojiGrid.displayName = 'EmojiGrid';\n\n// Export a method to scroll to category (this would typically be used via ref)\nexport const useEmojiGridScroll = (gridRef: React.RefObject<HTMLDivElement>) => {\n  const scrollToCategory = useCallback(\n    (categoryId: string) => {\n      if (!gridRef.current) return;\n\n      const categoryElement = gridRef.current.querySelector(\n        `[data-category-id=\"${categoryId}\"]`\n      ) as HTMLElement;\n\n      if (categoryElement) {\n        const categoryTop = categoryElement.offsetTop;\n        gridRef.current.scrollTo({\n          top: categoryTop - 8,\n          behavior: 'smooth',\n        });\n      }\n    },\n    [gridRef]\n  );\n\n  return { scrollToCategory };\n};\n","import React, { CSSProperties } from 'react';\nimport { EmojiData } from '../types';\n\ninterface PreviewProps {\n  emoji: EmojiData | null;\n  style?: CSSProperties;\n  className?: string;\n}\n\nexport const Preview: React.FC<PreviewProps> = ({ emoji, style, className }) => {\n  if (!emoji) {\n    return (\n      <div className={`preview empty ${className || ''}`} style={style}>\n        <div className=\"preview-placeholder\">Select an emoji</div>\n      </div>\n    );\n  }\n\n  return (\n    <div className={`preview ${className || ''}`} style={style}>\n      <span className=\"preview-emoji\">{emoji.emoji}</span>\n      <div className=\"preview-info\">\n        <div className=\"preview-name\">{emoji.name}</div>\n        <div className=\"preview-shortcode\">{emoji.shortcode}</div>\n      </div>\n    </div>\n  );\n};\n","import React, { CSSProperties } from 'react';\nimport { SkinTone, SKIN_TONE_MODIFIERS } from '../types';\n\ninterface SkinTonePickerProps {\n  baseEmoji: string;\n  currentTone: SkinTone;\n  onSelect: (tone: SkinTone) => void;\n  onClose: () => void;\n  style?: CSSProperties;\n  className?: string;\n}\n\nconst SKIN_TONE_LABELS: Record<SkinTone, string> = {\n  [SkinTone.Default]: 'Default',\n  [SkinTone.Light]: 'Light',\n  [SkinTone.MediumLight]: 'Medium-Light',\n  [SkinTone.Medium]: 'Medium',\n  [SkinTone.MediumDark]: 'Medium-Dark',\n  [SkinTone.Dark]: 'Dark',\n};\n\nexport const SkinTonePicker: React.FC<SkinTonePickerProps> = ({\n  baseEmoji,\n  currentTone,\n  onSelect,\n  onClose,\n  style,\n  className,\n}) => {\n  const handleSelect = (tone: SkinTone) => {\n    onSelect(tone);\n    onClose();\n  };\n\n  const handleOverlayKeyDown = (e: React.KeyboardEvent) => {\n    if (e.key === 'Escape' || e.key === 'Enter' || e.key === ' ') {\n      e.preventDefault();\n      onClose();\n    }\n  };\n\n  return (\n    <>\n      <div\n        className=\"skin-tone-overlay\"\n        onClick={onClose}\n        onKeyDown={handleOverlayKeyDown}\n        role=\"button\"\n        tabIndex={0}\n        aria-label=\"Close skin tone picker\"\n      />\n      <div className={`skin-tone-picker ${className || ''}`} style={style} role=\"dialog\">\n        <div className=\"skin-tone-grid\">\n          {(Object.keys(SKIN_TONE_MODIFIERS) as unknown as SkinTone[]).map((tone) => {\n            const modifier = SKIN_TONE_MODIFIERS[tone];\n            const emojiWithTone = modifier ? baseEmoji + modifier : baseEmoji;\n\n            return (\n              <button\n                key={tone}\n                type=\"button\"\n                className={`skin-tone-option ${currentTone === tone ? 'selected' : ''}`}\n                onClick={() => handleSelect(tone)}\n                aria-label={SKIN_TONE_LABELS[tone]}\n                title={SKIN_TONE_LABELS[tone]}\n              >\n                <span className=\"skin-tone-emoji\">{emojiWithTone}</span>\n              </button>\n            );\n          })}\n        </div>\n      </div>\n    </>\n  );\n};\n","import React, { useState, useMemo, useCallback, useRef } from 'react';\nimport { EmojiPickerProps, EmojiData, CategoryId, CategoryConfig, SkinTone } from '../types';\nimport { getAllEmojis, getBaseEmoji, getUnicodeFromEmoji, detectSkinTone } from '../utils/emojiData';\nimport { getAllCategories } from '../utils/categories';\nimport { useEmojiSearch } from '../hooks/useEmojiSearch';\nimport { useEmojiStorage } from '../hooks/useEmojiStorage';\nimport { useRecentlyUsed } from '../hooks/useRecentlyUsed';\nimport { useFrequentlyUsed } from '../hooks/useFrequentlyUsed';\nimport { useSkinTone } from '../hooks/useSkinTone';\nimport { SearchBar } from './SearchBar';\nimport { CategoryTabs } from './CategoryTabs';\nimport { EmojiGrid } from './EmojiGrid';\nimport { Preview } from './Preview';\nimport { SkinTonePicker } from './SkinTonePicker';\n\n/**\n * Main EmojiPicker component\n */\nexport const EmojiPicker: React.FC<EmojiPickerProps> = ({\n  onEmojiSelect,\n  presetEmoji,\n  theme = 'light',\n  width = 376,\n  height = 435,\n  className = '',\n  styles = {},\n  autoFocus = true,\n  showPreview = true,\n  showSkinTones = true,\n  enableFrequentlyUsed = true,\n  maxFrequentRows = 2,\n  storageKey = 'mm-emoji',\n  customStorage,\n  searchPlaceholder = 'Search emojis...',\n  searchDebounce = 300,\n}) => {\n  // State\n  const [activeCategory, setActiveCategory] = useState<string>(CategoryId.SmileysAndPeople);\n  const [hoveredEmoji, setHoveredEmoji] = useState<EmojiData | null>(null);\n  const [skinTonePickerEmoji, setSkinTonePickerEmoji] = useState<EmojiData | null>(null);\n\n  // Refs\n  const gridRef = useRef<HTMLDivElement>(null);\n  const searchRef = useRef<HTMLDivElement>(null);\n  const categoryTabsRef = useRef<HTMLDivElement>(null);\n\n  // Hooks\n  const storage = useEmojiStorage(customStorage, storageKey);\n  const { recentEmojis, addRecent } = useRecentlyUsed(storage);\n  const { frequentEmojis, addFrequent } = useFrequentlyUsed(storage);\n  const { getPreferredSkinTone, setPreferredSkinTone, applyTone } = useSkinTone(storage);\n\n  // Get all emojis\n  const allEmojis = useMemo(() => getAllEmojis(), []);\n\n  // Search\n  const { query, results, isSearching, updateQuery, clearQuery } = useEmojiSearch(\n    allEmojis,\n    searchDebounce\n  );\n\n  // Build categories with frequent/recent\n  const categories = useMemo(() => {\n    let cats = getAllCategories(false); // Don't include frequent by default\n\n    // Add frequent category if enabled and has items\n    if (enableFrequentlyUsed && frequentEmojis.length > 0) {\n      const maxEmojis = maxFrequentRows * 9; // 9 emojis per row\n      const frequentEmojiData = frequentEmojis\n        .slice(0, maxEmojis)\n        .map((storedEmoji) => {\n          // Extract base emoji for lookup (remove skin tone modifiers)\n          const baseEmoji = getBaseEmoji(storedEmoji);\n          const found = allEmojis.find((e) => e.emoji === baseEmoji);\n\n          // If found and the stored emoji has a tone, preserve it\n          if (found && storedEmoji !== baseEmoji) {\n            return { ...found, emoji: storedEmoji };\n          }\n          return found;\n        })\n        .filter((e): e is EmojiData => e !== undefined);\n\n      cats = [\n        {\n          id: CategoryId.Frequent,\n          name: 'Frequently Used',\n          icon: '🕒',\n          emojis: frequentEmojiData,\n        },\n        ...cats,\n      ];\n    }\n\n    // Add recent emojis to the first category\n    if (recentEmojis.length > 0) {\n      const recentEmojiData = recentEmojis\n        .slice(0, 18) // Show max 2 rows\n        .map((storedEmoji) => {\n          // Extract base emoji for lookup (remove skin tone modifiers)\n          const baseEmoji = getBaseEmoji(storedEmoji);\n          const found = allEmojis.find((e) => e.emoji === baseEmoji);\n\n          // If found and the stored emoji has a tone, preserve it\n          if (found && storedEmoji !== baseEmoji) {\n            return { ...found, emoji: storedEmoji };\n          }\n          return found;\n        })\n        .filter((e): e is EmojiData => e !== undefined);\n\n      if (recentEmojiData.length > 0) {\n        cats = [\n          {\n            id: 'recent',\n            name: 'Recently Used',\n            icon: '⏱️',\n            emojis: recentEmojiData,\n          },\n          ...cats,\n        ];\n      }\n    }\n\n    return cats;\n  }, [allEmojis, frequentEmojis, recentEmojis, enableFrequentlyUsed, maxFrequentRows]);\n\n  // Display categories (search results or regular categories)\n  const displayCategories: CategoryConfig[] = useMemo(() => {\n    if (isSearching) {\n      return [\n        {\n          id: 'search-results',\n          name: 'Search Results',\n          icon: '🔍',\n          emojis: results,\n        },\n      ];\n    }\n    return categories;\n  }, [isSearching, results, categories]);\n\n  // Handle emoji selection\n  const handleEmojiSelect = useCallback(\n    (emoji: EmojiData) => {\n      // Apply preferred skin tone if available\n      let finalEmoji = emoji.emoji;\n      if (emoji.supportsSkinTone) {\n        const preferredTone = getPreferredSkinTone(emoji.emoji);\n        if (preferredTone !== SkinTone.Default) {\n          finalEmoji = applyTone(emoji.emoji, preferredTone);\n        }\n      }\n\n      // Create final emoji data with updated metadata\n      const finalEmojiData: EmojiData = {\n        ...emoji,\n        emoji: finalEmoji,\n        unicode: getUnicodeFromEmoji(finalEmoji),\n        skinTone: detectSkinTone(finalEmoji),\n      };\n\n      // Track usage\n      addRecent(finalEmoji);\n      addFrequent(finalEmoji);\n\n      // Call parent callback\n      onEmojiSelect(finalEmojiData);\n    },\n    [onEmojiSelect, addRecent, addFrequent, getPreferredSkinTone, applyTone]\n  );\n\n  // Handle emoji hover\n  const handleEmojiHover = useCallback((emoji: EmojiData) => {\n    setHoveredEmoji(emoji);\n  }, []);\n\n  const handleEmojiHoverEnd = useCallback(() => {\n    setHoveredEmoji(null);\n  }, []);\n\n  // Handle long press (skin tone picker)\n  const handleLongPress = useCallback((emoji: EmojiData) => {\n    if (emoji.supportsSkinTone) {\n      setSkinTonePickerEmoji(emoji);\n    }\n  }, []);\n\n  // Handle skin tone selection\n  const handleSkinToneSelect = useCallback(\n    (tone: SkinTone) => {\n      if (!skinTonePickerEmoji) return;\n\n      const baseEmoji = getBaseEmoji(skinTonePickerEmoji.emoji);\n      setPreferredSkinTone(baseEmoji, tone);\n\n      // Apply the tone and select the emoji with updated metadata\n      const emojiWithTone = applyTone(skinTonePickerEmoji.emoji, tone);\n      const finalEmojiData: EmojiData = {\n        ...skinTonePickerEmoji,\n        emoji: emojiWithTone,\n        unicode: getUnicodeFromEmoji(emojiWithTone),\n        skinTone: tone,\n      };\n\n      handleEmojiSelect(finalEmojiData);\n      setSkinTonePickerEmoji(null);\n    },\n    [skinTonePickerEmoji, setPreferredSkinTone, applyTone, handleEmojiSelect]\n  );\n\n  // Handle category tab click\n  const handleCategoryClick = useCallback((categoryId: string) => {\n    setActiveCategory(categoryId);\n    // Scroll to category in grid (only scroll the grid, not the window)\n    if (gridRef.current) {\n      const categoryElement = gridRef.current.querySelector(\n        `[data-category-id=\"${categoryId}\"]`\n      ) as HTMLElement;\n      if (categoryElement) {\n        // Calculate offset based on heights of search and category tabs containers\n        // This ensures proper visual alignment when scrolling to categories\n        let offset = 0;\n\n        if (searchRef.current) {\n          offset += searchRef.current.offsetHeight;\n        }\n\n        if (categoryTabsRef.current) {\n          offset += categoryTabsRef.current.offsetHeight;\n        }\n\n        const scrollPosition = categoryElement.offsetTop - offset;\n        gridRef.current.scrollTo({\n          top: Math.max(0, scrollPosition),\n          behavior: 'smooth',\n        });\n      }\n    }\n  }, []);\n\n  // Determine theme class\n  const themeClass = useMemo(() => {\n    if (theme !== 'auto') return theme;\n\n    // Guard for SSR/non-DOM environments\n    if (typeof window === 'undefined') return 'light';\n\n    return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\n  }, [theme]);\n\n  return (\n    <div\n      className={`emoji-picker theme-${themeClass} ${className}`}\n      style={{\n        width: typeof width === 'number' ? `${width}px` : width,\n        height: typeof height === 'number' ? `${height}px` : height,\n        ...styles.picker,\n      }}\n      role=\"dialog\"\n      aria-label=\"Emoji Picker\"\n    >\n      <div ref={searchRef}>\n        {/* autoFocus is intentional and user-configurable via props */}\n        {/* eslint-disable jsx-a11y/no-autofocus */}\n        <SearchBar\n          value={query}\n          onChange={updateQuery}\n          onClear={clearQuery}\n          placeholder={searchPlaceholder}\n          autoFocus={autoFocus}\n          style={styles.search}\n        />\n        {/* eslint-enable jsx-a11y/no-autofocus */}\n      </div>\n\n      {!isSearching && (\n        <div ref={categoryTabsRef}>\n          <CategoryTabs\n            categories={categories}\n            activeCategory={activeCategory}\n            onCategoryClick={handleCategoryClick}\n            style={styles.categories}\n          />\n        </div>\n      )}\n\n      <EmojiGrid\n        ref={gridRef}\n        categories={displayCategories}\n        onEmojiSelect={handleEmojiSelect}\n        onEmojiHover={showPreview ? handleEmojiHover : undefined}\n        onEmojiHoverEnd={showPreview ? handleEmojiHoverEnd : undefined}\n        onLongPress={showSkinTones ? handleLongPress : undefined}\n        presetEmoji={typeof presetEmoji === 'string' ? presetEmoji : presetEmoji?.emoji}\n        onCategoryChange={!isSearching ? setActiveCategory : undefined}\n        style={styles.emojiGrid}\n      />\n\n      {showPreview && <Preview emoji={hoveredEmoji} style={styles.preview} />}\n\n      {skinTonePickerEmoji && showSkinTones && (\n        <SkinTonePicker\n          baseEmoji={getBaseEmoji(skinTonePickerEmoji.emoji)}\n          currentTone={getPreferredSkinTone(skinTonePickerEmoji.emoji)}\n          onSelect={handleSkinToneSelect}\n          onClose={() => setSkinTonePickerEmoji(null)}\n          style={styles.skinTonePicker}\n        />\n      )}\n    </div>\n  );\n};\n"],"names":["SkinTone","SKIN_TONE_MODIFIERS","CategoryId","GROUP_TO_CATEGORY","generateShortcode","name","generateKeywords","slug","keywords","word","cachedEmojiData","processEmojiData","allEmojis","dataByGroup","group","groupName","category","emojiObj","emoji","emojiData","char","_a","getAllEmojis","getEmojisByCategory","categoryId","applySkinTone","skinToneModifier","getBaseEmoji","getUnicodeFromEmoji","detectSkinTone","skinToneMap","modifier","tone","CATEGORIES","getAllCategories","includeFrequent","cat","getCategoryById","id","categoryDef","searchEmojis","emojis","query","normalizedQuery","scored","score","keywordMatches","keyword","a","b","debounce","func","wait","timeout","debouncedFunction","args","later","useEmojiSearch","debounceMs","setQuery","useState","debouncedQuery","setDebouncedQuery","debouncedSetQuery","useMemo","value","useEffect","results","updateQuery","useCallback","clearQuery","LocalStorageAdapter","prefix","__publicField","key","error","getEmojiUsageData","storage","defaultData","stored","parsed","saveEmojiUsageData","data","addToRecent","maxRecent","e","incrementFrequency","getFrequentEmojis","limit","saveSkinTonePreference","baseEmoji","skinTone","getSkinTonePreference","useEmojiStorage","customStorage","storageKey","useRecentlyUsed","recentEmojis","setRecentEmojis","addRecent","useFrequentlyUsed","maxFrequent","frequentEmojis","setFrequentEmojis","addFrequent","useSkinTone","skinTonePreferences","setSkinTonePreferences","getPreferredSkinTone","prev","setPreferredSkinTone","applyTone","SearchBar","onChange","onClear","placeholder","autoFocus","style","className","inputRef","useRef","handleChange","handleClear","jsx","jsxs","CategoryTabs","categories","activeCategory","onCategoryClick","EmojiButton","onClick","onMouseEnter","onMouseLeave","onLongPress","isSelected","longPressTimer","setLongPressTimer","React","longPressFired","setLongPressFired","clearTimer","handleMouseDown","timer","handleMouseUp","handleClick","handleMouseEnterInternal","handleMouseLeaveInternal","EmojiGrid","forwardRef","onEmojiSelect","onEmojiHover","onEmojiHoverEnd","presetEmoji","onCategoryChange","ref","internalRef","categoryRefs","gridRef","handleScroll","gridElement","scrollTop","gridHeight","element","elementTop","elementBottom","el","Preview","SKIN_TONE_LABELS","SkinTonePicker","currentTone","onSelect","onClose","handleSelect","handleOverlayKeyDown","Fragment","emojiWithTone","EmojiPicker","theme","width","height","styles","showPreview","showSkinTones","enableFrequentlyUsed","maxFrequentRows","searchPlaceholder","searchDebounce","setActiveCategory","hoveredEmoji","setHoveredEmoji","skinTonePickerEmoji","setSkinTonePickerEmoji","searchRef","categoryTabsRef","isSearching","cats","maxEmojis","frequentEmojiData","storedEmoji","found","recentEmojiData","displayCategories","handleEmojiSelect","finalEmoji","preferredTone","finalEmojiData","handleEmojiHover","handleEmojiHoverEnd","handleLongPress","handleSkinToneSelect","handleCategoryClick","categoryElement","offset","scrollPosition","themeClass"],"mappings":"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"}