import { nanoid } from "nanoid" import type { ReactNode } from "react" import React from "react" import { isInstanceOf } from "../../../helpers/is-instance-of" import { ReacordElement } from "../../internal/element.js" import type { ComponentInteraction } from "../../internal/interaction" import type { ActionRow, MessageOptions } from "../../internal/message" import { Node } from "../../internal/node.js" import type { ComponentEvent } from "../component-event" import { OptionNode } from "./option-node" export type SelectProps = { children?: ReactNode value?: string values?: string[] placeholder?: string multiple?: boolean minValues?: number maxValues?: number disabled?: boolean onChange?: (event: SelectChangeEvent) => void onChangeValue?: (value: string, event: SelectChangeEvent) => void onChangeMultiple?: (values: string[], event: SelectChangeEvent) => void } export type SelectChangeEvent = ComponentEvent & { values: string[] } export function Select(props: SelectProps) { return ( new SelectNode(props)}> {props.children} ) } class SelectNode extends Node { readonly customId = nanoid() override modifyMessageOptions(message: MessageOptions): void { const actionRow: ActionRow = [] message.actionRows.push(actionRow) const options = [...this.children] .filter(isInstanceOf(OptionNode)) .map((node) => node.options) const { multiple, value, values, minValues = 0, maxValues = 25, children, onChange, onChangeValue, onChangeMultiple, ...props } = this.props actionRow.push({ ...props, type: "select", customId: this.customId, options, values: [...(values || []), ...(value ? [value] : [])], minValues: multiple ? minValues : undefined, maxValues: multiple ? Math.max(minValues, maxValues) : undefined, }) } override handleComponentInteraction( interaction: ComponentInteraction, ): boolean { const isSelectInteraction = interaction.type === "select" && interaction.customId === this.customId && !this.props.disabled if (!isSelectInteraction) return false this.props.onChange?.(interaction.event) this.props.onChangeMultiple?.(interaction.event.values, interaction.event) if (interaction.event.values[0]) { this.props.onChangeValue?.(interaction.event.values[0], interaction.event) } return true } }