249 lines
4.4 KiB
TypeScript
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";
|