| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 |
- import React, { ReactNode, MouseEvent, forwardRef, LegacyRef, useCallback, useMemo } from 'react';
- import cls from 'classnames';
- import { cssClasses } from '@douyinfe/semi-foundation/tabs/constants';
- import { IconClose } from '@douyinfe/semi-icons';
- import { TabType, TabSize, TabPosition } from './interface';
- export interface TabItemProps {
- tab?: ReactNode;
- icon?: ReactNode;
- size?: TabSize;
- type?: TabType;
- tabPosition?: TabPosition;
- selected?: boolean;
- closable?: boolean;
- disabled?: boolean;
- itemKey?: string;
- handleKeyDown?: (event: React.KeyboardEvent, itemKey: string, closable: boolean) => void;
- deleteTabItem?: (tabKey: string, event: MouseEvent<Element>) => void;
- onClick?: (itemKey: string, e: MouseEvent<Element>) => void
- }
- const TabItem = (props: TabItemProps, ref: LegacyRef<HTMLDivElement>) => {
- const {
- tab,
- size,
- type,
- icon,
- selected,
- closable,
- disabled,
- itemKey,
- deleteTabItem,
- tabPosition,
- handleKeyDown,
- onClick,
- ...restProps
- } = props;
- const closableIcon = useMemo(() => {
- return (type === 'card' && closable) ?
- <IconClose
- aria-label="Close"
- role="button"
- className={`${cssClasses.TABS_TAB}-icon-close`}
- onClick={(e: MouseEvent<HTMLSpanElement>) => deleteTabItem(itemKey, e)}
- /> : null;
- }, [type, closable, deleteTabItem, itemKey]);
- const renderIcon = useCallback(
- (icon: ReactNode) => (
- <span>
- {icon}
- </span>
- ), []);
- const handleKeyDownInItem = useCallback(
- (event: React.KeyboardEvent) => {
- handleKeyDown && handleKeyDown(event, itemKey, closable);
- },
- [handleKeyDown, itemKey, closable],
- );
- const handleItemClick = useCallback(
- (e: MouseEvent) => {
- !disabled && onClick && onClick(itemKey, e);
- },
- [itemKey, disabled, onClick],
- );
- const panelIcon = icon ? renderIcon(icon) : null;
- const className = cls(
- cssClasses.TABS_TAB,
- `${cssClasses.TABS_TAB}-${type}`,
- `${cssClasses.TABS_TAB}-${tabPosition}`,
- `${cssClasses.TABS_TAB}-single`,
-
- {
- [cssClasses.TABS_TAB_ACTIVE]: selected,
- [cssClasses.TABS_TAB_DISABLED]: disabled,
- [`${cssClasses.TABS_TAB}-small`]: size === 'small',
- [`${cssClasses.TABS_TAB}-medium`]: size === 'medium',
- }
- );
-
- return (
- <div
- role="tab"
- id={`semiTab${itemKey}`}
- data-tabkey={`semiTab${itemKey}`}
- aria-controls={`semiTabPanel${itemKey}`}
- aria-disabled={disabled ? 'true' : 'false'}
- aria-selected={selected ? 'true' : 'false'}
- tabIndex={selected ? 0 : -1}
- onKeyDown={handleKeyDownInItem}
- onClick={handleItemClick}
- className={className}
- {...restProps}
- ref={ref}
- >
- {panelIcon}
- {tab}
- {closableIcon}
- </div>
- );
- };
- // Why is forwardRef needed here?
- // Because TabItem needs to be used in OverflowList (when tabs' type is collapsible),
- // OverflowList will pass ref to the outermost div DOM node of TabItem
- const ForwardTabItem = forwardRef<HTMLDivElement, TabItemProps>(TabItem);
- // @ts-ignore
- ForwardTabItem.elementType = 'Tabs.TabItem';
- export default ForwardTabItem;
|