1
0
Fork 0
mirror of https://github.com/jellyfin/jellyfin-web synced 2025-03-30 19:56:21 +00:00
jellyfin-web/src/components/common/SectionContainer.tsx
2024-10-14 16:03:55 -04:00

145 lines
4.2 KiB
TypeScript

import React, { type FC, type PropsWithChildren } from 'react';
import Box from '@mui/material/Box';
import Link from '@mui/material/Link';
import Typography from '@mui/material/Typography';
import ChevronRightIcon from '@mui/icons-material/ChevronRight';
import classNames from 'classnames';
import ItemsContainer, {
type ItemsContainerProps
} from 'elements/emby-itemscontainer/ItemsContainer';
import Scroller, { type ScrollerProps } from 'elements/emby-scroller/Scroller';
import Cards from 'components/cardbuilder/Card/Cards';
import Lists from 'components/listview/List/Lists';
import type { CardOptions } from 'types/cardOptions';
import type { ListOptions } from 'types/listOptions';
import type { ItemDto } from 'types/base/models/item-dto';
interface SectionHeaderProps {
className?: string;
itemsLength?: number;
url?: string;
title: string;
}
const SectionHeader: FC<SectionHeaderProps> = ({
title,
className,
itemsLength = 0,
url
}) => {
const sectionHeaderClass = classNames(
'sectionTitleContainer sectionTitleContainer-cards',
'padded-left',
className
);
return (
<Box className={sectionHeaderClass}>
{url && itemsLength > 5 ? (
<Link
className='clearLink button-flat sectionTitleTextButton'
underline='none'
href={url}
>
<Typography
className='sectionTitle sectionTitle-cards'
variant='h2'
>
{title}
</Typography>
<ChevronRightIcon sx={{ pt: '5px' }} />
</Link>
) : (
<Typography
className='sectionTitle sectionTitle-cards'
variant='h2'
>
{title}
</Typography>
)}
</Box>
);
};
interface SectionContainerProps {
className?: string;
items?: ItemDto[];
sectionHeaderProps?: Omit<SectionHeaderProps, 'itemsLength'>;
scrollerProps?: ScrollerProps;
itemsContainerProps?: ItemsContainerProps;
isListMode?: boolean;
isScrollerMode?: boolean;
noPadding?: boolean;
cardOptions?: CardOptions;
listOptions?: ListOptions;
}
const SectionContainer: FC<PropsWithChildren<SectionContainerProps>> = ({
className,
sectionHeaderProps,
scrollerProps,
itemsContainerProps,
isListMode = false,
isScrollerMode = true,
noPadding = false,
items = [],
cardOptions = {},
listOptions = {},
children
}) => {
const sectionClass = classNames('verticalSection', className);
const renderItems = () => {
if (React.isValidElement(children)) {
return children;
}
if (isListMode && !isScrollerMode) {
return <Lists items={items} listOptions={listOptions} />;
} else {
return <Cards items={items} cardOptions={cardOptions} />;
}
};
const content = (
<ItemsContainer
className={classNames(
{ scrollSlider: isScrollerMode },
itemsContainerProps?.className
)}
{...itemsContainerProps}
>
{renderItems()}
</ItemsContainer>
);
return (
<Box className={sectionClass}>
{sectionHeaderProps?.title && (
<SectionHeader
className={classNames(
{ 'no-padding': noPadding },
sectionHeaderProps?.className
)}
itemsLength={items.length}
{...sectionHeaderProps}
/>
)}
{isScrollerMode && !isListMode ? (
<Scroller
className={classNames(
{ 'no-padding': noPadding },
scrollerProps?.className
)}
{...scrollerProps}
>
{content}
</Scroller>
) : (
content
)}
</Box>
);
};
export default SectionContainer;