Created
November 28, 2019 18:19
-
-
Save khusamov/b62eabbd0a5808635067da9b8e2ec140 to your computer and use it in GitHub Desktop.
Паттерн как задавать значения по умолчанию
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, {Component, ContextType, FC, Fragment, MouseEvent, ReactNode} from 'react'; | |
import {FaTrashAlt} from 'react-icons/all'; | |
import classNames from 'classnames'; | |
import TabPanelContext from '../TabPanel/TabPanelContext'; | |
import ETabType from './ETabType'; | |
import styles from './TabHeader.scss'; | |
interface IRegularProps { | |
label?: string; | |
onRemove?: (item: any) => void; | |
onRemoveIconClick: (item: any) => void; | |
} | |
const Regular: FC<IRegularProps> = ( | |
({label, onRemove, onRemoveIconClick}) => ( | |
<Fragment> | |
{label} | |
{onRemove && ( | |
<FaTrashAlt | |
className={styles.removeIcon} | |
onClick={onRemoveIconClick} | |
title={`Удалить '${label}'`} | |
/> | |
)} | |
</Fragment> | |
) | |
); | |
interface ITabHeaderProps<T> { | |
label?: string; | |
item?: T; | |
/** | |
* Тип кнопки вкладки. | |
* @default ETabType.Regular | |
*/ | |
type?: ETabType; | |
} | |
const classNameTabTypeMap = { | |
[ETabType.Regular]: styles.Regular, | |
[ETabType.Space]: styles.Space, | |
[ETabType.AddButton]: styles.AddButton | |
}; | |
type TTabHeaderPropsWithDefaults<T> = ( | |
ITabHeaderProps<T> | |
& Required<Pick<ITabHeaderProps<T>, 'type'>> | |
& Readonly<{children?: ReactNode}> | |
); | |
/** | |
* Отображение кнопки вкладки в зависимости от типа: | |
* - Обычная кнопка: название вкладки и кнопка 'Удалить вкладку', | |
* - Space: пустое пространство, | |
* - AddButton: кнопка 'Добавить вкладку'. | |
*/ | |
export default class TabHeader<T = any> extends Component<ITabHeaderProps<T>> { | |
static contextType = TabPanelContext; | |
context!: ContextType<typeof TabPanelContext>; | |
private get propsWithDefault(): TTabHeaderPropsWithDefaults<T> { | |
return { | |
...this.props, | |
type: this.props.type || ETabType.Regular | |
}; | |
} | |
public render(): ReactNode { | |
const {label, type, children, item} = this.propsWithDefault; | |
const {onRemove} = this.context; | |
const className = classNames({ | |
[styles.TabHeader]: true, | |
[classNameTabTypeMap[type]]: true, | |
[styles.selected]: this.context.activeItem === item | |
}); | |
return ( | |
<div className={className} onClick={this.onTabHeaderClick}> | |
{(() => { | |
switch (type) { | |
case ETabType.Regular: return <Regular label={label} onRemove={onRemove} onRemoveIconClick={this.onRemoveIconClick}/>; | |
case ETabType.Space: return null; | |
case ETabType.AddButton: return children; | |
default: throw new Error(`Неизвестный тип вкладки '${type}'`); | |
} | |
})()} | |
</div> | |
); | |
} | |
private onTabHeaderClick = (event: MouseEvent<HTMLDivElement>) => { | |
event.stopPropagation(); | |
const {item} = this.props; | |
const {onChange} = this.context; | |
onChange(item); | |
}; | |
private onRemoveIconClick = (event: MouseEvent<SVGElement>) => { | |
event.stopPropagation(); | |
const {item} = this.props; | |
const {onRemove} = this.context; | |
if (onRemove) onRemove(item); | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment