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 { MessageOptions } from "../../internal/message" import { getNextActionRow } from "../../internal/message" import { Node } from "../../internal/node.js" import { OptionNode } from "./option-node" export type SelectProps = { children?: ReactNode value?: string values?: string[] placeholder?: string multiple?: boolean minValues?: number maxValues?: number disabled?: boolean onSelect?: (event: SelectEvent) => void onSelectValue?: (value: string) => void onSelectMultiple?: (values: string[]) => void } export type SelectEvent = { 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 = getNextActionRow(message) const options = [...this.children] .filter(isInstanceOf(OptionNode)) .map((node) => node.options) const { multiple, value, values, minValues = 0, maxValues = 25, children, onSelect, onSelectValue, onSelectMultiple, ...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 { if ( interaction.type === "select" && interaction.customId === this.customId && !this.props.disabled ) { this.props.onSelect?.({ values: interaction.values }) this.props.onSelectMultiple?.(interaction.values) if (interaction.values[0]) { this.props.onSelectValue?.(interaction.values[0]) } return true } return false } }