+3
packages/core-extensions/src/common/index.ts
+3
packages/core-extensions/src/common/index.ts
+1
-1
packages/core-extensions/src/common/manifest.json
+1
-1
packages/core-extensions/src/common/manifest.json
+31
packages/core-extensions/src/common/webpackModules/icons.ts
+31
packages/core-extensions/src/common/webpackModules/icons.ts
···
1
+
import { Icons, IconSize } from "@moonlight-mod/types/coreExtensions/common";
2
+
import { tokens } from "@moonlight-mod/wp/discord/components/common/index";
3
+
4
+
// This is defined in a Webpack module but we copy it here to be less breakage-prone
5
+
const sizes: Partial<Record<IconSize, number>> = {
6
+
xxs: 12,
7
+
xs: 16,
8
+
sm: 18,
9
+
md: 24,
10
+
lg: 32,
11
+
refresh_sm: 20
12
+
};
13
+
14
+
export const icons: Icons = {
15
+
parseProps(props) {
16
+
// NOTE: var() fallback is non-standard behavior, just for safety reasons
17
+
const color = props?.color ?? tokens?.colors?.["INTERACTIVE_NORMAL"] ?? "var(--interactive-normal)";
18
+
19
+
const size = sizes[props?.size ?? "md"];
20
+
21
+
return {
22
+
// note: this default size is also non-standard behavior, just for safety
23
+
width: size ?? props?.width ?? sizes.md!,
24
+
height: size ?? props?.width ?? sizes.md!,
25
+
26
+
fill: typeof color === "string" ? color : color.css,
27
+
className: props?.colorClass ?? ""
28
+
};
29
+
}
30
+
};
31
+
export default icons;
+6
packages/core-extensions/src/moonbase/index.tsx
+6
packages/core-extensions/src/moonbase/index.tsx
···
42
42
{ id: "react" },
43
43
{ id: "discord/components/common/index" },
44
44
{ ext: "moonbase", id: "stores" },
45
+
{ ext: "moonbase", id: "ThemeDarkIcon" },
45
46
{ id: "discord/modules/guild_settings/web/AppCard.css" },
46
47
{ ext: "contextMenu", id: "contextMenu" },
47
48
{ id: "discord/modules/modals/Modals" },
···
49
50
'"Missing channel in Channel.openChannelContextMenu"',
50
51
".forumOrHome]:"
51
52
]
53
+
},
54
+
55
+
ThemeDarkIcon: {
56
+
dependencies: [{ ext: "common", id: "icons" }, { id: "react" }]
52
57
},
53
58
54
59
settings: {
···
67
72
dependencies: [
68
73
{ id: "react" },
69
74
{ ext: "moonbase", id: "stores" },
75
+
{ ext: "moonbase", id: "ThemeDarkIcon" },
70
76
{ ext: "notices", id: "notices" },
71
77
{
72
78
ext: "spacepack",
+36
packages/core-extensions/src/moonbase/webpackModules/ThemeDarkIcon.tsx
+36
packages/core-extensions/src/moonbase/webpackModules/ThemeDarkIcon.tsx
···
1
+
// RIP to ThemeDarkIcon ????-2025
2
+
// <Cynthia> Failed to remap "ThemeDarkIcon" in "discord/components/common/index"
3
+
// <NotNite> bro are you fucking kidding me
4
+
// <NotNite> that's literally the icon we use for the update banner
5
+
6
+
import React from "@moonlight-mod/wp/react";
7
+
import icons from "@moonlight-mod/wp/common_icons";
8
+
import type { IconProps } from "@moonlight-mod/types/coreExtensions/common";
9
+
10
+
export default function ThemeDarkIcon(props?: IconProps) {
11
+
const parsed = icons.parseProps(props);
12
+
13
+
return (
14
+
<svg
15
+
aria-hidden="true"
16
+
role="img"
17
+
xmlns="http://www.w3.org/2000/svg"
18
+
width={parsed.width}
19
+
height={parsed.height}
20
+
fill="none"
21
+
viewBox="0 0 24 24"
22
+
>
23
+
<path
24
+
fill={parsed.fill}
25
+
className={parsed.className}
26
+
d="M20.52 18.96c.32-.4-.01-.96-.52-.96A11 11 0 0 1 9.77 2.94c.31-.78-.3-1.68-1.1-1.43a11 11 0 1 0 11.85 17.45Z"
27
+
/>
28
+
29
+
<path
30
+
fill={parsed.fill}
31
+
className={parsed.className}
32
+
d="m17.73 9.27-.76-2.02a.5.5 0 0 0-.94 0l-.76 2.02-2.02.76a.5.5 0 0 0 0 .94l2.02.76.76 2.02a.5.5 0 0 0 .94 0l.76-2.02 2.02-.76a.5.5 0 0 0 0-.94l-2.02-.76ZM19.73 2.62l.45 1.2 1.2.45c.21.08.21.38 0 .46l-1.2.45-.45 1.2a.25.25 0 0 1-.46 0l-.45-1.2-1.2-.45a.25.25 0 0 1 0-.46l1.2-.45.45-1.2a.25.25 0 0 1 .46 0Z"
33
+
/>
34
+
</svg>
35
+
);
36
+
}
+1
-1
packages/core-extensions/src/moonbase/webpackModules/ui/update.tsx
+1
-1
packages/core-extensions/src/moonbase/webpackModules/ui/update.tsx
···
7
7
import MarkupUtils from "@moonlight-mod/wp/discord/modules/markup/MarkupUtils";
8
8
import Flex from "@moonlight-mod/wp/discord/uikit/Flex";
9
9
import {
10
-
ThemeDarkIcon,
11
10
Button,
12
11
Text,
13
12
ModalRoot,
···
19
18
openModal
20
19
} from "@moonlight-mod/wp/discord/components/common/index";
21
20
import MarkupClasses from "@moonlight-mod/wp/discord/modules/messages/web/Markup.css";
21
+
import ThemeDarkIcon from "@moonlight-mod/wp/moonbase_ThemeDarkIcon";
22
22
23
23
const strings: Record<UpdateState, string> = {
24
24
[UpdateState.Ready]: "A new version of moonlight is available.",
+1
-1
packages/core-extensions/src/moonbase/webpackModules/updates.tsx
+1
-1
packages/core-extensions/src/moonbase/webpackModules/updates.tsx
···
3
3
import Notices from "@moonlight-mod/wp/notices_notices";
4
4
import { MoonlightBranch } from "@moonlight-mod/types";
5
5
import React from "@moonlight-mod/wp/react";
6
-
import { ThemeDarkIcon } from "@moonlight-mod/wp/discord/components/common/index";
6
+
import ThemeDarkIcon from "@moonlight-mod/wp/moonbase_ThemeDarkIcon";
7
7
8
8
function plural(str: string, num: number) {
9
9
return `${str}${num > 1 ? "s" : ""}`;
+5
packages/core-extensions/src/moonbase/wp.d.ts
+5
packages/core-extensions/src/moonbase/wp.d.ts
···
5
5
declare module "@moonlight-mod/wp/moonbase_stores" {
6
6
export * from "core-extensions/src/moonbase/webpackModules/stores";
7
7
}
8
+
9
+
declare module "@moonlight-mod/wp/moonbase_ThemeDarkIcon" {
10
+
import ThemeDarkIcon from "core-extensions/src/moonbase/webpackModules/ThemeDarkIcon";
11
+
export = ThemeDarkIcon;
12
+
}
+22
packages/types/src/coreExtensions/common.ts
+22
packages/types/src/coreExtensions/common.ts
···
1
+
import type { IconProps, IconSize } from "@moonlight-mod/mappings/discord/components/common/index";
2
+
1
3
export type ErrorBoundaryProps = React.PropsWithChildren<{
2
4
noop?: boolean;
3
5
fallback?: React.FC<any>;
···
9
11
error?: Error;
10
12
componentStack?: string;
11
13
};
14
+
15
+
export type ErrorBoundary = React.ComponentClass<ErrorBoundaryProps, ErrorBoundaryState>;
16
+
17
+
export type ParsedIconProps = {
18
+
width: number;
19
+
height: number;
20
+
fill: string;
21
+
className: string;
22
+
};
23
+
24
+
export interface Icons {
25
+
/**
26
+
* Parse icon props into their actual width/height.
27
+
* @param props The icon props
28
+
*/
29
+
parseProps(props?: IconProps): ParsedIconProps;
30
+
}
31
+
32
+
// Re-export so extension developers don't need to depend on mappings
33
+
export type { IconProps, IconSize };
+4
packages/types/src/discord/require.ts
+4
packages/types/src/discord/require.ts
···
1
1
import { AppPanels } from "../coreExtensions/appPanels";
2
2
import { Commands } from "../coreExtensions/commands";
3
+
import { ErrorBoundary, Icons } from "../coreExtensions/common";
3
4
import { DMList, MemberList, Messages } from "../coreExtensions/componentEditor";
4
5
import { ContextMenu, EvilItemParser } from "../coreExtensions/contextMenu";
5
6
import { Markdown } from "../coreExtensions/markdown";
···
13
14
declare function WebpackRequire(id: "appPanels_appPanels"): AppPanels;
14
15
15
16
declare function WebpackRequire(id: "commands_commands"): Commands;
17
+
18
+
declare function WebpackRequire(id: "common_ErrorBoundary"): ErrorBoundary;
19
+
declare function WebpackRequire(id: "common_icons"): Icons;
16
20
17
21
declare function WebpackRequire(id: "componentEditor_dmList"): DMList;
18
22
declare function WebpackRequire(id: "componentEditor_memberList"): MemberList;
+10
-1
packages/types/src/import.d.ts
+10
-1
packages/types/src/import.d.ts
···
10
10
export default commands;
11
11
}
12
12
13
-
declare module "@moonlight-mod/wp/common_ErrorBoundary";
13
+
declare module "@moonlight-mod/wp/common_ErrorBoundary" {
14
+
import { CoreExtensions } from "@moonlight-mod/types";
15
+
const ErrorBoundary: CoreExtensions.Common.ErrorBoundary;
16
+
export = ErrorBoundary;
17
+
}
18
+
declare module "@moonlight-mod/wp/common_icons" {
19
+
import { CoreExtensions } from "@moonlight-mod/types";
20
+
export const icons: CoreExtensions.Common.Icons;
21
+
export default icons;
22
+
}
14
23
declare module "@moonlight-mod/wp/common_stores";
15
24
16
25
declare module "@moonlight-mod/wp/componentEditor_dmList" {