diff --git a/sanityv3/schemas/components/ThemeSelector/themeColors.ts b/sanityv3/schemas/components/ThemeSelector/themeColors.ts index b87d0923b..fcff2c7b1 100644 --- a/sanityv3/schemas/components/ThemeSelector/themeColors.ts +++ b/sanityv3/schemas/components/ThemeSelector/themeColors.ts @@ -10,7 +10,9 @@ export const themeColors = [ { title: 'Mid Orange', value: 5 }, { title: 'Mid Blue 1', value: 6 }, { title: 'Mid Blue 2', value: 7 }, - { title: 'Mid Green', value: 8 }, + { title: 'Mid Blue 3', value: 8 }, + { title: 'Mid Green', value: 9 }, + { title: 'Mist Blue 2', value: 10 }, ] //Keep in sync with web/pageComponents/shared/textTeaser/theme @@ -91,6 +93,17 @@ export const getColorForTheme = (pattern: number) => { }, } case 8: + return { + background: { + value: defaultColors[6].value, + key: defaultColors[6].key, + }, + highlight: { + value: defaultColors[0].value, + key: defaultColors[0].key, + }, + } + case 9: return { background: { value: defaultColors[7].value, @@ -98,6 +111,17 @@ export const getColorForTheme = (pattern: number) => { }, highlight: {}, } + case 10: + return { + background: { + value: defaultColors[3].value, + key: defaultColors[3].key, + }, + highlight: { + value: defaultColors[6].value, + key: defaultColors[6].key, + }, + } case 0: default: diff --git a/sanityv3/schemas/documents/page.ts b/sanityv3/schemas/documents/page.ts index b869fe417..9387bc508 100644 --- a/sanityv3/schemas/documents/page.ts +++ b/sanityv3/schemas/documents/page.ts @@ -43,6 +43,12 @@ export default { fieldset: 'metadata', }, ...sharedHeroFields, + { + title: 'Is Campain', + name: 'isCampaign', + description: 'Set this to true if the page should be treated as campaign. the header title h1 will be hidden.', + type: 'boolean', + }, { name: 'content', type: 'array', @@ -68,6 +74,8 @@ export default { { type: 'videoPlayer' }, { type: 'videoPlayerCarousel' }, { type: 'table' }, + { type: 'grid' }, + { type: 'campaignBanner' }, Flags.HAS_FORMS && { type: 'form' }, Flags.HAS_NEWS && { type: 'newsList' }, { type: 'stockValuesApi' }, diff --git a/sanityv3/schemas/editors/blockContentType.tsx b/sanityv3/schemas/editors/blockContentType.tsx index e1dc5159b..3a1b19a50 100644 --- a/sanityv3/schemas/editors/blockContentType.tsx +++ b/sanityv3/schemas/editors/blockContentType.tsx @@ -19,6 +19,8 @@ export type BlockContentProps = { attachment?: boolean lists?: boolean smallText?: boolean + largeText?: boolean + extraLargeText?: boolean highlight?: boolean normalTextOverride?: { title: string @@ -48,14 +50,22 @@ const SmallTextRender = (props: any) => { const { children } = props return {children} } +const LargeTextRender = (props: any) => { + const { children } = props + return {children} +} +const ExtraLargeTextRender = (props: any) => { + const { children } = props + return {children} +} const Level2BaseStyle = (props: any) => { const { children } = props - return

{children}

+ return

