import React, { useState } from "react"; import Select, { ValueType, Styles } from "react-select"; import CreatableSelect from "react-select/creatable"; import { debounce } from "lodash"; import * as GQL from "src/core/generated-graphql"; import { useAllTagsForFilter, useAllMoviesForFilter, useAllStudiosForFilter, useAllPerformersForFilter, useMarkerStrings, useScrapePerformerList, useTagCreate, useStudioCreate, usePerformerCreate, useFindGalleries, } from "src/core/StashService"; import { useToast } from "src/hooks"; import { ListFilterModel } from "src/models/list-filter/filter"; import { FilterMode } from "src/models/list-filter/types"; export type ValidTypes = | GQL.SlimPerformerDataFragment | GQL.Tag | GQL.SlimStudioDataFragment | GQL.SlimMovieDataFragment; type Option = { value: string; label: string }; interface ITypeProps { type?: | "performers" | "studios" | "parent_studios" | "tags" | "sceneTags" | "movies"; } interface IFilterProps { ids?: string[]; initialIds?: string[]; onSelect?: (item: ValidTypes[]) => void; noSelectionString?: string; className?: string; isMulti?: boolean; isClearable?: boolean; isDisabled?: boolean; } interface ISelectProps { className?: string; items: Option[]; selectedOptions?: ValueType; creatable?: boolean; onCreateOption?: (value: string) => void; isLoading: boolean; isDisabled?: boolean; onChange: (item: ValueType) => void; initialIds?: string[]; isMulti: T; isClearable?: boolean; onInputChange?: (input: string) => void; placeholder?: string; showDropdown?: boolean; groupHeader?: string; closeMenuOnSelect?: boolean; noOptionsMessage?: string | null; } interface IFilterComponentProps extends IFilterProps { items: Array; onCreate?: (name: string) => Promise<{ item: ValidTypes; message: string }>; } interface IFilterSelectProps extends Omit, "onChange" | "items" | "onCreateOption"> {} interface ISceneGallerySelect { gallery?: Pick; sceneId: string; onSelect: ( item: | GQL.ValidGalleriesForSceneQuery["validGalleriesForScene"][0] | undefined ) => void; } const getSelectedValues = (selectedItems: ValueType) => selectedItems ? (Array.isArray(selectedItems) ? selectedItems : [selectedItems]).map( (item) => item.value ) : []; const SelectComponent = ({ type, initialIds, onChange, className, items, selectedOptions, isLoading, isDisabled = false, onCreateOption, isClearable = true, creatable = false, isMulti, onInputChange, placeholder, showDropdown = true, groupHeader, closeMenuOnSelect = true, noOptionsMessage = type !== "tags" ? "None" : null, }: ISelectProps & ITypeProps) => { const values = items.filter((item) => initialIds?.indexOf(item.value) !== -1); const defaultValue = (isMulti ? values : values[0]) as ValueType; const options = groupHeader ? [ { label: groupHeader, options: items, }, ] : items; const styles: Partial> = { option: (base) => ({ ...base, color: "#000", }), container: (base, props) => ({ ...base, zIndex: props.selectProps.isFocused ? 10 : base.zIndex, }), multiValueRemove: (base, props) => ({ ...base, color: props.selectProps.isFocused ? base.color : "#333333", }), }; const props = { options, value: selectedOptions, className, classNamePrefix: "react-select", onChange, isMulti, isClearable, defaultValue: defaultValue ?? undefined, noOptionsMessage: () => noOptionsMessage, placeholder: isDisabled ? "" : placeholder, onInputChange, isDisabled, isLoading, styles, closeMenuOnSelect, components: { IndicatorSeparator: () => null, ...((!showDropdown || isDisabled) && { DropdownIndicator: () => null }), ...(isDisabled && { MultiValueRemove: () => null }), }, }; return creatable ? ( ) : (