action row component
This commit is contained in:
@@ -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
45
src/action-row.tsx
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
12
src/main.ts
12
src/main.ts
@@ -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"
|
||||||
|
|||||||
Reference in New Issue
Block a user