// oxlint-disable typescript/no-explicit-any import type { BaseInputorContext, BaseInputorControllerOptions, BaseInputorSchema, InputorControllerInitializeHooks, } from "./base.ts" import { BaseInputorController } from "./base.ts" export const MULTI_SELECT_INPUTOR_TYPE_NAME = "multi-select" as const export type MultiSelectInputorTypeName = typeof MULTI_SELECT_INPUTOR_TYPE_NAME export interface MultiSelectOption { name: string label: string value: Value isSelected: boolean description?: string | undefined isDisabled?: boolean | undefined } export type MultiSelectOptions = Array> export type MultiSelectInputorExternalValue = MultiSelectOptions export type MultiSelectInputorInternalValue = MultiSelectOptions export interface MultiSelectInputorSchema extends BaseInputorSchema< MultiSelectInputorExternalValue > { inputorTypeName: MultiSelectInputorTypeName } export interface MultiSelectInputorContext extends BaseInputorContext< MultiSelectInputorExternalValue, MultiSelectInputorInternalValue > {} export interface MultiSelectInputorControllerOptions< Value = any, > extends BaseInputorControllerOptions< MultiSelectInputorExternalValue, MultiSelectInputorSchema > { minSelectCount?: number | undefined maxSelectCount?: number | undefined } export class MultiSelectInputorController extends BaseInputorController< MultiSelectInputorExternalValue, MultiSelectInputorInternalValue, MultiSelectInputorSchema, MultiSelectInputorContext > { declare schemaType: MultiSelectInputorSchema declare optionsType: MultiSelectInputorControllerOptions declare constructorType: typeof MultiSelectInputorController static inputorTypeName: MultiSelectInputorTypeName = MULTI_SELECT_INPUTOR_TYPE_NAME inputorTypeName: MultiSelectInputorTypeName = MULTI_SELECT_INPUTOR_TYPE_NAME voidExternalValue = [] as MultiSelectInputorExternalValue voidInternalValue = [] as MultiSelectInputorInternalValue private minSelectCount!: number private maxSelectCount!: number constructor(options: MultiSelectInputorControllerOptions) { super(options) } protected override async initialize( options: MultiSelectInputorControllerOptions, hooks?: InputorControllerInitializeHooks, ): Promise { await super.initialize(options, { ...hooks, onSchemaReady: async () => { this.minSelectCount = options.minSelectCount ?? 0 this.maxSelectCount = options.maxSelectCount ?? Infinity await hooks?.onSchemaReady?.() }, }) } async select(name: string): Promise { const internalValue = this.getInternalValue() const selectedCount = internalValue.filter((option) => option.isSelected).length const hasReachedMaxSelectCount = selectedCount >= this.maxSelectCount const updatedInternalValue = internalValue.map((option) => { const { name: optionName, isSelected, isDisabled } = option if (isDisabled === true) { return option } if (optionName !== name) { return option } const targetIsSelected = !isSelected if (targetIsSelected === true && hasReachedMaxSelectCount === true) { return option } else { return { ...option, isSelected: targetIsSelected, } } }) await this.updateInternalValue(updatedInternalValue) } }