buster/apps/web/src/components/ui/inputs/BusterInput/BusterInput.tsx

122 lines
3.5 KiB
TypeScript

import { Command } from 'cmdk';
import { useCallback, useState } from 'react';
import { useMemoizedFn } from '@/hooks/useMemoizedFn';
import type { BusterInputProps, BusterOnSelectParams } from './BusterInput.types';
import { BusterInputContainer } from './BusterInputContainer';
import { BusterInputEmpty } from './BusterInputEmpty';
import { BusterInputList } from './BusterInputList';
import { BusterItemsSelector } from './BusterItemSelector';
import { BusterMentionsInput } from './BusterMentionsInput';
export const BusterInput = ({
placeholder,
defaultValue,
value: valueProp,
emptyComponent,
submitting,
onSubmit,
disabled: disabledGlobal = false,
onStop,
sendIcon,
secondaryActions,
variant = 'default',
onChange,
ariaLabel = 'Buster Input',
readOnly,
autoFocus,
//suggestions
suggestionItems,
closeSuggestionOnSelect = true,
addSuggestionValueToInput = true,
onSuggestionItemClick,
filter,
shouldFilter,
//mentions
onMentionItemClick,
mentions,
}: BusterInputProps) => {
const [hasClickedSelect, setHasClickedSelect] = useState(false);
const [value, setValue] = useState(valueProp ?? defaultValue);
const showSuggestionList = !hasClickedSelect && suggestionItems.length > 0;
const onChangeInputValue = useCallback((value: string) => {
setValue(value);
setHasClickedSelect(false);
onChange?.(value);
}, []);
const onSelectItem = useMemoizedFn(({ onClick, ...params }: BusterOnSelectParams) => {
const { addValueToInput, value, loading, inputValue, label, disabled } = params;
if (disabled) {
console.warn('Item is disabled', params);
return;
}
if (submitting) {
console.warn('Input is submitting');
return;
}
if (loading) {
console.warn('Item is loading', params);
return;
}
console.log('onSelectItem', addValueToInput, params);
if (addValueToInput) setValue(inputValue ?? String(label));
onClick?.();
if (closeSuggestionOnSelect) setHasClickedSelect(true);
onSuggestionItemClick?.(params);
});
const onSubmitPreflight = useMemoizedFn((value: string) => {
if (submitting) {
console.warn('Input is submitting');
return;
}
if (disabledGlobal) {
console.warn('Input is disabledGlobal');
return;
}
onSubmit(value);
});
const onStopPreflight = useMemoizedFn(() => {
onStop();
});
return (
<Command label={ariaLabel} className="relative">
<BusterInputContainer
onSubmit={onSubmitPreflight}
onStop={onStopPreflight}
submitting={submitting}
disabled={disabledGlobal}
sendIcon={sendIcon}
secondaryActions={secondaryActions}
variant={variant}
>
<BusterMentionsInput
defaultValue={defaultValue}
readOnly={readOnly}
autoFocus={autoFocus}
placeholder={placeholder}
mentions={mentions}
value={value}
onChange={onChangeInputValue}
shouldFilter={shouldFilter}
filter={filter}
onMentionItemClick={onMentionItemClick}
/>
</BusterInputContainer>
<BusterInputList show={showSuggestionList}>
<BusterItemsSelector
suggestionItems={suggestionItems}
onSelect={onSelectItem}
addValueToInput={addSuggestionValueToInput}
closeOnSelect={closeSuggestionOnSelect}
/>
{emptyComponent && <BusterInputEmpty>{emptyComponent}</BusterInputEmpty>}
</BusterInputList>
</Command>
);
};