Files
cc-switch/src/icons/extracted/metadata.ts
YoVinchen a56a578e91 feat(ui): add icon picker, color picker and provider icon components
Implement comprehensive icon selection system for provider customization:

## New Components

### ProviderIcon (src/components/ProviderIcon.tsx)
- Render SVG icons by name with automatic fallback
- Display provider initials when icon not found
- Support custom sizing via size prop
- Use dangerouslySetInnerHTML for inline SVG rendering

### IconPicker (src/components/IconPicker.tsx)
- Grid-based icon selection with visual preview
- Real-time search filtering by name and keywords
- Integration with icon metadata for display names
- Responsive grid layout (6-10 columns based on screen)

### ColorPicker (src/components/ColorPicker.tsx)
- 12 preset colors for quick selection
- Native color input for custom color picking
- Hex input field for precise color entry
- Visual feedback for selected color state

## Icon Assets (src/icons/extracted/)
- 38 high-quality SVG icons for AI providers and platforms
- Includes: OpenAI, Claude, DeepSeek, Qwen, Kimi, Gemini, etc.
- Cloud platforms: AWS, Azure, Google Cloud, Cloudflare
- Auto-generated index.ts with getIcon/hasIcon helpers
- Metadata system with searchable keywords per icon

## Build Scripts
- scripts/extract-icons.js: Extract icons from simple-icons
- scripts/generate-icon-index.js: Generate TypeScript index file
2025-11-21 23:20:39 +08:00

316 lines
6.7 KiB
TypeScript

