Files
homarr/packages/widgets/src/custom-api/jsx-icon-adapter.tsx
T

249 lines
4.4 KiB
TypeScript

import {
IconActivity,
IconAlertCircle,
IconAlertTriangle,
IconApi,
IconArrowDown,
IconArrowLeft,
IconArrowRight,
IconArrowUp,
IconBell,
IconBluetooth,
IconBolt,
IconBookmark,
IconBrandDocker,
IconBug,
IconCalendar,
IconCamera,
IconChartBar,
IconChartLine,
IconChartPie,
IconCheck,
IconChevronDown,
IconChevronLeft,
IconChevronRight,
IconChevronUp,
IconCircleCheck,
IconCircleX,
IconClipboard,
IconClock,
IconCloud,
IconCloudOff,
IconCode,
IconCompass,
IconCopy,
IconCpu,
IconDatabase,
IconDeviceDesktop,
IconDeviceMobile,
IconDownload,
IconDroplet,
IconEdit,
IconExternalLink,
IconEye,
IconEyeOff,
IconFile,
IconFlag,
IconFlame,
IconFolder,
IconGauge,
IconGitBranch,
IconHeart,
IconHistory,
IconHome,
IconInfoCircle,
IconKey,
IconLink,
IconLoader,
IconLock,
IconLockOpen,
IconMail,
IconMap,
IconMapPin,
IconMinus,
IconMoon,
IconMusic,
IconNetwork,
IconPhoto,
IconPokeball,
IconPin,
IconPlayerPause,
IconPlayerPlay,
IconPlayerSkipBack,
IconPlayerSkipForward,
IconPlayerStop,
IconPlus,
IconPower,
IconProgress,
IconHeartbeat,
IconRefresh,
IconReload,
IconSearch,
IconServer,
IconSettings,
IconShield,
IconStar,
IconSun,
IconTerminal,
IconThermometer,
IconTrash,
IconTrendingDown,
IconTrendingUp,
IconUpload,
IconUser,
IconUsers,
IconVideo,
IconVolume,
IconVolume2,
IconVolumeOff,
IconWifi,
IconWifiOff,
IconWorld,
IconX,
IconSpeedboat,
} from "@tabler/icons-react";
function tablerIconExportToKey(exportName: string): string {
return exportName
.slice(4)
.replace(/([a-z0-9])([A-Z])/g, "$1-$2")
.replace(/([A-Z]+)([A-Z][a-z])/g, "$1-$2")
.replace(/([A-Za-z])(\d)/g, "$1-$2")
.toLowerCase();
}
const TABLER_ICON_IMPORTS = {
IconCheck,
IconX,
IconPlus,
IconMinus,
IconArrowUp,
IconArrowDown,
IconArrowLeft,
IconArrowRight,
IconChevronUp,
IconChevronDown,
IconChevronLeft,
IconChevronRight,
IconHome,
IconSettings,
IconUser,
IconUsers,
IconSearch,
IconBell,
IconMail,
IconHeart,
IconStar,
IconBookmark,
IconBrandDocker,
IconFlag,
IconPin,
IconPlayerPlay,
IconPlayerPause,
IconPlayerStop,
IconPlayerSkipForward,
IconPlayerSkipBack,
IconVolume,
IconVolumeOff,
IconVolume2,
IconWifi,
IconWifiOff,
IconBluetooth,
IconCloud,
IconCloudOff,
IconServer,
IconDatabase,
IconCpu,
IconDeviceDesktop,
IconDeviceMobile,
IconFolder,
IconFile,
IconDownload,
IconUpload,
IconRefresh,
IconReload,
IconPower,
IconBolt,
IconFlame,
IconDroplet,
IconSun,
IconMoon,
IconEye,
IconEyeOff,
IconLock,
IconLockOpen,
IconShield,
IconKey,
IconAlertTriangle,
IconAlertCircle,
IconInfoCircle,
IconCircleCheck,
IconCircleX,
IconTrash,
IconEdit,
IconCopy,
IconClipboard,
IconExternalLink,
IconLink,
IconPhoto,
IconPokeball,
IconCamera,
IconMusic,
IconVideo,
IconCalendar,
IconClock,
IconHistory,
IconMap,
IconMapPin,
IconCompass,
IconTerminal,
IconCode,
IconBug,
IconGitBranch,
IconNetwork,
IconWorld,
IconApi,
IconChartBar,
IconChartLine,
IconChartPie,
IconTrendingUp,
IconTrendingDown,
IconActivity,
IconProgress,
IconLoader,
IconThermometer,
IconGauge,
IconSpeedboat,
IconHeartbeat,
} as const;
const TABLER_ICON_MAP: Record<string, ComponentType<never>> = {
...Object.fromEntries(
Object.entries(TABLER_ICON_IMPORTS).map(([exportName, IconComponent]) => [
tablerIconExportToKey(exportName),
IconComponent,
]),
),
pulse: IconHeartbeat,
};
export const SAFE_TABLER_ICON_NAMES = Object.freeze(Object.keys(TABLER_ICON_MAP).toSorted());
function isValidIconProp(value: unknown): value is string | number {
return typeof value === "number" || typeof value === "string";
}
export function SafeTablerIcon(props: Record<string, unknown>) {
const name = props.name;
if (typeof name !== "string") return null;
const IconComponent = TABLER_ICON_MAP[name];
if (!IconComponent) return null;
const iconProps: Record<string, unknown> = {};
if (isValidIconProp(props.size)) iconProps.size = props.size;
if (typeof props.color === "string") iconProps.color = props.color;
if (isValidIconProp(props.stroke)) iconProps.stroke = props.stroke;
return createElement(IconComponent as never, iconProps);
}
import { createElement } from "react";
import type { ComponentType } from "react";