/* eslint-disable react/no-array-index-key */
import React, { FC, isValidElement } from 'react';
import styled from '@emotion/styled';
import { css } from '@emotion/react';
import { ArrowLeftOutlined, CaretDownOutlined, EllipsisOutlined } from '@ant-design/icons';
import useMedia from 'react-use/lib/useMedia';
import Button from '../../button';
import SimplePagination, { SimplePaginationProps } from '../../simple-pagination';
import { Title, TitleProps } from './Title';
import Dropdown from '../../dropdown';
import Menu from '../../menu';
import Space from '../../space';
import { ContentButtonProps, createButton } from '../../button/button';
interface MenuGroupDescriptor {
/** 标题 */
title: React.ReactNode;
/** 禁用 */
disabled?: boolean;
/** 行为 */
actions: {
/** 内容 */
content: React.ReactNode;
/** 图标 */
icon?: React.ReactNode;
/** 禁用 */
disabled?: boolean;
/** 点击回调 */
onClick?: () => void;
}[];
}
export interface HeaderProps extends TitleProps {
/** 返回回调 */
onBack?: () => void;
/** 主按钮 */
primaryAction?: ContentButtonProps | React.ReactNode;
/** 次级按钮组 */
secondaryActions?: ContentButtonProps[];
/** 额外的需要显示的东西 显示在左侧 */
additionalMetaData?: React.ReactNode | string;
/** 下拉菜单 */
actionGroups?: MenuGroupDescriptor[];
/** 额外的需要显示的东西 显示在右侧 */
additionalNavigation?: React.ReactNode;
/** 页面级分页 */
pagination?: SimplePaginationProps;
breadcrumb?: React.ReactNode;
headerStyle?: React.CSSProperties;
}
const StyledHeader = styled.div`
position: relative;
padding: 24px 24px 0;
${({ theme }) => css`
@media (min-width: ${theme.breakpoints.sm}) {
padding-right: 0;
padding-left: 0;
}
`}
`;
const HeaderRowCondensed = styled.div<{ hasBack: boolean }>`
display: flex;
align-items: flex-start;
justify-content: space-between;
${({ hasBack }) =>
hasBack &&
css`
@media (max-width: 991px) {
display: grid;
grid-template-areas:
'breadcrumbs actions'
'title title';
grid-template-columns: auto 1fr;
gap: 8px 16px;
}
`}
`;
const HeaderRow = styled.div`
display: flex;
justify-content: space-between;
margin-top: 8px;
`;
const HeaderTitleWrapper = styled.div`
flex: 1 1 auto;
grid-area: title;
align-self: center;
`;
const HeaderBreadcrumbWrapper = styled.div`
flex: 0 0 auto;
grid-area: breadcrumbs;
max-width: 100%;
margin-right: 16px;
`;
const HeaderLeftAlign = styled.div`
display: flex;
align-content: flex-start;
align-items: center;
`;
const HeaderAdditionalMetaData = styled.div<{ hasOnBack: boolean }>`
margin-left: 0;
@media (min-width: 992px) {
margin-left: ${({ hasOnBack }) => hasOnBack && '52px'};
}
`;
const HeaderRightAlign = styled.div`
display: flex;
flex: 1 1 auto;
grid-area: actions;
align-items: flex-start;
justify-content: flex-end;
margin-left: 16px;
white-space: nowrap;
`;
const HeaderAdditionalNavigationWrapper = styled.div`
display: flex;
flex: 1 0 auto;
justify-content: flex-end;
margin: 0 8px;
margin-right: 0;
@media (min-width: 490px) {
margin: 0 32px;
margin-right: 0;
}
`;
const HeaderPrimaryActionWrapper = styled.div`
flex: 0 0 auto;
margin-top: 0;
margin-left: 10px;
`;
const IconButton = styled.div`
position: relative;
display: flex;
align-items: center;
justify-content: center;
width: 36px;
min-height: 36px;
margin: 0;
padding: 2px;
cursor: pointer;
${({ theme }) => css`
color: #6d7175;
border: 1px solid #babfc3;
border-radius: ${theme.radii.md};
:hover {
background-color: ${theme.colors.gray[50]};
svg {
fill: ${theme.colors.gray[600]};
}
}
:active {
background-color: #f1f2f3;
svg {
fill: ${theme.colors.gray[700]};
}
}
`}
`;
export function isPrimaryAction(x: ContentButtonProps | React.ReactNode): x is ContentButtonProps {
return !isValidElement(x) && x !== undefined;
}
function PrimaryActionMarkup({
primaryAction,
}: {
primaryAction: ContentButtonProps | React.ReactNode;
}) {
let content = primaryAction;
if (isPrimaryAction(primaryAction)) {
const type = primaryAction.type === undefined ? 'primary' : primaryAction.type;
content = createButton(primaryAction, {
type,
});
}
return {content};
}
export const Header: FC = ({
subtitle,
titleMetadata,
title,
pagination,
thumbnail,
onBack,
secondaryActions = [],
actionGroups = [],
primaryAction,
additionalMetaData,
additionalNavigation,
breadcrumb,
headerStyle,
}) => {
const isNavigationCollapsed = useMedia('(max-width: 768px)');
let actionMenuMarkup;
actionMenuMarkup = isNavigationCollapsed ? (
{secondaryActions.map(({ content, onClick, disabled, icon }, index) => (
onClick && onClick(domEvent)}
>
{icon}
{content}
))}
{actionGroups.map((actionItem, index) => (
{actionItem.actions.map((item, i) => (
{item.icon}
{item.content}
))}
))}
}
trigger={['click']}
>
) : (
{secondaryActions.map(({ content, ...rest }, index) => (
))}
{actionGroups.map((actionItem, index) => (
{actionItem.actions.map((item, i) => (
{item.icon}
{item.content}
))}
}
trigger={['click']}
>
))}
);
if (actionGroups.length === 0 && secondaryActions.length === 0) {
actionMenuMarkup = null;
}
const paginationMarkup = pagination ? (
) : null;
const primaryActionMarkup = primaryAction ? (
) : null;
return (
{onBack ? (
) : null}
{actionMenuMarkup}
{primaryActionMarkup}
{paginationMarkup}
{additionalMetaData || additionalNavigation ? (
{additionalMetaData}
{additionalNavigation}
) : null}
);
};