action row component

This commit is contained in:
MapleLeaf
2021-12-21 23:47:42 -06:00
parent f53c6dba22
commit 7b3ce42138
5 changed files with 100 additions and 14 deletions

View File

@@ -5,7 +5,14 @@ import React from "react"
import { omit } from "../src/helpers/omit.js" import { omit } from "../src/helpers/omit.js"
import { raise } from "../src/helpers/raise.js" import { raise } from "../src/helpers/raise.js"
import type { ReacordRoot } from "../src/main.js" import type { ReacordRoot } from "../src/main.js"
import { Button, createRoot, Embed, EmbedField, Text } from "../src/main.js" import {
ActionRow,
Button,
createRoot,
Embed,
EmbedField,
Text,
} from "../src/main.js"
import { testBotToken, testChannelId } from "./test-environment.js" import { testBotToken, testChannelId } from "./test-environment.js"
const client = new Client({ const client = new Client({
@@ -121,6 +128,9 @@ test("kitchen sink", async () => {
complex <Text>button</Text> text complex <Text>button</Text> text
</Button> </Button>
<Button disabled>disabled button</Button> <Button disabled>disabled button</Button>
<ActionRow>
<Button>new action row</Button>
</ActionRow>
</>, </>,
) )
await assertMessages([ await assertMessages([
@@ -212,6 +222,17 @@ test("kitchen sink", async () => {
}, },
], ],
}, },
{
type: "ACTION_ROW",
components: [
{
type: "BUTTON",
label: "new action row",
style: "SECONDARY",
disabled: false,
},
],
},
], ],
}, },
]) ])

45
src/action-row.tsx Normal file
View File

@@ -0,0 +1,45 @@
import type {
MessageActionRowComponentOptions,
MessageOptions,
} from "discord.js"
import React from "react"
import { ContainerInstance } from "./container-instance.js"
export type ActionRowProps = {
children: React.ReactNode
}
export function ActionRow(props: ActionRowProps) {
return (
<reacord-element createInstance={() => new ActionRowInstance()}>
{props.children}
</reacord-element>
)
}
class ActionRowInstance extends ContainerInstance {
readonly name = "ActionRow"
constructor() {
super({ warnOnNonTextChildren: false })
}
// eslint-disable-next-line class-methods-use-this
override renderToMessage(options: MessageOptions) {
const row = {
type: "ACTION_ROW" as const,
components: [] as MessageActionRowComponentOptions[],
}
for (const child of this.children) {
if (!child.renderToActionRow) {
console.warn(`${child.name} is not an action row component`)
continue
}
child.renderToActionRow(row)
}
options.components ??= []
options.components.push(row)
}
}

View File

@@ -1,4 +1,8 @@
import type { MessageEmbedOptions, MessageOptions } from "discord.js" import type {
MessageActionRowOptions,
MessageEmbedOptions,
MessageOptions,
} from "discord.js"
export abstract class BaseInstance { export abstract class BaseInstance {
/** The name of the JSX element represented by this instance */ /** The name of the JSX element represented by this instance */
@@ -14,4 +18,8 @@ export abstract class BaseInstance {
/** If this element can be a child of an embed, /** If this element can be a child of an embed,
* the function to modify the embed options */ * the function to modify the embed options */
renderToEmbed?(options: MessageEmbedOptions): void renderToEmbed?(options: MessageEmbedOptions): void
/** If this element can be a child of an action row,
* the function to modify the action row options */
renderToActionRow?(options: MessageActionRowOptions): void
} }

View File

@@ -2,6 +2,7 @@ import type {
BaseMessageComponentOptions, BaseMessageComponentOptions,
EmojiResolvable, EmojiResolvable,
MessageActionRowOptions, MessageActionRowOptions,
MessageButtonOptions,
MessageButtonStyle, MessageButtonStyle,
MessageOptions, MessageOptions,
} from "discord.js" } from "discord.js"
@@ -36,6 +37,17 @@ class ButtonInstance extends ContainerInstance {
super({ warnOnNonTextChildren: true }) super({ warnOnNonTextChildren: true })
} }
private getButtonOptions(): Required<BaseMessageComponentOptions> &
MessageButtonOptions {
return {
...pick(this.props, "emoji", "disabled"),
type: "BUTTON",
style: this.props.style ? toUpper(this.props.style) : "SECONDARY",
label: this.getChildrenText(),
customId: nanoid(),
}
}
override renderToMessage(options: MessageOptions) { override renderToMessage(options: MessageOptions) {
options.components ??= [] options.components ??= []
@@ -56,12 +68,10 @@ class ButtonInstance extends ContainerInstance {
options.components.push(actionRow) options.components.push(actionRow)
} }
actionRow.components.push({ actionRow.components.push(this.getButtonOptions())
...pick(this.props, "emoji", "disabled"), }
type: "BUTTON",
style: this.props.style ? toUpper(this.props.style) : "SECONDARY", override renderToActionRow(row: MessageActionRowOptions) {
label: this.getChildrenText(), row.components.push(this.getButtonOptions())
customId: nanoid(),
})
} }
} }

View File

@@ -1,5 +1,7 @@
export * from "./button" /* eslint-disable import/no-unused-modules */
export * from "./embed" export * from "./action-row.js"
export * from "./embed-field" export * from "./button.js"
export * from "./root" export * from "./embed-field.js"
export * from "./text" export * from "./embed.js"
export * from "./root.js"
export * from "./text.js"