diff --git a/docs/contributing/guide.md b/docs/contributing/guide.md
index 5053c7b..284cae2 100644
--- a/docs/contributing/guide.md
+++ b/docs/contributing/guide.md
@@ -83,7 +83,7 @@ errors later.
## Questions?
If you have any questions, feel free to ask in our [Discord server](https://discord.gg/replugged) in
-the `#replugged-core` channel.
+the `#replugged-dev` channel.
## Thank you!
diff --git a/docs/contributing/replugged.md b/docs/contributing/replugged.md
index 4b1310c..a5c3679 100644
--- a/docs/contributing/replugged.md
+++ b/docs/contributing/replugged.md
@@ -91,7 +91,7 @@ errors later.
## Questions?
If you have any questions, feel free to ask in our [Discord server](https://discord.gg/replugged) in
-the `#replugged-core` channel.
+the `#replugged-dev` channel.
## Thank you!
diff --git a/docs/manifest.mdx b/docs/manifest.mdx
index df90a1f..29503e1 100644
--- a/docs/manifest.mdx
+++ b/docs/manifest.mdx
@@ -46,10 +46,11 @@ All keys in the [common section](#common), as well as the following:
All keys in the [common section](#common), as well as the following:
-| Key | Type | Description |
-| ---------------------- | ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| type | 'replugged-theme' | Must be `replugged-theme`. |
-| main | string | The path to the main entrypoint of your theme (CSS). The [theme template](https://github.com/replugged-org/theme-template) will allow you to also use SCSS and will handle compiling and updating the file location for you. |
+| Key | Type | Description |
+| ---------------------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| type | 'replugged-theme' | Must be `replugged-theme`. |
+| main | string | The path to the main entrypoint of your theme (CSS). The [theme template](https://github.com/replugged-org/theme-template) will allow you to also use SCSS and will handle compiling and updating the file location for you. |
+| splash | string | The path to Discord's splash screen entrypoint of your theme (CSS). The [theme template](https://github.com/replugged-org/theme-template) will allow you to also use SCSS and will handle compiling and updating the file location for you. |
## Types
diff --git a/docs/plugins/injecting.mdx b/docs/plugins/injecting.mdx
index b1a6106..cf90301 100644
--- a/docs/plugins/injecting.mdx
+++ b/docs/plugins/injecting.mdx
@@ -106,6 +106,7 @@ The injector class has an `uninjectAll` method which will remove all injections
```ts
import { Injector } from "replugged";
+
const injector = new Injector();
export function start() {
@@ -130,7 +131,7 @@ buttons that are shown in the top right corner when you hover over a message, li
reply, etc. The button order cannot be controlled.
```ts
-import { Injector, webpack } from "replugged";
+import { Injector } from "replugged";
const injector = new Injector();
@@ -211,3 +212,70 @@ export function stop(): void {
More examples can be found
[here](https://github.com/asportnoy/context-menu-demo/blob/main/src/index.tsx).
+
+### Slash Commands
+
+You can use the `registerSlashCommand` util to register a custom slash command under the Replugged
+command section. In the following example we are registering a slash command which sends a normal
+message or an , based on the value of the option.
+
+:::info
+
+The slash commands API is supported by TypeScript. An error will occur if you try to get the value
+of a nonexistent option in the registered slash command.
+
+:::
+
+```tsx
+import { Injector, types } from "replugged";
+const { ApplicationCommandOptionType } = types;
+
+const injector = new Injector();
+
+export function start(): void {
+ injector.utils.registerSlashCommand({
+ name: "my-command",
+ description: "Helpful command description",
+ options: [
+ {
+ name: "my-option",
+ description: "Very cool option description",
+ type: ApplicationCommandOptionType.Boolean,
+ required: true,
+ },
+ ],
+ executor: (interaction) => {
+ // You can access the guild and channel of where the command
+ // was executed with interaction.guild and interaction.channel
+
+ // Get the value of the option
+ const sendEmbed = interaction.getValue("my-option");
+
+ if (sendEmbed) {
+ return {
+ // Whether the message should be sent in the channel;
+ // By setting it to false, the message will be hidden
+ // from anyone except the executor of the slash command
+ send: false,
+ result: "This is a message",
+ };
+ } else {
+ return {
+ send: false,
+ embeds: [
+ {
+ color: 0x5865f2,
+ title: "Embed title",
+ description: "Embed description",
+ },
+ ],
+ };
+ }
+ },
+ });
+}
+
+export function stop(): void {
+ injector.uninjectAll();
+}
+```
diff --git a/docs/plugins/modules/common/stores/channels.mdx b/docs/plugins/modules/common/stores/channels.mdx
index 84fa1d5..debbeee 100644
--- a/docs/plugins/modules/common/stores/channels.mdx
+++ b/docs/plugins/modules/common/stores/channels.mdx
@@ -10,26 +10,36 @@ import RequiredNotice from "@site/src/components/RequiredNotice.mdx";
### Functions
-| Name | Parameters | Return Type | Description |
-| ---------------------------------------- | ------------------------------------------------------------------ | ---------------------------------------------- | ----------------------------------------------------------- |
-| `getAllThreadsForParent` | `channelId`: string | [] | Gets all fetched threads by its channel (parent) id |
-| `getBasicChannel` | `channelId`: string | \| undefined | Gets the basic channel by its id |
-| `getChannel` | `channelId`: string | \| undefined | Gets the channel by its id |
-| `getChannelId` | `guildId`: string
`fallbackToDefault`: boolean | string \| undefined | Gets the current selected channel id |
-| `getCurrentlySelectedChannelId` | `guildId`: string | string \| undefined | Gets the current selected channel id |
-| `getDMFromUserId` | `userId`: string | string \| undefined | Gets the DM channel id by its user id |
-| `getDMUserIds` | | string[] | Gets all DM channel ids |
-| `getGuildChannelsVersion` | `guildId`: string | number | Gets the channel version by guild id |
-| `getInitialOverlayState` | | Record> | Gets all guild and DM channels |
-| `getLastChannelFollowingDestination` | | { channelId: string, guildId: string } | Gets information on the last channel follow |
-| `getLastSelectedChannelId` | `guildId`: string | string \| undefined | Gets the last selected channel id |
-| `getLastSelectedChannels` | `guildId`: string | string \| undefined | Gets the last selected channel id by its guild id |
-| `getMostRecentSelectedTextChannelId` | `guildId`: string | string \| null | Gets the last selected text channel id by its guild id |
-| `getMutableBasicGuildChannelsForGuild` | `guildId`: string | Record> | Gets all basic channels by its guild id |
-| `getMutableGuildChannelsForGuild` | `guildId`: string | Record> | Gets all channels by its guild id |
-| `getMutablePrivateChannels` | | Record> | Gets all DM channels |
-| `getPrivateChannelsVersion` | | number | Gets the DM channel version |
-| `getSortedPrivateChannels` | | [] | Gets all DM channels sorted by the last message |
-| `getVoiceChannelId` | | string \| null | Gets the current voice channel id |
-| `hasChannel` | `channelId`: string | boolean | Checks if the channel id is registered in the channel store |
-| `loadAllGuildAndPrivateChannelsFromDisk` | | Record> | Gets all guild and DM channels |
+| Name | Parameters | Return Type | Description |
+| ---------------------------------------- | ----------------------------------------------------- | --------------------------------------------------------------------- | ----------------------------------------------------------- |
+| `getAllThreadsForParent` | `channelId`: string | [] | Gets all fetched threads by its channel (parent) id |
+| `getBasicChannel` | `channelId`: string | \| undefined | Gets the basic channel by its id |
+| `getChannel` | `channelId`: string | \| undefined | Gets the channel by its id |
+| `getChannelId` | `guildId`: string
`fallbackToDefault`: boolean | string \| undefined | Gets the current selected channel id |
+| `getChannelIds` | `guildId`: string | string[] | Gets all channel ids |
+| `getCurrentlySelectedChannelId` | `guildId`: string | string \| undefined | Gets the current selected channel id |
+| `getDMFromUserId` | `userId`: string | string \| undefined | Gets the DM channel id by its user id |
+| `getDMUserIds` | | string[] | Gets all DM channel ids |
+| `getGuildChannelsVersion` | `guildId`: string | number | Gets the channel version by guild id |
+| `getInitialOverlayState` | | Record> | Gets all guild and DM channels |
+| `getLastChannelFollowingDestination` | | [`LastChannelFollowingDestination`](#LastChannelFollowingDestination) | Gets information on the last channel follow |
+| `getLastSelectedChannelId` | `guildId`: string | string \| undefined | Gets the last selected channel id |
+| `getLastSelectedChannels` | `guildId`: string | string \| undefined | Gets the last selected channel id by its guild id |
+| `getMostRecentSelectedTextChannelId` | `guildId`: string | string \| null | Gets the last selected text channel id by its guild id |
+| `getMutableBasicGuildChannelsForGuild` | `guildId`: string | Record> | Gets all basic channels by its guild id |
+| `getMutableGuildChannelsForGuild` | `guildId`: string | Record> | Gets all channels by its guild id |
+| `getMutablePrivateChannels` | | Record> | Gets all DM channels |
+| `getPrivateChannelsVersion` | | number | Gets the DM channel version |
+| `getSortedPrivateChannels` | | [] | Gets all DM channels sorted by the last message |
+| `getVoiceChannelId` | | string \| null | Gets the current voice channel id |
+| `hasChannel` | `channelId`: string | boolean | Checks if the channel id is registered in the channel store |
+| `loadAllGuildAndPrivateChannelsFromDisk` | | Record> | Gets all guild and DM channels |
+
+### Types {#channels-types}
+
+#### `LastChannelFollowingDestination` {#LastChannelFollowingDestination}
+
+| Name | Type | Description |
+| ----------- | ------ | --------------------------------------- |
+| `channelId` | string | Channel id of the last followed channel |
+| `guildId` | string | Guild id of the last followed channel |
diff --git a/docs/plugins/modules/common/stores/messages.mdx b/docs/plugins/modules/common/stores/messages.mdx
index 3e494dd..f68b6bb 100644
--- a/docs/plugins/modules/common/stores/messages.mdx
+++ b/docs/plugins/modules/common/stores/messages.mdx
@@ -8,13 +8,16 @@ import RequiredNotice from "@site/src/components/RequiredNotice.mdx";
-
+
### Functions
| Name | Parameters | Return Type | Description |
| ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
| `clearChannel` | `channelId`: string | void | Clears all messages in a channel. This will only apply locally and the messages will be re-fetched. |
+| `createBotMessage` | `options`: [`CreateBotMessageOptions`](#CreateBotMessageOptions) | | Creates a bot message without sending it |
+| `createMessage` | `options`: [`CreateMessageOptions`](#CreateMessageOptions) | | Creates a message without sending it |
+| `createNonce` | | string | Generate a new snowflake id |
| `crosspostMessage` | `channelId`: string
`messageId`: string | Promise<[`HTTPResponse`](../utilities/api#HTTPResponse) \| void> | Makes a message public in an announcement channel |
| `deleteMessage` | `channelId`: string
`messageId`: string
`keepThreadArchived`: boolean | Promise | Deletes a message from a channel |
| `dismissAutomatedMessage` | `message`: | void | Dismisses an ephemeral message |
@@ -34,6 +37,7 @@ import RequiredNotice from "@site/src/components/RequiredNotice.mdx";
| `sendActivityBookmark` | `channelId`: string
`activityDetails`: string
`analyticsTriggeredFrom`: string
`suggestedInvite`: [`InviteSuggestion`](#InviteSuggestion) | Promise<[`HTTPResponse`](../utilities/api#HTTPResponse) \| void> | Sends an activity bookmark |
| `sendBotMessage` | `channelId`: string
`content`: string
`messageName`: string | void | Clyde sends a custom message |
| `sendClydeError` | `channelId`: string
`code`: number | void | Clyde sends an error message |
+| `sendClydeProfileOverride` | `channelId`: string
`clydeProfileURL`: string
`analyticsTriggeredFrom`: string
`suggestedInvite`: [`InviteSuggestion`](#InviteSuggestion) | Promise<[`HTTPResponse`](../utilities/api#HTTPResponse) \| void> | Sends a Clyde profile override |
| `sendGreetMessage` | `channelId`: string
`stickerId`: string
`options`: [`MessageGreetOptions`](#MessageGreetOptions) | Promise<[`HTTPResponse`](../utilities/api#HTTPResponse) \| void> | Sends a greet message |
| `sendInvite` | `channelId`: string
`inviteCode`: string
`analyticsTriggeredFrom`: string
`suggestedInvite`: [`InviteSuggestion`](#InviteSuggestion) | Promise<[`HTTPResponse`](../utilities/api#HTTPResponse) \| void> | Sends an invite |
| `sendMessage` | `channelId`: string
`message`: [`OutgoingMessage`](#OutgoingMessage)
`promise`: boolean
`options`: [`OutgoingMessageOptions`](#OutgoingMessageOptions) | Promise<[`HTTPResponse`](../utilities/api#HTTPResponse) \| void> | Sends a message |
@@ -44,6 +48,7 @@ import RequiredNotice from "@site/src/components/RequiredNotice.mdx";
| `trackJump` | `channelId`: string
`messageId`: string
`context`: string
`extraProperties`: Record | void | Tracks a jump for analytics |
| `truncateMessages` | `channelId`: string
`truncateBottom`: boolean
`truncateTop`: boolean | void | Truncates a message list |
| `updateEditMessage` | `channelId`: string
`textValue`: string
`richValue`: unknown | void | Updates an edit message |
+| `userRecordToServer` | `user`: | `UserServer` | Converts an user record into a simplified version for the server |
### Types {#messages-types}
@@ -54,6 +59,29 @@ import RequiredNotice from "@site/src/components/RequiredNotice.mdx";
| `parse` | string[] | Array of allowed mention types to parse from the content |
| `replied_user` | boolean | Whether to mention the author of the message being replied to |
+#### `CreateBotMessageOptions` {#CreateBotMessageOptions}
+
+| Name | Type | Default | Description |
+| ------------- | ------------------------- | ------- | ---------------------------------------------- |
+| `channelId` | string | | Id of the channel where the message belongs to |
+| `content` | string | | Content of the message |
+| `embeds` | [] | | Array of embedded content |
+| `loggingName` | string | | Message name for analytics |
+
+#### `CreateMessageOptions` {#CreateMessageOptions}
+
+| Name | Type | Default | Description |
+| ------------------ | --------------------------------------- | ------- | ---------------------------------------------- |
+| `allowedMentions` | [`AllowedMentions`](#AllowedMentions) | | Allowed mentions for the message |
+| `author` | | | Author of the message |
+| `channelId` | string | | Id of the channel where the message belongs to |
+| `content` | string | | Content of the message |
+| `flags` | number | | Message flags |
+| `messageReference` | [`MessageReference`](#MessageReference) | | Contains information for a reply |
+| `nonce` | string | | Id of the message |
+| `tts` | boolean | `false` | Whether the message is a TTS message |
+| `type` | number | `0` | Type of message |
+
#### `FocusMessageOptions` {#FocusMessageOptions}
| Name | Type | Default | Description |
diff --git a/docs/plugins/modules/common/utilities/constants.md b/docs/plugins/modules/common/utilities/constants.md
index 21a9589..510e199 100644
--- a/docs/plugins/modules/common/utilities/constants.md
+++ b/docs/plugins/modules/common/utilities/constants.md
@@ -11,6 +11,7 @@ description: All constants used in the client
| `CSSVariables` | Record | CSS variables |
| `Endpoints` | Record | Endpoints |
| `GuildFeatures` | Record | Guild features |
+| `MessageFlags` | Record | Message flags |
| `Paths` | Record | Web routes |
| `Permissions` | Record | Permissions |
| `raw` | Record | Raw module with all constants; check out its contents with Discord DevTools |
diff --git a/docs/plugins/modules/components/ErrorBoundary.mdx b/docs/plugins/modules/components/ErrorBoundary.mdx
index 1c96d60..1f1b198 100644
--- a/docs/plugins/modules/components/ErrorBoundary.mdx
+++ b/docs/plugins/modules/components/ErrorBoundary.mdx
@@ -16,5 +16,5 @@ const { ErrorBoundary } = components;
| Name | Type | Default | Description |
| ---------- | -------------------------------------------- | ------- | ----------------------------------------- |
| `fallback` | ReactNode | | Fallback elements to show |
-| `onError` | (error: unknown, errorInfo: unknown) => void | | Function ran when an error is triggered |
+| `onError` | (error: Error, errorInfo: ErrorInfo) => void | | Function ran when an error is triggered |
| `silent` | boolean | `false` | Whether to not print the error to console |
diff --git a/docs/plugins/modules/components/Loader.mdx b/docs/plugins/modules/components/Loader.mdx
index 0239008..83e98b4 100644
--- a/docs/plugins/modules/components/Loader.mdx
+++ b/docs/plugins/modules/components/Loader.mdx
@@ -17,16 +17,16 @@ const { Loader } = components;
### Enums
-| Enum | Description |
-| ------------- | ----------------------------------------------------------------------------------------------------------------- |
-| `Loader.Type` | Loader types
`WANDERING_CUBES` \| `CHASING_DOTS` \| `PULSING_ELLIPSIS` \| `SPINNING_CIRCLE` \| `LOW_MOTION` |
+| Enum | Description |
+| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
+| `Loader.Type` | Loader types
`WANDERING_CUBES` \| `CHASING_DOTS` \| `PULSING_ELLIPSIS` \| `SPINNING_CIRCLE` \| `SPINNING_CIRCLE_SIMPLE` \| `LOW_MOTION` |
### Props
:::info
The props of this component extend the attributes of the `span` element, or `div` if
-`Loader.Type.SPINNING_CIRCLE` type is used.
+`Loader.Type.SPINNING_CIRCLE` or `Loader.Type.SPINNING_CIRCLE_SIMPLE` type is used.
:::
diff --git a/docs/plugins/modules/components/Modal.mdx b/docs/plugins/modules/components/Modal.mdx
index 9de5fc9..2f54025 100644
--- a/docs/plugins/modules/components/Modal.mdx
+++ b/docs/plugins/modules/components/Modal.mdx
@@ -63,9 +63,10 @@ The props of this component extend the attributes of the `div` element.
:::
-| Name | Type | Default | Description |
-| ------------- | ------------- | ------- | ------------ |
-| `scrollerRef` | Ref | | Scroller ref |
+| Name | Type | Default | Description |
+| --------------- | -------------------------- | ------- | -------------- |
+| `scrollbarType` | "auto" \| "none" \| "thin" | `thin` | Scrollbar type |
+| `scrollerRef` | Ref | | Scroller ref |
#### `Modal.ModalFooter` {#ModalFooter}
@@ -102,12 +103,13 @@ The props of this component extend the attributes of the `div` element.
:::
-| Name | Type | Default | Description |
-| -------------------- | ---------- | -------- | ----------------------------------------------------------- |
-| `className` | string | | Component class name |
-| `fullscreenOnMobile` | boolean | `true` | Whether the modal is in fullscreen if app is in mobile view |
-| `hideShadow` | boolean | `false` | Whether the shadow is hidden |
-| `onAnimationEnd` | (): string | | Function ran when the modal stopped animating |
-| `role` | string | `dialog` | Modal element role |
-| `size` | string | `small` | Modal size |
-| `transitionState` | string | | Modal state |
+| Name | Type | Default | Description |
+| -------------------- | ------------- | -------- | ----------------------------------------------------------- |
+| `className` | string | | Component class name |
+| `fullscreenOnMobile` | boolean | `true` | Whether the modal is in fullscreen if app is in mobile view |
+| `hideShadow` | boolean | `false` | Whether the shadow is hidden |
+| `onAnimationEnd` | (): string | | Function ran when the modal stopped animating |
+| `returnRef` | Ref | | Returned ref |
+| `role` | string | `dialog` | Modal element role |
+| `size` | string | `small` | Modal size |
+| `transitionState` | string | | Modal state |
diff --git a/docs/plugins/modules/components/Tooltip.mdx b/docs/plugins/modules/components/Tooltip.mdx
index 6c1f91d..813b663 100644
--- a/docs/plugins/modules/components/Tooltip.mdx
+++ b/docs/plugins/modules/components/Tooltip.mdx
@@ -37,7 +37,6 @@ const { Tooltip } = components;
| `delay` | number | | How long the tooltip takes to appear in milliseconds |
| `disableTooltipPointerEvents` | boolean | `false` | Whether to disable pointer events on the tooltip |
| `forceOpen` | boolean | `false` | Whether the tooltip is always visible |
-| `hide` | boolean | `false` | Whether the tooltip is hidden |
| `hideOnClick` | boolean | `true` | Whether the tooltip hides after clicking anywhere |
| `onAnimationRest` | (result: unknown, spring: unknown, item?: unknown) => void | | Function ran when the tooltip is animating; its parameters are related to [react-spring](https://www.react-spring.dev/) |
| `onTooltipShow` | () => void | | Function ran when the tooltip shows up |
diff --git a/src/components/APIReferences.tsx b/src/components/APIReferences.tsx
index 3d5f313..8891c0f 100644
--- a/src/components/APIReferences.tsx
+++ b/src/components/APIReferences.tsx
@@ -7,6 +7,7 @@ const DiscordAPIDocs = (props): JSX.Element => {
export default {
Channel: () => ,
+ Embed: () => ,
Emoji: () => ,
Guild: () => ,
GuildMember: () => (