// Icon metadata for search and categorization
import { IconMetadata } from "@/types/icon";
export const iconMetadata: Record<string, IconMetadata> = {
alibaba: {
name: "alibaba",
displayName: "Alibaba",
category: "ai-provider",
keywords: ["qwen", "tongyi"],
defaultColor: "#FF6A00",
},
anthropic: {
name: "anthropic",
displayName: "Anthropic",
category: "ai-provider",
keywords: ["claude"],
defaultColor: "#D4915D",
},
aws: {
name: "aws",
displayName: "AWS",
category: "cloud",
keywords: ["amazon", "cloud"],
defaultColor: "#FF9900",
},
azure: {
name: "azure",
displayName: "Azure",
category: "cloud",
keywords: ["microsoft", "cloud"],
defaultColor: "#0078D4",
},
baidu: {
name: "baidu",
displayName: "Baidu",
category: "ai-provider",
keywords: ["ernie", "wenxin"],
defaultColor: "#2932E1",
},
bytedance: {
name: "bytedance",
displayName: "bytedance",
category: "other",
keywords: [],
defaultColor: "currentColor",
},
chatglm: {
name: "chatglm",
displayName: "chatglm",
category: "other",
keywords: [],
defaultColor: "currentColor",
},
claude: {
name: "claude",
displayName: "Claude",
category: "ai-provider",
keywords: ["anthropic"],
defaultColor: "#D4915D",
},
cloudflare: {
name: "cloudflare",
displayName: "Cloudflare",
category: "cloud",
keywords: ["cloudflare", "cdn"],
defaultColor: "#F38020",
},
cohere: {
name: "cohere",
displayName: "Cohere",
category: "ai-provider",
keywords: ["cohere"],
defaultColor: "#39594D",
},
copilot: {
name: "copilot",
displayName: "copilot",
category: "other",
keywords: [],
defaultColor: "currentColor",
},
deepseek: {
name: "deepseek",
displayName: "DeepSeek",
category: "ai-provider",
keywords: ["deep", "seek"],
defaultColor: "#1E88E5",
},
doubao: {
name: "doubao",
displayName: "doubao",
category: "other",
keywords: [],
defaultColor: "currentColor",
},
gemini: {
name: "gemini",
displayName: "Gemini",
category: "ai-provider",
keywords: ["google"],
defaultColor: "#4285F4",
},
gemma: {
name: "gemma",
displayName: "gemma",
category: "other",
keywords: [],
defaultColor: "currentColor",
},
github: {
name: "github",
displayName: "GitHub",
category: "tool",
keywords: ["git", "version control"],
defaultColor: "#181717",
},
githubcopilot: {
name: "githubcopilot",
displayName: "githubcopilot",
category: "other",
keywords: [],
defaultColor: "currentColor",
},
google: {
name: "google",
displayName: "Google",
category: "ai-provider",
keywords: ["gemini", "bard"],
defaultColor: "#4285F4",
},
googlecloud: {
name: "googlecloud",
displayName: "googlecloud",
category: "other",
keywords: [],
defaultColor: "currentColor",
},
grok: {
name: "grok",
displayName: "grok",
category: "other",
keywords: [],
defaultColor: "currentColor",
},
huawei: {
name: "huawei",
displayName: "Huawei",
category: "cloud",
keywords: ["huawei", "cloud"],
defaultColor: "#FF0000",
},
huggingface: {
name: "huggingface",
displayName: "Hugging Face",
category: "ai-provider",
keywords: ["huggingface", "hf"],
defaultColor: "#FFD21E",
},
hunyuan: {
name: "hunyuan",
displayName: "hunyuan",
category: "other",
keywords: [],
defaultColor: "currentColor",
},
kimi: {
name: "kimi",
displayName: "Kimi",
category: "ai-provider",
keywords: ["moonshot"],
defaultColor: "#6366F1",
},
meta: {
name: "meta",
displayName: "Meta",
category: "ai-provider",
keywords: ["facebook", "llama"],
defaultColor: "#0081FB",
},
midjourney: {
name: "midjourney",
displayName: "midjourney",
category: "other",
keywords: [],
defaultColor: "currentColor",
},
minimax: {
name: "minimax",
displayName: "MiniMax",
category: "ai-provider",
keywords: ["minimax"],
defaultColor: "#FF6B6B",
},
mistral: {
name: "mistral",
displayName: "Mistral",
category: "ai-provider",
keywords: ["mistral"],
defaultColor: "#FF7000",
},
notion: {
name: "notion",
displayName: "notion",
category: "other",
keywords: [],
defaultColor: "currentColor",
},
ollama: {
name: "ollama",
displayName: "ollama",
category: "other",
keywords: [],
defaultColor: "currentColor",
},
openai: {
name: "openai",
displayName: "OpenAI",
category: "ai-provider",
keywords: ["gpt", "chatgpt"],
defaultColor: "#00A67E",
},
palm: {
name: "palm",
displayName: "palm",
category: "other",
keywords: [],
defaultColor: "currentColor",
},
perplexity: {
name: "perplexity",
displayName: "Perplexity",
category: "ai-provider",
keywords: ["perplexity"],
defaultColor: "#20808D",
},
qwen: {
name: "qwen",
displayName: "qwen",
category: "other",
keywords: [],
defaultColor: "currentColor",
},
stability: {
name: "stability",
displayName: "stability",
category: "other",
keywords: [],
defaultColor: "currentColor",
},
tencent: {
name: "tencent",
displayName: "Tencent",
category: "ai-provider",
keywords: ["hunyuan"],
defaultColor: "#00A4FF",
},
vercel: {
name: "vercel",
displayName: "vercel",
category: "other",
keywords: [],
defaultColor: "currentColor",
},
wenxin: {
name: "wenxin",
displayName: "wenxin",
category: "other",
keywords: [],
defaultColor: "currentColor",
},
xai: {
name: "xai",
displayName: "xai",
category: "other",
keywords: [],
defaultColor: "currentColor",
},
yi: {
name: "yi",
displayName: "yi",
category: "other",
keywords: [],
defaultColor: "currentColor",
},
zeroone: {
name: "zeroone",
displayName: "zeroone",
category: "other",
keywords: [],
defaultColor: "currentColor",
},
zhipu: {
name: "zhipu",
displayName: "Zhipu AI",
category: "ai-provider",
keywords: ["chatglm", "glm"],
defaultColor: "#0F62FE",
},
};
export function getIconMetadata(name: string): IconMetadata | undefined {
return iconMetadata[name.toLowerCase()];
}
export function searchIcons(query: string): string[] {
const lowerQuery = query.toLowerCase();
return Object.values(iconMetadata)
.filter(
(meta) =>
meta.name.includes(lowerQuery) ||
meta.displayName.toLowerCase().includes(lowerQuery) ||
meta.keywords.some((k) => k.includes(lowerQuery)),
)
.map((meta) => meta.name);
}