Skip to content

Commit a14b9e5

Browse files
committed
feat(UI): use dropdown component in select components
1 parent e27d2ea commit a14b9e5

17 files changed

+909
-619
lines changed

datahub-web-react/src/alchemy-components/components/Select/AutoCompleteSelect.tsx

+68-78
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
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';
33
import styled from 'styled-components';
44
import { Input } from '../Input';
55
import {
66
ActionButtonsContainer,
77
Container,
8-
Dropdown,
98
LabelsWrapper,
109
OptionContainer,
1110
OptionLabel,
1211
OptionList,
1312
Placeholder,
13+
PortalDropdownContainer,
1414
SearchInputContainer,
1515
SelectBase,
1616
SelectLabel,
@@ -86,20 +86,6 @@ export default function AutoCompleteSelect<T>({
8686
const [query, setQuery] = useState('');
8787
const [isOpen, setIsOpen] = useState(false);
8888
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]);
10389

10490
const handleSelectClick = useCallback(() => {
10591
if (!isDisabled && !isReadOnly) {
@@ -134,75 +120,79 @@ export default function AutoCompleteSelect<T>({
134120

135121
return (
136122
<Container
137-
ref={selectRef}
138123
className={className}
139124
size={size || 'md'}
140125
width={props.width || 255}
141126
isSelected={selectedValue !== undefined}
142127
>
143128
{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+
)}
152170
>
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}
162175
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>
206196
</Container>
207197
);
208198
}

0 commit comments

Comments
 (0)