<script lang="ts">
import {
AlertTriangle,
ArrowDown,
ArrowLeft,
ArrowRight,
ArrowUp,
BadgeCheck,
Bell,
ChartColumnBig,
Check,
ChevronDown,
ChevronRight,
ChevronUp,
ChevronsDownUp,
ChevronsUpDown,
Circle,
CircleAlert,
CircleCheckBig,
CircleX,
Code2,
Copy,
Download,
Ellipsis,
Eye,
FileDiff,
EyeOff,
Lock,
LockOpen,
KeyRound,
File,
FileText,
FileX2,
Filter,
Folder,
FolderOpen,
Globe,
GlobeLock,
GitBranch,
GitCommitVertical,
GitMerge,
Home,
Info,
Keyboard,
LayoutList,
Lightbulb,
Link2,
ListFilter,
MessageCircleMore,
MessagesSquare,
Minimize2,
MousePointerClick,
Network,
Moon,
Palette,
PanelBottom,
PanelLeft,
PanelTop,
Pencil,
Pin,
Plus,
RefreshCw,
Search,
Settings,
SquareTerminal,
Star,
Sun,
Trash2,
Save,
Upload,
UserRound,
Users,
X,
} from "lucide-svelte";
export type AppIconName =
| "check"
| "triangle-alert"
// The four directions. Used as SIGNS — what is ahead, behind, arriving,
// leaving — so they are icons like everything else rather than characters
// that inherit whatever font the row happens to be in and sit on their own
// baseline.
| "arrow-up"
| "arrow-down"
| "arrow-left"
| "arrow-right"
/// Changes to files that are not committed.
| "file-diff"
| "chevron-down"
| "chevron-right"
| "chevron-up"
| "collapse-all"
| "expand-all"
| "circle"
| "circle-alert"
| "circle-check"
| "circle-x"
| "badge-check"
| "bell"
| "chart"
| "code"
| "copy"
| "download"
| "ellipsis"
| "eye"
| "eye-off"
| "lock"
| "lock-open"
| "key-round"
| "file"
| "file-text"
| "file-x"
| "filter"
| "folder"
| "folder-open"
| "globe"
| "globe-lock"
| "git-branch"
| "git-commit"
| "git-merge"
| "home"
| "info"
| "keyboard"
| "layout-list"
| "lightbulb"
| "link"
| "list-filter"
| "machines"
| "message-circle"
| "messages-square"
| "minimize"
| "mouse-pointer-click"
| "moon"
| "palette"
| "panel-bottom"
| "panel-left"
| "panel-top"
| "pencil"
| "pin"
| "plus"
| "refresh"
| "search"
| "settings"
| "square-terminal"
| "save"
| "star"
| "sun"
| "trash"
| "upload"
| "user"
| "users"
| "x";
export type AppIconSize =
| 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15
| 16 | 18 | 20 | 22 | 24 | 28 | 36 | 40;
interface Props {
name: AppIconName;
size?: AppIconSize;
strokeWidth?: number;
absoluteStrokeWidth?: boolean;
class?: string;
}
let {
name,
size = 16,
strokeWidth = 1.0,
absoluteStrokeWidth = true,
class: className = "",
}: Props = $props();
const iconByName = {
check: Check,
"triangle-alert": AlertTriangle,
"arrow-up": ArrowUp,
"arrow-down": ArrowDown,
"arrow-left": ArrowLeft,
"arrow-right": ArrowRight,
"file-diff": FileDiff,
"chevron-down": ChevronDown,
"chevron-right": ChevronRight,
"chevron-up": ChevronUp,
"collapse-all": ChevronsDownUp,
"expand-all": ChevronsUpDown,
circle: Circle,
"circle-alert": CircleAlert,
"circle-check": CircleCheckBig,
"circle-x": CircleX,
"badge-check": BadgeCheck,
bell: Bell,
chart: ChartColumnBig,
code: Code2,
copy: Copy,
download: Download,
ellipsis: Ellipsis,
eye: Eye,
"eye-off": EyeOff,
lock: Lock,
"lock-open": LockOpen,
"key-round": KeyRound,
file: File,
"file-text": FileText,
"file-x": FileX2,
filter: Filter,
folder: Folder,
"folder-open": FolderOpen,
globe: Globe,
"globe-lock": GlobeLock,
"git-branch": GitBranch,
"git-commit": GitCommitVertical,
"git-merge": GitMerge,
home: Home,
info: Info,
keyboard: Keyboard,
"layout-list": LayoutList,
lightbulb: Lightbulb,
link: Link2,
"list-filter": ListFilter,
machines: Network,
"message-circle": MessageCircleMore,
"messages-square": MessagesSquare,
minimize: Minimize2,
"mouse-pointer-click": MousePointerClick,
moon: Moon,
palette: Palette,
"panel-bottom": PanelBottom,
"panel-left": PanelLeft,
"panel-top": PanelTop,
pencil: Pencil,
pin: Pin,
plus: Plus,
refresh: RefreshCw,
search: Search,
settings: Settings,
"square-terminal": SquareTerminal,
save: Save,
star: Star,
sun: Sun,
trash: Trash2,
upload: Upload,
user: UserRound,
users: Users,
x: X,
} satisfies Record<AppIconName, typeof Search>;
let Icon = $derived(iconByName[name]);
</script>
<Icon
size={size}
style={`width: var(--wsb-icon-size-${size}); height: var(--wsb-icon-size-${size});`}
strokeWidth={strokeWidth}
{absoluteStrokeWidth}
class={className}
aria-hidden="true"
/>