|
1 |
| -import { Text } from '@components'; |
2 |
| -import React, { useCallback, useEffect, useRef, useState } from 'react'; |
| 1 | +import { Dropdown, Text } from '@components'; |
| 2 | +import React, { useCallback, useEffect, useState } from 'react'; |
3 | 3 | import styled from 'styled-components';
|
4 | 4 | import { Input } from '../Input';
|
5 | 5 | import {
|
6 | 6 | ActionButtonsContainer,
|
7 | 7 | Container,
|
8 |
| - Dropdown, |
9 | 8 | LabelsWrapper,
|
10 | 9 | OptionContainer,
|
11 | 10 | OptionLabel,
|
12 | 11 | OptionList,
|
13 | 12 | Placeholder,
|
| 13 | + PortalDropdownContainer, |
14 | 14 | SearchInputContainer,
|
15 | 15 | SelectBase,
|
16 | 16 | SelectLabel,
|
@@ -86,20 +86,6 @@ export default function AutoCompleteSelect<T>({
|
86 | 86 | const [query, setQuery] = useState('');
|
87 | 87 | const [isOpen, setIsOpen] = useState(false);
|
88 | 88 | const [selectedValue, setSelectedValue] = useState<Suggestion<T> | undefined>(undefined);
|
89 |
| - const selectRef = useRef<HTMLDivElement>(null); |
90 |
| - |
91 |
| - const handleDocumentClick = useCallback((e: MouseEvent) => { |
92 |
| - if (selectRef.current && !selectRef.current.contains(e.target as Node)) { |
93 |
| - setIsOpen(false); |
94 |
| - } |
95 |
| - }, []); |
96 |
| - |
97 |
| - useEffect(() => { |
98 |
| - document.addEventListener('click', handleDocumentClick); |
99 |
| - return () => { |
100 |
| - document.removeEventListener('click', handleDocumentClick); |
101 |
| - }; |
102 |
| - }, [handleDocumentClick]); |
103 | 89 |
|
104 | 90 | const handleSelectClick = useCallback(() => {
|
105 | 91 | if (!isDisabled && !isReadOnly) {
|
@@ -134,75 +120,79 @@ export default function AutoCompleteSelect<T>({
|
134 | 120 |
|
135 | 121 | return (
|
136 | 122 | <Container
|
137 |
| - ref={selectRef} |
138 | 123 | className={className}
|
139 | 124 | size={size || 'md'}
|
140 | 125 | width={props.width || 255}
|
141 | 126 | isSelected={selectedValue !== undefined}
|
142 | 127 | >
|
143 | 128 | {label && <SelectLabel onClick={handleSelectClick}>{label}</SelectLabel>}
|
144 |
| - <SelectBase |
145 |
| - isDisabled={isDisabled} |
146 |
| - isReadOnly={isReadOnly} |
147 |
| - isRequired={isRequired} |
148 |
| - isOpen={isOpen} |
149 |
| - onClick={handleSelectClick} |
150 |
| - fontSize={size} |
151 |
| - {...props} |
| 129 | + <input type="hidden" name={name} value={selectedValue?.value || ''} readOnly /> |
| 130 | + <Dropdown |
| 131 | + open={isOpen} |
| 132 | + onOpenChange={(open) => setIsOpen(open)} |
| 133 | + disabled={isDisabled} |
| 134 | + dropdownRender={() => ( |
| 135 | + <PortalDropdownContainer> |
| 136 | + <SearchInputContainer> |
| 137 | + <Input |
| 138 | + label="" |
| 139 | + type="text" |
| 140 | + icon={{ name: 'MagnifyingGlass', source: 'phosphor' }} |
| 141 | + placeholder={searchPlaceholder || ''} |
| 142 | + value={query} |
| 143 | + onChange={(e) => { |
| 144 | + setQuery(e.target.value); |
| 145 | + onSearch(e.target.value); |
| 146 | + }} |
| 147 | + /> |
| 148 | + </SearchInputContainer> |
| 149 | + <OptionList data-testid={optionListTestId}> |
| 150 | + {!displayedSuggestions.length && ( |
| 151 | + <NoSuggestions> |
| 152 | + <Text type="span" color="gray" weight="semiBold"> |
| 153 | + No results found |
| 154 | + </Text> |
| 155 | + </NoSuggestions> |
| 156 | + )} |
| 157 | + {displayedSuggestions?.map((option) => ( |
| 158 | + <OptionLabel |
| 159 | + key={option.value} |
| 160 | + onClick={() => handleOptionChange(option)} |
| 161 | + isSelected={selectedValue?.value === option.value} |
| 162 | + isDisabled={disabledValues?.includes(option.value)} |
| 163 | + > |
| 164 | + <OptionContainer>{render(option.data)}</OptionContainer> |
| 165 | + </OptionLabel> |
| 166 | + ))} |
| 167 | + </OptionList> |
| 168 | + </PortalDropdownContainer> |
| 169 | + )} |
152 | 170 | >
|
153 |
| - <SelectLabelContainer> |
154 |
| - {icon && <StyledIcon icon={icon} size="lg" />} |
155 |
| - <LabelsWrapper> |
156 |
| - {!selectedValue && placeholder && <Placeholder>{placeholder}</Placeholder>} |
157 |
| - {selectedValue && render(selectedValue.data)} |
158 |
| - </LabelsWrapper> |
159 |
| - </SelectLabelContainer> |
160 |
| - <SelectActionButtons |
161 |
| - selectedValues={selectedValue ? [selectedValue.value] : []} |
| 171 | + <SelectBase |
| 172 | + isDisabled={isDisabled} |
| 173 | + isReadOnly={isReadOnly} |
| 174 | + isRequired={isRequired} |
162 | 175 | isOpen={isOpen}
|
163 |
| - isDisabled={!!isDisabled} |
164 |
| - isReadOnly={!!isReadOnly} |
165 |
| - handleClearSelection={handleClearSelection} |
166 |
| - showClear |
167 |
| - /> |
168 |
| - </SelectBase> |
169 |
| - <input type="hidden" name={name} value={selectedValue?.value || ''} readOnly /> |
170 |
| - {isOpen && ( |
171 |
| - <Dropdown> |
172 |
| - <SearchInputContainer> |
173 |
| - <Input |
174 |
| - label="" |
175 |
| - type="text" |
176 |
| - icon={{ name: 'MagnifyingGlass', source: 'phosphor' }} |
177 |
| - placeholder={searchPlaceholder || ''} |
178 |
| - value={query} |
179 |
| - onChange={(e) => { |
180 |
| - setQuery(e.target.value); |
181 |
| - onSearch(e.target.value); |
182 |
| - }} |
183 |
| - /> |
184 |
| - </SearchInputContainer> |
185 |
| - <OptionList data-testid={optionListTestId}> |
186 |
| - {!displayedSuggestions.length && ( |
187 |
| - <NoSuggestions> |
188 |
| - <Text type="span" color="gray" weight="semiBold"> |
189 |
| - No results found |
190 |
| - </Text> |
191 |
| - </NoSuggestions> |
192 |
| - )} |
193 |
| - {displayedSuggestions?.map((option) => ( |
194 |
| - <OptionLabel |
195 |
| - key={option.value} |
196 |
| - onClick={() => handleOptionChange(option)} |
197 |
| - isSelected={selectedValue?.value === option.value} |
198 |
| - isDisabled={disabledValues?.includes(option.value)} |
199 |
| - > |
200 |
| - <OptionContainer>{render(option.data)}</OptionContainer> |
201 |
| - </OptionLabel> |
202 |
| - ))} |
203 |
| - </OptionList> |
204 |
| - </Dropdown> |
205 |
| - )} |
| 176 | + fontSize={size} |
| 177 | + {...props} |
| 178 | + > |
| 179 | + <SelectLabelContainer> |
| 180 | + {icon && <StyledIcon icon={icon} size="lg" />} |
| 181 | + <LabelsWrapper> |
| 182 | + {!selectedValue && placeholder && <Placeholder>{placeholder}</Placeholder>} |
| 183 | + {selectedValue && render(selectedValue.data)} |
| 184 | + </LabelsWrapper> |
| 185 | + </SelectLabelContainer> |
| 186 | + <SelectActionButtons |
| 187 | + selectedValues={selectedValue ? [selectedValue.value] : []} |
| 188 | + isOpen={isOpen} |
| 189 | + isDisabled={!!isDisabled} |
| 190 | + isReadOnly={!!isReadOnly} |
| 191 | + handleClearSelection={handleClearSelection} |
| 192 | + showClear |
| 193 | + /> |
| 194 | + </SelectBase> |
| 195 | + </Dropdown> |
206 | 196 | </Container>
|
207 | 197 | );
|
208 | 198 | }
|
|
0 commit comments