import { isSameDay } from 'date-fns';
import * as React from 'react';
import ReactSelect, { components, } from 'react-select';
import CreatableSelect from 'react-select/creatable';
import { Icon } from '../icons';
import { DataSource, InfiniteTable, } from '@infinite-table/infinite-react';
import { useCallback, useId, useMemo, useState } from 'react';
import { Resizable } from 're-resizable';
import Tooltip from '../Tooltip';
import { ensurePortalElement } from '../OverlayTrigger';
import { CheckBox } from '../CheckBox';
import { useAdaptableComputedCSSVars } from '../../View/AdaptableComputedCSSVarsContext';
import { Box, Flex } from '../Flex';
import clsx from 'clsx';
const resizableDirections = {
    right: true,
    bottom: true,
    bottomRight: true,
};
const defaultResizableSize = {
    width: '100%',
};
const checkboxStyle = {
    position: 'relative',
    top: 1,
};
const INFINITE_DOM_PROPS = {
    style: {
        // height: '100%',
        flex: 1,
        // maxHeight: '50vh',
        width: '100%',
    },
};
const infiniteContentValueClassName = 'InfiniteCell_content_value';
const renderValue = ({ renderBag, data, value }) => {
    if (data.tooltip) {
        const tooltipNode = typeof data.tooltip === 'string' ? data.tooltip : value;
        return (React.createElement(Tooltip, { label: tooltipNode },
            React.createElement("div", { className: infiniteContentValueClassName }, renderBag.value)));
    }
    return React.createElement("div", { className: infiniteContentValueClassName }, renderBag.value);
};
const INFINITE_COLUMNS_WITH_CHECKBOX = {
    label: {
        field: 'label',
        defaultFlex: 1,
        style: {
            lineHeight: '30px',
        },
        resizable: false,
        defaultSortable: false,
        renderSelectionCheckBox: (params) => {
            // disable reacting to onChange
            // as we handle selection change in the onCellClick
            return React.createElement(CheckBox, { className: "twa:mx-1", checked: params.rowInfo?.rowSelected ?? false });
        },
        renderHeaderSelectionCheckBox: true,
        className: 'ab-Select-CheckboxColumn',
        renderValue,
        renderHeader: (headerParams) => {
            const selected = headerParams.allRowsSelected
                ? true
                : headerParams.someRowsSelected
                    ? null
                    : false;
            const { api } = headerParams;
            return (React.createElement(React.Fragment, null,
                React.createElement(CheckBox, { className: "twa:mx-1", checked: selected, onChange: (selected) => {
                        if (selected) {
                            api.rowSelectionApi.selectAll();
                        }
                        else {
                            api.rowSelectionApi.deselectAll();
                        }
                    } }, headerParams.allRowsSelected ? '(Deselect All)' : '(Select All)')));
        },
        renderMenuIcon: false,
    },
};
const INFINITE_COLUMNS_WITH_RADIO = {
    label: {
        field: 'label',
        defaultFlex: 1,
        renderValue,
    },
};
const isRowDisabled = ({ data, }) => {
    return data ? !!data.isDisabled : false;
};
const rowClassName = ({ data }) => {
    const flags = data.isDisabled ? 'ab-Select-Row--disabled' : '';
    return `ab-Select-Row ${flags}`;
};
const fontCommonStyles = {
    fontSize: 'var(--ab-cmp-select__font-size)',
    fontFamily: 'var(--ab-cmp-select__font-family)',
};
const commonStyles = ({ isDisabled, }) => {
    return {
        color: 'var(--ab-cmp-input__color)',
        background: isDisabled
            ? 'var(--ab-cmp-input--disabled__background)'
            : 'var(--ab-cmp-input__background)',
        ...fontCommonStyles,
    };
};
const doesOptionMatchValue = function (value) {
    return (option) => {
        if (typeof option.value === 'object' && option.value instanceof Date) {
            return isSameDay(option.value, value);
        }
        return option.value === value;
    };
};
export const Select = function (props) {
    let maxLabelLength = 0;
    const inputId = useId();
    const computedCSSVars = useAdaptableComputedCSSVars();
    const CSS_VARS_VALUES = {
        '--ab-cmp-select-menu__max-width': computedCSSVars['--ab-cmp-select-menu__max-width'] || '60vw',
        '--ab-cmp-select-menu__min-width': computedCSSVars['--ab-cmp-select-menu__min-width'] || 150,
        '--ab-cmp-select-menu__max-height': computedCSSVars['--ab-cmp-select-menu__max-height'] || '60vh',
    };
    const searchableInMenulist = props.searchable === 'menulist';
    const searchableInline = props.searchable === 'inline';
    // relevant for menulist search only
    const menulistInputRef = React.useRef(null);
    const [isSelectMenuOpen, setIsSelectMenuOpen] = useState(false);
    const propsOnMenuOpen = props.onMenuOpen;
    const openSelectMenu = React.useCallback(() => {
        setIsSelectMenuOpen(true);
        // it's a react-select bug, onMenuOpen is not called with controlled menuIsOpen
        propsOnMenuOpen?.();
    }, [propsOnMenuOpen]);
    const closeSelectMenu = React.useCallback(() => {
        setIsSelectMenuOpen(false);
    }, []);
    const ref = React.useRef(null);
    const valueToOptionMap = new Map((props.options || []).map((opt) => {
        let label = opt.label;
        if (typeof label === 'string' || typeof label === 'number' || typeof label === 'boolean') {
            maxLabelLength = Math.max(maxLabelLength, `${label}`.length);
        }
        return [opt.value, opt];
    }));
    const findOptionByValue = (value) => {
        const option = valueToOptionMap.get(value);
        if (option) {
            return option;
        }
        // try date comparison if the value is a date
        // or if it's a number but the options are dates
        if ((typeof value === 'object' && value instanceof Date) ||
            (Array.isArray(props.options) &&
                props.options.length &&
                typeof props.options[0] === 'object' &&
                props.options[0].value instanceof Date)) {
            return (props.options || []).find(doesOptionMatchValue(value)) ?? null;
        }
        return null;
    };
    const renderMultipleValues = props.renderMultipleValues;
    const isMulti = props.isMulti ?? Array.isArray(props.value);
    const showHeaderSelectionCheckbox = isMulti && (props.showHeaderSelectionCheckbox ?? false);
    const skipDefaultFiltering = props.skipDefaultFiltering ?? false;
    let selectedOption = null;
    if (isMulti) {
        selectedOption =
            (props.value ?? []).map((value) => {
                const option = findOptionByValue(value);
                if (!option) {
                    return {
                        value,
                        label: value,
                    };
                }
                return option;
            }) ?? null;
    }
    else {
        selectedOption = findOptionByValue(props.value);
        if (!selectedOption &&
            props.value !== undefined &&
            props.value !== null &&
            props.value !== '') {
            selectedOption = {
                value: props.value,
                label: props.value,
            };
        }
    }
    let disabled = props.disabled ?? false;
    const accessLevel = props.accessLevel ?? 'Full';
    if (accessLevel === 'Hidden') {
        return null;
    }
    if (accessLevel === 'ReadOnly') {
        disabled = true;
    }
    /**
     * If on each render a new reference is passed, the menu will not open using the keyboard.
     */
    /**
     * Use refs for isSelectMenuOpen, openSelectMenu, and closeSelectMenu so that
     * SelectContainer is stable across re-renders. If SelectContainer gets a new
     * reference when menu opens/closes, react-select recreates its internal
     * component tree, the DummyInput is removed from DOM, and focus is lost.
     */
    const isSelectMenuOpenRef = React.useRef(isSelectMenuOpen);
    isSelectMenuOpenRef.current = isSelectMenuOpen;
    const openSelectMenuRef = React.useRef(openSelectMenu);
    openSelectMenuRef.current = openSelectMenu;
    const closeSelectMenuRef = React.useRef(closeSelectMenu);
    closeSelectMenuRef.current = closeSelectMenu;
    const SelectContainer = React.useMemo(() => {
        return (selectContainerProps) => {
            return (React.createElement(components.SelectContainer, { ...selectContainerProps, innerProps: {
                    // @ts-ignore
                    'data-name': props['data-name'],
                    'data-id': props['data-id'],
                    'data-test': props.searchable || false,
                    ...selectContainerProps.innerProps,
                    onMouseDown: (e) => {
                        if (!searchableInMenulist) {
                            return;
                        }
                        if (!isSelectMenuOpenRef.current) {
                            openSelectMenuRef.current();
                            e.stopPropagation();
                            e.preventDefault();
                        }
                    },
                    onKeyDownCapture: (e) => {
                        if (!searchableInMenulist) {
                            return;
                        }
                        if (isSelectMenuOpenRef.current) {
                            if (e.key === 'Escape') {
                                closeSelectMenuRef.current();
                                e.stopPropagation();
                                e.preventDefault();
                                e.nativeEvent.stopImmediatePropagation();
                                // we do this because the focus is lost when the menu is closed
                                // and document.body is set as the active element
                                requestAnimationFrame(() => {
                                    document.getElementById(inputId)?.focus();
                                    // we need to do it again
                                    // also don't store a ref to the input element
                                    // but query the DOM again
                                    // as the old ref is no longer in the DOM
                                    // because of a react-select bug I presume
                                    requestAnimationFrame(() => {
                                        document.getElementById(inputId)?.focus();
                                    });
                                });
                            }
                        }
                        else {
                            // open the menu
                            if (e.key === 'Enter' || e.key === ' ' || e.key === 'ArrowDown') {
                                openSelectMenuRef.current();
                                e.stopPropagation();
                                e.preventDefault();
                                e.nativeEvent.stopImmediatePropagation();
                            }
                        }
                    },
                } }));
        };
    }, [searchableInMenulist]);
    const resizable = props.resizable ?? false;
    const ValueContainer = React.useMemo(() => {
        return (props) => {
            let { children, ...inputProps } = props;
            const initialChildren = children;
            const currentValues = inputProps.getValue();
            const customRenderValue = renderMultipleValues?.(currentValues, {
                focused: focusedRef.current,
                placeholder: props.placeholder,
            });
            const title = typeof customRenderValue === 'string' ? customRenderValue : '';
            children = customRenderValue ? (React.createElement(Box, { className: "twa:flex twa:flex-row twa:flex-1 twa:flex-nowrap twa:items-center twa:overflow-hidden twa:h-full" },
                React.createElement("span", { title: title, "data-name": "multi-value-text", style: {
                        flex: '0 1 auto',
                        appearance: 'none',
                        border: 'none',
                        background: 'transparent',
                        outline: 'none',
                        whiteSpace: 'nowrap',
                        overflow: 'hidden',
                        textOverflow: 'ellipsis',
                    } }, customRenderValue),
                initialChildren[1])) : (initialChildren);
            return (React.createElement(components.ValueContainer, { ...inputProps, innerProps: {
                    'data-name': 'value-container',
                    ...inputProps.innerProps,
                } }, children));
        };
    }, [renderMultipleValues, props.placeholder]);
    const sizeRef = React.useRef({ ...defaultResizableSize });
    const MenuComponent = React.useMemo(() => {
        return (menuProps) => {
            const { isLoading } = menuProps;
            const theChildren = (React.createElement(React.Fragment, null,
                menuProps.children,
                React.createElement("div", { style: {
                        display: isLoading ? 'block' : 'none',
                        position: 'absolute',
                        inset: 0,
                        background: `var(--ab-cmp-select-loading__background)`,
                        zIndex: 1,
                    } })));
            const onResizeStop = useCallback((_e, _direction, ref) => {
                const newSize = {
                    width: ref.style.width,
                    height: ref.style.height,
                };
                sizeRef.current = newSize;
            }, []);
            return (React.createElement(React.Fragment, null,
                React.createElement(components.Menu, { ...menuProps, innerProps: {
                        // @ts-ignore
                        'data-name': 'menu-container',
                        'data-resizable': resizable,
                        ...menuProps.innerProps,
                        onBlur: (e) => {
                            if (!searchableInMenulist) {
                                return;
                            }
                            const { relatedTarget } = e;
                            const menuDOMNode = menuProps.innerRef && 'current' in menuProps.innerRef
                                ? menuProps.innerRef.current
                                : null;
                            if ((menuDOMNode && relatedTarget == menuDOMNode) ||
                                menuDOMNode?.contains(relatedTarget)) {
                                // ignore the event if the focus is still inside the menu
                                return;
                            }
                            requestAnimationFrame(() => {
                                // wee need to wait for the single value selection to complete before closing
                                closeSelectMenu();
                            });
                        },
                        onMouseDown: (event) => {
                            if (!props.isMulti) {
                                menuProps.innerProps?.onMouseDown?.(event);
                            }
                            if (!searchableInMenulist) {
                                return;
                            }
                            if (props.isMulti) {
                                // to avoid the menu closing when clicking inside it
                                event.stopPropagation();
                            }
                        },
                    } }, resizable ? (React.createElement(Resizable, { className: "ab-Select-MenuContainer-Resizable", enable: resizableDirections, 
                    // ideally we wouldn't need those to be computed values
                    // and instead pass the CSS var name, like `var(--ab-cmp-select-menu__min-width)`
                    // to the Resizable component, but it won't respect them
                    // so we needed to read the CSS variables from the DOM, using CSSNumericVariableWatch
                    // and then pass the actual values to Resizable
                    minWidth: CSS_VARS_VALUES['--ab-cmp-select-menu__min-width'], maxHeight: CSS_VARS_VALUES['--ab-cmp-select-menu__max-height'], maxWidth: CSS_VARS_VALUES['--ab-cmp-select-menu__max-width'], defaultSize: sizeRef.current, onResizeStop: onResizeStop, onResizeStart: (e) => {
                        e.preventDefault();
                    } }, theChildren)) : (theChildren))));
        };
    }, [resizable, JSON.stringify(CSS_VARS_VALUES)]);
    const SelectComponent = props.isCreatable ? CreatableSelect : ReactSelect;
    const ClearIndicator = React.useMemo(() => {
        return (clearIndicatorProps) => {
            return (React.createElement(components.ClearIndicator, { ...clearIndicatorProps },
                React.createElement(Icon, { name: "close" })));
        };
    }, []);
    const MenuList = React.useMemo(() => {
        return (props) => {
            const { setValue, getValue, focusedOption, options, selectProps } = props;
            const { filterOption, inputValue, isLoading } = selectProps;
            // Focus the input when MenuList mounts
            React.useEffect(() => {
                if (menulistInputRef.current) {
                    menulistInputRef.current.focus();
                }
            }, []);
            const filterFunction = React.useCallback(({ data }) => filterOption({ data, label: `${data.label}`, value: data.value }, inputValue), [filterOption, inputValue]);
            const hasFilter = inputValue !== '' && !skipDefaultFiltering;
            const filteredOptionsValues = new Set();
            const filteredOptions = !hasFilter
                ? options
                : options.filter((data) => {
                    const included = filterOption({ data, label: `${data.label}`, value: data.value }, inputValue);
                    if (included) {
                        filteredOptionsValues.add(data.value);
                    }
                    return included;
                });
            const focusedOptionIndex = options
                .filter((option) => filterFunction({ data: option }))
                .indexOf(focusedOption);
            const valueStrKey = getValue()
                // if we simply map, then if we have [] or [''], they will map to the same value
                // but we need it to be different
                // so we can trigger a change when the value changes
                .map((option, index) => `${index}-${option.value}`)
                .join(',');
            const selectedRows = useMemo(() => {
                const selectedRows = [];
                // we build the Infinite Table selection
                getValue().forEach((option) => {
                    // if there are no filters, include everything that is in the value
                    // but if there is a filter (which will be smaller than the current value)
                    // only include the current options that match the filter
                    if (!hasFilter || filteredOptionsValues.has(option.value)) {
                        selectedRows.push(option.value);
                    }
                });
                return selectedRows;
            }, [valueStrKey, inputValue, hasFilter]);
            const rowSelection = React.useMemo(() => {
                return isMulti
                    ? {
                        selectedRows,
                        deselectedRows: [],
                        defaultSelection: false,
                    }
                    : selectedRows[0];
            }, [selectedRows, isMulti]);
            const onRowSelectionChange = React.useCallback((selectionParams) => {
                let selection = [];
                const { selectedRows, defaultSelection, deselectedRows } = selectionParams;
                if (hasFilter) {
                    if (defaultSelection === true && deselectedRows.length === 0) {
                        // all selected
                        const currentValue = getValue();
                        const includedKeys = new Set();
                        // add all the options that are in the current value
                        selection = currentValue.map((option) => {
                            includedKeys.add(option.value);
                            return option;
                        });
                        // also add all the options that match the filter
                        filteredOptions.forEach((option) => {
                            // make sure you don't add the same option twice
                            if (!includedKeys.has(option.value)) {
                                selection.push({ value: option.value });
                            }
                        });
                    }
                    else if (defaultSelection === false && selectedRows.length === 0) {
                        // we need to clear the selection
                        // but we have a filter, so we need to clear only those options that are included in the filter
                        // and leave the rest
                        const currentValue = getValue();
                        selection = currentValue.filter((row) => !filteredOptionsValues.has(row.value));
                    }
                    else {
                        // some selected
                        const currentValue = getValue();
                        const includedKeys = new Set();
                        // start with an empty selection
                        selection = [];
                        // add those in the value that are not in the filter
                        selection = currentValue.filter((row) => {
                            const res = !filteredOptionsValues.has(row.value);
                            if (res) {
                                includedKeys.add(row.value);
                            }
                            return res;
                        });
                        // and now also add those in the filter that are actually selected
                        selectedRows.forEach((row) => {
                            if (!includedKeys.has(row)) {
                                selection.push({ value: row });
                            }
                        });
                    }
                }
                else {
                    if (defaultSelection === true && deselectedRows.length === 0) {
                        // all selected
                        selection = options.map((option) => {
                            return { value: option.value };
                        });
                    }
                    else if (defaultSelection === false && selectedRows.length === 0) {
                        // none selected
                        selection = [];
                    }
                    else {
                        // some selected
                        selection = selectedRows.map((row) => {
                            return { value: row };
                        });
                    }
                }
                //@ts-ignore
                setValue(selection, 'select-option');
            }, [setValue, filterOption, inputValue, hasFilter, filteredOptions, rowSelection, valueStrKey]);
            const onSingleRowSelectionChange = React.useCallback((value) => {
                if (value == undefined && rowSelection != undefined) {
                    return;
                }
                //@ts-ignore
                setValue({ value }, 'select-option');
            }, [setValue]);
            const onCellClick = React.useCallback(({ rowIndex, api, dataSourceApi }) => {
                if (isMulti) {
                    const pk = dataSourceApi.getPrimaryKeyByIndex(rowIndex);
                    api.rowSelectionApi.toggleRowSelection(pk);
                }
                if (searchableInMenulist) {
                    requestAnimationFrame(() => {
                        menulistInputRef.current?.focus();
                    });
                }
            }, []);
            const prevInputValueRef = React.useRef('');
            return (React.createElement(DataSource, { 
                // @ts-ignore
                // data={props.options}
                // @ts-ignore
                data: filteredOptions, primaryKey: "value", selectionMode: isMulti ? 'multi-row' : 'single-row', 
                // @ts-ignore
                onRowSelectionChange: isLoading ? null : isMulti ? onRowSelectionChange : onSingleRowSelectionChange, rowSelection: rowSelection, isRowDisabled: isRowDisabled },
                searchableInMenulist && (React.createElement(Flex, { className: "twa:p-1 ab-Select-MenulistSearchContainer" },
                    React.createElement("input", { ref: menulistInputRef, "data-name": "menulist-search-input", style: {
                            width: '100%',
                        }, className: 'ab-Select-MenulistSearch ab-Input ab-Input--type-text', autoCorrect: "off", autoComplete: "off", spellCheck: "false", type: "text", value: inputValue, onChange: (e) => {
                            const currentValue = e.currentTarget.value;
                            onInputChange(currentValue, {
                                action: 'input-change',
                                prevInputValue: prevInputValueRef.current,
                            });
                            prevInputValueRef.current = currentValue;
                        }, onMouseDown: (e) => {
                            e.stopPropagation();
                            const inputElement = e.target;
                            inputElement?.focus?.();
                        }, onTouchEnd: (e) => {
                            e.stopPropagation();
                            const inputElement = e.target;
                            inputElement?.focus?.();
                        }, placeholder: "Search..." }))),
                React.createElement(InfiniteTable, { header: isMulti && showHeaderSelectionCheckbox ? true : false, rowClassName: rowClassName, showZebraRows: false, rowHeight: '--ab-grid-row-height', onCellClick: isLoading ? null : onCellClick, keyboardNavigation: isLoading ? false : 'row', activeRowIndex: focusedOptionIndex, keyboardSelection: true, columns: isMulti ? INFINITE_COLUMNS_WITH_CHECKBOX : INFINITE_COLUMNS_WITH_RADIO, domProps: INFINITE_DOM_PROPS })));
        };
    }, [isMulti, skipDefaultFiltering, showHeaderSelectionCheckbox]);
    const DropdownIndicator = React.useMemo(() => {
        return (dropdownIndicatorProps) => {
            return (React.createElement(components.DropdownIndicator, { ...dropdownIndicatorProps, innerProps: {
                    ...dropdownIndicatorProps.innerProps,
                } },
                React.createElement(Icon, { name: "triangle-down", style: { height: 20, width: 20 } })));
        };
    }, []);
    const focusedRef = React.useRef(false);
    const onFocus = React.useCallback(() => {
        focusedRef.current = true;
        props.onFocus?.();
    }, [props.onFocus]);
    const onBlur = React.useCallback(() => {
        focusedRef.current = false;
        props.onBlur?.();
    }, [props.onBlur]);
    const [inputValue, setInputValue] = React.useState('');
    const onInputChange = React.useCallback((value, actionMeta) => {
        if (isMulti && actionMeta.action === 'set-value') {
            // when selecting an option, don't clear the input filter
            return;
        }
        setInputValue(value);
        props.onInputChange?.(value);
    }, [props.onInputChange, isMulti]);
    /**
     * Use refs for selectedOption and renderSingleValue so that the
     * SingleValue component function is stable across re-renders.
     * If SingleValue gets a new reference on each render, selectComponents changes,
     * react-select recreates its internal component tree, the DummyInput is removed
     * from DOM, and focus is lost (the keyboard stops working).
     * See the comment above SelectContainer about this exact issue.
     */
    const selectedOptionRef = React.useRef(selectedOption);
    selectedOptionRef.current = selectedOption;
    const renderSingleValueRef = React.useRef(props.renderSingleValue);
    renderSingleValueRef.current = props.renderSingleValue;
    const SingleValue = React.useMemo(() => {
        return (singleValueProps) => {
            return (React.createElement(components.SingleValue, { ...singleValueProps }, renderSingleValueRef.current
                ? renderSingleValueRef.current(selectedOptionRef.current)
                : singleValueProps.children));
        };
    }, []);
    const selectComponents = useMemo(() => {
        return {
            SelectContainer,
            ValueContainer,
            Menu: MenuComponent,
            SingleValue,
            ClearIndicator,
            DropdownIndicator,
            MenuList,
        };
    }, [
        SelectContainer,
        ValueContainer,
        MenuComponent,
        SingleValue,
        ClearIndicator,
        DropdownIndicator,
        MenuList,
    ]);
    return (React.createElement(React.Fragment, null,
        React.createElement(SelectComponent, { ref: ref, openMenuOnClick: searchableInMenulist ? false : undefined, openMenuOnFocus: searchableInMenulist ? false : undefined, menuIsOpen: searchableInMenulist ? isSelectMenuOpen : undefined, isSearchable: searchableInline, "aria-label": props['aria-label'], onKeyDown: props.onKeyDown, inputValue: inputValue, inputId: inputId, onInputChange: onInputChange, onFocus: onFocus, onBlur: onBlur, onMenuOpen: props.onMenuOpen, isLoading: props.isLoading, options: props.options, className: clsx(props.className, 'ab-Select'), isDisabled: disabled, menuPlacement: props.menuPlacement ?? 'auto', hideSelectedOptions: false, isMulti: isMulti, value: selectedOption, blurInputOnSelect: false, menuPosition: props.menuPosition ?? 'absolute', 
            // This needed so the menu is not clipped by overflow: hidden
            menuPortalTarget: ensurePortalElement(), isClearable: props.isClearable, closeMenuOnSelect: props.closeMenuOnSelect, onChange: (option) => {
                if (isMulti) {
                    const value = option.map((x) => x?.value);
                    props.onChange(value);
                }
                else {
                    props.onChange(option?.value);
                }
                if (searchableInMenulist) {
                    // ensure element keeps focus
                    requestAnimationFrame(() => {
                        menulistInputRef.current?.focus();
                    });
                }
            }, placeholder: props.placeholder, createOptionPosition: 'first', 
            // formatCreateLabel={(inputValue) => inputValue} // can we make this auto??
            // we use this:  https://react-select.com/creatable
            components: selectComponents, 
            /**
             * Using styles is the preferred way to style react-select.
             * https://react-select.com/styles#the-styles-prop
             */
            styles: {
                // Typescript issue with csstype@3.1.3
                // https://github.com/JedWatson/react-select/issues/5825#issuecomment-1850472549
                // Remove
                container: (baseStyle) => {
                    return {
                        ...baseStyle,
                        ...props.style,
                        ...props.styles?.container,
                    };
                },
                // @ts-ignorets-ignore when fixed
                menuPortal: (baseStyle) => {
                    return {
                        ...baseStyle,
                        // needed to avoid tooltips from being displayed under this menu
                        // as otherwise react-select uses zIndex 1
                        zIndex: 'auto',
                        textAlign: 'left',
                    };
                },
                // @ts-ignore
                menu: (baseStyle, state) => {
                    return {
                        ...baseStyle,
                        // needed to avoid tooltips from being displayed under this menu
                        // as otherwise react-select uses zIndex 1
                        zIndex: 'auto',
                        width: resizable ? '100%' : `${Math.max(maxLabelLength, 10)}ch`,
                        '--ab-cmp-select-menu__min-height': `min(${(props.options || []).length + (showHeaderSelectionCheckbox ? 1 : 0)} * var(--ab-grid-row-height) + ${searchableInMenulist ? 40 : 0}px, ${searchableInMenulist ? 22 : 20}rem)`,
                        maxHeight: 'var(--ab-cmp-select-menu__max-height)',
                        minWidth: 'var(--ab-cmp-select-menu__min-width)',
                        maxWidth: 'var(--ab-cmp-select-menu__max-width)',
                        ...commonStyles(state),
                        ...props.menuStyle,
                    };
                },
                // @ts-ignore
                option: (baseStyle, state) => {
                    const style = {
                        ...baseStyle,
                        ...commonStyles(state),
                        '&:active': {
                            background: 'var(--ab-cmp-select-option-active__background)',
                        },
                    };
                    if (state.isSelected) {
                        style.background = 'var(--ab-cmp-select-option-active__background)';
                        style.color = 'var(--ab-cmp-select-option-active__color)';
                    }
                    if (state.isFocused) {
                        style.background = 'var(--ab-cmp-select-option-focused__background)';
                    }
                    return style;
                },
                // @ts-ignore
                input: (baseStyle, state) => {
                    return {
                        ...baseStyle,
                        padding: props.size === 'small' ? 0 : baseStyle.padding,
                        color: 'var(--ab-cmp-select__color)',
                    };
                },
                valueContainer: (baseStyle) => {
                    return {
                        ...baseStyle,
                        padding: props.size === 'small' ? `0 var(--ab-space-1)` : baseStyle.padding,
                        ...props.styles?.valueContainer,
                    };
                },
                // @ts-ignore
                singleValue: (baseStyle, state) => {
                    return {
                        ...baseStyle,
                        ...commonStyles(state),
                    };
                },
                // @ts-ignore
                control: (baseStyle, state) => {
                    return {
                        ...baseStyle,
                        ...commonStyles(state), // height: 30,
                        minHeight: props.size === 'small' ? 0 : 'var(--ab-input-height)',
                        boxShadow: state.isFocused ? 'var(--ab-cmp-select-focused__box-shadow)' : 'none',
                        outline: state.isFocused ? 'var(--ab-cmp-select-focused__outline)' : 'none',
                        border: 'var(--ab-cmp-select__border)',
                        borderRadius: 'var(--ab-cmp-select__border-radius)',
                        '&:hover': {
                            border: 'var(--ab-cmp-select__border)',
                        },
                        ...props.styles?.control,
                    };
                },
                // @ts-ignore
                dropdownIndicator: (baseStyle) => {
                    return {
                        ...baseStyle,
                        padding: 0,
                        ...props.styles?.dropdownIndicator,
                    };
                },
                // @ts-ignore
                clearIndicator: (baseStyle) => {
                    return {
                        ...baseStyle,
                        padding: '2px 3px',
                    };
                },
                multiValue: (baseStyle) => {
                    return {
                        ...baseStyle,
                        color: 'var(--ab-cmp-select__color)',
                        background: 'var(--ab-cmp-select-multi-value__background)',
                        border: 'var(--ab-cmp-select__border)',
                    };
                },
                multiValueLabel: (baseStyle) => {
                    return {
                        ...baseStyle,
                        ...fontCommonStyles,
                        color: 'var(--ab-cmp-select__color)',
                    };
                },
            } })));
};
