import { useId } from "@radix-ui/react-id"; import * as React from "react"; import type { GroupBase, Props, SingleValue, MultiValue, SelectComponentsConfig, MenuPlacement, } from "react-select"; import ReactSelect, { components as reactSelectComponents } from "react-select"; import classNames from "@calcom/lib/classNames"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import { Label } from "../inputs/Label"; import { ControlComponent, InputComponent, MenuComponent, MenuListComponent, OptionComponent, SingleValueComponent, ValueContainerComponent, MultiValueComponent, } from "./components"; export type SelectProps< Option, IsMulti extends boolean = false, Group extends GroupBase = GroupBase > = Props; export const getReactSelectProps = < Option, IsMulti extends boolean = false, Group extends GroupBase = GroupBase >({ className, components, menuPlacement = "auto", }: { className?: string; components: SelectComponentsConfig; menuPlacement?: MenuPlacement; }) => ({ menuPlacement, className: classNames("block h-[36px] w-full min-w-0 flex-1 rounded-md", className), classNamePrefix: "cal-react-select", components: { ...reactSelectComponents, IndicatorSeparator: () => null, Input: InputComponent, Option: OptionComponent, Control: ControlComponent, SingleValue: SingleValueComponent, Menu: MenuComponent, MenuList: MenuListComponent, ValueContainer: ValueContainerComponent, MultiValue: MultiValueComponent, ...components, }, }); export const Select = < Option, IsMulti extends boolean = false, Group extends GroupBase = GroupBase >({ className, components, styles, ...props }: SelectProps) => { const reactSelectProps = React.useMemo(() => { return getReactSelectProps({ className, components: components || {}, }); }, [className, components]); return ( ({ ...defaultStyles, backgroundColor: state.isSelected ? state.isFocused ? "var(--brand-color)" : "var(--brand-color)" : state.isFocused ? "var(--brand-color-dark-mode)" : "var(--brand-text-color)", }), ...styles, }} /> ); }; type IconLeadingProps = { icon: React.ReactNode; children?: React.ReactNode; } & React.ComponentProps; export const IconLeading = ({ icon, children, ...props }: IconLeadingProps) => { return ( {icon} {children} ); }; export const SelectField = function SelectField< Option, IsMulti extends boolean = false, Group extends GroupBase = GroupBase >( props: { name?: string; containerClassName?: string; label?: string; labelProps?: React.ComponentProps; className?: string; error?: string; } & SelectProps ) { const { t } = useLocale(); const { label = t(props.name || ""), containerClassName, labelProps, className, ...passThrough } = props; const id = useId(); return ( {!!label && ( {label} )} ); }; /** * TODO: It should replace Select after through testing */ export function SelectWithValidation< Option extends { label: string; value: string }, IsMulti extends boolean = false, Group extends GroupBase = GroupBase >({ required = false, onChange, value, ...remainingProps }: SelectProps & { required?: boolean }) { const [hiddenInputValue, _setHiddenInputValue] = React.useState(() => { if (value instanceof Array || !value) { return; } return value.value || ""; }); const setHiddenInputValue = React.useCallback((value: MultiValue | SingleValue) => { let hiddenInputValue = ""; if (value instanceof Array) { hiddenInputValue = value.map((val) => val.value).join(","); } else { hiddenInputValue = value?.value || ""; } _setHiddenInputValue(hiddenInputValue); }, []); React.useEffect(() => { if (!value) { return; } setHiddenInputValue(value); }, [value, setHiddenInputValue]); return ( { setHiddenInputValue(value); if (onChange) { onChange(value, ...remainingArgs); } }} /> {required && ( {}} // TODO:Not able to get focus to work // onFocus={() => selectRef.current?.focus()} required={required} /> )} ); }