import { useMemo, useState } from 'react' import { Button } from '@astryxdesign/core/Button' import { Center } from '@astryxdesign/core/Center' import { ClickableCard } from '@astryxdesign/core/ClickableCard' import { Divider } from '@astryxdesign/core/Divider' import { Grid } from '@astryxdesign/core/Grid' import { Heading } from '@astryxdesign/core/Heading' import { HStack } from '@astryxdesign/core/HStack' import { Icon } from '@astryxdesign/core/Icon' import type { IconName } from '@astryxdesign/core/Icon' import { Text } from '@astryxdesign/core/Text' import { TextInput } from '@astryxdesign/core/TextInput' import { useToast } from '@astryxdesign/core/Toast' import { ToggleButton, ToggleButtonGroup } from '@astryxdesign/core/ToggleButton' import { VStack } from '@astryxdesign/core/VStack' import { ChevronLeft, ChevronRight, icons, Search, type LucideIcon, } from 'lucide-react' import { Page, PageHeader } from '../components/Page' type IconSet = 'semantic' | 'lucide' interface SemanticIcon { name: IconName label: string } const SEMANTIC_ICONS: SemanticIcon[] = [ { name: 'close', label: '关闭' }, { name: 'chevronDown', label: '向下展开' }, { name: 'chevronLeft', label: '向左' }, { name: 'chevronRight', label: '向右' }, { name: 'chevronsLeft', label: '跳到开头' }, { name: 'chevronsRight', label: '跳到末尾' }, { name: 'check', label: '确认' }, { name: 'success', label: '成功' }, { name: 'error', label: '错误' }, { name: 'warning', label: '警告' }, { name: 'info', label: '信息' }, { name: 'calendar', label: '日历' }, { name: 'clock', label: '时间' }, { name: 'externalLink', label: '外部链接' }, { name: 'menu', label: '菜单' }, { name: 'moreHorizontal', label: '更多' }, { name: 'search', label: '搜索' }, { name: 'upload', label: '上传' }, { name: 'arrowUp', label: '向上' }, { name: 'arrowDown', label: '向下' }, { name: 'arrowsUpDown', label: '排序' }, { name: 'funnel', label: '筛选' }, { name: 'eyeSlash', label: '隐藏' }, { name: 'viewColumns', label: '列设置' }, { name: 'copy', label: '复制' }, { name: 'checkDouble', label: '已复制' }, { name: 'wrench', label: '设置' }, { name: 'stop', label: '停止' }, { name: 'microphone', label: '麦克风' }, ] interface LucideEntry { name: string Icon: LucideIcon } const LUCIDE_ICONS: LucideEntry[] = Object.entries(icons) .map(([name, Icon]) => ({ name, Icon })) .sort((a, b) => a.name.localeCompare(b.name)) const LUCIDE_PAGE_SIZE = 120 export function IconsPage() { const [activeSet, setActiveSet] = useState('semantic') const [query, setQuery] = useState('') const [page, setPage] = useState(1) const showToast = useToast() const changeSet = (value: string | null) => { setActiveSet(value === 'lucide' ? 'lucide' : 'semantic') setPage(1) } const changeQuery = (value: string) => { setQuery(value) setPage(1) } const copyUsage = async (code: string, name: string) => { try { if (!navigator.clipboard) throw new Error('Clipboard unavailable') await navigator.clipboard.writeText(code) showToast({ body: `已复制 ${name} 的用法`, type: 'info' }) } catch { showToast({ body: '复制失败,请检查浏览器权限', type: 'error' }) } } const normalizedQuery = query.trim().toLowerCase() const filteredSemantic = useMemo( () => SEMANTIC_ICONS.filter( (icon) => normalizedQuery.length === 0 || icon.name.toLowerCase().includes(normalizedQuery) || icon.label.includes(query.trim()), ), [normalizedQuery, query], ) const filteredLucide = useMemo( () => normalizedQuery.length === 0 ? LUCIDE_ICONS : LUCIDE_ICONS.filter((icon) => icon.name.toLowerCase().includes(normalizedQuery), ), [normalizedQuery], ) const totalPages = Math.max(1, Math.ceil(filteredLucide.length / LUCIDE_PAGE_SIZE)) const currentPage = Math.min(page, totalPages) const pageStart = (currentPage - 1) * LUCIDE_PAGE_SIZE const pageItems = filteredLucide.slice( pageStart, pageStart + LUCIDE_PAGE_SIZE, ) const isSemantic = activeSet === 'semantic' const visibleCount = isSemantic ? filteredSemantic.length : filteredLucide.length return ( {isSemantic ? '语义图标通过名称使用,会自动适配当前主题。' : 'Lucide 图标以组件形式传入 Icon,可与语义图标混用。'} {visibleCount === 0 ? (
没有找到匹配的图标。 试试更短的关键词。
) : isSemantic ? ( <> 共 {filteredSemantic.length} 个语义图标 {filteredSemantic.map((semanticIcon) => ( void copyUsage( ``, semanticIcon.name, ) } label={`复制 ${semanticIcon.name} 图标用法`}> {semanticIcon.name} {semanticIcon.label} ))} ) : ( <> 显示 {pageStart + 1}–{Math.min(pageStart + LUCIDE_PAGE_SIZE, filteredLucide.length)} 个,共 {filteredLucide.length} 个图标