This commit is contained in:
mats committed 2026-09-12 20:29:38 +02:00
1 parent 61df5e3dcc
commit c0a94d3b6d
25 files changed
+2143 -348

No files matched your search

+131 -26
View File
@@ -1,33 +1,138 @@
type IconProps = { name: string; size?: number }
import type { ComponentType, SVGProps } from 'react'
import {
Search,
Sun,
Moon,
Copy,
Check,
Eye,
ArrowRight,
ArrowLeft,
Menu,
Layers,
Sparkles,
Terminal,
AlertTriangle,
AlertCircle,
Info,
CheckCircle2,
X,
Plus,
Minus,
Trash2,
ExternalLink,
ChevronDown,
ChevronRight,
ChevronLeft,
ChevronUp,
Filter,
SlidersHorizontal,
Code2,
Cpu,
Database,
User,
Shield,
Folder,
FileText,
Calendar,
Clock,
RefreshCw,
Download,
Upload,
Settings,
HelpCircle,
type LucideIcon,
type LucideProps,
} from 'lucide-react'
const paths: Record<string, string> = {
search: 'M11 19a8 8 0 1 0 0-16 8 8 0 0 0 0 16Zm6-2 4 4',
sun: 'M12 3v2m0 14v2M4 12h2m12 0h2M12 8a4 4 0 1 1 0 8 4 4 0 0 1 0-8Z',
moon: 'M21 12.8A9 9 0 1 1 11.2 3a7 7 0 0 0 9.8 9.8Z',
copy: 'M8 8h10v12H8zM6 16H4V4h12v2',
check: 'm5 12 4 4L19 6',
eye: 'M2 12s3.5-6 10-6 10 6 10 6-3.5 6-10 6S2 12 2 12Zm10 3a3 3 0 1 0 0-6 3 3 0 0 0 0 6Z',
arrow: 'M5 12h14m-6-6 6 6-6 6',
menu: 'M4 6h16M4 12h16M4 18h16',
layers: 'm12 3 9 5-9 5-9-5 9-5Zm-9 9 9 5 9-5M3 16l9 5 9-5',
sparkle: 'm12 3 2.5 6.5L21 12l-6.5 2.5L12 21l-2.5-6.5L3 12l6.5-2.5L12 3Z',
terminal: 'm4 17 6-6-6-6m8 14h8',
export type { LucideIcon, LucideProps }
const iconMap: Record<string, LucideIcon> = {
// Northstar legacy shorthands
search: Search,
sun: Sun,
moon: Moon,
copy: Copy,
check: Check,
eye: Eye,
arrow: ArrowRight,
'arrow-right': ArrowRight,
'arrow-left': ArrowLeft,
menu: Menu,
layers: Layers,
sparkle: Sparkles,
sparkles: Sparkles,
terminal: Terminal,
// Common UI primitives
close: X,
x: X,
plus: Plus,
minus: Minus,
trash: Trash2,
'trash-2': Trash2,
settings: Settings,
filter: Filter,
sliders: SlidersHorizontal,
refresh: RefreshCw,
download: Download,
upload: Upload,
external: ExternalLink,
'external-link': ExternalLink,
info: Info,
warning: AlertTriangle,
'alert-triangle': AlertTriangle,
alert: AlertCircle,
'alert-circle': AlertCircle,
'check-circle': CheckCircle2,
help: HelpCircle,
'chevron-down': ChevronDown,
'chevron-right': ChevronRight,
'chevron-left': ChevronLeft,
'chevron-up': ChevronUp,
code: Code2,
cpu: Cpu,
database: Database,
user: User,
shield: Shield,
folder: Folder,
file: FileText,
calendar: Calendar,
clock: Clock,
}
export function Icon({ name, size = 18 }: IconProps) {
export type IconName = keyof typeof iconMap | string
export type IconProps = Omit<SVGProps<SVGSVGElement>, 'ref'> & {
name?: IconName
icon?: LucideIcon | ComponentType<{ size?: number | string; strokeWidth?: number; className?: string }>
size?: number | string
strokeWidth?: number
className?: string
}
/**
* Universal Icon component backed by lucide-react.
* Accepts either a shorthand name (e.g. name="sparkle", name="check")
* or a direct Lucide icon component (e.g. icon={Sparkles}).
*/
export function Icon({
name,
icon: IconComponent,
size = 18,
strokeWidth = 1.8,
className,
...props
}: IconProps) {
const Component = IconComponent || (name ? iconMap[name.toLowerCase()] : undefined) || Layers
return (
<svg
width={size}
height={size}
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="1.8"
strokeLinecap="round"
strokeLinejoin="round"
<Component
size={size}
strokeWidth={strokeWidth}
className={className}
aria-hidden="true"
>
<path d={paths[name] || paths.layers} />
</svg>
{...props}
/>
)
}