{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "emoji-picker",
  "type": "registry:ui",
  "title": "Emoji Picker",
  "description": "Searchable, virtualized emoji grid with skin-aware cells and an active emoji footer.",
  "dependencies": [
    "@base-ui/react@^1.8.0",
    "frimousse@^0.4.0",
    "lucide-react@^1.47.0"
  ],
  "registryDependencies": [
    "https://control-ui.dev/r/core.json",
    "https://control-ui.dev/r/spinner.json"
  ],
  "files": [
    {
      "path": "src/registry/knob-contracts/emoji-picker-knobs.ts",
      "target": "@components/control-ui/knob-contracts/emoji-picker-knobs.ts",
      "type": "registry:component",
      "content": "// Generated from src/registry/sources/control-ui/recipes/emoji-picker.css by scripts/gen-knob-contracts.ts — run `bun run sync:knobs`.\nexport const emojiPickerKnobs = [\n  \"--cui-emoji-picker-cell-size\",\n  \"--cui-emoji-picker-height\",\n  \"--cui-emoji-picker-cell-radius\",\n  \"--cui-emoji-picker-active-background\",\n  \"--cui-emoji-picker-header-background\",\n  \"--cui-emoji-picker-header-foreground\",\n] as const;\nexport type EmojiPickerKnobStyle = Partial<Record<(typeof emojiPickerKnobs)[number], string>>;\n"
    },
    {
      "path": "src/registry/sources/control-ui/recipes/emoji-picker.css",
      "target": "@components/control-ui/styles/recipes/emoji-picker.css",
      "type": "registry:file",
      "content": "@layer components {\n  :where([data-control-family=\"emoji-picker\"][data-slot=\"root\"]) {\n    --cui-emoji-picker-cell-size: calc(var(--spacing) * 10);\n    --cui-emoji-picker-cell-radius: var(--radius-control);\n    --cui-emoji-picker-active-background: var(--accent);\n    --cui-emoji-picker-header-background: var(--popover);\n    --cui-emoji-picker-header-foreground: var(--muted-foreground);\n    --cui-emoji-picker-height: 22rem;\n  }\n  :where([data-control-family=\"emoji-picker\"][data-slot=\"root\"]:not([data-variant=\"reactions\"])) {\n    inline-size: calc(var(--_emoji-picker-columns) * var(--cui-emoji-picker-cell-size) + var(--spacing) * 4);\n    max-inline-size: 100%;\n    block-size: var(--cui-emoji-picker-height);\n    color: var(--foreground);\n    font-family: var(--font-sans);\n  }\n\n  :where([data-control-family=\"emoji-picker\"][data-slot=\"categories\"]) {\n    display: flex;\n    justify-content: space-between;\n    flex-shrink: 0;\n    overflow-x: auto;\n    padding-inline: calc(var(--spacing) * 1.5);\n  }\n  :where([data-control-family=\"emoji-picker\"][data-slot=\"category\"]) {\n    display: grid;\n    place-items: center;\n    flex: 0 0 calc(var(--spacing) * 9);\n    block-size: calc(var(--spacing) * 9);\n    border-radius: var(--cui-emoji-picker-cell-radius);\n    color: var(--muted-foreground);\n    cursor: pointer;\n  }\n  :where([data-control-family=\"emoji-picker\"][data-slot=\"category\"]:hover) {\n    color: var(--foreground);\n    background: var(--cui-emoji-picker-active-background);\n  }\n  :where([data-control-family=\"emoji-picker\"][data-slot=\"category\"] svg) {\n    inline-size: calc(var(--spacing) * 4);\n    block-size: calc(var(--spacing) * 4);\n  }\n  :where([data-control-family=\"emoji-picker\"][data-slot=\"recent\"]) {\n    padding-inline: calc(var(--spacing) * 2);\n    padding-block: calc(var(--spacing) * 1);\n  }\n  :where([data-control-family=\"emoji-picker\"][data-slot=\"recent-label\"]) {\n    color: var(--muted-foreground);\n    font-size: var(--text-caption);\n    padding-inline: calc(var(--spacing) * 1);\n  }\n  :where([data-control-family=\"emoji-picker\"]:is([data-slot=\"recent-grid\"], [data-variant=\"reactions\"])) {\n    display: flex;\n  }\n  :where(\n    [data-control-family=\"emoji-picker\"][data-slot=\"root\"]:has(input:not(:placeholder-shown))\n      :is([data-slot=\"categories\"], [data-slot=\"recent\"])\n  ) {\n    display: none;\n  }\n  :where([data-control-family=\"emoji-picker\"][data-slot=\"error\"]) {\n    display: flex;\n    flex-direction: column;\n    align-items: center;\n    justify-content: center;\n    gap: calc(var(--spacing) * 2);\n    block-size: 100%;\n    color: var(--muted-foreground);\n    font-size: var(--text-label);\n  }\n  :where([data-control-family=\"emoji-picker\"][data-slot=\"error\"] button) {\n    color: var(--foreground);\n    text-decoration: underline;\n    min-block-size: 44px;\n    cursor: pointer;\n  }\n  :where([data-control-family=\"emoji-picker\"][data-slot=\"search\"]) {\n    position: relative;\n    margin: calc(var(--spacing) * 2);\n    margin-block-end: calc(var(--spacing) * 1);\n  }\n\n  :where([data-control-family=\"emoji-picker\"][data-slot=\"search-icon\"]) {\n    position: absolute;\n    inset-inline-start: calc(var(--spacing) * 2.5);\n    inline-size: calc(var(--spacing) * 4);\n    block-size: calc(var(--spacing) * 4);\n    color: var(--muted-foreground);\n    pointer-events: none;\n  }\n\n  :where([data-control-family=\"emoji-picker\"][data-slot=\"search-input\"]) {\n    block-size: var(--control-h-sm);\n    padding-inline: calc(var(--spacing) * 8) calc(var(--spacing) * 2.5);\n    border: var(--control-rim-width) solid var(--control-rim);\n    border-radius: var(--radius-control);\n    background: var(--control-fill);\n    box-shadow: var(--shadow-inset);\n    color: var(--foreground);\n    font-size: var(--text-label);\n    --focus-ring-offset: calc(var(--focus-ring-width) * -1);\n  }\n\n  :where([data-control-family=\"emoji-picker\"][data-slot=\"search-input\"])::placeholder {\n    color: var(--muted-foreground);\n  }\n\n  :where([data-control-family=\"emoji-picker\"][data-slot=\"content\"]) {\n    overflow-y: auto;\n    overscroll-behavior: contain;\n    scrollbar-width: thin;\n  }\n\n  :where([data-control-family=\"emoji-picker\"][data-slot=\"loading\"]),\n  :where([data-control-family=\"emoji-picker\"][data-slot=\"empty\"]) {\n    color: var(--muted-foreground);\n    font-size: var(--text-label);\n  }\n\n  :where([data-control-family=\"emoji-picker\"][data-slot=\"list\"]) {\n    padding-block-end: calc(var(--spacing) * 1);\n  }\n\n  :where([data-control-family=\"emoji-picker\"][data-slot=\"category-header\"]) {\n    padding: calc(var(--spacing) * 1.5) calc(var(--spacing) * 2.5) calc(var(--spacing) * 1);\n    background: var(--cui-emoji-picker-header-background);\n    color: var(--cui-emoji-picker-header-foreground);\n    font-size: var(--text-caption);\n    font-weight: var(--font-weight-medium);\n  }\n\n  :where([data-control-family=\"emoji-picker\"][data-slot=\"row\"]) {\n    padding-inline: calc(var(--spacing) * 1.5);\n  }\n\n  :where([data-control-family=\"emoji-picker\"][data-slot=\"emoji\"]) {\n    inline-size: var(--cui-emoji-picker-cell-size);\n    block-size: var(--cui-emoji-picker-cell-size);\n    border-radius: var(--cui-emoji-picker-cell-radius);\n    background: transparent;\n    font-size: 1.25rem;\n    line-height: 1;\n    cursor: default;\n  }\n\n  :where([data-control-family=\"emoji-picker\"][data-slot=\"emoji\"][data-active]) {\n    background: var(--cui-emoji-picker-active-background);\n  }\n\n  :where([data-control-family=\"emoji-picker\"][data-slot=\"footer\"]) {\n    gap: calc(var(--spacing) * 2);\n    min-block-size: calc(var(--spacing) * 11);\n    padding-inline: calc(var(--spacing) * 2.5);\n    border-block-start: 1px solid var(--border);\n    color: var(--muted-foreground);\n    font-size: var(--text-label);\n  }\n\n  :where([data-control-family=\"emoji-picker\"][data-slot=\"footer-emoji\"]) {\n    font-size: 1.25rem;\n    line-height: 1;\n  }\n\n  :where([data-control-family=\"emoji-picker\"][data-slot=\"footer-label\"]) {\n    color: var(--foreground);\n  }\n\n  @media (pointer: coarse) {\n    :where([data-control-family=\"emoji-picker\"][data-slot=\"root\"]) {\n      --cui-emoji-picker-cell-size: 44px;\n    }\n    :where([data-control-family=\"emoji-picker\"][data-slot=\"category\"]) {\n      flex-basis: 44px;\n      block-size: 44px;\n    }\n    :where([data-control-family=\"emoji-picker\"][data-slot=\"search-input\"]) {\n      font-size: 16px;\n    }\n  }\n}\n\n@property --cui-emoji-picker-cell-size {\n  syntax: \"<length>\";\n  inherits: true;\n  initial-value: 0px;\n}\n\n@property --cui-emoji-picker-height {\n  syntax: \"<length>\";\n  inherits: true;\n  initial-value: 0px;\n}\n\n@property --cui-emoji-picker-cell-radius {\n  syntax: \"<length-percentage>\";\n  inherits: true;\n  initial-value: 0px;\n}\n\n@property --cui-emoji-picker-active-background {\n  syntax: \"<color>\";\n  inherits: true;\n  initial-value: transparent;\n}\n\n@property --cui-emoji-picker-header-background {\n  syntax: \"<color>\";\n  inherits: true;\n  initial-value: transparent;\n}\n\n@property --cui-emoji-picker-header-foreground {\n  syntax: \"<color>\";\n  inherits: true;\n  initial-value: transparent;\n}\n"
    },
    {
      "path": "src/registry/sources/control-ui/ui/emoji-picker.tsx",
      "target": "@components/control-ui/ui/emoji-picker.tsx",
      "type": "registry:ui",
      "content": "\"use client\";\n\nimport { Toolbar as ToolbarPrimitive } from \"@base-ui/react/toolbar\";\n\nimport {\n  defaultEmojiDataResolver,\n  type Emoji,\n  type EmojiData,\n  type EmojiDataResolver,\n  type EmojiPickerListCategoryHeaderProps,\n  type EmojiPickerListEmojiProps,\n  type EmojiPickerListRowProps,\n  EmojiPicker as EmojiPickerPrimitive,\n} from \"frimousse\";\nimport {\n  FlagIcon,\n  HandIcon,\n  HashIcon,\n  HeartIcon,\n  LeafIcon,\n  LightbulbIcon,\n  PizzaIcon,\n  PlaneIcon,\n  SearchIcon,\n  SmileIcon,\n  VolleyballIcon,\n} from \"lucide-react\";\nimport {\n  type ComponentProps,\n  type CSSProperties,\n  createContext,\n  type KeyboardEvent,\n  type RefObject,\n  useContext,\n  useImperativeHandle,\n  useRef,\n  useState,\n} from \"react\";\nimport type { EmojiPickerKnobStyle } from \"@/components/control-ui/knob-contracts/emoji-picker-knobs\";\nimport { cn } from \"@/components/control-ui/lib/cn\";\nimport { Spinner } from \"@/components/control-ui/ui/spinner\";\n\ntype EmojiPickerLoadState = { status: \"loading\" } | { status: \"error\" } | { status: \"ready\"; data: EmojiData };\ntype EmojiPickerContextValue = {\n  columns: number;\n  rootRef: RefObject<HTMLDivElement | null>;\n  viewportRef: RefObject<HTMLDivElement | null>;\n  loadState: EmojiPickerLoadState;\n  retryEmojiData: () => void;\n  selectEmoji: (emoji: Emoji) => void;\n};\nconst EmojiPickerContext = createContext<EmojiPickerContextValue | null>(null);\n\nfunction useEmojiPicker() {\n  const picker = useContext(EmojiPickerContext);\n  if (!picker) throw new Error(\"EmojiPicker parts must be rendered inside <EmojiPicker>.\");\n  return picker;\n}\n\ntype EmojiPickerStyle = { style?: CSSProperties & EmojiPickerKnobStyle };\n\nexport type EmojiPickerProps = Omit<ComponentProps<typeof EmojiPickerPrimitive.Root>, \"style\"> & EmojiPickerStyle;\n\nexport function EmojiPicker({\n  className,\n  columns = 8,\n  style,\n  ref,\n  onEmojiSelect,\n  resolveEmojiData = defaultEmojiDataResolver,\n  ...props\n}: EmojiPickerProps) {\n  const rootRef = useRef<HTMLDivElement>(null);\n  const viewportRef = useRef<HTMLDivElement>(null);\n  const [loadState, setLoadState] = useState<EmojiPickerLoadState>({ status: \"loading\" });\n  const [retryAttempt, setRetryAttempt] = useState(0);\n  useImperativeHandle(ref, () => {\n    if (!rootRef.current) throw new Error(\"EmojiPicker root is not mounted.\");\n    return rootRef.current;\n  });\n  const loadEmojiData: EmojiDataResolver = async (locale, options) => {\n    setLoadState({ status: \"loading\" });\n    try {\n      const data = await resolveEmojiData(locale, options);\n      if (!options.signal?.aborted) setLoadState({ status: \"ready\", data });\n      return data;\n    } catch (error) {\n      if (!options.signal?.aborted) setLoadState({ status: \"error\" });\n      throw error;\n    }\n  };\n  const retryEmojiData = () => {\n    setLoadState({ status: \"loading\" });\n    setRetryAttempt((attempt) => attempt + 1);\n  };\n  const selectEmoji = (emoji: Emoji) => onEmojiSelect?.(emoji);\n  const pickerStyle = { \"--_emoji-picker-columns\": columns, ...style } satisfies CSSProperties & { \"--_emoji-picker-columns\": number };\n  return (\n    <EmojiPickerContext.Provider value={{ columns, rootRef, viewportRef, loadState, retryEmojiData, selectEmoji }}>\n      <EmojiPickerPrimitive.Root\n        key={retryAttempt}\n        data-control-ui=\"emoji-picker\"\n        data-control-family=\"emoji-picker\"\n        data-slot=\"root\"\n        columns={columns}\n        className={cn(\"isolate flex flex-col\", className)}\n        {...props}\n        ref={rootRef}\n        style={pickerStyle}\n        onEmojiSelect={selectEmoji}\n        resolveEmojiData={loadEmojiData}\n      />\n    </EmojiPickerContext.Provider>\n  );\n}\n\nfunction stopPickerNavigation(event: KeyboardEvent<HTMLDivElement>) {\n  if (event.key !== \"Escape\" && event.key !== \"Tab\") event.stopPropagation();\n}\n\nconst categoryIcons = new Map([\n  [0, SmileIcon],\n  [1, HandIcon],\n  [3, LeafIcon],\n  [4, PizzaIcon],\n  [5, PlaneIcon],\n  [6, VolleyballIcon],\n  [7, LightbulbIcon],\n  [8, HeartIcon],\n  [9, FlagIcon],\n]);\n\nfunction emojiCategoryRows(emojiData: EmojiData, columns: number) {\n  let rowOffset = 0;\n  return emojiData.categories.flatMap((category) => {\n    const emojiCount = emojiData.emojis.filter((emoji) => emoji.category === category.index).length;\n    if (emojiCount === 0) return [];\n    const startRow = rowOffset;\n    rowOffset += Math.ceil(emojiCount / columns);\n    return [{ ...category, startRow }];\n  });\n}\n\nexport function EmojiPickerCategories({ \"aria-label\": ariaLabel = \"Emoji categories\", onKeyDown, ...props }: ComponentProps<\"div\">) {\n  const { columns, loadState, rootRef, viewportRef } = useEmojiPicker();\n  if (loadState.status !== \"ready\") return null;\n  const categories = emojiCategoryRows(loadState.data, columns);\n  const scrollToCategory = (startRow: number, categoryIndex: number) => {\n    const root = rootRef.current;\n    const viewport = viewportRef.current;\n    if (!root || !viewport) return;\n    const metrics = getComputedStyle(root);\n    const rowHeight = Number.parseFloat(metrics.getPropertyValue(\"--frimousse-row-height\"));\n    const headerHeight = Number.parseFloat(metrics.getPropertyValue(\"--frimousse-category-header-height\"));\n    viewport.scrollTo({ top: startRow * rowHeight + categoryIndex * headerHeight });\n  };\n  return (\n    <ToolbarPrimitive.Root\n      data-control-ui=\"emoji-picker\"\n      data-control-family=\"emoji-picker\"\n      data-slot=\"categories\"\n      aria-label={ariaLabel}\n      {...props}\n      onKeyDown={(event) => {\n        onKeyDown?.(event);\n        stopPickerNavigation(event);\n      }}\n    >\n      {categories.map((category, categoryIndex) => {\n        const CategoryIcon = categoryIcons.get(category.index) ?? HashIcon;\n        return (\n          <ToolbarPrimitive.Button\n            key={category.index}\n            type=\"button\"\n            aria-label={category.label}\n            data-control-ui=\"emoji-picker\"\n            data-control-family=\"emoji-picker\"\n            data-slot=\"category\"\n            onClick={() => scrollToCategory(category.startRow, categoryIndex)}\n          >\n            <CategoryIcon aria-hidden=\"true\" />\n          </ToolbarPrimitive.Button>\n        );\n      })}\n    </ToolbarPrimitive.Root>\n  );\n}\n\nexport type EmojiPickerRecentProps = ComponentProps<\"div\"> & { emojis: readonly Emoji[]; label?: string };\n\nexport type EmojiPickerReactionsProps = ComponentProps<\"div\"> & { emojis: readonly Emoji[]; onEmojiSelect: (emoji: Emoji) => void };\n\nexport function EmojiPickerReactions({\n  emojis,\n  onEmojiSelect,\n  \"aria-label\": ariaLabel = \"Reactions\",\n  onKeyDown,\n  ...props\n}: EmojiPickerReactionsProps) {\n  return (\n    <ToolbarPrimitive.Root\n      aria-label={ariaLabel}\n      data-control-ui=\"emoji-picker\"\n      data-control-family=\"emoji-picker\"\n      data-slot=\"root\"\n      data-variant=\"reactions\"\n      {...props}\n      onKeyDown={(event) => {\n        onKeyDown?.(event);\n        stopPickerNavigation(event);\n      }}\n    >\n      {emojis.map((emoji) => (\n        <ToolbarPrimitive.Button\n          key={emoji.emoji}\n          type=\"button\"\n          aria-label={emoji.label}\n          data-control-ui=\"emoji-picker\"\n          data-control-family=\"emoji-picker\"\n          data-slot=\"emoji\"\n          onClick={() => onEmojiSelect(emoji)}\n        >\n          {emoji.emoji}\n        </ToolbarPrimitive.Button>\n      ))}\n    </ToolbarPrimitive.Root>\n  );\n}\n\nexport function EmojiPickerRecent({ emojis, label = \"Recently used\", ...props }: EmojiPickerRecentProps) {\n  const picker = useEmojiPicker();\n  if (emojis.length === 0) return null;\n  return (\n    <div data-control-ui=\"emoji-picker\" data-control-family=\"emoji-picker\" data-slot=\"recent\" {...props}>\n      <div data-control-ui=\"emoji-picker\" data-control-family=\"emoji-picker\" data-slot=\"recent-label\">\n        {label}\n      </div>\n      <EmojiPickerReactions\n        data-control-ui=\"emoji-picker\"\n        data-slot=\"recent-grid\"\n        emojis={emojis.slice(0, picker.columns)}\n        aria-label={label}\n        onEmojiSelect={picker.selectEmoji}\n      />\n    </div>\n  );\n}\n\nexport type EmojiPickerSearchProps = Omit<ComponentProps<typeof EmojiPickerPrimitive.Search>, \"style\"> & EmojiPickerStyle;\n\nexport function EmojiPickerSearch({\n  className,\n  placeholder = \"Search emoji…\",\n  \"aria-label\": ariaLabel = \"Search emoji\",\n  ...props\n}: EmojiPickerSearchProps) {\n  return (\n    <div data-control-ui=\"emoji-picker\" data-control-family=\"emoji-picker\" data-slot=\"search\" className=\"flex items-center\">\n      <SearchIcon aria-hidden=\"true\" data-control-ui=\"emoji-picker\" data-control-family=\"emoji-picker\" data-slot=\"search-icon\" />\n      <EmojiPickerPrimitive.Search\n        data-control-ui=\"emoji-picker\"\n        data-control-family=\"emoji-picker\"\n        data-slot=\"search-input\"\n        placeholder={placeholder}\n        aria-label={ariaLabel}\n        className={cn(\"min-w-0 flex-1\", className)}\n        {...props}\n      />\n    </div>\n  );\n}\n\nfunction EmojiPickerRow({ children, className, ...props }: EmojiPickerListRowProps) {\n  return (\n    <div\n      data-control-ui=\"emoji-picker\"\n      data-control-family=\"emoji-picker\"\n      data-slot=\"row\"\n      className={cn(\"scroll-my-1\", className)}\n      {...props}\n    >\n      {children}\n    </div>\n  );\n}\n\nfunction EmojiPickerEmoji({ emoji, className, ...props }: EmojiPickerListEmojiProps) {\n  return (\n    <button\n      type=\"button\"\n      data-control-ui=\"emoji-picker\"\n      data-control-family=\"emoji-picker\"\n      data-slot=\"emoji\"\n      data-active={emoji.isActive ? \"\" : undefined}\n      className={cn(\"flex items-center justify-center\", className)}\n      {...props}\n    >\n      {emoji.emoji}\n    </button>\n  );\n}\n\nfunction EmojiPickerCategoryHeader({ category, className, ...props }: EmojiPickerListCategoryHeaderProps) {\n  return (\n    <div data-control-ui=\"emoji-picker\" data-control-family=\"emoji-picker\" data-slot=\"category-header\" className={className} {...props}>\n      {category.label}\n    </div>\n  );\n}\n\nexport type EmojiPickerContentProps = Omit<ComponentProps<typeof EmojiPickerPrimitive.Viewport>, \"style\"> & EmojiPickerStyle;\n\nexport function EmojiPickerContent({ className, ref, ...props }: EmojiPickerContentProps) {\n  const { viewportRef, loadState, retryEmojiData } = useEmojiPicker();\n  useImperativeHandle(ref, () => {\n    if (!viewportRef.current) throw new Error(\"EmojiPicker viewport is not mounted.\");\n    return viewportRef.current;\n  });\n  return (\n    <EmojiPickerPrimitive.Viewport\n      data-control-ui=\"emoji-picker\"\n      data-control-family=\"emoji-picker\"\n      data-slot=\"content\"\n      className={cn(\"relative min-h-0 flex-1 outline-none\", className)}\n      {...props}\n      ref={viewportRef}\n    >\n      {loadState.status === \"error\" ? (\n        <div data-control-ui=\"emoji-picker\" data-control-family=\"emoji-picker\" data-slot=\"error\" role=\"alert\">\n          <span>Couldn’t load emoji.</span>\n          <button type=\"button\" onClick={retryEmojiData}>\n            Try again\n          </button>\n        </div>\n      ) : (\n        <>\n          <EmojiPickerPrimitive.Loading\n            data-control-ui=\"emoji-picker\"\n            data-control-family=\"emoji-picker\"\n            data-slot=\"loading\"\n            className=\"absolute inset-0 flex items-center justify-center\"\n          >\n            <Spinner label=\"Loading emoji\" />\n          </EmojiPickerPrimitive.Loading>\n          <EmojiPickerPrimitive.Empty\n            data-control-ui=\"emoji-picker\"\n            data-control-family=\"emoji-picker\"\n            data-slot=\"empty\"\n            className=\"absolute inset-0 flex items-center justify-center\"\n          >\n            No emoji found.\n          </EmojiPickerPrimitive.Empty>\n          <EmojiPickerPrimitive.List\n            data-control-ui=\"emoji-picker\"\n            data-control-family=\"emoji-picker\"\n            data-slot=\"list\"\n            className=\"select-none\"\n            components={{ Row: EmojiPickerRow, Emoji: EmojiPickerEmoji, CategoryHeader: EmojiPickerCategoryHeader }}\n          />\n        </>\n      )}\n    </EmojiPickerPrimitive.Viewport>\n  );\n}\n\nexport type EmojiPickerFooterProps = Omit<ComponentProps<\"div\">, \"style\" | \"children\"> & EmojiPickerStyle & { placeholder?: string };\n\nexport function EmojiPickerFooter({ className, placeholder = \"Pick an emoji…\", ...props }: EmojiPickerFooterProps) {\n  return (\n    <div\n      data-control-ui=\"emoji-picker\"\n      data-control-family=\"emoji-picker\"\n      data-slot=\"footer\"\n      className={cn(\"flex min-w-0 items-center\", className)}\n      {...props}\n    >\n      <EmojiPickerPrimitive.ActiveEmoji>\n        {({ emoji }) =>\n          emoji ? (\n            <>\n              <span data-control-ui=\"emoji-picker\" data-control-family=\"emoji-picker\" data-slot=\"footer-emoji\" className=\"flex-none\">\n                {emoji.emoji}\n              </span>\n              <span data-control-ui=\"emoji-picker\" data-control-family=\"emoji-picker\" data-slot=\"footer-label\" className=\"truncate\">\n                {emoji.label}\n              </span>\n            </>\n          ) : (\n            <span data-control-ui=\"emoji-picker\" data-control-family=\"emoji-picker\" data-slot=\"footer-placeholder\" className=\"truncate\">\n              {placeholder}\n            </span>\n          )\n        }\n      </EmojiPickerPrimitive.ActiveEmoji>\n    </div>\n  );\n}\n"
    }
  ],
  "css": {
    "@import \"../components/control-ui/styles/recipes/emoji-picker.css\"": {}
  }
}
