import { useEffect, useRef, useState } from 'react' import { IconArrowsShuffle, IconCircleOff, IconLoader2, IconMoodSad, IconUpload } from '@tabler/icons-react' import { EmojiPicker, type EmojiPickerListCategoryHeaderProps, type EmojiPickerListEmojiProps, type EmojiPickerListRowProps } from 'frimousse' import { useResetWorkspaceIcon, useSaveWorkspaceIcon } from '@/client/features/settings/api' import { workspaceProviderIcon } from '@/client/features/home/workspace-presentation' import { useWorkspaceLayoutCtx } from '@/client/features/workspace/WorkspaceLayoutContext' import { APP_ICON_CHOICES } from '@/client/lib/app-icon-registry' import { cn } from '@/client/lib/cn' import { GRADIENT_PRESETS, type IconGradient, gradientCss, randomGradient, renderEmojiIcon, renderGlyphIcon } from '@/client/features/settings/render-icon' import { EMOJI_FONT, FAVORITE_EMOJI } from './icon-picker-options' type Mode = 'emoji' | 'icon' | 'upload' // The selected background: a preset id (or 'shuffle'), and its gradient — null // means transparent. Only the rasterized result is persisted. type IconBg = { id: string; gradient: IconGradient | null } // ── Frimousse list parts (module-level so the virtualized list keeps stable // component identities across re-renders) ─────────────────────────────────── function EmojiCategoryHeader({ category, ...props }: EmojiPickerListCategoryHeaderProps) { return (
Favorites
{/* Fixed 13 columns to mirror the frimousse rows below — the 26 favorites always land as two clean rows. */}{error}
) : saving ? (Saving…
) : null}