{children}

} const Level3BaseStyle = (props: any) => { const { children } = props - return

{children}

+ return

{children}

} // H1 not allowed in block content since it should be a document title. @@ -70,6 +80,8 @@ export const configureBlockContent = (options: BlockContentProps = {}): BlockDef externalLink = true, attachment = false, lists = true, + largeText = false, + extraLargeText = false, smallText = true, highlight = false, extendedStyles = [], @@ -119,6 +131,16 @@ export const configureBlockContent = (options: BlockContentProps = {}): BlockDef value: 'smallText', component: SmallTextRender, } + const largeTextConfig = { + title: 'Large text', + value: 'largeText', + component: LargeTextRender, + } + const extraLargeTextConfig = { + title: 'Extra large text', + value: 'extraLargeText', + component: ExtraLargeTextRender, + } const externalLinkConfig = { name: 'link', type: 'object', @@ -267,6 +289,12 @@ export const configureBlockContent = (options: BlockContentProps = {}): BlockDef if (smallText) { config?.styles?.push(smallTextConfig) } + if (largeText) { + config?.styles?.push(largeTextConfig) + } + if (extraLargeText) { + config?.styles?.push(extraLargeTextConfig) + } if (externalLink) { config?.marks?.annotations?.push(externalLinkConfig) diff --git a/sanityv3/schemas/index.js b/sanityv3/schemas/index.js index 253bf2314..1b4a7283c 100644 --- a/sanityv3/schemas/index.js +++ b/sanityv3/schemas/index.js @@ -94,6 +94,14 @@ import card from './objects/card' import cardsList from './objects/cardsList' import backgroundOptions from './objects/background/backgroundOptions' import imageBackground from './objects/background/imageBackground' +import grid from './objects/grid/index' +import span3 from './objects/grid/rowTypes/span3' +import span2and1 from './objects/grid/rowTypes/span2and1' +import gridTextBlock from './objects/grid/cellTypes/gridTextBlock' +import campaignBanner from './objects/campaignBanner' +import gridTeaser from './objects/grid/cellTypes/gridTeaser' +import threeColumns from './objects/grid/rowTypes/3columns' +import gridColorTheme from './objects/grid/theme' const routeSchemas = languages.map(({ name, title }) => { return route(name, title) @@ -182,6 +190,14 @@ const RemainingSchemas = [ cardsList, backgroundOptions, imageBackground, + grid, + span3, + span2and1, + gridTextBlock, + campaignBanner, + gridTeaser, + threeColumns, + gridColorTheme, ] // Then we give our schema to the builder and provide the result to Sanity diff --git a/sanityv3/schemas/objects/campaignBanner/index.tsx b/sanityv3/schemas/objects/campaignBanner/index.tsx new file mode 100644 index 000000000..42e6603b8 --- /dev/null +++ b/sanityv3/schemas/objects/campaignBanner/index.tsx @@ -0,0 +1,130 @@ +/* eslint-disable react/display-name */ +import blocksToText from '../../../helpers/blocksToText' +import { configureBlockContent } from '../../editors' +import { validateCharCounterEditor } from '../../validations/validateCharCounterEditor' + +import type { Image, PortableTextBlock, Reference, Rule, ValidationContext } from 'sanity' +import type { ColorSelectorValue } from '../../components/ColorSelector' + +const blockConfigTitle = { + h2: false, + h3: false, + h4: false, + internalLink: false, + externalLink: false, + attachment: false, + lists: false, + smallText: true, + largeText: true, + extraLargeText: true, +} +const blockConfigContent = { + h2: false, + h3: false, + h4: false, + internalLink: false, + externalLink: false, + attachment: false, + lists: false, + smallText: true, +} + +const blockTitleType = configureBlockContent({ ...blockConfigTitle }) +const blockContentType = configureBlockContent({ ...blockConfigContent }) + +export type CampaignBanner = { + _type: 'campaignBanner' + overline?: string + title?: PortableTextBlock[] + text?: PortableTextBlock[] + image: Image + imagePosition?: string + imageSize?: string + background?: ColorSelectorValue +} + +export default { + name: 'campaignBanner', + title: 'Campaign Banner', + type: 'object', + localize: true, + fieldsets: [ + { + title: 'Background image', + name: 'backgroundImage', + description: 'Settings for the background image', + options: { + collapsible: true, + collapsed: true, + }, + }, + ], + fields: [ + { + name: 'title', + title: 'Title content', + type: 'array', + of: [blockTitleType], + validation: (Rule: Rule) => + Rule.custom((value: PortableTextBlock[], ctx: ValidationContext) => { + return validateCharCounterEditor(value, 600) + }).warning(), + }, + { + name: 'text', + title: 'Text content', + type: 'array', + of: [blockContentType], + validation: (Rule: Rule) => + Rule.custom((value: PortableTextBlock[], ctx: ValidationContext) => { + return validateCharCounterEditor(value, 600) + }).warning(), + }, + { + title: 'Image', + name: 'backgroundImage', + type: 'image', + options: { + hotspot: true, + collapsed: false, + }, + fieldset: 'backgroundImage', + }, + { + name: 'attribution', + title: 'Credit', + description: '', + type: 'string', + }, + { + title: 'Apply light gradient', + name: 'useLightOverlay', + type: 'boolean', + description: 'Applies a white gradient over semi transparent background image.', + fieldset: 'backgroundImage', + }, + { + title: 'Background Color', + description: 'Fallback if no background image. Default is white.', + name: 'backgroundColor', + type: 'colorlist', + fieldset: 'backgroundImage', + }, + ], + preview: { + select: { + title: 'title', + text: 'text', + image: 'backgroundImage.asset', + }, + prepare({ title, text, image }: { title: PortableTextBlock[]; text: PortableTextBlock[]; image: Reference }) { + const plainTitle = blocksToText(title || text) + + return { + title: plainTitle || 'Missing title/content', + subtitle: 'Campaign banner component', + media: image, + } + }, + }, +} diff --git a/sanityv3/schemas/objects/grid/cellTypes/gridTeaser.tsx b/sanityv3/schemas/objects/grid/cellTypes/gridTeaser.tsx new file mode 100644 index 000000000..772dbb45f --- /dev/null +++ b/sanityv3/schemas/objects/grid/cellTypes/gridTeaser.tsx @@ -0,0 +1,163 @@ +/* eslint-disable react/display-name */ +import blocksToText from '../../../../helpers/blocksToText' +import { configureBlockContent } from '../../../editors' +import { validateCharCounterEditor } from '../../../validations/validateCharCounterEditor' + +import type { PortableTextBlock, Reference, Rule, ValidationContext } from 'sanity' +import type { DownloadableImage } from './../../downloadableImage' +import type { DownloadableFile } from '../../files' +import type { ImageWithAlt } from '../../imageWithAlt' +import type { LinkSelector } from '../../linkSelector' +import type { ColorSelectorValue } from '../../../components/ColorSelector' +import { LeftAlignedImage, RightAlignedImage } from '../../../../icons' +import { RadioIconSelector } from '../../../components' + +const blockContentType = configureBlockContent({ + smallText: true, + largeText: true, + extraLargeText: true, +}) + +const imageAlignmentOptions = [ + { value: 'left', icon: LeftAlignedImage }, + { value: 'right', icon: RightAlignedImage }, +] + +export type GridTeaser = { + _type: 'gridTeaser' + content?: PortableTextBlock[] + quote: string + author: string + authorTitle?: string + action?: (LinkSelector | DownloadableFile | DownloadableImage)[] + image: ImageWithAlt + imagePosition?: string + background?: ColorSelectorValue +} + +export default { + name: 'gridTeaser', + title: 'Grid Teaser', + type: 'object', + localize: true, + fieldsets: [ + { + title: 'Quote', + name: 'quote', + description: '', + options: { + collapsible: true, + collapsed: true, + }, + }, + { + name: 'link', + title: 'Link', + description: 'Select either an internal link or external URL.', + }, + { + name: 'design', + title: 'Design options', + }, + ], + fields: [ + { + name: 'content', + title: 'Content', + type: 'array', + of: [blockContentType], + validation: (Rule: Rule) => + Rule.custom((value: PortableTextBlock[], ctx: ValidationContext) => { + return validateCharCounterEditor(value, 600) + }).warning(), + }, + { + name: 'quote', + type: 'text', + title: 'Quote', + description: 'Highlighted quote from the article.', + rows: 5, + }, + { + name: 'author', + type: 'string', + title: 'Name', + }, + { + name: 'authorTitle', + type: 'string', + title: 'Title', + description: 'Optional title for the author.', + }, + { + name: 'action', + title: 'Link/action', + description: 'Select the link or downloadable file for the teaser', + type: 'array', + of: [ + { type: 'linkSelector', title: 'Link' }, + { type: 'downloadableImage', title: 'Downloadable image' }, + { type: 'downloadableFile', title: 'Downloadable file' }, + ], + validation: (Rule: Rule) => Rule.max(1).error('Only one action is permitted'), + }, + { + name: 'image', + title: 'Image', + type: 'imageWithAlt', + validation: (Rule: Rule) => Rule.required(), + }, + { + name: 'imagePosition', + title: 'Image position', + description: + 'On span 3 one can select which side the image will be on for larger screens. On mobile and single column the image will be above', + type: 'string', + components: { + input: function ({ onChange, value }: { onChange: any; value: string }) { + return ( + + ) + }, + }, + }, + { + name: 'theme', + title: 'Theme', + description: 'If no theme set, normal text color is set', + type: 'themeList', + }, + ], + preview: { + select: { + title: 'content', + text: 'quote', + image: 'image.asset', + }, + prepare({ + title, + text, + image, + }: { + title: PortableTextBlock[] + text: PortableTextBlock[] + isBigText: boolean + bigText: PortableTextBlock[] + image: Reference + }) { + const plainTitle = blocksToText(title || text) + + return { + title: plainTitle || 'Missing content/quote', + subtitle: 'Grid Teaser component', + media: image, + } + }, + }, +} diff --git a/sanityv3/schemas/objects/grid/cellTypes/gridTextBlock.tsx b/sanityv3/schemas/objects/grid/cellTypes/gridTextBlock.tsx new file mode 100644 index 000000000..91edbab3e --- /dev/null +++ b/sanityv3/schemas/objects/grid/cellTypes/gridTextBlock.tsx @@ -0,0 +1,83 @@ +/* eslint-disable @typescript-eslint/ban-ts-comment */ +import { text_field } from '@equinor/eds-icons' +import type { PortableTextBlock, Reference, Rule } from 'sanity' +import type { ColorSelectorValue } from '../../../components/ColorSelector' +import blocksToText from '../../../../helpers/blocksToText' +import { EdsIcon } from '../../../../icons' +import { configureBlockContent } from '../../../editors' + +const blockContentType = configureBlockContent({ + smallText: true, + largeText: true, + extraLargeText: true, +}) + +type GridTextBlock = { + content?: string + action?: Reference[] + background?: ColorSelectorValue +} + +export default { + name: 'gridTextBlock', + title: 'Grid Text block', + type: 'object', + fields: [ + { + name: 'content', + title: 'Content', + type: 'array', + of: [blockContentType], + }, + { + title: 'Text Alignment', + name: 'textAlignment', + description: 'Overrides background image alignment', + type: 'string', + options: { + list: [ + { title: 'Left', value: 'left' }, + { title: 'Right', value: 'right' }, + { title: 'Center', value: 'center' }, + ], + }, + initialValue: 'left', + }, + { + name: 'action', + title: 'Link/action', + description: 'Select the link or downloadable file', + type: 'array', + of: [ + { type: 'linkSelector', title: 'Link' }, + { type: 'downloadableImage', title: 'Downloadable image' }, + { type: 'downloadableFile', title: 'Downloadable file' }, + ], + validation: (Rule: Rule) => Rule.max(1).error('Only one action is permitted'), + }, + { + name: 'theme', + type: 'themeList', + }, + { + name: 'backgroundImage', + type: 'imageBackground', + title: 'Background Image', + description: 'Content alignment is ignored on this', + }, + ].filter((e) => e), + preview: { + select: { + title: 'content', + }, + prepare({ title }: { title: PortableTextBlock[] }) { + const plainTitle = blocksToText(title) + + return { + title: plainTitle || 'Missing title/content', + subtitle: 'Grid text block component', + media: EdsIcon(text_field), + } + }, + }, +} diff --git a/sanityv3/schemas/objects/grid/index.tsx b/sanityv3/schemas/objects/grid/index.tsx new file mode 100644 index 000000000..9fe2bc528 --- /dev/null +++ b/sanityv3/schemas/objects/grid/index.tsx @@ -0,0 +1,64 @@ +import { configureBlockContent } from '../../editors' +import { PortableTextBlock } from 'sanity' +import { EdsIcon } from '../../../icons' +import { table_chart } from '@equinor/eds-icons' + +export type Grid = { + _type: 'grid' +} + +export default { + title: 'Grid', + name: 'grid', + type: 'object', + fieldsets: [ + { + title: 'Design options', + name: 'design', + description: 'Some options for design', + options: { + collapsible: true, + collapsed: false, + }, + }, + ], + fields: [ + { + name: 'gridRows', + title: 'Grid rows', + description: 'Add different types of rows', + type: 'array', + of: [ + { + type: 'span3', + title: 'Span 3 columns', + name: 'span3', + }, + { + type: 'span2and1', + title: 'Span 2 columns and one single column', + name: 'span2and1', + }, + { + type: 'threeColumns', + title: '3 columns', + name: 'threeColumns', + }, + ], + }, + ], + preview: { + select: { + title: 'title', + }, + prepare({ title = [] }: { title: PortableTextBlock[] }) { + const plainTitle = 'Grid' + + return { + title: plainTitle, + subtitle: 'Grid component', + media: () => EdsIcon(table_chart), + } + }, + }, +} diff --git a/sanityv3/schemas/objects/grid/rowTypes/3columns.tsx b/sanityv3/schemas/objects/grid/rowTypes/3columns.tsx new file mode 100644 index 000000000..c6a9cefac --- /dev/null +++ b/sanityv3/schemas/objects/grid/rowTypes/3columns.tsx @@ -0,0 +1,41 @@ +import blocksToText from '../../../../helpers/blocksToText' +import { PortableTextBlock, Rule } from 'sanity' +import { EdsIcon } from '../../../../icons' +import { table_chart } from '@equinor/eds-icons' + +export type Span2And1 = { + _type: 'threeColumns' +} + +export default { + title: '3 columns', + name: 'threeColumns', + type: 'object', + fields: [ + { + name: 'columns', + title: 'List of 3 columns', + type: 'array', + of: [ + { name: 'gridTextBlock', type: 'gridTextBlock', title: 'Text block' }, + { type: 'figure' }, + { type: 'gridTeaser' }, + ], + validation: (Rule: Rule) => Rule.max(3).error('Only three is permitted'), + }, + ], + preview: { + select: { + title: 'title', + }, + prepare({ title = [] }: { title: PortableTextBlock[] }) { + const plainTitle = title.length > 0 ? blocksToText(title) : '3 columns type' + + return { + title: plainTitle, + subtitle: '3 columns component', + media: () => EdsIcon(table_chart), + } + }, + }, +} diff --git a/sanityv3/schemas/objects/grid/rowTypes/span2and1.tsx b/sanityv3/schemas/objects/grid/rowTypes/span2and1.tsx new file mode 100644 index 000000000..791e9357c --- /dev/null +++ b/sanityv3/schemas/objects/grid/rowTypes/span2and1.tsx @@ -0,0 +1,61 @@ +import blocksToText from '../../../../helpers/blocksToText' +import { configureBlockContent } from '../../../editors' + +import { PortableTextBlock, Rule } from 'sanity' +import { EdsIcon } from '../../../../icons' +import { table_chart } from '@equinor/eds-icons' + +export type Span2And1 = { + _type: 'span2and1' +} + +export default { + title: 'Span 2 and 1 column', + name: 'span2and1', + type: 'object', + fields: [ + { + name: 'span2', + title: 'The span 2 content', + type: 'array', + of: [ + { name: 'gridTextBlock', type: 'gridTextBlock', title: 'Text block' }, + { type: 'videoPlayer' }, + { type: 'iframe' }, + { type: 'figure' }, + ], + validation: (Rule: Rule) => Rule.max(1).error('Only one is permitted'), + }, + { + title: 'Align Span 2 on the right', + name: 'alignSpan2Right', + description: 'Will align the span 2 on the right side. If not selected on the left', + type: 'boolean', + }, + { + name: 'singleColumn', + title: 'The single column content', + type: 'array', + of: [ + { name: 'gridTextBlock', type: 'gridTextBlock', title: 'Text block' }, + { type: 'figure' }, + { type: 'gridTeaser' }, + ], + validation: (Rule: Rule) => Rule.max(1).error('Only one is permitted'), + }, + ], + preview: { + select: { + title: 'title', + }, + prepare({ title = [] }: { title: PortableTextBlock[] }) { + const plainTitle = title.length > 0 ? blocksToText(title) : 'Span 2 and 1 type' + + return { + title: plainTitle, + subtitle: 'Span 2 and 1 component', + media: () => EdsIcon(table_chart), + } + }, + }, +} diff --git a/sanityv3/schemas/objects/grid/rowTypes/span3.tsx b/sanityv3/schemas/objects/grid/rowTypes/span3.tsx new file mode 100644 index 000000000..82bd7afa4 --- /dev/null +++ b/sanityv3/schemas/objects/grid/rowTypes/span3.tsx @@ -0,0 +1,44 @@ +import blocksToText from '../../../../helpers/blocksToText' +import { PortableTextBlock, Rule } from 'sanity' +import { EdsIcon } from '../../../../icons' +import { table_chart } from '@equinor/eds-icons' + +export type Span3 = { + _type: 'span3' +} + +export default { + title: 'Span 3', + name: 'span3', + type: 'object', + fields: [ + { + name: 'content', + title: 'Span 3 type', + description: 'Select one type of content for span 3 type', + type: 'array', + of: [ + { name: 'gridTextBlock', type: 'gridTextBlock', title: 'Text block' }, + { type: 'videoPlayer' }, + { type: 'iframe' }, + { type: 'figure' }, + { type: 'gridTeaser' }, + ], + validation: (Rule: Rule) => Rule.max(1).error('Only one is permitted'), + }, + ], + preview: { + select: { + title: 'title', + }, + prepare({ title = [] }: { title: PortableTextBlock[] }) { + const plainTitle = title.length > 0 ? blocksToText(title) : 'Span 3 type' + + return { + title: plainTitle, + subtitle: 'Span 3 component', + media: () => EdsIcon(table_chart), + } + }, + }, +} diff --git a/sanityv3/schemas/objects/grid/theme.tsx b/sanityv3/schemas/objects/grid/theme.tsx new file mode 100644 index 000000000..6d00e2da7 --- /dev/null +++ b/sanityv3/schemas/objects/grid/theme.tsx @@ -0,0 +1,15 @@ +export default { + name: 'gridColorTheme', + title: 'Grid Color theme', + description: 'Text color on background color. Call to actions will be black or white text', + type: 'string', + options: { + list: [ + { title: 'normal', value: 'normal' }, + { title: 'red on white', value: 'redOnWhite' }, + { title: 'white on dark blue', value: 'whiteOnDarkBlue' }, + { title: 'dark blue on light blue', value: 'darkBlueOnLightBlue' }, + ], + }, + initialValue: 'normal', +} diff --git a/web/core/Link/ReadMoreLink.tsx b/web/core/Link/ReadMoreLink.tsx index 98066ab05..04351242c 100644 --- a/web/core/Link/ReadMoreLink.tsx +++ b/web/core/Link/ReadMoreLink.tsx @@ -19,7 +19,7 @@ export const ReadMoreLink = forwardRef(fun group inline-flex align-baseline - w-max + w-fit text-slate-80 leading-0 `, @@ -27,6 +27,7 @@ export const ReadMoreLink = forwardRef(fun ) const contentClassNames = ` relative + w-fit after:content-[''] after:block after:absolute diff --git a/web/lib/queries/common/pageContentFields.ts b/web/lib/queries/common/pageContentFields.ts index 474ffd3ac..b70a97acf 100644 --- a/web/lib/queries/common/pageContentFields.ts +++ b/web/lib/queries/common/pageContentFields.ts @@ -1,3 +1,4 @@ +import gridContentFields from '../gridContentFields' import { iframeCarouselFields } from '../iframeCarouselFields' import { tableFields } from '../table' import { videoPlayerCarouselFields } from '../videoPlayerCarouselFields' @@ -512,6 +513,58 @@ _type == "keyNumbers" =>{ ${background}, }, }, + _type == "grid" => { + "type": _type, + "id": _key, + title, + "gridRows": gridRows[]{ + "type": _type, + "id": _key, + _type == "span3" => { + "type": _type, + "id": _key, + "content": content[0] { + ${gridContentFields} + }, + }, + _type == "span2and1" => { + "type": _type, + "id": _key, + alignSpan2Right, + "span2": { + "content": span2[0] { + ${gridContentFields} + } + }, + "singleColumn": { + "content": singleColumn[0] { + ${gridContentFields} + }, + } + }, + _type == "threeColumns" => { + "type": _type, + "id": _key, + "columns": columns[]{ + ${gridContentFields} + } + } + }, + }, + _type == "campaignBanner" => { + "type": _type, + "id": _key, + title, + "text": text[]{..., ${markDefs}}, + "backgroundImage": backgroundImage { + ..., + "extension": asset-> extension + }, + attribution, + useLightOverlay, + "backgroundColor": coalesce(backgroundColor.title, 'White'), + "backgroundUtility":coalesce(backgroundColor.key, ""), + }, ` export default pageContentFields diff --git a/web/lib/queries/gridContentFields.ts b/web/lib/queries/gridContentFields.ts new file mode 100644 index 000000000..3e0841675 --- /dev/null +++ b/web/lib/queries/gridContentFields.ts @@ -0,0 +1,82 @@ +import downloadableFileFields from './common/actions/downloadableFileFields' +import downloadableImageFields from './common/actions/downloadableImageFields' +import linkSelectorFields from './common/actions/linkSelectorFields' +import background from './common/background' +import markDefs from './common/blockEditorMarks' +import { videoPlayerFields } from './videoPlayerFields' + +const gridContentFields = /* groq */ ` +_type == "videoPlayer" => { + ${videoPlayerFields} +}, +_type == "iframe" => { +"type": _type, +"id": _key, +title, +ingress[]{ +..., +${markDefs}, +}, +description[]{ +..., +${markDefs}, +}, +frameTitle, +"action": action[0]{ +${linkSelectorFields}, +}, +url, +"cookiePolicy": coalesce(cookiePolicy, 'none'), +"designOptions": { +"aspectRatio": coalesce(aspectRatio, '16:9'), +${background}, +height, +}, +}, +_type == "gridTextBlock"=>{ +"type": _type, +"id": _key, +"theme": coalesce(theme.value, null), +textAlignment, +content[]{..., ${markDefs}}, +"action": action[0]{ +${linkSelectorFields}, +${downloadableFileFields}, +${downloadableImageFields}, +}, +backgroundImage +}, +_type == "figure"=>{ +"type": _type, +"id": _key, +"figure": figure{ +_type, +image, +attribution, +caption +}, +"designOptions": { +${background}, +}, +}, +_type == "gridTeaser" => { + "type": _type, + "id": _key, + content[]{..., ${markDefs}}, + author, + authorTitle, + quote, + "imagePosition": coalesce(imagePosition, 'left'), + "theme": coalesce(theme.value, null), + "image": image { + ..., + "extension": asset-> extension + }, + "action": action[0]{ + ${linkSelectorFields}, + ${downloadableFileFields}, + ${downloadableImageFields}, + }, + }, +` +export default gridContentFields diff --git a/web/lib/queries/routes.ts b/web/lib/queries/routes.ts index eab45faab..21bfd0355 100644 --- a/web/lib/queries/routes.ts +++ b/web/lib/queries/routes.ts @@ -23,6 +23,9 @@ export const routeQuery = /* groq */ ` "seoAndSome": content->${seoAndSomeFields}, "hero": content->${heroFields}, "template": content->_type, + content->_type == "page" => { + "isCampaign":content->isCampaign + }, "breadcrumbs": { ${breadcrumbsQuery} }, diff --git a/web/pageComponents/pageTemplates/TopicPage.tsx b/web/pageComponents/pageTemplates/TopicPage.tsx index 2f726302b..4e69f39b3 100644 --- a/web/pageComponents/pageTemplates/TopicPage.tsx +++ b/web/pageComponents/pageTemplates/TopicPage.tsx @@ -39,6 +39,7 @@ type TopicPageProps = { const TopicPage = ({ data }: TopicPageProps) => { const titleStyles = useSharedTitleStyles(data?.hero?.type, data?.content?.[0]) const { breadcrumbs } = data + return ( <> { pageTitle={data?.title} /> - + {!data?.isCampaign && ( + + )} {breadcrumbs && breadcrumbs?.enableBreadcrumbs && ( { /> )} - {data.hero.type !== HeroTypes.DEFAULT && ( + {data.hero.type !== HeroTypes.DEFAULT && !data?.isCampaign && ( )} diff --git a/web/pageComponents/pageTemplates/shared/SharedPageContent.tsx b/web/pageComponents/pageTemplates/shared/SharedPageContent.tsx index 00293120c..69da7f9ae 100644 --- a/web/pageComponents/pageTemplates/shared/SharedPageContent.tsx +++ b/web/pageComponents/pageTemplates/shared/SharedPageContent.tsx @@ -51,10 +51,14 @@ import { TextTeaserData, KeyNumbersData, CardsListData, + GridData, + CampaignBannerData, } from '../../../types/types' +import Grid from '@sections/Grid/Grid' +import { CampaignBanner } from '@sections/CampaignBanner' // How could we do this for several different component types? -type ComponentProps = +export type ComponentProps = | TeaserData | TextBlockData | FullWidthImageData @@ -286,6 +290,10 @@ export const PageContent = ({ data }: PageContentProps) => { return ( ) + case 'grid': + return + case 'campaignBanner': + return default: return null } diff --git a/web/pageComponents/shared/VideoPlayer.tsx b/web/pageComponents/shared/VideoPlayer.tsx index 3408cd509..a9f645c09 100644 --- a/web/pageComponents/shared/VideoPlayer.tsx +++ b/web/pageComponents/shared/VideoPlayer.tsx @@ -13,7 +13,7 @@ import TitleText from '../shared/portableText/TitleText' import { urlFor } from '../../common/helpers' import IngressText from './portableText/IngressText' import { ButtonLink } from './ButtonLink' -import { twMerge } from 'tailwind-merge' +import envisTwMerge from '../../twMerge' import { VideoJS } from '@components/VideoJsPlayer' const DynamicVideoJsComponent = dynamic>( @@ -29,7 +29,12 @@ const StyledHeading = styled(TitleText)` text-align: left; ` -const StyledFigure = styled.figure<{ $allowFullScreen?: boolean; $aspectRatio?: string; $height?: number }>` +const StyledFigure = styled.figure<{ + $allowFullScreen?: boolean + $aspectRatio?: string + $height?: number + $overrideHeight?: string +}>` margin: 0 auto; position: relative; video::-webkit-media-controls-fullscreen-button { @@ -39,7 +44,7 @@ const StyledFigure = styled.figure<{ $allowFullScreen?: boolean; $aspectRatio?: }} } - ${({ $aspectRatio, $height }) => { + ${({ $aspectRatio, $height, $overrideHeight }) => { if (!$height) { switch ($aspectRatio) { case VideoPlayerRatios['1:1']: @@ -61,7 +66,7 @@ const StyledFigure = styled.figure<{ $allowFullScreen?: boolean; $aspectRatio?: } case VideoPlayerRatios['16:9']: return { - height: '56.25%', + height: $overrideHeight ?? '56.25%', width: '100%', } case VideoPlayerRatios['9:16']: @@ -128,15 +133,17 @@ type VideoJsComponentType = { video: VideoType videoControls: VideoControlsType designOptions: VideoDesignOptionsType + height?: string } -export const VideoJsComponent = ({ video, videoControls, designOptions }: VideoJsComponentType) => { +export const VideoJsComponent = ({ video, videoControls, designOptions, height }: VideoJsComponentType) => { const { width: w, height: h } = getThumbnailRatio(designOptions.aspectRatio) return ( { +const VideoPlayer = ({ + anchor, + data, + className, + bgClassName, + height, +}: { + data: VideoPlayerData + anchor?: string + className?: string + bgClassName?: string + height?: string +}) => { const { title, ingress, action, video, videoControls, designOptions } = data return ( - -
+ +
{title && } {ingress && ( @@ -166,7 +185,7 @@ const VideoPlayer = ({ anchor, data, className }: { data: VideoPlayerData; ancho )} - +
) diff --git a/web/pageComponents/shared/portableText/Blocks.tsx b/web/pageComponents/shared/portableText/Blocks.tsx index 31aec9d7c..7581e6d40 100644 --- a/web/pageComponents/shared/portableText/Blocks.tsx +++ b/web/pageComponents/shared/portableText/Blocks.tsx @@ -21,8 +21,21 @@ type TypeProps = { children?: React.ReactNode } -const defaultBlocks: BlockType = { +/* const defaultBlocks: BlockType = { smallText: ({ children }: TypeProps) =>

{children}

, + largeText: ({ children,className }: TypeProps) =>

{children}

, + extraLargeText: ({ children, className }: TypeProps) => { + return

{children}

+ }, +} */ +const defaultBlocks = (className?: string): BlockType => { + return { + smallText: ({ children }: TypeProps) => {children}, + largeText: ({ children }: TypeProps) => {children}, + extraLargeText: ({ children }: TypeProps) => { + return {children} + }, + } } const defaultMarks: MarkType = { @@ -68,6 +81,7 @@ type BlockProps = { * Override other styling to the wrapping block */ className?: string + blocksClassName?: string /** * If needed to connect with aria-describedby and such */ @@ -84,6 +98,7 @@ export default function Blocks({ types, components, proseClassName = '', + blocksClassName = '', className = '', id, }: BlockProps) { @@ -93,7 +108,7 @@ export default function Blocks({ ...defaultComponents, block: { ...defaultComponents.block, - ...defaultBlocks, + ...defaultBlocks(blocksClassName), ...blocks, } as BlockType, marks: { diff --git a/web/pageComponents/shared/textTeaser/theme.ts b/web/pageComponents/shared/textTeaser/theme.ts index 097750938..c3dccdcc3 100644 --- a/web/pageComponents/shared/textTeaser/theme.ts +++ b/web/pageComponents/shared/textTeaser/theme.ts @@ -1,13 +1,12 @@ +import { ColorKeyTokens } from '../../../styles/colorKeyToUtilityMap' import { BackgroundColours } from '../../../types' export type ThemeColors = { background: BackgroundColours + backgroundUtility?: keyof ColorKeyTokens highlight?: string + textUtility?: keyof ColorKeyTokens dark?: boolean - utility?: { - background?: string - highlight?: string - } } //Keep in sync with sanityv3/schemas/components/ThemeSelector/themeColors /*export const getColorForTheme = (pattern: number): ThemeColors => { @@ -108,10 +107,27 @@ export const getColorForTheme = (pattern: number): ThemeColors => { case 7: return { background: 'Mid Blue', highlight: 'var(--bg-mid-yellow)' } case 8: + return { + background: 'Mid Blue', + backgroundUtility: 'blue-50', + highlight: 'var(--bg-white)', + textUtility: 'white-100', + } + case 9: return { background: 'Mid Green', highlight: 'black' } + case 10: + return { + background: 'Mist Blue', + backgroundUtility: 'mist-blue-100', + textUtility: 'blue-50', + } case 0: default: - return { background: 'White' } + return { + background: 'White', + backgroundUtility: 'white-100', + textUtility: 'energy-red-100', + } } } diff --git a/web/sections/CampaignBanner/CampaignBanner.tsx b/web/sections/CampaignBanner/CampaignBanner.tsx new file mode 100644 index 000000000..76c48c84a --- /dev/null +++ b/web/sections/CampaignBanner/CampaignBanner.tsx @@ -0,0 +1,111 @@ +import { forwardRef, HTMLAttributes } from 'react' +import { useSanityLoader } from '../../lib/hooks/useSanityLoader' +import { twMerge } from 'tailwind-merge' +import { CampaignBannerData } from '../../types/types' +import Blocks from '../../pageComponents/shared/portableText/Blocks' +import { PortableTextBlock } from '@portabletext/types' +import isEmpty from '../../pageComponents/shared/portableText/helpers/isEmpty' +import { BlockType } from '../../pageComponents/shared/portableText/helpers/defaultSerializers' + +const DEFAULT_MAX_WIDTH = 1920 + +/* eslint-disable @typescript-eslint/ban-ts-comment */ +const campaignTitleBlocks: BlockType = { + //@ts-ignore + smallText: ({ children }: PortableTextBlock) => {<>{children}}, + //@ts-ignore + largeText: ({ children }: PortableTextBlock) => ( + {<>{children}} + ), + //@ts-ignore + extraLargeText: ({ children }: PortableTextBlock) => { + return ( + + {<>{children}} + + ) + }, + //@ts-ignore + normal: ({ children }: PortableTextBlock) => { + if (isEmpty(children)) return null + return ( + + <>{children} + + ) + }, +} +/* eslint-enable @typescript-eslint/ban-ts-comment */ + +export type CampaignBannerProps = { + data: CampaignBannerData + className?: string +} & HTMLAttributes + +const CampaignBanner = forwardRef(function CampaignBanner({ data, className }, ref) { + const { + title, + text, + backgroundImage, + backgroundColor, + backgroundUtility, + useLightOverlay = false, + attribution, + } = data + console.log('CampaignBanner', data) + const props = useSanityLoader(backgroundImage, DEFAULT_MAX_WIDTH, undefined) + const src = props?.src + + const backgroundClassNames = twMerge( + `[container:inline-size] + relative + ${useLightOverlay ? '' : 'dark'} + w-full + 2xl:aspect-[10/3] + bg-local + bg-center + bg-no-repeat + bg-cover + mb-40 + `, + className, + ) + + const scrimGradient = useLightOverlay ? `white-center-gradient ` : `black-center-gradient` + + return ( +
+ {/** Scrim */} +
+
+
+

+ +

+
+
+ +
+
+
+
+ ) +}) +export default CampaignBanner diff --git a/web/sections/CampaignBanner/index.ts b/web/sections/CampaignBanner/index.ts new file mode 100644 index 000000000..b132edd2a --- /dev/null +++ b/web/sections/CampaignBanner/index.ts @@ -0,0 +1,2 @@ +//"use client"; +export { default as CampaignBanner, type CampaignBannerProps } from './CampaignBanner' diff --git a/web/sections/Grid/Grid.tsx b/web/sections/Grid/Grid.tsx new file mode 100644 index 000000000..47f8e6ed2 --- /dev/null +++ b/web/sections/Grid/Grid.tsx @@ -0,0 +1,49 @@ +import { twMerge } from 'tailwind-merge' +import { GridData } from '../../types/types' +import { HTMLAttributes, forwardRef } from 'react' +import Span3 from './Span3' +import Span2And1 from './Span2And1' +import ThreeColumns from './ThreeColumns' + +export type GridProps = { + data: GridData + anchor?: string + className?: string +} & HTMLAttributes + +const Grid = forwardRef(function Grid({ data, anchor, className = '', ...rest }, ref) { + const { gridRows = [] } = data + return ( +
+ {gridRows.map((row) => { + return ( + <> + {row?.type === 'span3' && } + {row?.type === 'span2and1' && } + {row?.type === 'threeColumns' && } + + ) + })} +
+ ) +}) + +export default Grid diff --git a/web/sections/Grid/GridFigure.tsx b/web/sections/Grid/GridFigure.tsx new file mode 100644 index 000000000..42a33120e --- /dev/null +++ b/web/sections/Grid/GridFigure.tsx @@ -0,0 +1,21 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +import Image from '../../pageComponents/shared/SanityImage' +import type { FigureData } from '../../types/types' + +type GridFigureProps = { + data: FigureData + className?: string +} + +const GridFigure = ({ data }: GridFigureProps) => { + console.log('data', data) + const { figure, designOptions } = data + const { image, caption, attribution } = figure + return ( +
+ +
+ ) +} + +export default GridFigure diff --git a/web/sections/Grid/GridLinkArrow.tsx b/web/sections/Grid/GridLinkArrow.tsx new file mode 100644 index 000000000..8bbbfac3a --- /dev/null +++ b/web/sections/Grid/GridLinkArrow.tsx @@ -0,0 +1,70 @@ +/* eslint-disable @typescript-eslint/ban-ts-comment */ +import { twMerge } from 'tailwind-merge' +import { getUrlFromAction } from '../../common/helpers' +import { BaseLink } from '@core/Link' +import { getLocaleFromName } from '../../lib/localization' +import { ArrowRight } from '../../icons' +import { LinkData } from '../../types/types' +import { getColorForTheme } from '../../pageComponents/shared/textTeaser/theme' +import { colorKeyToUtilityMap } from '../../styles/colorKeyToUtilityMap' + +//type Theme = 'redOnWhite' | 'whiteOnDarkBlue' | 'darkBlueOnLightBlue' + +type GridLinkArrowProps = { + theme: string + action?: LinkData + className?: string +} + +const GridLinkArrow = ({ theme, action, className }: GridLinkArrowProps) => { + const url = action && getUrlFromAction(action) + //@ts-ignore + const { backgroundUtility, textUtility } = getColorForTheme(theme) + let bgClassName = '' + let textClassName = '' + if (theme !== null) { + //@ts-ignore + bgClassName = colorKeyToUtilityMap[backgroundUtility]?.background + //@ts-ignore + textClassName = colorKeyToUtilityMap[textUtility]?.text + } + + const variantClassName = () => { + switch (backgroundUtility) { + case 'white-100': + return 'text-energy-red-100 hover:bg-energy-red-100 hover:text-white-100 focus-visible:bg-energy-red-100 focus-visible:text-white-100' + case 'mist-blue-100': + return `${textClassName} hover:bg-white-100 hover:${textClassName} focus-visible:bg-white-100 focus-visible:${textClassName}` + case 'blue-50': + return `text-white-100 hover:bg-white-100 hover:text-blue-50 focus-visible:bg-white-100 focus-visible:text-blue-50` + default: + return 'text-white-100 hover:bg-white-100 hover:text-slate-80 focus-visible:bg-white-100 focus-visible:text-slate-80' + } + } + + return ( + <> + {action && url && ( +
+ + {`${action.label} ${ + action.extension ? `(${action.extension.toUpperCase()})` : '' + }`} + + +
+ )} + + ) +} + +export default GridLinkArrow diff --git a/web/sections/Grid/GridTeaser.tsx b/web/sections/Grid/GridTeaser.tsx new file mode 100644 index 000000000..d618f8074 --- /dev/null +++ b/web/sections/Grid/GridTeaser.tsx @@ -0,0 +1,105 @@ +/* eslint-disable @typescript-eslint/ban-ts-comment */ +import { forwardRef, HTMLAttributes } from 'react' +import { twMerge } from 'tailwind-merge' +import Img from 'next/image' +import { GridTeaserData } from '../../types/types' +import { urlFor } from '../../common/helpers' +import { gridContentBlocks } from './GridTextBlock' +import { RowType } from './mapGridContent' +import { PortableText } from '@portabletext/react' +import GridLinkArrow from './GridLinkArrow' +import { colorKeyToUtilityMap } from '../../styles/colorKeyToUtilityMap' +import { getColorForTheme } from '../../pageComponents/shared/textTeaser/theme' + +export type GridTeaserProps = { + data: GridTeaserData + rowType?: RowType + className?: string +} & HTMLAttributes + +export const GridTeaser = forwardRef(function GridTeaser({ data, rowType }, ref) { + const { image, action, content, quote, author, authorTitle, theme, background, imagePosition } = data + const imageSrc = urlFor(image).size(1200, 800).auto('format').toString() + const altTag = image?.isDecorative ? '' : image?.alt || '' + //@ts-ignore + const { backgroundUtility, textUtility } = getColorForTheme(theme) + + let bgClassName = '' + let textClassName = '' + if (theme !== null) { + //@ts-ignore + bgClassName = colorKeyToUtilityMap[backgroundUtility]?.background + //@ts-ignore + textClassName = colorKeyToUtilityMap[textUtility]?.text + } + const aligment = `${imagePosition === 'left' ? '' : '-order-1 text-left'}` + + return ( +
+ {image && ( +
+ {altTag} +
+ )} + +
+
+ {content && ( + + )} + {quote && ( +
+
+ + Quote symbol + + + {quote &&

{quote}

} +
+
+ {author && {author}} + {authorTitle &&
{authorTitle}
} +
+
+ )} +
+ {/*@ts-ignore*/} + {action && } +
+
+ ) +}) diff --git a/web/sections/Grid/GridTextBlock.tsx b/web/sections/Grid/GridTextBlock.tsx new file mode 100644 index 000000000..b29bfdc62 --- /dev/null +++ b/web/sections/Grid/GridTextBlock.tsx @@ -0,0 +1,85 @@ +import { twMerge } from 'tailwind-merge' +import { BlockType } from '../../pageComponents/shared/portableText/helpers/defaultSerializers' +import { PortableTextBlock } from '@portabletext/types' +import { PortableText } from '@portabletext/react' +import { getUrlFromAction } from '../../common/helpers' +import GridLinkArrow from './GridLinkArrow' +import { colorKeyToUtilityMap } from '../../styles/colorKeyToUtilityMap' +import { getColorForTheme } from '../../pageComponents/shared/textTeaser/theme' + +type Theme = 'redOnWhite' | 'whiteOnDarkBlue' | 'darkBlueOnLightBlue' + +type GridTextBlockProps = { + data: any + className?: string +} + +/* eslint-disable @typescript-eslint/ban-ts-comment */ +export const gridContentBlocks: BlockType = { + //@ts-ignore + smallText: ({ children }: PortableTextBlock) =>
{<>{children}}
, + //@ts-ignore + largeText: ({ children }: PortableTextBlock) =>
{<>{children}}
, + //@ts-ignore + extraLargeText: ({ children }: PortableTextBlock) => { + return
{<>{children}}
+ }, + //@ts-ignore + normal: ({ children }: PortableTextBlock) => { + return ( + + <>{children} + + ) + }, +} +/* eslint-enable @typescript-eslint/ban-ts-comment */ + +const GridTextBlock = ({ data, className }: GridTextBlockProps) => { + const { action, content, textAlignment = 'left', theme, backgroundImage } = data + const { backgroundUtility, textUtility } = getColorForTheme(theme) + + const url = action && getUrlFromAction(action) + + const contentAlignment = { + center: 'justify-center text-center', + right: 'justify-center text-start xl:items-end xl:text-end xl:ml-auto', + left: 'justify-center text-start xl:items-start xl:mr-auto', + } + + /* eslint-disable @typescript-eslint/ban-ts-comment */ + //@ts-ignore + const contentClassNames = twMerge(`${contentAlignment[textAlignment]}`, className) + let bgClassName = '' + let textClassName = '' + if (theme !== null) { + //@ts-ignore + bgClassName = colorKeyToUtilityMap[backgroundUtility]?.background + //@ts-ignore + textClassName = colorKeyToUtilityMap[textUtility]?.text + } + + return ( +
+
+ {content && ( + + )} +
+ {action && url && } +
+ ) +} + +export default GridTextBlock diff --git a/web/sections/Grid/Span2And1.tsx b/web/sections/Grid/Span2And1.tsx new file mode 100644 index 000000000..9b801e9c4 --- /dev/null +++ b/web/sections/Grid/Span2And1.tsx @@ -0,0 +1,30 @@ +import { twMerge } from 'tailwind-merge' +import { Fragment, HTMLAttributes, forwardRef } from 'react' +import { mapGridContent } from './mapGridContent' + +export type Span2And1Props = { + data: any + className?: string +} & HTMLAttributes + +const Span2And1 = forwardRef(function Span2And1({ data, className = '' }, ref) { + const { singleColumn, span2, alignSpan2Right = false } = data + const borderStyling = `shadow-md` //`border border-moss-green-60` + return ( + + {alignSpan2Right ? ( + <> +
{mapGridContent(singleColumn?.content)}
+
{mapGridContent(span2?.content)}
+ + ) : ( + <> +
{mapGridContent(span2?.content)}
+
{mapGridContent(singleColumn?.content)}
+ + )} +
+ ) +}) + +export default Span2And1 diff --git a/web/sections/Grid/Span3.tsx b/web/sections/Grid/Span3.tsx new file mode 100644 index 000000000..f051b638d --- /dev/null +++ b/web/sections/Grid/Span3.tsx @@ -0,0 +1,31 @@ +import { twMerge } from 'tailwind-merge' +import { HTMLAttributes, forwardRef } from 'react' +import { mapGridContent } from './mapGridContent' + +export type Span3Props = { + data: any + className?: string +} & HTMLAttributes + +const Span3 = forwardRef(function Span3({ data, className = '', ...rest }, ref) { + console.log('data?.content', data?.content) + return ( +
+ {mapGridContent(data?.content, 'span3')} +
+ ) +}) + +export default Span3 diff --git a/web/sections/Grid/ThreeColumns.tsx b/web/sections/Grid/ThreeColumns.tsx new file mode 100644 index 000000000..f8d99017b --- /dev/null +++ b/web/sections/Grid/ThreeColumns.tsx @@ -0,0 +1,29 @@ +import { twMerge } from 'tailwind-merge' +import { Fragment, HTMLAttributes, forwardRef } from 'react' +import { mapGridContent } from './mapGridContent' + +export type ThreeColumnsProps = { + data: any + className?: string +} & HTMLAttributes + +const ThreeColumns = forwardRef(function ThreeColumns( + { data, className = '' }, + ref, +) { + const { columns = [] } = data + const borderStyling = `shadow-md` //`border border-moss-green-60` + return ( + + {columns.map((column: any) => { + return ( +
+ {mapGridContent(column)} +
+ ) + })} +
+ ) +}) + +export default ThreeColumns diff --git a/web/sections/Grid/index.ts b/web/sections/Grid/index.ts new file mode 100644 index 000000000..9af6487d1 --- /dev/null +++ b/web/sections/Grid/index.ts @@ -0,0 +1,2 @@ +//"use client"; +export { default as Grid, type GridProps } from './Grid' diff --git a/web/sections/Grid/mapGridContent.tsx b/web/sections/Grid/mapGridContent.tsx new file mode 100644 index 000000000..322e9d5a0 --- /dev/null +++ b/web/sections/Grid/mapGridContent.tsx @@ -0,0 +1,36 @@ +import { ComponentProps } from '../../pageComponents/pageTemplates/shared/SharedPageContent' +import { FigureData, IFrameData, VideoPlayerData } from '../../types/types' +import Figure from '../../pageComponents/topicPages/Figure' +import IFrame from '../../pageComponents/topicPages/IFrame' +import VideoPlayer from '../../pageComponents/shared/VideoPlayer' +import GridTextBlock from './GridTextBlock' +import { GridTeaser } from './GridTeaser' +import GridFigure from './GridFigure' + +export type RowType = 'span3' | 'span2and1' | undefined + +export const mapGridContent = (data: ComponentProps, rowType?: RowType): React.ReactNode => { + switch (data.type) { + case 'gridTextBlock': + return + case 'gridTeaser': + return + case 'figure': + return + case 'iframe': + return