All checks were successful
Gitea Auto Deploy / Deploy-Container (push) Successful in 1m21s
113 lines
2.8 KiB
TypeScript
113 lines
2.8 KiB
TypeScript
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
'use client'
|
|
import dynamic from "next/dynamic"
|
|
import type { SingleValue } from "react-select"
|
|
import Image from "next/image"
|
|
import useLocaleStore from "@/stores/localeStore"
|
|
import ParseText from "../parseText"
|
|
import { themeColors } from "@/constant/constant"
|
|
import type { Props as SelectProps } from "react-select"
|
|
import { JSX } from "react"
|
|
|
|
const Select = dynamic(
|
|
() => import("react-select").then(m => m.default),
|
|
{ ssr: false }
|
|
) as <Option, IsMulti extends boolean = false>(
|
|
props: SelectProps<Option, IsMulti>
|
|
) => JSX.Element
|
|
|
|
export type SelectOption = {
|
|
value: string
|
|
label: string
|
|
imageUrl: string
|
|
}
|
|
|
|
type SelectCustomProp = {
|
|
customSet: SelectOption[]
|
|
excludeSet: SelectOption[]
|
|
selectedCustomSet: string
|
|
placeholder: string
|
|
setSelectedCustomSet: (value: string) => void
|
|
}
|
|
|
|
export default function SelectCustomImage({ customSet, excludeSet, selectedCustomSet, placeholder, setSelectedCustomSet }: SelectCustomProp) {
|
|
const options: SelectOption[] = customSet
|
|
const { locale, theme } = useLocaleStore()
|
|
|
|
const c = themeColors[theme] || themeColors.winter
|
|
|
|
const customStyles = {
|
|
option: (p: any, s: any) => ({
|
|
...p,
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
gap: '8px',
|
|
padding: '8px 12px',
|
|
backgroundColor: s.isFocused ? c.bgHover : c.bg,
|
|
color: c.text,
|
|
cursor: 'pointer'
|
|
}),
|
|
|
|
singleValue: (p: any) => ({
|
|
...p,
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
gap: '8px',
|
|
color: c.text
|
|
}),
|
|
|
|
control: (p: any) => ({
|
|
...p,
|
|
backgroundColor: c.bg,
|
|
borderColor: c.border,
|
|
boxShadow: 'none'
|
|
}),
|
|
|
|
menu: (p: any) => ({
|
|
...p,
|
|
backgroundColor: c.bg,
|
|
color: c.text,
|
|
zIndex: 9999
|
|
}),
|
|
|
|
menuPortal: (p: any) => ({
|
|
...p,
|
|
zIndex: 9999
|
|
})
|
|
}
|
|
|
|
const formatOptionLabel = (option: SelectOption) => (
|
|
<div className="flex items-center gap-1 w-full h-full">
|
|
<Image
|
|
unoptimized
|
|
crossOrigin="anonymous"
|
|
src={option.imageUrl}
|
|
alt=""
|
|
width={125}
|
|
height={125}
|
|
className="w-8 h-8 object-contain bg-warning-content rounded-full"
|
|
/>
|
|
<ParseText className='font-bold' text={option.label} locale={locale} />
|
|
</div>
|
|
)
|
|
|
|
return (
|
|
<Select
|
|
options={options.filter(opt => !excludeSet.some(ex => ex.value === opt.value))}
|
|
value={options.find(opt => {
|
|
return opt.value === selectedCustomSet
|
|
}) || null}
|
|
onChange={(selected: SingleValue<SelectOption>) => {
|
|
setSelectedCustomSet(selected?.value || '')
|
|
}}
|
|
formatOptionLabel={formatOptionLabel}
|
|
styles={customStyles}
|
|
placeholder={placeholder}
|
|
className="my-react-select-container"
|
|
classNamePrefix="my-react-select"
|
|
isSearchable
|
|
isClearable
|
|
/>
|
|
)
|
|
}
|