chore: remove unused ref (#203)
This commit is contained in:
parent
c1af8df24c
commit
a4542d7442
|
|
@ -156,141 +156,136 @@ export type ComboboxProps = {
|
|||
error?: boolean;
|
||||
};
|
||||
|
||||
export const Combobox = forwardRef<HTMLInputElement, ComboboxProps>(
|
||||
({
|
||||
items,
|
||||
selectedValue = { value: '', label: '' },
|
||||
withAutocomplete = false,
|
||||
leftIcon = 'search',
|
||||
onChange,
|
||||
onBlur,
|
||||
error = false,
|
||||
}) => {
|
||||
const [filteredItems, setFilteredItems] = useState<ComboboxItem[]>([]);
|
||||
const [autocompleteItems, setAutocompleteItems] = useState<ComboboxItem[]>(
|
||||
[]
|
||||
);
|
||||
export const Combobox: React.FC<ComboboxProps> = ({
|
||||
items,
|
||||
selectedValue = { value: '', label: '' },
|
||||
withAutocomplete = false,
|
||||
leftIcon = 'search',
|
||||
onChange,
|
||||
onBlur,
|
||||
error = false,
|
||||
}) => {
|
||||
const [filteredItems, setFilteredItems] = useState<ComboboxItem[]>([]);
|
||||
const [autocompleteItems, setAutocompleteItems] = useState<ComboboxItem[]>(
|
||||
[]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
// If the selected value doesn't exist in the list of items, we add it
|
||||
if (
|
||||
items.filter((item) => item === selectedValue).length === 0 &&
|
||||
selectedValue.value !== undefined &&
|
||||
autocompleteItems.length === 0 &&
|
||||
withAutocomplete
|
||||
) {
|
||||
setAutocompleteItems([selectedValue]);
|
||||
}
|
||||
}, [autocompleteItems.length, items, selectedValue, withAutocomplete]);
|
||||
useEffect(() => {
|
||||
// If the selected value doesn't exist in the list of items, we add it
|
||||
if (
|
||||
items.filter((item) => item === selectedValue).length === 0 &&
|
||||
selectedValue.value !== undefined &&
|
||||
autocompleteItems.length === 0 &&
|
||||
withAutocomplete
|
||||
) {
|
||||
setAutocompleteItems([selectedValue]);
|
||||
}
|
||||
}, [autocompleteItems.length, items, selectedValue, withAutocomplete]);
|
||||
|
||||
useEffect(() => {
|
||||
useEffect(() => {
|
||||
setFilteredItems(items);
|
||||
}, [items]);
|
||||
|
||||
const buttonRef = useRef<HTMLButtonElement>(null);
|
||||
|
||||
const handleSearch = useDebounce((searchValue: string) => {
|
||||
if (searchValue === '') {
|
||||
setFilteredItems(items);
|
||||
}, [items]);
|
||||
|
||||
const buttonRef = useRef<HTMLButtonElement>(null);
|
||||
|
||||
const handleSearch = useDebounce((searchValue: string) => {
|
||||
if (searchValue === '') {
|
||||
setFilteredItems(items);
|
||||
|
||||
if (withAutocomplete) {
|
||||
setAutocompleteItems([]);
|
||||
handleComboboxChange({} as ComboboxItem);
|
||||
}
|
||||
} else {
|
||||
const filteredValues = items.filter((item) =>
|
||||
cleanString(item.label).startsWith(cleanString(searchValue))
|
||||
);
|
||||
|
||||
if (withAutocomplete && filteredValues.length === 0) {
|
||||
// If the search value doesn't exist in the list of items, we add it
|
||||
setAutocompleteItems([{ value: searchValue, label: searchValue }]);
|
||||
}
|
||||
setFilteredItems(filteredValues);
|
||||
}
|
||||
}, 200);
|
||||
|
||||
const handleInputChange = (
|
||||
event: React.ChangeEvent<HTMLInputElement>
|
||||
): void => {
|
||||
event.stopPropagation();
|
||||
handleSearch(event.target.value);
|
||||
};
|
||||
|
||||
const handleInputClick = (): void => {
|
||||
buttonRef.current?.click();
|
||||
};
|
||||
|
||||
const handleComboboxChange = (optionSelected: ComboboxItem): void => {
|
||||
onChange(optionSelected);
|
||||
};
|
||||
|
||||
const handleLeaveTransition = (): void => {
|
||||
setFilteredItems(items);
|
||||
if (selectedValue.value === undefined && withAutocomplete) {
|
||||
if (withAutocomplete) {
|
||||
setAutocompleteItems([]);
|
||||
handleComboboxChange({} as ComboboxItem);
|
||||
}
|
||||
};
|
||||
} else {
|
||||
const filteredValues = items.filter((item) =>
|
||||
cleanString(item.label).startsWith(cleanString(searchValue))
|
||||
);
|
||||
|
||||
return (
|
||||
<ComboboxLib
|
||||
value={selectedValue}
|
||||
by="value"
|
||||
onChange={handleComboboxChange}
|
||||
>
|
||||
{({ open }) => (
|
||||
<div className="relative">
|
||||
<ComboboxInput
|
||||
onChange={handleInputChange}
|
||||
onClick={handleInputClick}
|
||||
open={open}
|
||||
leftIcon={leftIcon}
|
||||
onBlur={onBlur}
|
||||
error={error}
|
||||
/>
|
||||
<ComboboxLib.Button ref={buttonRef} className="hidden" />
|
||||
if (withAutocomplete && filteredValues.length === 0) {
|
||||
// If the search value doesn't exist in the list of items, we add it
|
||||
setAutocompleteItems([{ value: searchValue, label: searchValue }]);
|
||||
}
|
||||
setFilteredItems(filteredValues);
|
||||
}
|
||||
}, 200);
|
||||
|
||||
<Transition
|
||||
show={open}
|
||||
as={Fragment}
|
||||
enter="transition duration-400 ease-out"
|
||||
leave="transition ease-out duration-100"
|
||||
leaveFrom="opacity-100"
|
||||
leaveTo="opacity-0"
|
||||
afterLeave={handleLeaveTransition}
|
||||
>
|
||||
<ComboboxLib.Options className="absolute max-h-60 w-full z-10 overflow-auto rounded-b-xl border-solid border-slate6 border bg-black pt-2 px-3 text-base focus:outline-none sm:text-sm">
|
||||
{[...autocompleteItems, ...filteredItems].length === 0 ||
|
||||
filteredItems === undefined ? (
|
||||
<NoResults />
|
||||
) : (
|
||||
<>
|
||||
{autocompleteItems.length > 0 && <span>Create new</span>}
|
||||
{autocompleteItems.map(
|
||||
(autocompleteOption: ComboboxItem) => (
|
||||
<ComboboxOption
|
||||
key={autocompleteOption.value}
|
||||
option={autocompleteOption}
|
||||
/>
|
||||
)
|
||||
)}
|
||||
{autocompleteItems.length > 0 &&
|
||||
filteredItems.length > 0 && (
|
||||
<Separator css={{ mb: '$2' }} />
|
||||
)}
|
||||
{filteredItems.map((option: ComboboxItem) => (
|
||||
<ComboboxOption key={option.value} option={option} />
|
||||
))}
|
||||
</>
|
||||
)}
|
||||
</ComboboxLib.Options>
|
||||
</Transition>
|
||||
</div>
|
||||
)}
|
||||
</ComboboxLib>
|
||||
);
|
||||
}
|
||||
);
|
||||
const handleInputChange = (
|
||||
event: React.ChangeEvent<HTMLInputElement>
|
||||
): void => {
|
||||
event.stopPropagation();
|
||||
handleSearch(event.target.value);
|
||||
};
|
||||
|
||||
const handleInputClick = (): void => {
|
||||
buttonRef.current?.click();
|
||||
};
|
||||
|
||||
const handleComboboxChange = (optionSelected: ComboboxItem): void => {
|
||||
onChange(optionSelected);
|
||||
};
|
||||
|
||||
const handleLeaveTransition = (): void => {
|
||||
setFilteredItems(items);
|
||||
if (selectedValue.value === undefined && withAutocomplete) {
|
||||
setAutocompleteItems([]);
|
||||
handleComboboxChange({} as ComboboxItem);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<ComboboxLib
|
||||
value={selectedValue}
|
||||
by="value"
|
||||
onChange={handleComboboxChange}
|
||||
>
|
||||
{({ open }) => (
|
||||
<div className="relative">
|
||||
<ComboboxInput
|
||||
onChange={handleInputChange}
|
||||
onClick={handleInputClick}
|
||||
open={open}
|
||||
leftIcon={leftIcon}
|
||||
onBlur={onBlur}
|
||||
error={error}
|
||||
/>
|
||||
<ComboboxLib.Button ref={buttonRef} className="hidden" />
|
||||
|
||||
<Transition
|
||||
show={open}
|
||||
as={Fragment}
|
||||
enter="transition duration-400 ease-out"
|
||||
leave="transition ease-out duration-100"
|
||||
leaveFrom="opacity-100"
|
||||
leaveTo="opacity-0"
|
||||
afterLeave={handleLeaveTransition}
|
||||
>
|
||||
<ComboboxLib.Options className="absolute max-h-60 w-full z-10 overflow-auto rounded-b-xl border-solid border-slate6 border bg-black pt-2 px-3 text-base focus:outline-none sm:text-sm">
|
||||
{[...autocompleteItems, ...filteredItems].length === 0 ||
|
||||
filteredItems === undefined ? (
|
||||
<NoResults />
|
||||
) : (
|
||||
<>
|
||||
{autocompleteItems.length > 0 && <span>Create new</span>}
|
||||
{autocompleteItems.map((autocompleteOption: ComboboxItem) => (
|
||||
<ComboboxOption
|
||||
key={autocompleteOption.value}
|
||||
option={autocompleteOption}
|
||||
/>
|
||||
))}
|
||||
{autocompleteItems.length > 0 && filteredItems.length > 0 && (
|
||||
<Separator css={{ mb: '$2' }} />
|
||||
)}
|
||||
{filteredItems.map((option: ComboboxItem) => (
|
||||
<ComboboxOption key={option.value} option={option} />
|
||||
))}
|
||||
</>
|
||||
)}
|
||||
</ComboboxLib.Options>
|
||||
</Transition>
|
||||
</div>
|
||||
)}
|
||||
</ComboboxLib>
|
||||
);
|
||||
};
|
||||
|
||||
Combobox.displayName = 'Combobox';
|
||||
|
|
|
|||
|
|
@ -134,48 +134,45 @@ export abstract class Form {
|
|||
}
|
||||
);
|
||||
|
||||
static readonly Combobox = forwardRef<HTMLInputElement, Form.ComboboxProps>(
|
||||
(props, ref) => {
|
||||
const {
|
||||
id,
|
||||
validators,
|
||||
value: [value, setValue],
|
||||
validationEnabled: [validationEnabled, setValidationEnabled],
|
||||
} = useFormFieldContext();
|
||||
static readonly Combobox: React.FC<Form.ComboboxProps> = (props) => {
|
||||
const {
|
||||
id,
|
||||
validators,
|
||||
value: [value, setValue],
|
||||
validationEnabled: [validationEnabled, setValidationEnabled],
|
||||
} = useFormFieldContext();
|
||||
|
||||
const comboboxValue = useMemo(() => {
|
||||
// if it's with autocomplete maybe won't be on the items list
|
||||
const item = props.items.find((item) => item.label === value);
|
||||
if (props.withAutocomplete && !item && value !== '') {
|
||||
//return the selected value if the item doesn't exist
|
||||
return { label: value, value: value };
|
||||
}
|
||||
return item;
|
||||
}, [props.items, props.withAutocomplete, value]);
|
||||
const comboboxValue = useMemo(() => {
|
||||
// if it's with autocomplete maybe won't be on the items list
|
||||
const item = props.items.find((item) => item.label === value);
|
||||
if (props.withAutocomplete && !item && value !== '') {
|
||||
//return the selected value if the item doesn't exist
|
||||
return { label: value, value: value };
|
||||
}
|
||||
return item;
|
||||
}, [props.items, props.withAutocomplete, value]);
|
||||
|
||||
const isValid = useFormFieldValidatorValue(id, validators, value);
|
||||
const isValid = useFormFieldValidatorValue(id, validators, value);
|
||||
|
||||
const handleComboboxChange = (option: ComboboxItem): void => {
|
||||
if (props.onChange) props.onChange(option);
|
||||
setValue(option.label);
|
||||
};
|
||||
const handleComboboxChange = (option: ComboboxItem): void => {
|
||||
if (props.onChange) props.onChange(option);
|
||||
setValue(option.label);
|
||||
};
|
||||
|
||||
const handleComboboxBlur = (): void => {
|
||||
setValidationEnabled(true);
|
||||
};
|
||||
const handleComboboxBlur = (): void => {
|
||||
setValidationEnabled(true);
|
||||
};
|
||||
|
||||
return (
|
||||
<Combobox
|
||||
ref={ref}
|
||||
{...props}
|
||||
onChange={handleComboboxChange}
|
||||
selectedValue={comboboxValue || ({} as ComboboxItem)}
|
||||
onBlur={handleComboboxBlur}
|
||||
error={validationEnabled && !isValid}
|
||||
/>
|
||||
);
|
||||
}
|
||||
);
|
||||
return (
|
||||
<Combobox
|
||||
{...props}
|
||||
onChange={handleComboboxChange}
|
||||
selectedValue={comboboxValue || ({} as ComboboxItem)}
|
||||
onBlur={handleComboboxBlur}
|
||||
error={validationEnabled && !isValid}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
static readonly ColorPicker: React.FC<Form.ColorPickerProps> = ({
|
||||
logo,
|
||||
|
|
|
|||
Loading…
Reference in New Issue