import React, { Fragment, ReactElement } from 'react' import Wrapper from './Wrapper' import HeaderSlot from './HeaderSlot' import Tags from './Tags' import Headline from './Headline' import Intro from './Intro' import Picture from './Picture' import Headshot from '../Headshot' import Columnists from './Columnists' import LiveBlogIndicator from './LiveBlogIndicator' import MainImage from '../MainImage' import { FollowButtonSlot } from './FollowButtonSlot' import Flourish from '../content-tree/Flourish' import classnames from 'classnames' import type { ArticleQuery } from '@financial-times/cp-content-pipeline-client' export type TopperProps = { content: ArticleQuery['content'] slot?: string followButtonSlot?: FollowButtonSlot showPremiumLabel?: boolean readNextSlot?: () => ReactElement } const Topper: React.FC = ({ content, slot, followButtonSlot, showPremiumLabel = false, readNextSlot, }) => { const { topper } = content if (!topper) { return null } const isPackage = content.__typename === 'ContentPackage' const isLiveBlog = content.__typename === 'LiveBlogPackage' const isBasic = topper.__typename === 'BasicTopper' const isOpinion = topper.__typename === 'OpinionTopper' const isFlourish = topper.__typename === 'TopperWithFlourish' && !!topper.leadFlourish const mainImageTopper = isBasic || isOpinion || topper.__typename === 'BrandedTopper' const hasLayout = ('layoutConfiguration' in topper && topper.layoutConfiguration) || ('layout' in topper && topper.layout) const hasLayoutWidth = 'layoutWidth' in topper && topper.layoutWidth const hasDesign = 'design' in topper && topper.design const hasHeadshot = 'headshot' in topper && topper.headshot const hasCoverImage = 'coverImage' in topper && topper.coverImage const hasByline = !!content.byline const hasColumnists = 'columnists' in topper && !!topper.columnists && topper.columnists.length > 0 const modifiers: string[] = [] isPackage && modifiers.push('package') isPackage && hasDesign && modifiers.push(`package-${topper.design}`) isOpinion && modifiers.push('opinion') if (hasLayout) { const layoutName = 'layoutConfiguration' in topper ? topper.layoutConfiguration?.name : 'layout' in topper ? topper.layout : undefined layoutName && modifiers.push(layoutName) } // TODO: Split this modifier into two separate ones when refactoring styles and markup ;(hasHeadshot || hasCoverImage) && modifiers.push('has-headshot') slot && modifiers.push('right-rail') hasLayoutWidth && modifiers.push(topper.layoutWidth === 'full-grid' ? 'full-grid' : 'in-line') const getMostRecentPostPublishedDate = () => { const defaultPublishDate = content.publishedDate if (isLiveBlog) { const posts = content?.liveBlogPosts || [] const mostRecentPublishedDate = posts.reduce( (storedPublishDate, currentPost) => { const thisDate = currentPost?.publishedDate ?? '' return thisDate > storedPublishDate ? thisDate : storedPublishDate }, posts[0]?.publishedDate ?? '' ) if (mostRecentPublishedDate) { return mostRecentPublishedDate } } return defaultPublishDate } return ( {topper.headerSlot && }
{isLiveBlog ? (
) : ( )} {topper.intro && ( )} {isLiveBlog && isFlourish ? ( ) : ( '' )} {hasLayout && mainImageTopper && topper.layoutConfiguration?.assetSlot === 'inside-topper' && ( )} {hasHeadshot && hasColumnists && hasByline && (
)} {hasCoverImage && ( // TODO: Move to its own styles
)} {hasColumnists && hasByline && ( )}
{readNextSlot && (
{readNextSlot()}
)}
{'images' in topper && !mainImageTopper && ( )}
) } export default Topper