diff --git a/src/components/PluginSettings/index.tsx b/src/components/PluginSettings/index.tsx index 278020055..9bbed1906 100644 --- a/src/components/PluginSettings/index.tsx +++ b/src/components/PluginSettings/index.tsx @@ -292,10 +292,10 @@ export default function PluginSettings() { if (!pluginFilter(p)) continue; - const isRequired = p.required || depMap[p.name]?.some(d => settings.plugins[d].enabled); + const isRequired = p.required || p.isDependency || depMap[p.name]?.some(d => settings.plugins[d].enabled); if (isRequired) { - const tooltipText = p.required + const tooltipText = p.required || !depMap[p.name] ? "This plugin is required for Vencord to function." : makeDependencyList(depMap[p.name]?.filter(d => settings.plugins[d].enabled)); diff --git a/src/plugins/_core/supportHelper.tsx b/src/plugins/_core/supportHelper.tsx index fff6d44e7..05b151bd9 100644 --- a/src/plugins/_core/supportHelper.tsx +++ b/src/plugins/_core/supportHelper.tsx @@ -142,7 +142,7 @@ export default definePlugin({ required: true, description: "Helps us provide support to you", authors: [Devs.Ven], - dependencies: ["CommandsAPI", "UserSettingsAPI", "MessageAccessoriesAPI"], + dependencies: ["UserSettingsAPI", "MessageAccessoriesAPI"], settings, diff --git a/src/plugins/friendInvites/index.ts b/src/plugins/friendInvites/index.ts index 1ab042dab..5a83d9dcf 100644 --- a/src/plugins/friendInvites/index.ts +++ b/src/plugins/friendInvites/index.ts @@ -27,7 +27,6 @@ export default definePlugin({ name: "FriendInvites", description: "Create and manage friend invite links via slash commands (/create friend invite, /view friend invites, /revoke friend invites).", authors: [Devs.afn, Devs.Dziurwa], - dependencies: ["CommandsAPI"], commands: [ { name: "create friend invite", diff --git a/src/plugins/index.ts b/src/plugins/index.ts index 2f705e38a..2a0886a98 100644 --- a/src/plugins/index.ts +++ b/src/plugins/index.ts @@ -107,6 +107,11 @@ for (const p of pluginsValues) if (isPluginEnabled(p.name)) { settings[d].enabled = true; dep.isDependency = true; }); + + if (p.commands?.length) { + Plugins.CommandsAPI.isDependency = true; + settings.CommandsAPI.enabled = true; + } } for (const p of pluginsValues) { diff --git a/src/plugins/messageTags/index.ts b/src/plugins/messageTags/index.ts index 05d5e4596..77f506166 100644 --- a/src/plugins/messageTags/index.ts +++ b/src/plugins/messageTags/index.ts @@ -84,8 +84,6 @@ export default definePlugin({ authors: [Devs.Luna], settings, - dependencies: ["CommandsAPI"], - async start() { for (const tag of await getTags()) createTagCommand(tag); }, diff --git a/src/plugins/moreCommands/index.ts b/src/plugins/moreCommands/index.ts index 61312acc1..02f3c3738 100644 --- a/src/plugins/moreCommands/index.ts +++ b/src/plugins/moreCommands/index.ts @@ -33,7 +33,6 @@ export default definePlugin({ name: "MoreCommands", description: "echo, lenny, mock", authors: [Devs.Arjix, Devs.echo, Devs.Samu], - dependencies: ["CommandsAPI"], commands: [ { name: "echo", diff --git a/src/plugins/moreKaomoji/index.ts b/src/plugins/moreKaomoji/index.ts index b5e33d960..9a691fc4d 100644 --- a/src/plugins/moreKaomoji/index.ts +++ b/src/plugins/moreKaomoji/index.ts @@ -24,7 +24,6 @@ export default definePlugin({ name: "MoreKaomoji", description: "Adds more Kaomoji to discord. ヽ(´▽`)/", authors: [Devs.JacobTm], - dependencies: ["CommandsAPI"], commands: [ { name: "dissatisfaction", description: " >﹏<" }, { name: "smug", description: "ಠ_ಠ" }, diff --git a/src/plugins/petpet/index.ts b/src/plugins/petpet/index.ts index 3d726caec..1d3267094 100644 --- a/src/plugins/petpet/index.ts +++ b/src/plugins/petpet/index.ts @@ -88,7 +88,6 @@ export default definePlugin({ name: "petpet", description: "Adds a /petpet slash command to create headpet gifs from any image", authors: [Devs.Ven], - dependencies: ["CommandsAPI"], commands: [ { inputType: ApplicationCommandInputType.BUILT_IN, diff --git a/src/plugins/silentTyping/index.tsx b/src/plugins/silentTyping/index.tsx index 2a6a64283..ad28999aa 100644 --- a/src/plugins/silentTyping/index.tsx +++ b/src/plugins/silentTyping/index.tsx @@ -88,7 +88,7 @@ export default definePlugin({ name: "SilentTyping", authors: [Devs.Ven, Devs.Rini, Devs.ImBanana], description: "Hide that you are typing", - dependencies: ["CommandsAPI", "ChatInputButtonAPI"], + dependencies: ["ChatInputButtonAPI"], settings, contextMenus: { "textarea-context": ChatBarContextCheckbox diff --git a/src/plugins/spotifyShareCommands/index.ts b/src/plugins/spotifyShareCommands/index.ts index c263a0145..4b4168914 100644 --- a/src/plugins/spotifyShareCommands/index.ts +++ b/src/plugins/spotifyShareCommands/index.ts @@ -76,7 +76,6 @@ export default definePlugin({ name: "SpotifyShareCommands", description: "Share your current Spotify track, album or artist via slash command (/track, /album, /artist)", authors: [Devs.katlyn], - dependencies: ["CommandsAPI"], commands: [ { name: "track", diff --git a/src/utils/lazyReact.tsx b/src/utils/lazyReact.tsx index 637f15256..8c76b9d70 100644 --- a/src/utils/lazyReact.tsx +++ b/src/utils/lazyReact.tsx @@ -19,7 +19,7 @@ export type LazyComponentType

= React.FunctionComponent

* @param attempts How many times to try to get the component before giving up * @returns Result of factory function */ -export function LazyComponent

(factory: () => AnyComponentType

, attempts = 5, err: string | (() => string) = `LazyComponent factory failed:\n${factory}`): LazyComponentType

{ +export function LazyComponent

(factory: () => React.ComponentType

, attempts = 5, err: string | (() => string) = `LazyComponent factory failed:\n${factory}`): LazyComponentType

{ const get = makeLazy(factory, attempts, { isIndirect: true }); let InnerComponent = null as AnyComponentType

| null; diff --git a/src/utils/types.ts b/src/utils/types.ts index e5486e9a5..dd3c11576 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -72,13 +72,13 @@ export interface PluginDef { stop?(): void; patches?: Omit[]; /** - * List of commands. If you specify these, you must add CommandsAPI to dependencies + * List of commands that your plugin wants to register */ commands?: Command[]; /** * A list of other plugins that your plugin depends on. * These will automatically be enabled and loaded before your plugin - * Common examples are CommandsAPI, MessageEventsAPI... + * Generally these will be API plugins */ dependencies?: string[], /** diff --git a/src/webpack/api.tsx b/src/webpack/api.tsx index 28fe5e66b..572d1f4a2 100644 --- a/src/webpack/api.tsx +++ b/src/webpack/api.tsx @@ -171,7 +171,7 @@ function printFilter(filter: FilterFn) { return String(filter); } -function wrapWebpackComponent

(err: string | (() => string)): [WrapperComponent: LazyComponentType

, setInnerComponent: (rawComponent: any, parsedComponent: AnyComponentType

) => void] { +function wrapWebpackComponent

(err: string | (() => string)): [WrapperComponent: LazyComponentType

, setInnerComponent: (rawComponent: any, parsedComponent: React.ComponentType

) => void] { let InnerComponent = null as AnyComponentType

| null; let findFailedLogged = false; @@ -186,7 +186,7 @@ function wrapWebpackComponent

(err: string | (() => string)) WrapperComponent[SYM_LAZY_COMPONENT_INNER] = () => InnerComponent; - function setInnerComponent(RawComponent: any, ParsedComponent: AnyComponentType

) { + function setInnerComponent(RawComponent: any, ParsedComponent: React.ComponentType

) { InnerComponent = ParsedComponent; Object.assign(WrapperComponent, RawComponent); } @@ -281,7 +281,7 @@ export function find(filter: FilterFn, parse: (module: ModuleExports) = * @param parse A function that takes the found component as its first argument and returns a component. Useful if you want to wrap the found component in something. Defaults to the original component * @returns The component if found, or a noop component */ -export function findComponent

(filter: FilterFn, parse: (component: ModuleExports) => AnyComponentType

= m => m, { isIndirect = false }: { isIndirect?: boolean; } = {}) { +export function findComponent

(filter: FilterFn, parse: (component: ModuleExports) => React.ComponentType

= m => m, { isIndirect = false }: { isIndirect?: boolean; } = {}) { if (typeof filter !== "function") { throw new Error("Invalid filter. Expected a function got " + typeof filter); } @@ -311,8 +311,8 @@ export function findComponent

(filter: FilterFn, parse: (com * @param parse A function that takes the found component as its first argument and returns a component. Useful if you want to wrap the found component in something. Defaults to the original component * @returns The component if found, or a noop component */ -export function findExportedComponent

(...props: PropsFilter | [...PropsFilter, (component: ModuleExports) => AnyComponentType

]) { - const parse = (typeof props.at(-1) === "function" ? props.pop() : m => m) as (component: ModuleExports) => AnyComponentType

; +export function findExportedComponent

(...props: PropsFilter | [...PropsFilter, (component: ModuleExports) => React.ComponentType

]) { + const parse = (typeof props.at(-1) === "function" ? props.pop() : m => m) as (component: ModuleExports) => React.ComponentType

; const newProps = props as PropsFilter; const filter = filters.byProps(...newProps); @@ -339,8 +339,8 @@ export function findExportedComponent

(...props: PropsFilter * @param parse A function that takes the found component as its first argument and returns a component. Useful if you want to wrap the found component in something. Defaults to the original component * @returns The component if found, or a noop component */ -export function findComponentByCode

(...code: CodeFilter | [...CodeFilter, (component: ModuleExports) => AnyComponentType

]) { - const parse = (typeof code.at(-1) === "function" ? code.pop() : m => m) as (component: ModuleExports) => AnyComponentType

; +export function findComponentByCode

(...code: CodeFilter | [...CodeFilter, (component: ModuleExports) => React.ComponentType

]) { + const parse = (typeof code.at(-1) === "function" ? code.pop() : m => m) as (component: ModuleExports) => React.ComponentType

; const newCode = code as CodeFilter; const ComponentResult = findComponent

(filters.componentByCode(...newCode), parse, { isIndirect: true }); @@ -362,8 +362,8 @@ export function findComponentByCode

(...code: CodeFilter | [ * @param parse A function that takes the found component as its first argument and returns a component. Useful if you want to wrap the found component in something. Defaults to the original component * @returns The component if found, or a noop component */ -export function findComponentByFields

(...fields: PropsFilter | [...PropsFilter, (component: ModuleExports) => AnyComponentType

]) { - const parse = (typeof fields.at(-1) === "function" ? fields.pop() : m => m) as (component: ModuleExports) => AnyComponentType

; +export function findComponentByFields

(...fields: PropsFilter | [...PropsFilter, (component: ModuleExports) => React.ComponentType

]) { + const parse = (typeof fields.at(-1) === "function" ? fields.pop() : m => m) as (component: ModuleExports) => React.ComponentType

; const newFields = fields as PropsFilter; const ComponentResult = findComponent

(filters.componentByFields(...newFields), parse, { isIndirect: true }); diff --git a/src/webpack/common/components.ts b/src/webpack/common/components.ts index 5460d4050..d94373d07 100644 --- a/src/webpack/common/components.ts +++ b/src/webpack/common/components.ts @@ -44,6 +44,8 @@ export let Avatar: t.Avatar = NoopComponent; export let FocusLock: t.FocusLock = NoopComponent; export let useToken: t.useToken; +export let Icons = {} as t.Icons; + export const MaskedLink = findComponentByCode("MASKED_LINK)"); export const Timestamp = findComponentByCode(".Messages.MESSAGE_EDITED_TIMESTAMP_A11Y_LABEL.format"); export const Flex = findComponent(filters.byProps("Justify", "Align", "Wrap")) as t.Flex; @@ -76,5 +78,6 @@ export const Forms = findByProps("FormItem", "Button", m => { Heading } = m); + Icons = m; return m; }); diff --git a/src/webpack/common/types/components.d.ts b/src/webpack/common/types/components.d.ts index 286ad3f98..fa9396718 100644 --- a/src/webpack/common/types/components.d.ts +++ b/src/webpack/common/types/components.d.ts @@ -18,6 +18,8 @@ import type { ComponentType, CSSProperties, FunctionComponent, HtmlHTMLAttributes, HTMLProps, KeyboardEvent, MouseEvent, PropsWithChildren, PropsWithRef, ReactNode, Ref } from "react"; +import { IconNames } from "./iconNames"; + export type TextVariant = "heading-sm/normal" | "heading-sm/medium" | "heading-sm/semibold" | "heading-sm/bold" | "heading-md/normal" | "heading-md/medium" | "heading-md/semibold" | "heading-md/bold" | "heading-lg/normal" | "heading-lg/medium" | "heading-lg/semibold" | "heading-lg/bold" | "heading-xl/normal" | "heading-xl/medium" | "heading-xl/bold" | "heading-xxl/normal" | "heading-xxl/medium" | "heading-xxl/bold" | "eyebrow" | "heading-deprecated-14/normal" | "heading-deprecated-14/medium" | "heading-deprecated-14/bold" | "text-xxs/normal" | "text-xxs/medium" | "text-xxs/semibold" | "text-xxs/bold" | "text-xs/normal" | "text-xs/medium" | "text-xs/semibold" | "text-xs/bold" | "text-sm/normal" | "text-sm/medium" | "text-sm/semibold" | "text-sm/bold" | "text-md/normal" | "text-md/medium" | "text-md/semibold" | "text-md/bold" | "text-lg/normal" | "text-lg/medium" | "text-lg/semibold" | "text-lg/bold" | "display-sm" | "display-md" | "display-lg" | "code"; export type FormTextTypes = Record<"DEFAULT" | "INPUT_PLACEHOLDER" | "DESCRIPTION" | "LABEL_BOLD" | "LABEL_SELECTED" | "LABEL_DESCRIPTOR" | "ERROR" | "SUCCESS", string>; export type HeadingTag = `h${1 | 2 | 3 | 4 | 5 | 6}`; @@ -76,7 +78,7 @@ export type Forms = { }; export type Tooltip = ComponentType<{ - text: ReactNode; + text: ReactNode | ComponentType; children: FunctionComponent<{ onClick(): void; onMouseEnter(): void; @@ -516,3 +518,10 @@ export type Avatar = ComponentType; }>>; + +export type Icon = AnyComponentType & { + size?: string; + colorClass?: string; +}>; + +export type Icons = Record; diff --git a/src/webpack/common/types/iconNames.d.ts b/src/webpack/common/types/iconNames.d.ts new file mode 100644 index 000000000..f09b666b2 --- /dev/null +++ b/src/webpack/common/types/iconNames.d.ts @@ -0,0 +1,14 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2024 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import { LiteralUnion } from "type-fest"; + +// copy(Object.keys(findByProps("EyeIcon")).filter(k => k.endsWith("Icon")).map(JSON.stringify).join("|")) + +export type IconNames = LiteralUnion< + "AIcon" | "AccessibilityIcon" | "AchievementsIcon" | "ActivitiesIcon" | "ActivitiesPlusIcon" | "AirplayIcon" | "AnalyticsIcon" | "AngleBracketsIcon" | "AnnouncementsChatIcon" | "AnnouncementsIcon" | "AnnouncementsLockIcon" | "AnnouncementsWarningIcon" | "AppleBrandLightIcon" | "AppleNeutralIcon" | "AppsIcon" | "ArrowAngleDownLeftIcon" | "ArrowAngleLeftDownIcon" | "ArrowAngleLeftUpIcon" | "ArrowAngleRightDownIcon" | "ArrowAngleRightUpIcon" | "ArrowAngleUpLeftIcon" | "ArrowLargeDownIcon" | "ArrowLargeLeftIcon" | "ArrowLargeRightIcon" | "ArrowLargeUpIcon" | "ArrowSmallDownIcon" | "ArrowSmallLeftIcon" | "ArrowSmallRightIcon" | "ArrowSmallUpIcon" | "ArrowsLeftRightIcon" | "ArrowsUpDownIcon" | "AsteriskIcon" | "AtIcon" | "AttachmentIcon" | "BIcon" | "BackspaceIcon" | "BadgeIcon" | "BeakerIcon" | "BellIcon" | "BellSlashIcon" | "BellZIcon" | "BicycleIcon" | "BillIcon" | "BluetoothIcon" | "BlurBackgroundIcon" | "BoldIcon" | "BookCheckIcon" | "BookmarkIcon" | "BookmarkOutlineIcon" | "BoostTier1Icon" | "BoostTier1SimpleIcon" | "BoostTier2Icon" | "BoostTier2SimpleIcon" | "BoostTier3Icon" | "BoostTier3SimpleIcon" | "BrowserCheckeredIcon" | "BrowserIcon" | "BrowserLinkIcon" | "BrowserPlusIcon" | "BrowserQuestionMarkIcon" | "BugIcon" | "CalendarIcon" | "CalendarMinusIcon" | "CalendarPlusIcon" | "CalendarRetryIcon" | "CalendarXIcon" | "CameraIcon" | "CameraSwapIcon" | "CarIcon" | "ChannelListIcon" | "ChannelListMagnifyingGlassIcon" | "ChannelListMinusIcon" | "ChannelListPlusIcon" | "ChannelListRetryIcon" | "ChannelNotificationIcon" | "ChannelsFollowedIcon" | "ChatArrowRightIcon" | "ChatCheckIcon" | "ChatDotsIcon" | "ChatEyeIcon" | "ChatIcon" | "ChatMarkUnreadIcon" | "ChatMinusIcon" | "ChatPlusIcon" | "ChatRetryIcon" | "ChatSlowModeIcon" | "ChatSmileIcon" | "ChatSpeakIcon" | "ChatWarningIcon" | "ChatXIcon" | "CheckmarkLargeBoldIcon" | "CheckmarkLargeIcon" | "CheckmarkSmallBoldIcon" | "CheckmarkSmallIcon" | "ChevronLargeDownIcon" | "ChevronLargeLeftIcon" | "ChevronLargeRightIcon" | "ChevronLargeUpIcon" | "ChevronSmallDownIcon" | "ChevronSmallLeftIcon" | "ChevronSmallRightIcon" | "ChevronSmallUpIcon" | "CircleCheckIcon" | "CircleInformationIcon" | "CircleMinusIcon" | "CirclePlayIcon" | "CirclePlusIcon" | "CircleQuestionIcon" | "CircleWarningIcon" | "CircleXIcon" | "ClipboardCheckIcon" | "ClipboardListIcon" | "ClipsGalleryIcon" | "ClipsIcon" | "ClockIcon" | "ClockWarningIcon" | "ClockXIcon" | "CloudDownloadIcon" | "ClydeIcon" | "CollapseListIcon" | "CompassIcon" | "ConnectionAverageIcon" | "ConnectionBadIcon" | "ConnectionFineIcon" | "ConnectionUnknownIcon" | "ContactsIcon" | "CopyIcon" | "CreditCardIcon" | "CropIcon" | "CrownIcon" | "CrunchyrollBrandLightIcon" | "CrunchyrollNeutralIcon" | "DenyIcon" | "DoorEnterIcon" | "DoorExitIcon" | "DoubleCheckmarkIcon" | "DownloadIcon" | "DpadIcon" | "DragIcon" | "EducationIcon" | "EmbedIcon" | "EnvelopeIcon" | "ExpandGifIcon" | "ExperimentalLootboxIcon" | "ExperimentalPineappleSpongebobIcon" | "EyeDropperIcon" | "EyeIcon" | "EyePlusIcon" | "EyeSlashIcon" | "FacebookNeutralIcon" | "FileDenyIcon" | "FileIcon" | "FileUpIcon" | "FileWarningIcon" | "FiltersHorizontalIcon" | "FireIcon" | "FlagIcon" | "FlagMinusIcon" | "FlagPlusIcon" | "FlagRetryIcon" | "FlashIcon" | "FlipHorizontalIcon" | "FlipVerticalIcon" | "FolderIcon" | "FolderPlusIcon" | "FoodIcon" | "ForumIcon" | "ForumLockIcon" | "ForumWarningIcon" | "FriendsIcon" | "FullscreenEnterIcon" | "FullscreenExitIcon" | "GameControllerIcon" | "GifIcon" | "GiftIcon" | "GlobeEarthIcon" | "GridHorizontalIcon" | "GridSquareIcon" | "GridVerticalIcon" | "GroupArrowDownIcon" | "GroupArrowRightIcon" | "GroupIcon" | "GroupMinusIcon" | "GroupPlusIcon" | "GroupRetryIcon" | "HammerIcon" | "HammerMinusIcon" | "HammerPlusIcon" | "HammerRetryIcon" | "HammerXIcon" | "HandRequestSpeakIcon" | "HandRequestSpeakListIcon" | "HashmarkIcon" | "HdIcon" | "HeadphonesDenyIcon" | "HeadphonesIcon" | "HeadphonesSlashIcon" | "HeartIcon" | "HeartOutlineIcon" | "HomeIcon" | "HomeSlashIcon" | "HourglassIcon" | "HubIcon" | "IdIcon" | "ImageFileIcon" | "ImageFileUpIcon" | "ImageIcon" | "ImageLockIcon" | "ImagePlusIcon" | "ImageSparkleIcon" | "ImageTextIcon" | "ImageWarningIcon" | "ImagesIcon" | "InboxIcon" | "InstagramNeutralIcon" | "InventoryIcon" | "ItalicIcon" | "KeyIcon" | "KeyboardIcon" | "LanguageIcon" | "LaptopPhoneIcon" | "LettersIcon" | "LightbulbIcon" | "LinkExternalMediumIcon" | "LinkExternalSmallIcon" | "LinkIcon" | "LinkPlusIcon" | "ListBulletsIcon" | "ListNumberedIcon" | "LocationIcon" | "LockIcon" | "LockUnlockedIcon" | "MagicWandIcon" | "MagnifyingGlassIcon" | "ManaIcon" | "MaximizeIcon" | "MedalIcon" | "MenuIcon" | "MicrophoneArrowRightIcon" | "MicrophoneDenyIcon" | "MicrophoneIcon" | "MicrophoneSlashIcon" | "MinimizeIcon" | "MinusIcon" | "MobilePhoneControllerIcon" | "MobilePhoneIcon" | "MobilePhonePlusIcon" | "MobilePhoneSettingsIcon" | "MobilePhoneShareIcon" | "MobilePhoneSpeakerIcon" | "MobilePhoneVideoIcon" | "MobilePhoneXIcon" | "ModerationIcon" | "MoreHorizontalIcon" | "MoreVerticalIcon" | "MusicIcon" | "MusicSlashIcon" | "NatureIcon" | "NearbyScanIcon" | "NewUserIcon" | "NewUserSimpleIcon" | "NintendoSwitchNeutralIcon" | "NitroWheelIcon" | "ObjectIcon" | "PaintPaletteIcon" | "PaintbrushThickIcon" | "PaintbrushThickMinusIcon" | "PaintbrushThickPlusIcon" | "PaintbrushThickRetryIcon" | "PaintbrushThinIcon" | "PaintbrushThinMinusIcon" | "PaintbrushThinPlusIcon" | "PaintbrushThinRetryIcon" | "PaperIcon" | "PaperPlusIcon" | "PauseIcon" | "PencilIcon" | "PencilSparkleIcon" | "PhoneCallIcon" | "PhoneHangUpIcon" | "PhoneIcon" | "PiggyBankIcon" | "PinIcon" | "PinUprightIcon" | "PinUprightSlashIcon" | "PlayIcon" | "PlaystationNeutralIcon" | "PlusLargeIcon" | "PlusMediumIcon" | "PlusSmallIcon" | "PollsIcon" | "PrivacyAndSafetyIcon" | "PuzzlePieceIcon" | "PuzzlePieceMinusIcon" | "PuzzlePiecePlusIcon" | "PuzzlePieceRetryIcon" | "QrCodeIcon" | "QuestsIcon" | "QuoteIcon" | "ReactionIcon" | "ReceiptIcon" | "RecordPlayerIcon" | "RedoIcon" | "RefreshIcon" | "RemixIcon" | "RetryIcon" | "RibbonIcon" | "RobotIcon" | "RotateIcon" | "ScienceIcon" | "ScreenArrowIcon" | "ScreenIcon" | "ScreenSlashIcon" | "ScreenStreamIcon" | "ScreenSystemRequirementsIcon" | "ScreenXIcon" | "SendMessageIcon" | "ServerGridIcon" | "ServerIcon" | "SettingsArrowUpIcon" | "SettingsCircleIcon" | "SettingsIcon" | "SettingsInfoIcon" | "SettingsPlusIcon" | "ShareIcon" | "ShieldAtIcon" | "ShieldIcon" | "ShieldLockIcon" | "ShieldUserIcon" | "ShopIcon" | "ShopMinusIcon" | "ShopPlusIcon" | "ShopSparkleIcon" | "SignPostIcon" | "SlashBoxIcon" | "SlashIcon" | "SlashMinusIcon" | "SlashPlusIcon" | "SlashRetryIcon" | "SoundboardIcon" | "SoundboardSlashIcon" | "SparklesIcon" | "SpeedometerIcon" | "SpoilerIcon" | "StaffBadgeIcon" | "StageIcon" | "StageListIcon" | "StageLockIcon" | "StageMinusIcon" | "StageModeratorIcon" | "StagePlusIcon" | "StageRetryIcon" | "StageXIcon" | "StampIcon" | "StarIcon" | "StarOutlineIcon" | "StarShootingIcon" | "StickerDeadIcon" | "StickerIcon" | "StickerMinusIcon" | "StickerPlusIcon" | "StickerRetryIcon" | "StickerSadIcon" | "StickerSmallIcon" | "StickerWink1Icon" | "StickerWink2Icon" | "StopIcon" | "StrikethroughIcon" | "SuperReactionIcon" | "TagIcon" | "TagsIcon" | "TextIcon" | "TextLockIcon" | "TextWarningIcon" | "ThemeDarkIcon" | "ThemeLightIcon" | "ThemeMidnightIcon" | "ThreadIcon" | "ThreadLockIcon" | "ThreadMinusIcon" | "ThreadPlusIcon" | "ThreadRetryIcon" | "ThreadWarningIcon" | "ThumbsDownIcon" | "ThumbsUpIcon" | "TicketIcon" | "TiktokNeutralIcon" | "TimerIcon" | "TopicsIcon" | "TrainIcon" | "TrashIcon" | "TreehouseIcon" | "TrophyIcon" | "TvIcon" | "TwitterNeutralIcon" | "UnderlineIcon" | "UndoIcon" | "UnknownGameIcon" | "UnsendIcon" | "UploadIcon" | "UserArrowDiagonalBottomRightIcon" | "UserCheckIcon" | "UserCircleIcon" | "UserCircleStatusIcon" | "UserClockIcon" | "UserIcon" | "UserMinusIcon" | "UserPlayIcon" | "UserPlusIcon" | "UserRetryIcon" | "UserSquareIcon" | "UserStatusIcon" | "VideoIcon" | "VideoLockIcon" | "VideoSlashIcon" | "VoiceBluetoothIcon" | "VoiceLockIcon" | "VoiceLowIcon" | "VoiceNormalIcon" | "VoiceWarningIcon" | "VoiceXIcon" | "WalletIcon" | "WarningIcon" | "WaveformIcon" | "WaveformSlashIcon" | "WebhookIcon" | "WebhookPlusIcon" | "WidgetsIcon" | "WidgetsMinusIcon" | "WidgetsPlusIcon" | "WidgetsRetryIcon" | "WindowLaunchIcon" | "WindowReturnIcon" | "WindowTopIcon" | "WindowTopOutlineIcon" | "WrenchIcon" | "XLargeBoldIcon" | "XLargeIcon" | "XNeutralIcon" | "XSmallBoldIcon" | "XSmallIcon" | "XboxNeutralIcon" | "YoutubeNeutralIcon", + string +>;