import { wait } from "@web3r/flowerkit/fn"; import { getFormDataFromObj } from "@web3r/flowerkit/net"; import type { RefObject } from "react"; import type { ActionMeta, OnChangeValue } from "react-select"; import { getSelectOptionsFromUrl } from "./getSelectOptionsFromUrl"; import type { TOptionType, TSelectUserValue, IStateActions, IOnSelectChangeRequestConfig, ISelect, TInputRef, TSelectPackageAPI, } from "../config/types"; type TOnOptionChangeParams = { data: OnChangeValue; onSelectChangeRequest?: IOnSelectChangeRequestConfig; stateActions: IStateActions; selectOptions: TOptionType[]; selectRef: RefObject; inputRef: TInputRef; onChange?: ISelect["onChange"]; name: string; actionData?: ActionMeta; }; /** * Handles the change of a selected option. * If `onSelectChangeRequest` is provided, it performs an asynchronous request * (e.g., to fetch additional data) and then calls the user's `onChange`. * @template IsMulti * @returns {Promise} */ export const onOptionChange = async ({ data, onSelectChangeRequest, stateActions, selectOptions, selectRef, inputRef, onChange, name, actionData, }: TOnOptionChangeParams): Promise => { const { action } = actionData || {}; // If an async change request is configured, perform it first if (onSelectChangeRequest) { const { onBeforeSend = () => stateActions.setSelectLoading(true), onSuccess = (data) => Promise.resolve(data), onError = () => Promise.resolve(undefined), onDone = () => wait(500).then(() => stateActions.setSelectLoading(false)), requestCfg = {}, getData = (selectValue: TSelectUserValue) => { if (name.endsWith("]") || Array.isArray(selectValue)) { return new FormData(); } else { return getFormDataFromObj({ [name]: selectValue }); } }, } = onSelectChangeRequest; onBeforeSend(); try { const resp = await getSelectOptionsFromUrl({ ...requestCfg, data: getData(data), }); await onSuccess({ resp, stateActions }); } catch (error) { try { await onError({ error, stateActions }); } catch (onErrorError) { console.error("[Select] onSelectChangeRequest.onError failed", onErrorError); } } finally { try { await Promise.resolve(onDone({ stateActions })); } catch (onDoneError) { console.error("[Select] onSelectChangeRequest.onDone failed", onDoneError); } } } stateActions.setSelectValue(data); // Invoke the user's onChange handler if provided if (typeof onChange === "function") { return onChange({ type: "select", refs: { selectRef, inputRef, }, data: { action, name, value: data, options: selectOptions, }, stateActions, }); } return Promise.resolve(); };