{"version":3,"sources":["utils/helpers/attributeType/index.ts","utils/components/Corporate/ContentTypeAttributes/StyledAttributeIcon.ts","utils/components/Corporate/ContentTypeAttributes/AttributeIcon.tsx","utils/components/Corporate/ContentTypeAttributes/getAttributeRenderer.tsx","utils/helpers/contentType/index.ts","utils/components/Corporate/ContentTypeAttributes/index.tsx","utils/helpers/jss/index.ts","components/Corporate/FeaturedContent/StyledFeaturedContent.ts","utils/components/Corporate/Grid/GridVisualiser.tsx","components/Corporate/FeaturedContent/StyledSecondaryCard.ts","components/Corporate/FeaturedContent/SecondaryCard.tsx","utils/helpers/featuredContentType/index.ts","utils/components/Corporate/FeaturedContentIcon/index.tsx","components/Corporate/FeaturedContent/index.tsx"],"names":["AttributeType","getAttributeType","value","key","getTypeFromValue","pickAttributeByType","attributes","attributeName","attrs","filter","attr","length","attrType","undefined","type","includesAttributeWithType","hasOwnProperty","includesAttributesWithTypes","types","i","NoBreakWrapper","styled","span","IconWrapper","theme","card","attributeIcon","icons","location","Marker","cost","Cost","time","Time","statusIcons","StatusType","book","Book","underReview","UnderReview","inProgress","InProgress","planned","Planned","closed","Closed","open","OpenForFeedback","completed","Completed","AttributeIcon","attribute","Icon","classNameAttribute","classNameStatus","statusIcon","className","ariaHidden","defaultOptions","showIcon","translations","Span","getAttributeRenderer","options","capacity","noun","parseInt","capacitySingular","capacityPlural","lastUpdated","date","dateConverter","visualDate","publicationLastUpdated","newsDate","whatsOnCost","getMultipleAttributeRenderer","statusName","timeSpecificity","timeUnit","timeEstimate","getTimeEstimate","costSpecificity","costEstimate","getCostEstimate","ContentType","getContentType","ContentTypeAttributes","contentType","Wrapper","useTranslation","t","attributeRenderers","project","projectRenderer","push","publication","service","timeRenderer","costRenderer","renderings","map","renderer","Boolean","rendering","index","Fragment","role","normalizeJssFields","data","filters","normalized","keys","Object","indexOf","forEach","val","jss","background","css","colors","Container","div","mq","element","white","black","primary","secondaryContainerMarginOffset","size","grid","gutter","Column","Grid","Item","Row","defaultDetailsTopPadding","spacing","pt","defaultDetailsBottomPadding","pb","DetailsContainer","py","SmallImageContainer","mt","mb","my","LargeImageContainer","circleConfig","left","right","Circle","lessThan","tertiary","config","imageSize","imagePosition","CoverImage","img","ContainedImage","Category","p","text_xscap","Description","StyledContentRichText","text_l","props","isBanner","AttributesWrapper","text_s","secondary","SecondaryContainer","SecondaryRow","SecondaryItem","LinkIconContainer","NavLink","action","LinkIconBannerContainer","TitleIconWrapper","ArrowWrapper","svg","ArrowBannerWrapper","Title","h2","heading_xl","heading_l","heading_m","heading_s","heading_xs","TitleBanner","h1","heading_xxl","GridContainer","HeaderText","HeaderContainer","Card","plainCard","boxShadow","boxShadowHover","restrictCardTitle","SecondaryCard","FeaturedContentType","title","description","link","primaryCategory","linkObject","getLink","StyledLink","isValidLinkObject","Arrow","External","pin","color","clipboard","FeaturedContentIcon","icon","bgClasses","lightPink","lightOrange","imgSizeClasses","small","featured","none","imgPosClasses","EditContainer","compose","withEditModeNotice","isValidSecondaryItem","item","withSitecoreContext","withEditMode","sitecoreContext","editMode","dataLayer","useDataLayer","handleLinkClick","url","pageTitle","route","fields","pageUrl","window","pathname","handleLinkClickEvent","datasource","noticeEnabled","noticeLevel","noticeMessage","backgroundColour","items","categoryTitle","categoryIcon","hasItems","primaryItem","secondaryItems","slice","image","anchorId","toLowerCase","split","join","imageWidth","width","imageHeight","height","imageAspect","colour","src","buildConfig","bgColorClass","imgSizeClass","imgPosClass","imageConfig","order","col","xs","lg","offset","getImageColumnConfig","detailsConfig","getDetailsColumnConfig","secondaryItemsClass","secondaryItemConfig","imageProps","imageTransparentPlaceholderSrc","convertSrcJss","alt","createSrcSet","containerNotice","id","onClick","field","as"],"mappings":"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","file":"static/js/FeaturedContent.fa8687f4.chunk.js","sourcesContent":["import getTypeFromValue from '_utils/helpers/getTypeFromValue';\r\n\r\n// note! enum values match keys sent by server\r\nexport enum AttributeType {\r\n capacity = 'capacity',\r\n cost = 'cost',\r\n lastUpdated = 'lastUpdated',\r\n location = 'location',\r\n statusIcon = 'statusIcon',\r\n statusName = 'statusName',\r\n time = 'time',\r\n timeSpecificity = 'timeSpecificity',\r\n timeUnit = 'timeUnit',\r\n timeEstimate = 'timeEstimate',\r\n costEstimate = 'costEstimate',\r\n costSpecificity = 'costSpecificity',\r\n whatsOnCost = 'whatsOnCost',\r\n newsDate = 'newsDate'\r\n}\r\n\r\nexport type Attribute = {\r\n type: AttributeType;\r\n value: any;\r\n};\r\n\r\n/**\r\n * @param target either a string representation of a attribute type or an object containing a attribute type\r\n * @param key optional used to retrieve attributeType value (if passing an object)\r\n */\r\nexport const getAttributeType = (value: string | object, key: string = 'type'): AttributeType => {\r\n return getTypeFromValue(AttributeType, value, key);\r\n};\r\n\r\n/**\r\n * @param target either a string representation of a attribute type or an object containing a attribute type\r\n * @param key optional used to retrieve attributeType value (if passing an object)\r\n */\r\nexport const pickAttributeByType = (\r\n attributes,\r\n attributeName: string,\r\n key: string = 'type'\r\n): Attribute => {\r\n if (!attributes || !attributeName) {\r\n return null;\r\n }\r\n\r\n let attrs = attributes?.filter((attr) => attr[key] === attributeName);\r\n\r\n if (attrs.length) {\r\n const attr = attrs[0];\r\n let attrType: AttributeType = getAttributeType(attr, key);\r\n\r\n if (attrType !== undefined) {\r\n // found a known type\r\n return {\r\n ...attr,\r\n type: attrType\r\n };\r\n } else {\r\n // treat as generic\r\n return {\r\n ...attr,\r\n type: undefined\r\n };\r\n }\r\n }\r\n\r\n return null;\r\n};\r\n\r\nexport const includesAttributeWithType = (\r\n attributes: { [key: string]: Attribute },\r\n type: AttributeType\r\n) => {\r\n if (!attributes) {\r\n return false;\r\n }\r\n\r\n return attributes.hasOwnProperty(type);\r\n};\r\n\r\nexport const includesAttributesWithTypes = (\r\n attributes: { [key: string]: Attribute },\r\n types: AttributeType[]\r\n) => {\r\n if (!attributes || !types) {\r\n return false;\r\n }\r\n\r\n for (let i = 0; i < types.length; i++) {\r\n const type = types[i];\r\n if (!includesAttributeWithType(attributes, type)) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n};\r\n\r\n// Old loose definitions Please migrate to strict ones above\r\n// DELETED use pickAttributeByType\r\n// export const getAttributeByType = (attributes, attributeType) => {\r\n\r\n// };\r\n\r\n// DELETED use AttributeIcon in utils/components/ContentTypeAttributes\r\n// export const AttributeIcon = ({ attribute }) => {\r\n\r\n// };\r\n","import styled from 'styled-components';\r\n// import { svg } from '_utils/styles/';\r\n\r\n/* \r\ninexplicably\r\nadding ${svg(24, 24)} into style defn, causes server error when deployed \r\nObject(...) is not a function TypeError: Object(...) is not a function \r\n*/\r\n\r\nexport const NoBreakWrapper = styled.span`\r\n white-space: nowrap;\r\n`;\r\n\r\nexport const IconWrapper = styled.span`\r\n position: relative;\r\n display: inline-block;\r\n margin-right: 8px;\r\n transform: translateY(-10%);\r\n height: 20px;\r\n white-space: nowrap;\r\n\r\n svg,\r\n img {\r\n vertical-align: middle;\r\n width: 20px;\r\n height: auto;\r\n }\r\n\r\n path {\r\n fill: ${({ theme }) => theme.card.attributeIcon};\r\n }\r\n`;\r\n","import React from 'react';\r\nimport { IconWrapper, NoBreakWrapper } from './StyledAttributeIcon';\r\nimport { AttributeType } from '_utils/helpers/attributeType';\r\nimport { StatusType } from '_utils/helpers/statusType';\r\nimport {\r\n Book,\r\n Closed,\r\n Completed,\r\n Cost,\r\n InProgress,\r\n Marker,\r\n OpenForFeedback,\r\n Planned,\r\n Time,\r\n UnderReview\r\n} from '_utils/icons';\r\n\r\nconst icons = {\r\n [AttributeType.location]: Marker,\r\n [AttributeType.cost]: Cost,\r\n [AttributeType.time]: Time\r\n};\r\n\r\nconst statusIcons = {\r\n [StatusType.book]: Book,\r\n [StatusType.underReview]: UnderReview,\r\n [StatusType.inProgress]: InProgress,\r\n [StatusType.planned]: Planned,\r\n [StatusType.closed]: Closed,\r\n [StatusType.open]: OpenForFeedback,\r\n [StatusType.completed]: Completed\r\n};\r\n\r\nconst AttributeIcon = ({ attribute }) => {\r\n if (!attribute) {\r\n return null;\r\n }\r\n\r\n let Icon = null;\r\n let classNameAttribute = attribute.type;\r\n let classNameStatus = '';\r\n\r\n if (attribute.type === AttributeType.statusIcon) {\r\n Icon = statusIcons[attribute.value];\r\n classNameStatus = attribute.value;\r\n } else {\r\n Icon = icons[attribute.type];\r\n }\r\n\r\n if (!Icon) {\r\n // console.log('no icon found for ', attribute.type);\r\n return null;\r\n }\r\n\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n \r\n );\r\n};\r\n\r\nexport default AttributeIcon;\r\n","import React, { ReactNode } from 'react';\r\nimport styled from 'styled-components';\r\nimport {\r\n AttributeType,\r\n Attribute,\r\n includesAttributesWithTypes\r\n} from '_utils/helpers/attributeType';\r\nimport AttributeIcon from './AttributeIcon';\r\nimport { dateConverter, getTimeEstimate, getCostEstimate } from '_utils/helpers';\r\nimport { AttributeRendererOptions } from './definitions';\r\n\r\nconst defaultOptions = {\r\n showIcon: true,\r\n translations: null\r\n};\r\n\r\nconst Span = styled.span``;\r\n\r\nexport function getAttributeRenderer(\r\n attribute: Attribute,\r\n options?: AttributeRendererOptions\r\n): () => ReactNode {\r\n options = { ...defaultOptions, ...options };\r\n\r\n const value = attribute?.value;\r\n\r\n if (value === '' || value === undefined || value === null) {\r\n return () => null;\r\n }\r\n\r\n switch (attribute?.type) {\r\n case AttributeType.location: {\r\n return () => (\r\n \r\n {options.showIcon && }\r\n {value}\r\n \r\n );\r\n }\r\n\r\n case AttributeType.capacity: {\r\n const noun =\r\n parseInt(value, 10) === 1\r\n ? options.translations.capacitySingular\r\n : options.translations.capacityPlural;\r\n return () => `${value} ${noun}`;\r\n }\r\n\r\n case AttributeType.lastUpdated: {\r\n return () => {\r\n let date = dateConverter(value)?.visualDate;\r\n return date\r\n ? `${\r\n options?.translations?.publicationLastUpdated\r\n ? options?.translations?.publicationLastUpdated + ' '\r\n : ''\r\n }${date}`\r\n : null;\r\n };\r\n }\r\n\r\n case AttributeType.newsDate: {\r\n return () => value;\r\n }\r\n\r\n case AttributeType.whatsOnCost: {\r\n return () => (\r\n \r\n {options.showIcon && }\r\n {value}\r\n \r\n );\r\n }\r\n }\r\n\r\n return () => null;\r\n}\r\n\r\nexport function getMultipleAttributeRenderer(\r\n attributes: { [key: string]: Attribute },\r\n options?: AttributeRendererOptions\r\n): () => ReactNode {\r\n options = { ...defaultOptions, ...options };\r\n\r\n if (!attributes) {\r\n return () => null;\r\n }\r\n\r\n if (\r\n includesAttributesWithTypes(attributes, [AttributeType.statusName, AttributeType.statusIcon])\r\n ) {\r\n const statusName = attributes[AttributeType.statusName];\r\n const statusIcon = attributes[AttributeType.statusIcon];\r\n\r\n if (statusName && statusName.value) {\r\n return () => (\r\n \r\n {!!(statusIcon && options.showIcon) && }\r\n {statusName.value}\r\n \r\n );\r\n }\r\n }\r\n\r\n if (\r\n includesAttributesWithTypes(attributes, [\r\n AttributeType.timeSpecificity,\r\n AttributeType.timeUnit,\r\n AttributeType.timeEstimate\r\n ])\r\n ) {\r\n const timeSpecificity = attributes[AttributeType.timeSpecificity]?.value || '';\r\n const timeUnit = attributes[AttributeType.timeUnit]?.value || '';\r\n const timeEstimate = attributes[AttributeType.timeEstimate]?.value || '';\r\n\r\n const time = getTimeEstimate(timeSpecificity, timeUnit, timeEstimate);\r\n\r\n if (time) {\r\n return () => (\r\n \r\n \r\n {time}\r\n \r\n );\r\n } else {\r\n return null;\r\n }\r\n }\r\n\r\n if (\r\n includesAttributesWithTypes(attributes, [\r\n AttributeType.costSpecificity,\r\n AttributeType.costEstimate\r\n ])\r\n ) {\r\n const costEstimate = attributes[AttributeType.costEstimate]?.value || '';\r\n const costSpecificity = attributes[AttributeType.costSpecificity]?.value || '';\r\n\r\n const cost = getCostEstimate(costSpecificity, costEstimate);\r\n\r\n if (cost) {\r\n return () => (\r\n \r\n {options.showIcon && }\r\n {cost}\r\n \r\n );\r\n }\r\n }\r\n\r\n return () => null;\r\n}\r\n","import getTypeFromValue from '_utils/helpers/getTypeFromValue';\r\n\r\n// note! enum values match keys sent by server\r\nexport enum ContentType {\r\n collection = 'collection',\r\n committee = 'committee',\r\n focus = 'focus',\r\n place = 'place',\r\n profile = 'profile',\r\n program = 'program',\r\n project = 'project',\r\n publication = 'publication',\r\n service = 'service',\r\n space = 'space'\r\n}\r\n\r\n/**\r\n * @param target either a string representation of a content type or an object containing a content type\r\n * @param key optional used to retrieve contentType value (if passing an object)\r\n */\r\nexport const getContentType = (value: string | object, key: string = 'type'): ContentType => {\r\n return getTypeFromValue(ContentType, value, key);\r\n};\r\n","import React from 'react';\r\n\r\nimport { ContentType } from '_utils/helpers/contentType';\r\nimport { pickAttributeByType, AttributeType, Attribute } from '_utils/helpers/attributeType';\r\nimport { getAttributeRenderer, getMultipleAttributeRenderer } from './getAttributeRenderer';\r\nimport { useTranslation } from 'react-i18next';\r\n\r\nexport * from './getAttributeRenderer';\r\nexport * from './definitions';\r\n\r\nexport type WrapperProps = {};\r\n\r\ntype ContentTypeAttributesProps = {\r\n attributes: any[];\r\n contentType: ContentType;\r\n Wrapper: React.ComponentType;\r\n};\r\n\r\nconst ContentTypeAttributes: React.FC = ({\r\n attributes,\r\n contentType,\r\n Wrapper\r\n}) => {\r\n const [t] = useTranslation();\r\n\r\n let publicationLastUpdated = t('publication-related-content-last-updated-prefix');\r\n\r\n if (publicationLastUpdated === 'publication-related-content-last-updated-prefix') {\r\n publicationLastUpdated = '';\r\n }\r\n\r\n const translations = {\r\n publicationLastUpdated,\r\n capacitySingular: t('space-capacity-unit-singular'),\r\n capacityPlural: t('space-capacity-unit-plural')\r\n };\r\n\r\n let attributeRenderers: any[] = [];\r\n\r\n if (contentType === ContentType.project) {\r\n const statusName = pickAttributeByType(attributes, AttributeType.statusName);\r\n const statusIcon = pickAttributeByType(attributes, AttributeType.statusIcon);\r\n\r\n const projectRenderer = getMultipleAttributeRenderer({\r\n [AttributeType.statusName]: statusName,\r\n [AttributeType.statusIcon]: statusIcon\r\n });\r\n\r\n attributeRenderers.push(projectRenderer);\r\n }\r\n\r\n attributeRenderers.push(\r\n getAttributeRenderer(pickAttributeByType(attributes, AttributeType.location))\r\n );\r\n\r\n attributeRenderers.push(\r\n getAttributeRenderer(pickAttributeByType(attributes, AttributeType.capacity), {\r\n translations\r\n })\r\n );\r\n\r\n attributeRenderers.push(\r\n getAttributeRenderer(pickAttributeByType(attributes, AttributeType.whatsOnCost))\r\n );\r\n\r\n // lastUpdated can appear for other (unwanted) contentTypes - only display for publication\r\n if (contentType === ContentType.publication) {\r\n attributeRenderers.push(\r\n getAttributeRenderer(pickAttributeByType(attributes, AttributeType.lastUpdated), {\r\n translations\r\n })\r\n );\r\n }\r\n\r\n attributeRenderers.push(\r\n getAttributeRenderer(pickAttributeByType(attributes, AttributeType.newsDate))\r\n );\r\n\r\n if (contentType === ContentType.service) {\r\n const timeSpecificity: Attribute = pickAttributeByType(\r\n attributes,\r\n AttributeType.timeSpecificity\r\n );\r\n const timeUnit: Attribute = pickAttributeByType(attributes, AttributeType.timeUnit);\r\n const timeEstimate: Attribute = pickAttributeByType(attributes, AttributeType.timeEstimate);\r\n const costEstimate: Attribute = pickAttributeByType(attributes, AttributeType.costEstimate);\r\n const costSpecificity: Attribute = pickAttributeByType(\r\n attributes,\r\n AttributeType.costSpecificity\r\n );\r\n\r\n const timeRenderer = getMultipleAttributeRenderer({\r\n [AttributeType.timeSpecificity]: timeSpecificity,\r\n [AttributeType.timeUnit]: timeUnit,\r\n [AttributeType.timeEstimate]: timeEstimate\r\n });\r\n\r\n const costRenderer = getMultipleAttributeRenderer(\r\n {\r\n [AttributeType.costEstimate]: costEstimate,\r\n [AttributeType.costSpecificity]: costSpecificity\r\n },\r\n { showIcon: timeRenderer !== null }\r\n );\r\n\r\n attributeRenderers.push(timeRenderer, costRenderer);\r\n }\r\n\r\n const renderings = attributeRenderers\r\n .map((renderer) => (typeof renderer === 'function' ? renderer() : null))\r\n .filter(Boolean);\r\n\r\n if (renderings.length === 0) {\r\n return null;\r\n }\r\n\r\n return (\r\n \r\n {renderings.map((rendering, index) => (\r\n \r\n {index > 0 && ยท }\r\n {rendering}\r\n \r\n ))}\r\n \r\n );\r\n};\r\n\r\nexport default ContentTypeAttributes;\r\n","export const normalizeJssFields = (data: object, filters = []): any => {\r\n if (!data) {\r\n return data;\r\n }\r\n\r\n let normalized = {};\r\n\r\n const keys = Object.keys(data).filter((key) => !filters.length || filters.indexOf(key) > -1);\r\n\r\n keys.forEach((key) => {\r\n const val = data[key];\r\n if (val && typeof val === 'object' && val.hasOwnProperty('jss')) {\r\n normalized[key] = val.jss;\r\n } else {\r\n normalized[key] = val;\r\n }\r\n });\r\n\r\n return normalized;\r\n};\r\n","import styled, { css } from 'styled-components';\r\nimport { Grid } from '_utils/components/Corporate';\r\nimport { NavLink } from 'react-router-dom';\r\nimport StyledContentRichText from '_components/Corporate/ContentRichText/StyledContentRichText';\r\nimport { spacing } from '_utils/props';\r\n\r\nimport {\r\n mq,\r\n heading_xl,\r\n heading_l,\r\n heading_m,\r\n heading_s,\r\n heading_xs,\r\n text_l,\r\n text_s,\r\n text_xscap,\r\n svg,\r\n heading_xxl\r\n} from '_utils/styles';\r\n\r\nfunction background({ theme, background }) {\r\n return css`\r\n background-color: ${theme.colors.background[background]};\r\n `;\r\n}\r\n\r\nexport const Container = styled.div`\r\n ${background}\r\n width: 100%;\r\n position: relative;\r\n overflow: hidden;\r\n\r\n &.featured-image {\r\n ${mq('lg')} {\r\n display: flex;\r\n width: 100%;\r\n align-items: center;\r\n justify-content: center;\r\n min-height: 552px;\r\n }\r\n\r\n ${mq('xl')} {\r\n min-height: 640px;\r\n }\r\n\r\n /* ie11 cant do margin auto (Grid.Container) in flex */\r\n @media all and (-ms-high-contrast: none) {\r\n display: block;\r\n }\r\n @media print {\r\n display: flex;\r\n margin-top: 20px;\r\n }\r\n }\r\n\r\n &.bg-tertiary {\r\n color: ${({ theme }) => theme.colors.element.white};\r\n }\r\n @media print {\r\n &.bg-tertiary {\r\n color: ${({ theme }) => theme.colors.element.black};\r\n }\r\n background-color: ${({ theme }) => theme.colors.background.primary};\r\n page-break-inside: avoid;\r\n }\r\n`;\r\n\r\n// offset for secondary item container overlap\r\n// (accounts for grid gutters at passed in size)\r\nconst secondaryContainerMarginOffset = (size) => ({ theme }) =>\r\n theme.grid.gutter.size[size] / 2 + 32;\r\n\r\nexport const Column = styled(Grid.Item)`\r\n display: flex;\r\n flex-direction: column;\r\n align-items: flex-start;\r\n justify-content: center;\r\n\r\n /* match container size, for circular image */\r\n .featured-image & {\r\n ${mq('lg')} {\r\n min-height: 552px;\r\n }\r\n\r\n ${mq('xl')} {\r\n min-height: 640px;\r\n }\r\n }\r\n`;\r\n\r\nexport const Row = styled(Grid.Row)`\r\n .featured-image & {\r\n ${mq('lg')} {\r\n height: 100%;\r\n }\r\n }\r\n\r\n .secondary-items & {\r\n padding-bottom: 32px;\r\n }\r\n\r\n .secondary-items.featured-image & {\r\n ${mq('lg')} {\r\n padding-bottom: 0;\r\n }\r\n }\r\n`;\r\n\r\nconst defaultDetailsTopPadding = ({ theme }) => css`\r\n /* 40px */\r\n ${spacing({ theme, pt: 8 })}\r\n\r\n /* 64px */\r\n ${mq('md')} {\r\n ${spacing({ theme, pt: 7 })}\r\n }\r\n\r\n /* 120px */\r\n ${mq('lg')} {\r\n ${spacing({ theme, pt: 9 })}\r\n }\r\n`;\r\n\r\nconst defaultDetailsBottomPadding = ({ theme }) => css`\r\n\r\n /* 40px */\r\n ${spacing({ theme, pb: 8 })}\r\n\r\n /* 64px */\r\n ${mq('md')} {\r\n ${spacing({ theme, pb: 7 })}\r\n }\r\n\r\n /* 120px */\r\n ${mq('lg')} {\r\n ${spacing({ theme, pb: 9 })}\r\n }\r\n`;\r\n\r\nexport const DetailsContainer = styled.div`\r\n width: '100%';\r\n display: flex;\r\n flex-direction: column;\r\n width: 100%;\r\n position: relative;\r\n z-index: 3;\r\n\r\n .simple-image & {\r\n padding-top: 4px;\r\n ${defaultDetailsBottomPadding}\r\n\r\n ${mq('lg')} {\r\n ${({ theme }) => spacing({ theme, py: 8 })}\r\n }\r\n }\r\n\r\n .featured-image & {\r\n ${defaultDetailsTopPadding}\r\n ${defaultDetailsBottomPadding}\r\n\r\n ${mq('lg')} {\r\n ${({ theme }) => spacing({ theme, py: 8 })}\r\n }\r\n }\r\n\r\n .no-image & {\r\n ${defaultDetailsTopPadding}\r\n ${defaultDetailsBottomPadding}\r\n }\r\n`;\r\n\r\nexport const SmallImageContainer = styled.div`\r\n /* ie11 needs height */\r\n @media all and (-ms-high-contrast: none) {\r\n height: 100%;\r\n }\r\n\r\n width: 100%;\r\n ${({ theme }) => spacing({ theme, mt: 8, mb: '4px' })}\r\n\r\n ${mq('lg')} {\r\n ${({ theme }) => spacing({ theme, my: 8 })}\r\n }\r\n`;\r\n\r\nexport const LargeImageContainer = styled.div`\r\n ${background}\r\n display: block;\r\n width: 100%;\r\n height: 324px;\r\n position: relative;\r\n\r\n ${mq('md')} {\r\n height: 432px;\r\n }\r\n\r\n ${mq('lg')} {\r\n position: absolute;\r\n width: 56%;\r\n left: 0;\r\n top: 0;\r\n height: 100%;\r\n\r\n .right-image & {\r\n left: auto;\r\n right: 0;\r\n }\r\n }\r\n\r\n @media print {\r\n width: 50%;\r\n }\r\n`;\r\n\r\nconst circleConfig = {\r\n left: css`\r\n left: 0;\r\n\r\n img {\r\n left: 0;\r\n transform: translateX(-11.5%);\r\n }\r\n `,\r\n right: css`\r\n right: 0;\r\n\r\n img {\r\n right: 0;\r\n transform: translateX(11.5%);\r\n }\r\n `\r\n};\r\n\r\nconst handleCircleConfig = ({ theme, config: { background, imageSize, imagePosition } }) => {\r\n if (imageSize !== 'featured') {\r\n return css`\r\n display: none;\r\n `;\r\n }\r\n\r\n return css`\r\n ${circleConfig[imagePosition]}\r\n\r\n img {\r\n background-color: ${theme.colors.background[background]};\r\n }\r\n `;\r\n};\r\n\r\nexport const Circle = styled.div`\r\n ${mq.lessThan('lg')} {\r\n display: none;\r\n }\r\n\r\n position: absolute;\r\n top: 50%;\r\n transform: translateY(-50%);\r\n height: 171%;\r\n width: 2048px;\r\n\r\n img {\r\n position: absolute;\r\n background-color: ${({ theme }) => theme.colors.background.tertiary};\r\n border-radius: 100%;\r\n height: 100%;\r\n width: auto;\r\n }\r\n\r\n ${handleCircleConfig}\r\n`;\r\n\r\nconst fitImage = () => `\r\n position: absolute;\r\n width: 100%;\r\n height: 100%;\r\n left: 0;\r\n top: 0;\r\n`;\r\n\r\nexport const CoverImage = styled.img`\r\n ${fitImage}\r\n object-fit: cover;\r\n font-family: 'object-fit: cover';\r\n @media print {\r\n page-break-inside: avoid;\r\n }\r\n`;\r\n\r\nexport const ContainedImage = styled.img`\r\n width: 100%;\r\n height: auto;\r\n\r\n .portrait & {\r\n width: auto;\r\n height: 176px;\r\n\r\n ${mq('sm')} {\r\n height: 347px;\r\n }\r\n ${mq('md')} {\r\n height: 472px;\r\n }\r\n ${mq('lg')} {\r\n height: 368px;\r\n }\r\n }\r\n`;\r\n\r\nexport const Category = styled.p`\r\n ${text_xscap}\r\n margin: 0;\r\n`;\r\n\r\nexport const Description = styled(StyledContentRichText)`\r\n ${text_l}\r\n\r\n margin: 0;\r\n \r\n ${mq.lessThan('md')}{\r\n line-height: ${props => props.isBanner ? '28px' : '24px'};\r\n }\r\n &:not(:first-child) {\r\n ${({ theme }) => spacing({ theme, mt: 3 })}\r\n }\r\n`;\r\n\r\nexport const AttributesWrapper = styled.span`\r\n ${text_s}\r\n margin: 0;\r\n display: block;\r\n color: ${({ theme }) => theme.card.secondary};\r\n\r\n ${Container}.bg-tertiary & {\r\n color: ${({ theme }) => theme.colors.element.white};\r\n path {\r\n fill: ${({ theme }) => theme.colors.element.white};\r\n }\r\n }\r\n\r\n &:not(:first-child) {\r\n ${({ theme }) => spacing({ theme, mt: 3 })}\r\n }\r\n`;\r\n\r\nexport const SecondaryContainer = styled(Grid.Container)`\r\n position: relative;\r\n padding-bottom: 32px;\r\n\r\n margin-top: -${secondaryContainerMarginOffset('xs')}px;\r\n\r\n ${mq('md')} {\r\n margin-top: -${secondaryContainerMarginOffset('md')}px;\r\n }\r\n\r\n ${mq('lg')} {\r\n margin-top: -${secondaryContainerMarginOffset('lg')}px;\r\n }\r\n\r\n @media print {\r\n margin-top: 32px;\r\n }\r\n`;\r\n\r\nexport const SecondaryRow = styled(Grid.Row)`\r\n list-style: none;\r\n padding: 0;\r\n`;\r\n\r\nexport const SecondaryItem = styled(Grid.Item)`\r\n /*tighter vertical spacing then normal grid itesm */\r\n\r\n ${mq.lessThan('lg')} {\r\n &:not(:first-child) {\r\n ${({ theme }) => spacing({ theme, mt: -1 })}\r\n }\r\n }\r\n\r\n ${mq('lg')} {\r\n margin-top: 0;\r\n align-self: stretch;\r\n }\r\n`;\r\n\r\nexport const LinkIconContainer = styled(NavLink)`\r\n display: block;\r\n color: inherit;\r\n text-decoration: none;\r\n\r\n &:hover {\r\n color: ${({ theme }) => theme.card.action};\r\n }\r\n\r\n ${Container}.bg-tertiary &:hover {\r\n color: ${({ theme }) => theme.colors.element.white};\r\n }\r\n`;\r\n\r\nexport const LinkIconBannerContainer = styled(NavLink)`\r\n display: block;\r\n color: inherit;\r\n text-decoration: none;\r\n\r\n &:hover {\r\n color: ${({ theme }) => theme.card.action};\r\n }\r\n`;\r\n\r\n// https://snook.ca/archives/html_and_css/icon-wrap-after-text\r\nexport const TitleIconWrapper = styled.span`\r\n white-space: nowrap;\r\n line-height: 0;\r\n`;\r\n\r\nexport const ArrowWrapper = styled.span`\r\n ${svg(14, 14)}\r\n width: 19px;\r\n margin-left: 12px;\r\n display: inline-block;\r\n\r\n ${mq('lg')} {\r\n margin-left: 16px;\r\n width: 24px;\r\n }\r\n\r\n path {\r\n fill: ${({ theme }) => theme.card.action};\r\n }\r\n\r\n ${Container}.bg-tertiary & {\r\n path {\r\n fill: ${({ theme }) => theme.colors.element.white};\r\n }\r\n }\r\n`;\r\n\r\nexport const ArrowBannerWrapper = styled.span`\r\n ${svg(14, 14)}\r\n width: 19px;\r\n margin-left: 12px;\r\n display: inline-block;\r\n\r\n ${mq('lg')} {\r\n margin-left: 16px;\r\n width: 24px;\r\n }\r\n\r\n path {\r\n fill: ${({ theme }) => theme.card.action};\r\n }\r\n`;\r\n\r\nexport const Title = styled.h2`\r\n display: inline;\r\n h2& {\r\n ${heading_xl}\r\n }\r\n\r\n h3& {\r\n ${heading_l}\r\n }\r\n\r\n h4& {\r\n ${heading_m}\r\n }\r\n\r\n h5& {\r\n ${heading_s}\r\n }\r\n\r\n h6& {\r\n ${heading_xs}\r\n }\r\n\r\n &:not(:first-child) {\r\n ${({ theme }) => spacing({ theme, mt: 1 })}\r\n }\r\n`;\r\n\r\nexport const TitleBanner = styled.h1`\r\n ${heading_xxl}\r\n`\r\n\r\nexport const GridContainer = styled(Grid.Container)`\r\n @media print {\r\n width: 50%;\r\n margin: 0;\r\n page-break-inside: avoid;\r\n }\r\n`;\r\n\r\nexport const HeaderText = styled.p`\r\n ${heading_l}\r\n`\r\n\r\nexport const HeaderContainer = styled.div`\r\n display: flex;\r\n align-items: center;\r\n ${({theme}) => spacing({theme, mb: 3})};\r\n & svg {\r\n width: 32px;\r\n margin-right: 10px;\r\n }\r\n ${mq.lessThan('md')} {\r\n & svg {\r\n width: 24px;\r\n }\r\n }\r\n`\r\n","import React from 'react';\r\nimport styled from 'styled-components';\r\nimport { Grid } from '_utils/components/Corporate';\r\n\r\nexport const Container = styled.div`\r\n position: fixed;\r\n pointer-events: none;\r\n width: 100%;\r\n height: 100vh;\r\n left: 0;\r\n top: 0;\r\n`;\r\n\r\nexport const Item = styled(Grid.Item)`\r\n position: relative;\r\n`;\r\n\r\nexport const Fill = styled.div`\r\n background-color: #00000011;\r\n height: 100vh;\r\n width: 100%;\r\n`;\r\n\r\nexport default function GridVisualiser() {\r\n return (\r\n \r\n \r\n \r\n {[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12].map((_, i) => {\r\n return (\r\n \r\n \r\n \r\n );\r\n })}\r\n \r\n \r\n \r\n );\r\n}\r\n","import styled from 'styled-components';\r\nimport { NavLink } from 'react-router-dom';\r\n\r\nimport {\r\n plainCard,\r\n text_xscap,\r\n heading_s,\r\n text_s,\r\n mq,\r\n svg,\r\n restrictCardTitle\r\n} from '_utils/styles';\r\nimport { spacing } from '_utils/props';\r\n\r\nexport const Card = styled(NavLink)`\r\n ${({ theme }) => plainCard({ theme })}\r\n ${({ theme }) => spacing({ theme, p: 3 })}\r\n width: 100%;\r\n display: flex;\r\n\r\n flex: 1 0 auto;\r\n flex-direction: column;\r\n justify-content: flex-start;\r\n color: inherit;\r\n text-decoration: none;\r\n\r\n position: relative;\r\n\r\n ${mq('lg')} {\r\n height: 100%;\r\n }\r\n\r\n &:after {\r\n content: '';\r\n position: absolute;\r\n width: 98%;\r\n height: 90%;\r\n left: 50%;\r\n bottom: 0;\r\n transform: translateX(-50%);\r\n box-shadow: ${({ theme }) => theme.card.boxShadow};\r\n transition: box-shadow 0.2s linear;\r\n z-index: -1;\r\n }\r\n\r\n &:hover {\r\n &:after {\r\n box-shadow: ${({ theme }) => theme.card.boxShadowHover};\r\n }\r\n }\r\n`;\r\n\r\nexport const Category = styled.p`\r\n ${text_xscap}\r\n margin: 0;\r\n`;\r\n\r\nexport const AttributesWrapper = styled.span`\r\n ${text_s}\r\n margin: 8px 0 0 0;\r\n display: block;\r\n color: ${({ theme }) => theme.card.secondary};\r\n flex: none;\r\n`;\r\n\r\nexport const LinkIconContainer = styled.span`\r\n display: flex;\r\n align-items: center;\r\n`;\r\n\r\nexport const ArrowWrapper = styled.span`\r\n ${svg(14, 14)}\r\n width: 14px;\r\n margin-left: 12px;\r\n flex: none;\r\n align-self: flex-start;\r\n\r\n path {\r\n fill: ${({ theme }) => theme.card.action};\r\n }\r\n`;\r\n\r\nexport const Title = styled.span`\r\n ${heading_s}\r\n\r\n &:not(:first-child) {\r\n ${({ theme }) => spacing({ theme, mt: 1 })}\r\n }\r\n\r\n ${Card}:hover & {\r\n color: ${({ theme }) => theme.card.action};\r\n }\r\n\r\n ${restrictCardTitle}\r\n`;\r\n\r\nexport const TitleIconWrapper = styled.span`\r\n white-space: nowrap;\r\n line-height: 0;\r\n`;\r\n","import React from 'react';\r\n\r\nimport {\r\n Card,\r\n Category,\r\n Title,\r\n AttributesWrapper,\r\n LinkIconContainer,\r\n ArrowWrapper\r\n} from './StyledSecondaryCard';\r\nimport NavLink from '../NavItem';\r\nimport ContentTypeAttributes from '_utils/components/Corporate/ContentTypeAttributes';\r\nimport { getContentType } from '_utils/helpers/contentType';\r\nimport Arrow from '_utils/icons/Arrow';\r\nimport External from '_utils/icons/External';\r\nimport { getLink, isValidLinkObject } from '_utils/helpers/link';\r\nimport { TitleIconWrapper } from './StyledFeaturedContent';\r\n\r\nfunction SecondaryCard({ title, description, link, attributes, primaryCategory, type }) {\r\n let contentType = getContentType(type);\r\n\r\n const linkObject = getLink(link);\r\n\r\n return (\r\n \r\n {primaryCategory && {primaryCategory}}\r\n {title && (\r\n \r\n \r\n {title}\r\n {isValidLinkObject(linkObject) && (\r\n <TitleIconWrapper>\r\n \r\n <ArrowWrapper>\r\n {linkObject.type !== 'external' && <Arrow ariaHidden={true} />}\r\n {linkObject.type === 'external' && <External ariaHidden={true} />}\r\n </ArrowWrapper>\r\n </TitleIconWrapper>\r\n )}\r\n \r\n \r\n )}\r\n\r\n \r\n \r\n );\r\n}\r\n\r\nexport default SecondaryCard;\r\n","import getTypeFromValue from '_utils/helpers/getTypeFromValue';\r\n\r\n// note! enum values match keys sent by server\r\nexport enum FeaturedContentType {\r\n pin = 'pin',\r\n clipboard = 'clipboard'\r\n}\r\n\r\n/**\r\n * @param target either a string representation of a content type or an object containing a content type\r\n * @param key optional used to retrieve contentType value (if passing an object)\r\n */\r\nexport const getFeatureContentType = (value: string | object, key: string = 'type'): FeaturedContentType => {\r\n return getTypeFromValue(FeaturedContentType, value, key);\r\n};\r\n","import React from 'react';\r\nimport {FeaturedContentType} from \"../../../helpers/featuredContentType\";\r\nimport {\r\n Pin,\r\n Clipboard\r\n} from '_utils/icons';\r\n\r\nconst icons = {\r\n [FeaturedContentType.pin]: ,\r\n [FeaturedContentType.clipboard]: ,\r\n};\r\n\r\nexport default function FeaturedContentIcon({ icon }) {\r\n if (icons[icon]) {\r\n return icons[icon];\r\n }\r\n\r\n return null;\r\n}\r\n","import React, { useEffect, useState } from 'react';\r\nimport styled from 'styled-components';\r\nimport { compose } from 'ramda';\r\nimport { withSitecoreContext } from '@sitecore-jss/sitecore-jss-react';\r\n\r\nimport { normalizeJssFields } from '_utils/helpers/jss';\r\nimport { useDataLayer } from '_utils/hooks';\r\nimport { handleLinkClickEvent } from '_utils/helpers/trackEvents';\r\nimport {\r\n Container,\r\n LargeImageContainer,\r\n GridContainer,\r\n Row,\r\n Column,\r\n SmallImageContainer,\r\n DetailsContainer,\r\n Category,\r\n Title,\r\n TitleBanner,\r\n LinkIconContainer,\r\n LinkIconBannerContainer,\r\n ArrowWrapper,\r\n ArrowBannerWrapper,\r\n Description,\r\n AttributesWrapper,\r\n ContainedImage,\r\n CoverImage,\r\n SecondaryContainer,\r\n SecondaryRow,\r\n SecondaryItem,\r\n Circle,\r\n TitleIconWrapper,\r\n HeaderText,\r\n HeaderContainer\r\n} from './StyledFeaturedContent';\r\n\r\nimport { withEditMode, withEditModeNotice } from '_containers/BaseComponent';\r\nimport { getContentType } from '_utils/helpers/contentType';\r\nimport GridVisualiser from '_utils/components/Corporate/Grid/GridVisualiser';\r\nimport ContentTypeAttributes from '_utils/components/Corporate/ContentTypeAttributes';\r\nimport { FeaturedContentConfig } from './definitions';\r\nimport SecondaryCard from './SecondaryCard';\r\nimport Arrow from '_utils/icons/Arrow';\r\nimport External from '_utils/icons/External';\r\nimport NavLink from '../NavItem';\r\nimport { createSrcSet, convertSrcJss } from '_utils/media';\r\nimport { imageTransparentPlaceholderSrc } from '_utils/styles';\r\nimport { getLink, isValidLinkObject } from '_utils/helpers/link';\r\nimport FeaturedContentIcon from '../../../utils/components/Corporate/FeaturedContentIcon';\r\n\r\nconst bgClasses = {\r\n secondary: 'bg-secondary',\r\n tertiary: 'bg-tertiary',\r\n lightPink: 'bg-secondary',\r\n lightOrange: 'bg-secondary'\r\n};\r\n\r\nconst imgSizeClasses = {\r\n small: 'simple-image',\r\n featured: 'featured-image',\r\n none: 'no-image'\r\n};\r\n\r\nconst imgPosClasses = {\r\n left: 'left-image',\r\n right: 'right-image'\r\n};\r\n\r\nconst EditContainer = compose(withEditModeNotice)(styled.div``);\r\n\r\nfunction getImageColumnConfig(config: FeaturedContentConfig) {\r\n const order = config.imagePosition === 'right' ? 2 : 1;\r\n\r\n if (config.imageSize === 'none') {\r\n return {};\r\n }\r\n\r\n if (config.imageSize === 'featured') {\r\n return {};\r\n }\r\n\r\n // Simple / Small\r\n return {\r\n col: { xs: 8, lg: 5 },\r\n offset: { xs: 0, lg: 0 },\r\n order: { xs: 1, lg: order }\r\n };\r\n}\r\n\r\nfunction getDetailsColumnConfig(config: FeaturedContentConfig) {\r\n const order = config.imagePosition === 'right' ? 1 : 2;\r\n\r\n if (config.imageSize === 'none') {\r\n return { col: { xs: 12 } };\r\n }\r\n\r\n if (config.imageSize === 'featured') {\r\n const offsetLg = config.imagePosition === 'left' ? 7 : 0;\r\n\r\n return {\r\n col: { xs: 12, lg: 5 },\r\n offset: { xs: 0, lg: offsetLg },\r\n order: { xs: 2, lg: order }\r\n };\r\n }\r\n\r\n // default to Simple / Small\r\n return {\r\n col: { xs: 12, lg: 6 },\r\n offset: { xs: 0, lg: config.imagePosition === 'right' ? 0 : 1 },\r\n order\r\n };\r\n}\r\n\r\nfunction buildConfig(options): FeaturedContentConfig {\r\n let config: FeaturedContentConfig = {\r\n background: 'tertiary',\r\n imageSize: 'featured',\r\n imagePosition: 'left'\r\n };\r\n\r\n if (options?.colour?.toLowerCase() === 'light beige') {\r\n config.background = 'secondary';\r\n }\r\n\r\n if (options?.colour?.toLowerCase() === 'light pink') {\r\n config.background = 'lightPink';\r\n }\r\n\r\n if (options?.colour?.toLowerCase() === 'light orange') {\r\n config.background = 'lightOrange';\r\n }\r\n\r\n if (options?.imageSize?.toLowerCase() === 'featured') {\r\n config.imageSize = 'featured';\r\n }\r\n\r\n if (options?.imageSize?.toLowerCase() === 'simple') {\r\n config.imageSize = 'small';\r\n }\r\n\r\n if (options?.imageSize?.toLowerCase() === 'none' || !options.image?.value?.src) {\r\n config.imageSize = 'none';\r\n }\r\n\r\n if (options?.imagePosition?.toLowerCase() === 'right') {\r\n config.imagePosition = 'right';\r\n }\r\n\r\n return config;\r\n}\r\n\r\nconst isValidSecondaryItem = (item) => {\r\n if (!item) {\r\n return false;\r\n }\r\n\r\n // TODO convey validation to author\r\n const { title } = item;\r\n\r\n return Boolean(title);\r\n};\r\n\r\nfunction FeaturedContent({ sitecoreContext, rendering, editMode }) {\r\n const dataLayer = useDataLayer();\r\n\r\n const handleLinkClick = (url: string) => {\r\n if (!dataLayer) {\r\n return;\r\n }\r\n\r\n const pageTitle = sitecoreContext?.route?.fields?.pageTitle?.value || '';\r\n const pageUrl = window.location.pathname;\r\n\r\n handleLinkClickEvent(dataLayer, url, pageTitle, pageUrl);\r\n };\r\n\r\n const fields = rendering?.fields?.data?.datasource || rendering?.fields;\r\n\r\n if (!fields) {\r\n return (\r\n \r\n );\r\n }\r\n\r\n const normalized = normalizeJssFields(fields);\r\n\r\n let {\r\n backgroundColour,\r\n imagePosition,\r\n imageSize,\r\n items,\r\n categoryTitle,\r\n categoryIcon\r\n } = normalized;\r\n\r\n backgroundColour = backgroundColour?.value;\r\n imagePosition = imagePosition?.value;\r\n imageSize = imageSize?.value;\r\n categoryTitle = categoryTitle?.value;\r\n categoryIcon = categoryIcon?.value;\r\n\r\n const hasItems = items && items.length;\r\n\r\n if (!hasItems) {\r\n if (editMode) {\r\n return (\r\n \r\n );\r\n } else {\r\n return null;\r\n }\r\n }\r\n\r\n const primaryItem = items[0];\r\n\r\n let secondaryItems = items?.slice(1, 4) || [];\r\n\r\n if (!editMode) {\r\n secondaryItems = secondaryItems.filter(isValidSecondaryItem);\r\n }\r\n\r\n const { image, title, description, attributes, primaryCategory, type, link } = primaryItem;\r\n const anchorId = title\r\n ? title\r\n .toLowerCase()\r\n .split(' ')\r\n .join('-')\r\n : '';\r\n\r\n let imageWidth = image?.value?.width;\r\n let imageHeight = image?.value?.height;\r\n\r\n const linkObject = getLink(link);\r\n\r\n imageWidth = parseInt(imageWidth, 10) || 0;\r\n imageHeight = parseInt(imageHeight, 10) || 0;\r\n\r\n let imageAspect: 'portrait' | 'landscape' = imageHeight > imageWidth ? 'portrait' : 'landscape';\r\n\r\n let contentType = getContentType(type);\r\n\r\n const config = buildConfig({\r\n colour: backgroundColour,\r\n imageSize,\r\n imagePosition,\r\n image\r\n });\r\n\r\n const bgColorClass = bgClasses[config.background];\r\n const imgSizeClass = imgSizeClasses[config.imageSize];\r\n const imgPosClass = imgPosClasses[config.imagePosition];\r\n const imageConfig = getImageColumnConfig(config);\r\n const detailsConfig = getDetailsColumnConfig(config);\r\n const secondaryItemsClass = secondaryItems.length ? 'secondary-items' : '';\r\n\r\n const secondaryItemConfig = {\r\n col: { xs: 12, lg: 12 / secondaryItems.length }\r\n };\r\n\r\n let imageProps = {};\r\n\r\n if (config.imageSize !== 'none' && image?.value?.src) {\r\n imageProps = {\r\n className: 'lazyload',\r\n src: imageTransparentPlaceholderSrc,\r\n 'data-src': convertSrcJss(image.value.src, 640),\r\n alt: image?.value?.alt\r\n };\r\n\r\n if (config.imageSize === 'small') {\r\n imageProps['data-srcset'] = createSrcSet(image.value.src, [640, 1200]);\r\n }\r\n\r\n if (config.imageSize === 'featured') {\r\n imageProps['data-srcset'] = createSrcSet(image.value.src, [640, 1200, 1600]);\r\n }\r\n }\r\n\r\n let containerNotice = {\r\n noticeEnabled: true,\r\n noticeLevel: hasItems ? 'info' : 'warning',\r\n noticeMessage: hasItems\r\n ? `Please use 'Edit related item' screen to modify items in the Featured content component.`\r\n : `Featured content component has no items. Please use 'Edit related item' screen to add items.`\r\n };\r\n\r\n return (\r\n \r\n \r\n {false && }\r\n {config.imageSize === 'featured' && (\r\n \r\n \r\n \r\n )}\r\n \r\n \r\n {config.imageSize === 'small' && (\r\n \r\n \r\n \r\n \r\n \r\n )}\r\n \r\n \r\n \"\"\r\n \r\n \r\n {(categoryIcon || categoryTitle) && (\r\n \r\n {categoryIcon && }\r\n {categoryTitle && {categoryTitle}}\r\n \r\n )}\r\n {primaryCategory && {primaryCategory}}\r\n {title && (\r\n <>\r\n {categoryIcon || categoryTitle ? (\r\n handleLinkClick(linkObject?.url)}\r\n >\r\n \r\n {title}\r\n {isValidLinkObject(linkObject) && (\r\n \r\n \r\n \r\n \r\n \r\n \r\n )}\r\n \r\n \r\n ) : (\r\n handleLinkClick(linkObject?.url)}\r\n >\r\n \r\n {title}\r\n {isValidLinkObject(linkObject) && (\r\n <TitleIconWrapper>\r\n \r\n <ArrowWrapper>\r\n {linkObject.type !== 'external' && <Arrow ariaHidden={true} />}\r\n {linkObject.type === 'external' && <External ariaHidden={true} />}\r\n </ArrowWrapper>\r\n </TitleIconWrapper>\r\n )}\r\n \r\n \r\n )}\r\n \r\n )}\r\n {description && (\r\n \r\n )}\r\n \r\n \r\n \r\n \r\n \r\n \r\n {secondaryItems.length > 0 && (\r\n \r\n \r\n {secondaryItems.map((item, index) => (\r\n \r\n \r\n \r\n ))}\r\n \r\n \r\n )}\r\n \r\n );\r\n}\r\n\r\nexport default compose(withSitecoreContext(), withEditMode)(FeaturedContent);\r\n\r\n"],"sourceRoot":""}