non-interactive buttons

This commit is contained in:
MapleLeaf
2021-12-21 14:57:23 -06:00
parent 249a2a2457
commit f53c6dba22
8 changed files with 175 additions and 150 deletions

67
src/button.tsx Normal file
View File

@@ -0,0 +1,67 @@
import type {
BaseMessageComponentOptions,
EmojiResolvable,
MessageActionRowOptions,
MessageButtonStyle,
MessageOptions,
} from "discord.js"
import { nanoid } from "nanoid"
import React from "react"
import { ContainerInstance } from "./container-instance.js"
import { last } from "./helpers/last.js"
import { pick } from "./helpers/pick.js"
import { toUpper } from "./helpers/to-upper.js"
export type ButtonStyle = Exclude<Lowercase<MessageButtonStyle>, "link">
export type ButtonProps = {
style?: ButtonStyle
emoji?: EmojiResolvable
disabled?: boolean
children?: React.ReactNode
}
export function Button(props: ButtonProps) {
return (
<reacord-element createInstance={() => new ButtonInstance(props)}>
{props.children}
</reacord-element>
)
}
class ButtonInstance extends ContainerInstance {
readonly name = "Button"
constructor(private readonly props: ButtonProps) {
super({ warnOnNonTextChildren: true })
}
override renderToMessage(options: MessageOptions) {
options.components ??= []
// i hate this
let actionRow:
| (Required<BaseMessageComponentOptions> & MessageActionRowOptions)
| undefined = last(options.components)
if (
!actionRow ||
actionRow.components[0]?.type === "SELECT_MENU" ||
actionRow.components.length >= 5
) {
actionRow = {
type: "ACTION_ROW",
components: [],
}
options.components.push(actionRow)
}
actionRow.components.push({
...pick(this.props, "emoji", "disabled"),
type: "BUTTON",
style: this.props.style ? toUpper(this.props.style) : "SECONDARY",
label: this.getChildrenText(),
customId: nanoid(),
})
}
}

3
src/helpers/last.ts Normal file
View File

@@ -0,0 +1,3 @@
export function last<T>(array: T[]): T | undefined {
return array[array.length - 1]
}

4
src/helpers/to-upper.ts Normal file
View File

@@ -0,0 +1,4 @@
/** A typesafe version of toUpperCase */
export function toUpper<S extends string>(string: S) {
return string.toUpperCase() as Uppercase<S>
}

View File

@@ -1,3 +1,4 @@
export * from "./button"
export * from "./embed"
export * from "./embed-field"
export * from "./root"