File size: 3,667 Bytes
3f70191
 
 
 
 
 
 
bd7ca0d
 
 
3f70191
bd7ca0d
 
 
 
 
 
3f70191
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bd7ca0d
 
 
 
 
 
 
 
3f70191
bd7ca0d
3f70191
 
bd7ca0d
 
 
3f70191
bd7ca0d
 
 
3f70191
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3962b04
 
 
 
 
 
 
 
 
 
 
 
3f70191
 
 
 
 
 
 
 
3962b04
 
 
 
 
 
 
 
3f70191
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bd7ca0d
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
import Select, { MultiValue, components, OptionProps, MultiValueGenericProps } from 'react-select'

interface OptionType {
  value: string
  label: string
  count?: number
}

interface MultiSelectProps {
  label: string
  options: OptionType[]
  selected: string[]
  onChange: (selected: string[]) => void
  placeholder?: string
  className?: string
}

// Custom option component to show counts
const CustomOption = (props: OptionProps<OptionType>) => {
  const { data } = props
  return (
    <components.Option {...props}>
      <div className="flex items-center justify-between w-full">
        <span>{data.label}</span>
        {data.count !== undefined && (
          <span className="text-xs text-gray-500 ml-2">
            ({data.count.toLocaleString()})
          </span>
        )}
      </div>
    </components.Option>
  )
}

// Custom multi-value label to show abbreviated text
const CustomMultiValueLabel = (props: MultiValueGenericProps<OptionType>) => {
  return (
    <components.MultiValueLabel {...props}>
      <span className="truncate max-w-[100px]" title={props.data.label}>
        {props.data.label}
      </span>
    </components.MultiValueLabel>
  )
}

export default function MultiSelect({
  label,
  options,
  selected,
  onChange,
  placeholder = 'Select...',
  className = ''
}: MultiSelectProps) {
  const selectedOptions = options.filter(opt => selected.includes(opt.value))

  const handleChange = (newValue: MultiValue<OptionType>) => {
    onChange(newValue.map(opt => opt.value))
  }

  return (
    <div className={className}>
      <label className="block text-sm font-medium text-gray-700 mb-1">
        {label}
      </label>
      <Select<OptionType, true>
        isMulti
        options={options}
        value={selectedOptions}
        onChange={handleChange}
        placeholder={placeholder}
        components={{ 
          Option: CustomOption,
          MultiValueLabel: CustomMultiValueLabel
        }}
        className="react-select-container"
        classNamePrefix="react-select"
        styles={{
          control: (base, state) => ({
            ...base,
            minHeight: '38px',
            borderColor: state.isFocused ? '#3b82f6' : '#d1d5db',
            boxShadow: state.isFocused ? '0 0 0 1px #3b82f6' : 'none',
            '&:hover': {
              borderColor: state.isFocused ? '#3b82f6' : '#9ca3af'
            }
          }),
          placeholder: (base) => ({
            ...base,
            color: '#9ca3af'
          }),
          singleValue: (base) => ({
            ...base,
            color: '#111827'
          }),
          input: (base) => ({
            ...base,
            color: '#111827'
          }),
          menu: (base) => ({
            ...base,
            zIndex: 50
          }),
          menuList: (base) => ({
            ...base,
            maxHeight: '320px'
          }),
          option: (base, state) => ({
            ...base,
            color: '#111827',
            backgroundColor: state.isFocused ? '#f3f4f6' : 'white',
            '&:active': {
              backgroundColor: '#e5e7eb'
            }
          }),
          multiValue: (base) => ({
            ...base,
            backgroundColor: '#dbeafe',
            borderRadius: '4px'
          }),
          multiValueLabel: (base) => ({
            ...base,
            color: '#1e40af',
            fontSize: '0.875rem'
          }),
          multiValueRemove: (base) => ({
            ...base,
            color: '#1e40af',
            ':hover': {
              backgroundColor: '#bfdbfe',
              color: '#1e3a8a'
            }
          })
        }}
      />
    </div>
  )
}