mirror of https://github.com/buster-so/buster.git
dropdown updates
This commit is contained in:
parent
284e708862
commit
56e31bd0d4
|
@ -44,7 +44,7 @@ export const StatusDropdownContent: React.FC<{
|
||||||
});
|
});
|
||||||
}, [isAdmin, status, onChangeStatus]);
|
}, [isAdmin, status, onChangeStatus]);
|
||||||
|
|
||||||
const onSelect = useMemoizedFn((item: DropdownItems[number]) => {
|
const onSelect = useMemoizedFn((item: DropdownItem<VerificationStatus>) => {
|
||||||
const _item = item as DropdownItem<VerificationStatus>;
|
const _item = item as DropdownItem<VerificationStatus>;
|
||||||
onChangeStatus(_item.value as VerificationStatus);
|
onChangeStatus(_item.value as VerificationStatus);
|
||||||
});
|
});
|
||||||
|
@ -54,7 +54,7 @@ export const StatusDropdownContent: React.FC<{
|
||||||
emptyStateText="Nothing to see here..."
|
emptyStateText="Nothing to see here..."
|
||||||
items={items}
|
items={items}
|
||||||
onSelect={(v) => {
|
onSelect={(v) => {
|
||||||
console.log(v);
|
v;
|
||||||
}}
|
}}
|
||||||
selectType="single"
|
selectType="single"
|
||||||
menuHeader="Status">
|
menuHeader="Status">
|
||||||
|
|
|
@ -38,7 +38,7 @@ export interface DropdownItem<T = string> {
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
loading?: boolean;
|
loading?: boolean;
|
||||||
selected?: boolean;
|
selected?: boolean;
|
||||||
items?: DropdownItems;
|
items?: DropdownItems<T>;
|
||||||
link?: string;
|
link?: string;
|
||||||
linkIcon?: 'arrow-right' | 'arrow-external' | 'caret-right';
|
linkIcon?: 'arrow-right' | 'arrow-external' | 'caret-right';
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ export interface DropdownDivider {
|
||||||
export type DropdownItems<T = string> = (DropdownItem<T> | DropdownDivider | React.ReactNode)[];
|
export type DropdownItems<T = string> = (DropdownItem<T> | DropdownDivider | React.ReactNode)[];
|
||||||
|
|
||||||
export interface DropdownProps<T = string> extends DropdownMenuProps {
|
export interface DropdownProps<T = string> extends DropdownMenuProps {
|
||||||
items: DropdownItems;
|
items: DropdownItems<T>;
|
||||||
selectType?: 'single' | 'multiple' | 'none';
|
selectType?: 'single' | 'multiple' | 'none';
|
||||||
menuHeader?: string | React.ReactNode; //if string it will render a search box
|
menuHeader?: string | React.ReactNode; //if string it will render a search box
|
||||||
closeOnSelect?: boolean;
|
closeOnSelect?: boolean;
|
||||||
|
@ -68,8 +68,12 @@ const dropdownItemKey = (item: DropdownItems[number], index: number) => {
|
||||||
return `item-${index}`;
|
return `item-${index}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Dropdown: React.FC<DropdownProps> = React.memo(
|
export const Test = <T extends string = string>({}: { items: DropdownItems<T> }) => {
|
||||||
({
|
return <></>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Dropdown = React.memo(
|
||||||
|
<T extends string>({
|
||||||
items,
|
items,
|
||||||
selectType = 'none',
|
selectType = 'none',
|
||||||
menuHeader,
|
menuHeader,
|
||||||
|
@ -86,7 +90,7 @@ export const Dropdown: React.FC<DropdownProps> = React.memo(
|
||||||
footerContent,
|
footerContent,
|
||||||
dir,
|
dir,
|
||||||
modal
|
modal
|
||||||
}) => {
|
}: DropdownProps<T>) => {
|
||||||
const { filteredItems, searchText, handleSearchChange } = useDebounceSearch({
|
const { filteredItems, searchText, handleSearchChange } = useDebounceSearch({
|
||||||
items,
|
items,
|
||||||
searchPredicate: (item, searchText) => {
|
searchPredicate: (item, searchText) => {
|
||||||
|
@ -163,9 +167,11 @@ export const Dropdown: React.FC<DropdownProps> = React.memo(
|
||||||
if ((item as DropdownItem).value && !(item as DropdownItem).items) {
|
if ((item as DropdownItem).value && !(item as DropdownItem).items) {
|
||||||
hotkeyIndex++;
|
hotkeyIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onSelect;
|
||||||
return (
|
return (
|
||||||
<DropdownItemSelector
|
<DropdownItemSelector
|
||||||
item={item}
|
item={item as DropdownItems<T>[number]}
|
||||||
index={hotkeyIndex}
|
index={hotkeyIndex}
|
||||||
selectType={selectType}
|
selectType={selectType}
|
||||||
onSelect={onSelect}
|
onSelect={onSelect}
|
||||||
|
@ -182,9 +188,10 @@ export const Dropdown: React.FC<DropdownProps> = React.memo(
|
||||||
if ((item as DropdownItem).value && !(item as DropdownItem).items) {
|
if ((item as DropdownItem).value && !(item as DropdownItem).items) {
|
||||||
hotkeyIndex++;
|
hotkeyIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DropdownItemSelector
|
<DropdownItemSelector
|
||||||
item={item}
|
item={item as DropdownItems<T>[number]}
|
||||||
index={hotkeyIndex}
|
index={hotkeyIndex}
|
||||||
selectType={selectType}
|
selectType={selectType}
|
||||||
onSelect={onSelect}
|
onSelect={onSelect}
|
||||||
|
@ -208,42 +215,47 @@ export const Dropdown: React.FC<DropdownProps> = React.memo(
|
||||||
|
|
||||||
Dropdown.displayName = 'Dropdown';
|
Dropdown.displayName = 'Dropdown';
|
||||||
|
|
||||||
const DropdownItemSelector: React.FC<{
|
const DropdownItemSelector = React.memo(
|
||||||
item: DropdownItems[number];
|
<T extends string>({
|
||||||
index: number;
|
item,
|
||||||
onSelect: DropdownProps['onSelect'];
|
index,
|
||||||
closeOnSelect: boolean;
|
onSelect,
|
||||||
selectType: DropdownProps['selectType'];
|
closeOnSelect,
|
||||||
}> = React.memo(({ item, index, onSelect, closeOnSelect, selectType }) => {
|
selectType
|
||||||
if ((item as DropdownDivider).type === 'divider') {
|
}: {
|
||||||
return <DropdownMenuSeparator />;
|
item: DropdownItems<T>[number];
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof item === 'object' && React.isValidElement(item)) {
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<DropdownItem
|
|
||||||
{...(item as DropdownItem)}
|
|
||||||
closeOnSelect={closeOnSelect}
|
|
||||||
onSelect={onSelect}
|
|
||||||
selectType={selectType}
|
|
||||||
index={index}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
DropdownItemSelector.displayName = 'DropdownItemSelector';
|
|
||||||
|
|
||||||
const DropdownItem: React.FC<
|
|
||||||
DropdownItem & {
|
|
||||||
onSelect: DropdownProps['onSelect'];
|
|
||||||
closeOnSelect: boolean;
|
|
||||||
index: number;
|
index: number;
|
||||||
selectType: DropdownProps['selectType'];
|
onSelect?: (value: T) => void;
|
||||||
|
closeOnSelect: boolean;
|
||||||
|
selectType: DropdownProps<T>['selectType'];
|
||||||
|
}) => {
|
||||||
|
if ((item as DropdownDivider).type === 'divider') {
|
||||||
|
return <DropdownMenuSeparator />;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof item === 'object' && React.isValidElement(item)) {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DropdownItem<T>
|
||||||
|
{...(item as DropdownItem<T>)}
|
||||||
|
closeOnSelect={closeOnSelect}
|
||||||
|
onSelect={onSelect}
|
||||||
|
selectType={selectType}
|
||||||
|
index={index}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
> = ({
|
) as <T extends string>(props: {
|
||||||
|
item: DropdownItems<T>[number];
|
||||||
|
index: number;
|
||||||
|
onSelect?: (value: T) => void;
|
||||||
|
closeOnSelect: boolean;
|
||||||
|
selectType: DropdownProps<T>['selectType'];
|
||||||
|
}) => JSX.Element;
|
||||||
|
|
||||||
|
const DropdownItem = <T extends string>({
|
||||||
label,
|
label,
|
||||||
value,
|
value,
|
||||||
showIndex,
|
showIndex,
|
||||||
|
@ -262,6 +274,11 @@ const DropdownItem: React.FC<
|
||||||
truncate,
|
truncate,
|
||||||
link,
|
link,
|
||||||
linkIcon
|
linkIcon
|
||||||
|
}: DropdownItem<T> & {
|
||||||
|
onSelect?: (value: T) => void;
|
||||||
|
closeOnSelect: boolean;
|
||||||
|
index: number;
|
||||||
|
selectType: DropdownProps<T>['selectType'];
|
||||||
}) => {
|
}) => {
|
||||||
const onClickItem = useMemoizedFn((e: React.MouseEvent<HTMLDivElement>) => {
|
const onClickItem = useMemoizedFn((e: React.MouseEvent<HTMLDivElement>) => {
|
||||||
if (onClick) onClick();
|
if (onClick) onClick();
|
||||||
|
@ -295,7 +312,6 @@ const DropdownItem: React.FC<
|
||||||
const renderContent = () => {
|
const renderContent = () => {
|
||||||
const content = (
|
const content = (
|
||||||
<>
|
<>
|
||||||
{showIndex && <span className="text-gray-light">{index}</span>}
|
|
||||||
{icon && !loading && <span className="text-icon-color">{icon}</span>}
|
{icon && !loading && <span className="text-icon-color">{icon}</span>}
|
||||||
{loading && <CircleSpinnerLoader size={9} />}
|
{loading && <CircleSpinnerLoader size={9} />}
|
||||||
<div className={cn('flex flex-col gap-y-1', truncate && 'overflow-hidden')}>
|
<div className={cn('flex flex-col gap-y-1', truncate && 'overflow-hidden')}>
|
||||||
|
@ -310,6 +326,7 @@ const DropdownItem: React.FC<
|
||||||
linkIcon={linkIcon}
|
linkIcon={linkIcon}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
{showIndex && <span className="text-gray-light ml-auto w-2 text-center">{index}</span>}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -372,41 +389,42 @@ const DropdownItem: React.FC<
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const DropdownSubMenuWrapper = React.memo(
|
interface DropdownSubMenuWrapperProps<T extends string> {
|
||||||
({
|
items: DropdownItems<T> | undefined;
|
||||||
items,
|
children: React.ReactNode;
|
||||||
children,
|
closeOnSelect: boolean;
|
||||||
closeOnSelect,
|
onSelect?: (value: T) => void;
|
||||||
onSelect,
|
selectType: DropdownProps<T>['selectType'];
|
||||||
selectType
|
}
|
||||||
}: {
|
|
||||||
items: DropdownItems | undefined;
|
const DropdownSubMenuWrapper = <T extends string>({
|
||||||
children: React.ReactNode;
|
items,
|
||||||
closeOnSelect: boolean;
|
children,
|
||||||
onSelect?: DropdownProps['onSelect'];
|
closeOnSelect,
|
||||||
selectType: DropdownProps['selectType'];
|
onSelect,
|
||||||
}) => {
|
selectType
|
||||||
return (
|
}: DropdownSubMenuWrapperProps<T>) => {
|
||||||
<DropdownMenuSub>
|
return (
|
||||||
<DropdownMenuSubTrigger>{children}</DropdownMenuSubTrigger>
|
<DropdownMenuSub>
|
||||||
<DropdownMenuPortal>
|
<DropdownMenuSubTrigger>{children}</DropdownMenuSubTrigger>
|
||||||
<DropdownMenuSubContent>
|
<DropdownMenuPortal>
|
||||||
{items?.map((item, index) => (
|
<DropdownMenuSubContent>
|
||||||
<DropdownItemSelector
|
{items?.map((item, index) => (
|
||||||
key={dropdownItemKey(item, index)}
|
<DropdownItemSelector<T>
|
||||||
item={item}
|
key={dropdownItemKey(item, index)}
|
||||||
index={index}
|
item={item}
|
||||||
onSelect={onSelect}
|
index={index}
|
||||||
closeOnSelect={closeOnSelect}
|
onSelect={onSelect}
|
||||||
selectType={selectType}
|
closeOnSelect={closeOnSelect}
|
||||||
/>
|
selectType={selectType}
|
||||||
))}
|
/>
|
||||||
</DropdownMenuSubContent>
|
))}
|
||||||
</DropdownMenuPortal>
|
</DropdownMenuSubContent>
|
||||||
</DropdownMenuSub>
|
</DropdownMenuPortal>
|
||||||
);
|
</DropdownMenuSub>
|
||||||
}
|
);
|
||||||
);
|
};
|
||||||
|
|
||||||
DropdownSubMenuWrapper.displayName = 'DropdownSubMenuWrapper';
|
DropdownSubMenuWrapper.displayName = 'DropdownSubMenuWrapper';
|
||||||
|
|
||||||
const DropdownMenuHeaderSelector: React.FC<{
|
const DropdownMenuHeaderSelector: React.FC<{
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
import { MOCK_CHAT } from './MOCK_CHAT';
|
|
||||||
import { useChatIndividual } from './useChatIndividual';
|
import { useChatIndividual } from './useChatIndividual';
|
||||||
import { useMessageIndividual } from './useMessageIndividual';
|
import { useMessageIndividual } from './useMessageIndividual';
|
||||||
|
|
||||||
export * from './ChatProvider';
|
export * from './ChatProvider';
|
||||||
|
|
||||||
export { useChatIndividual, useMessageIndividual };
|
export { useChatIndividual, useMessageIndividual };
|
||||||
|
|
||||||
console.log(MOCK_CHAT);
|
|
||||||
|
|
Loading…
Reference in New Issue