From 8956edbd2f628bded7bd74ca44c2b1980768e32e Mon Sep 17 00:00:00 2001 From: Christel Westerberg Date: Mon, 1 Jul 2024 17:09:48 +0200 Subject: [PATCH 1/4] feat: add imagevault images to RTE --- components/Current/Aside/Puff/index.tsx | 3 +- components/Current/Blocks/Text.tsx | 3 + components/Current/Preamble/index.tsx | 3 +- .../Current/currentRenderOptions.module.css | 6 + components/Current/currentRenderOptions.tsx | 474 ++++++++++++++++++ components/JsonToHtml/index.tsx | 7 +- components/JsonToHtml/jsontohtml.module.css | 6 +- components/JsonToHtml/renderOptions.tsx | 85 +++- types/rte/attrs.ts | 10 +- types/rte/enums.ts | 1 + types/rte/node.ts | 12 +- 11 files changed, 577 insertions(+), 33 deletions(-) create mode 100644 components/Current/currentRenderOptions.module.css create mode 100644 components/Current/currentRenderOptions.tsx diff --git a/components/Current/Aside/Puff/index.tsx b/components/Current/Aside/Puff/index.tsx index f435c442d..a08f99605 100644 --- a/components/Current/Aside/Puff/index.tsx +++ b/components/Current/Aside/Puff/index.tsx @@ -6,6 +6,7 @@ import { Button } from "@scandic-hotels/design-system/current" import Image from "@/components/Image" import JsonToHtml from "@/components/JsonToHtml" +import { renderOptions as currentRenderOption } from "./../../currentRenderOptions" import { renderOptions } from "./renderOptions" import styles from "./puff.module.css" @@ -44,7 +45,7 @@ export default function Puff({
diff --git a/components/Current/Blocks/Text.tsx b/components/Current/Blocks/Text.tsx index d79bf1518..4d20bd1fc 100644 --- a/components/Current/Blocks/Text.tsx +++ b/components/Current/Blocks/Text.tsx @@ -1,5 +1,7 @@ import JsonToHtml from "@/components/JsonToHtml" +import { renderOptions } from "./../currentRenderOptions" + import type { TextProps } from "@/types/components/current/blocks/text" export default function Text({ text }: TextProps) { @@ -7,6 +9,7 @@ export default function Text({ text }: TextProps) { ) } diff --git a/components/Current/Preamble/index.tsx b/components/Current/Preamble/index.tsx index d615a6da6..ef0dc682a 100644 --- a/components/Current/Preamble/index.tsx +++ b/components/Current/Preamble/index.tsx @@ -1,5 +1,6 @@ import JsonToHtml from "@/components/JsonToHtml" +import { renderOptions as currentRenderOption } from "./../currentRenderOptions" import Breadcrumbs from "./Breadcrumbs" import { renderOptions } from "./renderOptions" @@ -27,7 +28,7 @@ export default function Preamble({ ) : null} diff --git a/components/Current/currentRenderOptions.module.css b/components/Current/currentRenderOptions.module.css new file mode 100644 index 000000000..2e564ffac --- /dev/null +++ b/components/Current/currentRenderOptions.module.css @@ -0,0 +1,6 @@ +.image { + height: auto; + margin-bottom: var(--Spacing-x2); + max-width: 100%; + object-fit: cover; +} diff --git a/components/Current/currentRenderOptions.tsx b/components/Current/currentRenderOptions.tsx new file mode 100644 index 000000000..ae8c465be --- /dev/null +++ b/components/Current/currentRenderOptions.tsx @@ -0,0 +1,474 @@ +import Image from "@/components/Image" +import Link from "@/components/TempDesignSystem/Link" + +import styles from "./currentRenderOptions.module.css" + +import type { EmbedByUid } from "@/types/components/jsontohtml" +import { EmbedEnum } from "@/types/requests/utils/embeds" +import type { Attributes } from "@/types/rte/attrs" +import { RTEItemTypeEnum, RTETypeEnum } from "@/types/rte/enums" +import type { + RTEDefaultNode, + RTENext, + RTENode, + RTERegularNode, +} from "@/types/rte/node" +import { RTEMarkType } from "@/types/rte/node" +import type { RenderOptions } from "@/types/rte/option" + +function extractPossibleAttributes(attrs: Attributes | undefined) { + if (!attrs) return {} + const props: Record = {} + if (attrs.id) { + props.id = attrs.id + } + + if (attrs.class) { + props.className = attrs.class + } else if (attrs["class-name"]) { + props.className = attrs["class-name"] + } else if (attrs.classname) { + props.className = attrs.classname + } else if (attrs?.style?.["text-align"]) { + props.style = { + textAlign: attrs?.style?.["text-align"], + } + } + + return props +} + +export const renderOptions: RenderOptions = { + [RTETypeEnum.a]: ( + node: RTERegularNode, + embeds: EmbedByUid, + next: RTENext, + fullRenderOptions: RenderOptions + ) => { + if (node.attrs.url) { + const props = extractPossibleAttributes(node.attrs) + return ( + + {next(node.children, embeds, fullRenderOptions)} + + ) + } + return null + }, + + [RTETypeEnum.blockquote]: ( + node: RTEDefaultNode, + embeds: EmbedByUid, + next: RTENext, + fullRenderOptions: RenderOptions + ) => { + const props = extractPossibleAttributes(node.attrs) + return ( +
+ {next(node.children, embeds, fullRenderOptions)} +
+ ) + }, + + [RTETypeEnum.code]: ( + node: RTEDefaultNode, + embeds: EmbedByUid, + next: RTENext, + fullRenderOptions: RenderOptions + ) => { + const props = extractPossibleAttributes(node.attrs) + return ( + + {next(node.children, embeds, fullRenderOptions)} + + ) + }, + + [RTETypeEnum.embed]: ( + node: RTEDefaultNode, + embeds: EmbedByUid, + next: RTENext, + fullRenderOptions: RenderOptions + ) => { + const props = extractPossibleAttributes(node.attrs) + if (node.attrs.src) { + props.src = node.attrs.src + } + if (node.attrs.url) { + props.src = node.attrs.url + } + if (!props.src) { + return null + } + return ( + + ) + }, + + [RTETypeEnum.h1]: ( + node: RTEDefaultNode, + embeds: EmbedByUid, + next: RTENext, + fullRenderOptions: RenderOptions + ) => { + const props = extractPossibleAttributes(node.attrs) + return ( +

+ {next(node.children, embeds, fullRenderOptions)} +

+ ) + }, + + [RTETypeEnum.h2]: ( + node: RTEDefaultNode, + embeds: EmbedByUid, + next: RTENext, + fullRenderOptions: RenderOptions + ) => { + const props = extractPossibleAttributes(node.attrs) + return ( +

+ {next(node.children, embeds, fullRenderOptions)} +

+ ) + }, + + [RTETypeEnum.h3]: ( + node: RTEDefaultNode, + embeds: EmbedByUid, + next: RTENext, + fullRenderOptions: RenderOptions + ) => { + const props = extractPossibleAttributes(node.attrs) + return ( +

+ {next(node.children, embeds, fullRenderOptions)} +

+ ) + }, + + [RTETypeEnum.h4]: ( + node: RTEDefaultNode, + embeds: EmbedByUid, + next: RTENext, + fullRenderOptions: RenderOptions + ) => { + const props = extractPossibleAttributes(node.attrs) + return ( +

+ {next(node.children, embeds, fullRenderOptions)} +

+ ) + }, + + [RTETypeEnum.h5]: ( + node: RTEDefaultNode, + embeds: EmbedByUid, + next: RTENext, + fullRenderOptions: RenderOptions + ) => { + const props = extractPossibleAttributes(node.attrs) + return ( +
+ {next(node.children, embeds, fullRenderOptions)} +
+ ) + }, + + [RTETypeEnum.h6]: ( + node: RTEDefaultNode, + embeds: EmbedByUid, + next: RTENext, + fullRenderOptions: RenderOptions + ) => { + const props = extractPossibleAttributes(node.attrs) + return ( +
+ {next(node.children, embeds, fullRenderOptions)} +
+ ) + }, + + [RTETypeEnum.hr]: () => { + return
+ }, + + [RTETypeEnum.li]: ( + node: RTEDefaultNode, + embeds: EmbedByUid, + next: RTENext, + fullRenderOptions: RenderOptions + ) => { + const props = extractPossibleAttributes(node.attrs) + return ( +
  • + {next(node.children, embeds, fullRenderOptions)} +
  • + ) + }, + + [RTETypeEnum.ol]: ( + node: RTEDefaultNode, + embeds: EmbedByUid, + next: RTENext, + fullRenderOptions: RenderOptions + ) => { + const props = extractPossibleAttributes(node.attrs) + return ( +
      + {next(node.children, embeds, fullRenderOptions)} +
    + ) + }, + + [RTETypeEnum.p]: ( + node: RTEDefaultNode, + embeds: EmbedByUid, + next: RTENext, + fullRenderOptions: RenderOptions + ) => { + const props = extractPossibleAttributes(node.attrs) + return ( +

    + {next(node.children, embeds, fullRenderOptions)} +

    + ) + }, + + [RTETypeEnum.reference]: ( + node: RTENode, + embeds: EmbedByUid, + next: RTENext, + fullRenderOptions: RenderOptions + ) => { + if ("attrs" in node) { + const type = node.attrs.type + if (type === RTEItemTypeEnum.asset) { + const image = embeds?.[node?.attrs?.["asset-uid"]] + if (image?.node.__typename === EmbedEnum.SysAsset) { + const alt = image?.node?.title ?? node.attrs.alt + const alignment = node.attrs?.style?.["text-align"] + ? { + alignSelf: node.attrs?.style?.["text-align"], + } + : {} + return ( + {alt} + ) + } + } else { + const props = extractPossibleAttributes(node.attrs) + const href = node.attrs?.locale + ? `/${node.attrs.locale}${node.attrs.href}` + : node.attrs.href + return ( + + {next(node.children, embeds, fullRenderOptions)} + + ) + } + } + + return null + }, + + [RTETypeEnum.table]: ( + node: RTEDefaultNode, + embeds: EmbedByUid, + next: RTENext, + fullRenderOptions: RenderOptions + ) => { + const props = extractPossibleAttributes(node.attrs) + return ( + + {next(node.children, embeds, fullRenderOptions)} +
    + ) + }, + + [RTETypeEnum.thead]: ( + node: RTEDefaultNode, + embeds: EmbedByUid, + next: RTENext, + fullRenderOptions: RenderOptions + ) => { + const props = extractPossibleAttributes(node.attrs) + return ( + + {next(node.children, embeds, fullRenderOptions)} + + ) + }, + + [RTETypeEnum.tbody]: ( + node: RTEDefaultNode, + embeds: EmbedByUid, + next: RTENext, + fullRenderOptions: RenderOptions + ) => { + const props = extractPossibleAttributes(node.attrs) + return ( + + {next(node.children, embeds, fullRenderOptions)} + + ) + }, + + [RTETypeEnum.tfoot]: ( + node: RTEDefaultNode, + embeds: EmbedByUid, + next: RTENext, + fullRenderOptions: RenderOptions + ) => { + const props = extractPossibleAttributes(node.attrs) + return ( + + {next(node.children, embeds, fullRenderOptions)} + + ) + }, + + [RTETypeEnum.tr]: ( + node: RTEDefaultNode, + embeds: EmbedByUid, + next: RTENext, + fullRenderOptions: RenderOptions + ) => { + const props = extractPossibleAttributes(node.attrs) + return ( + + {next(node.children, embeds, fullRenderOptions)} + + ) + }, + + [RTETypeEnum.th]: ( + node: RTEDefaultNode, + embeds: EmbedByUid, + next: RTENext, + fullRenderOptions: RenderOptions + ) => { + const props = extractPossibleAttributes(node.attrs) + return ( + + {next(node.children, embeds, fullRenderOptions)} + + ) + }, + + [RTETypeEnum.td]: ( + node: RTEDefaultNode, + embeds: EmbedByUid, + next: RTENext, + fullRenderOptions: RenderOptions + ) => { + const props = extractPossibleAttributes(node.attrs) + return ( + + {next(node.children, embeds, fullRenderOptions)} + + ) + }, + + [RTETypeEnum.ul]: ( + node: RTEDefaultNode, + embeds: EmbedByUid, + next: RTENext, + fullRenderOptions: RenderOptions + ) => { + const props = extractPossibleAttributes(node.attrs) + return ( +
      + {next(node.children, embeds, fullRenderOptions)} +
    + ) + }, + + /** TextNode wrappers */ + [RTEMarkType.bold]: (children: React.ReactNode) => { + return {children} + }, + + [RTEMarkType.italic]: (children: React.ReactNode) => { + return {children} + }, + + [RTEMarkType.underline]: (children: React.ReactNode) => { + return {children} + }, + + [RTEMarkType.strikethrough]: (children: React.ReactNode) => { + return {children} + }, + + [RTEMarkType.inlineCode]: (children: React.ReactNode) => { + return {children} + }, + + [RTEMarkType.subscript]: (children: React.ReactNode) => { + return {children} + }, + + [RTEMarkType.superscript]: (children: React.ReactNode) => { + return {children} + }, + + [RTEMarkType.break]: (children: React.ReactNode) => { + return ( + <> +
    + {children} + + ) + }, + + [RTEMarkType.classnameOrId]: ( + children: React.ReactNode, + className?: string, + id?: string + ) => { + let props = { + className, + id, + } + if (!className) { + delete props.className + } + if (!id) { + delete props.id + } + return ( + + {children} + + ) + }, + + /** + * Contentstack can return something called `default` as seen here in their + * own SDK (https://github.com/contentstack/contentstack-utils-javascript/blob/master/src/options/default-node-options.ts#L89) + */ + default: ( + node: RTEDefaultNode, + embeds: EmbedByUid, + next: RTENext, + fullRenderOptions: RenderOptions + ) => { + return next(node.children, embeds, fullRenderOptions) + }, +} diff --git a/components/JsonToHtml/index.tsx b/components/JsonToHtml/index.tsx index 9beebccae..689bd0460 100644 --- a/components/JsonToHtml/index.tsx +++ b/components/JsonToHtml/index.tsx @@ -10,5 +10,10 @@ export default function JsonToHtml({ if (!Array.isArray(nodes) || !nodes.length) { return null } - return <>{nodesToHtml(nodes, embeds, renderOptions).filter(Boolean)} + console.log({ nodes }) + return ( +
    + {nodesToHtml(nodes, embeds, renderOptions).filter(Boolean)} +
    + ) } diff --git a/components/JsonToHtml/jsontohtml.module.css b/components/JsonToHtml/jsontohtml.module.css index 2e564ffac..178802905 100644 --- a/components/JsonToHtml/jsontohtml.module.css +++ b/components/JsonToHtml/jsontohtml.module.css @@ -1,6 +1,8 @@ .image { - height: auto; - margin-bottom: var(--Spacing-x2); max-width: 100%; + width: 100%; + height: 365px; object-fit: cover; + border-radius: var(--Corner-radius-Medium); + padding: var(--Spacing-x1) var(--Spacing-x0); } diff --git a/components/JsonToHtml/renderOptions.tsx b/components/JsonToHtml/renderOptions.tsx index 1b745815e..cd748e58e 100644 --- a/components/JsonToHtml/renderOptions.tsx +++ b/components/JsonToHtml/renderOptions.tsx @@ -1,14 +1,23 @@ import Image from "@/components/Image" import Link from "@/components/TempDesignSystem/Link" +import { insertResponseToImageVaultAsset } from "@/utils/imageVault" + +import Divider from "../TempDesignSystem/Divider" +import BiroScript from "../TempDesignSystem/Text/BiroScript" +import Body from "../TempDesignSystem/Text/Body" +import Caption from "../TempDesignSystem/Text/Caption" +import Subtitle from "../TempDesignSystem/Text/Subtitle" +import Title from "../TempDesignSystem/Text/Title" import styles from "./jsontohtml.module.css" import type { EmbedByUid } from "@/types/components/jsontohtml" import { EmbedEnum } from "@/types/requests/utils/embeds" -import type { Attributes } from "@/types/rte/attrs" +import type { Attributes, RTEImageVaultAttrs } from "@/types/rte/attrs" import { RTEItemTypeEnum, RTETypeEnum } from "@/types/rte/enums" import type { RTEDefaultNode, + RTEImageNode, RTENext, RTENode, RTERegularNode, @@ -69,9 +78,9 @@ export const renderOptions: RenderOptions = { ) => { const props = extractPossibleAttributes(node.attrs) return ( -
    + {next(node.children, embeds, fullRenderOptions)} -
    + ) }, @@ -120,9 +129,9 @@ export const renderOptions: RenderOptions = { ) => { const props = extractPossibleAttributes(node.attrs) return ( -

    + {next(node.children, embeds, fullRenderOptions)} - </h1> + ) }, @@ -134,9 +143,9 @@ export const renderOptions: RenderOptions = { ) => { const props = extractPossibleAttributes(node.attrs) return ( -

    + {next(node.children, embeds, fullRenderOptions)} - </h2> + ) }, @@ -148,9 +157,9 @@ export const renderOptions: RenderOptions = { ) => { const props = extractPossibleAttributes(node.attrs) return ( -

    + {next(node.children, embeds, fullRenderOptions)} - </h3> + ) }, @@ -162,9 +171,9 @@ export const renderOptions: RenderOptions = { ) => { const props = extractPossibleAttributes(node.attrs) return ( -

    + {next(node.children, embeds, fullRenderOptions)} - </h4> + ) }, @@ -176,9 +185,9 @@ export const renderOptions: RenderOptions = { ) => { const props = extractPossibleAttributes(node.attrs) return ( -

    + {next(node.children, embeds, fullRenderOptions)} - </h5> + ) }, @@ -190,14 +199,14 @@ export const renderOptions: RenderOptions = { ) => { const props = extractPossibleAttributes(node.attrs) return ( -
    - {next(node.children, embeds, fullRenderOptions)} -
    + +
    {next(node.children, embeds, fullRenderOptions)}
    +
    ) }, [RTETypeEnum.hr]: () => { - return
    + return }, [RTETypeEnum.li]: ( @@ -236,9 +245,9 @@ export const renderOptions: RenderOptions = { ) => { const props = extractPossibleAttributes(node.attrs) return ( -

    + {next(node.children, embeds, fullRenderOptions)} -

    + ) }, @@ -254,11 +263,7 @@ export const renderOptions: RenderOptions = { const image = embeds?.[node?.attrs?.["asset-uid"]] if (image?.node.__typename === EmbedEnum.SysAsset) { const alt = image?.node?.title ?? node.attrs.alt - const alignment = node.attrs?.style?.["text-align"] - ? { - alignSelf: node.attrs?.style?.["text-align"], - } - : {} + const props = extractPossibleAttributes(node.attrs) return ( ) } @@ -287,6 +292,36 @@ export const renderOptions: RenderOptions = { return null }, + [RTETypeEnum.ImageVault]: (node: RTEImageNode) => { + if ("attrs" in node) { + const type = node.type + if (type === RTETypeEnum.ImageVault) { + const attrs = node.attrs as RTEImageVaultAttrs + const image = insertResponseToImageVaultAsset(attrs) + const alt = image.meta.alt ?? image.title + + const height = parseInt(attrs.height.replaceAll("px", "")) + const width = parseInt(attrs.width.replaceAll("px", "")) + const props = extractPossibleAttributes(attrs) + return ( +
    + {alt} + {image.meta.caption} +
    + ) + } + } + + return null + }, + [RTETypeEnum.table]: ( node: RTEDefaultNode, embeds: EmbedByUid, diff --git a/types/rte/attrs.ts b/types/rte/attrs.ts index f8bb36e30..dd658872d 100644 --- a/types/rte/attrs.ts +++ b/types/rte/attrs.ts @@ -1,6 +1,8 @@ +import { InsertResponse } from "../components/imageVaultImage" import { RTEItemTypeEnum } from "./enums" -import type { EmbedTypesEnum, RTEItemType } from "./enums" + import type { Lang } from "@/constants/languages" +import type { EmbedTypesEnum, RTEItemType } from "./enums" export interface Attributes { [key: string]: any @@ -36,3 +38,9 @@ export interface RTELinkAttrs extends Attributes { target: HTMLAnchorElement["target"] type: RTEItemTypeEnum.entry } + +export interface RTEImageVaultAttrs extends Attributes, InsertResponse { + height: string + width: string + style: string[] +} diff --git a/types/rte/enums.ts b/types/rte/enums.ts index b5eb2a6a1..271c800aa 100644 --- a/types/rte/enums.ts +++ b/types/rte/enums.ts @@ -36,6 +36,7 @@ export enum RTETypeEnum { thead = "thead", tr = "tr", ul = "ul", + ImageVault = "ImageVault", } export type RTEType = keyof typeof RTETypeEnum diff --git a/types/rte/node.ts b/types/rte/node.ts index c762f33bb..dca0f9281 100644 --- a/types/rte/node.ts +++ b/types/rte/node.ts @@ -5,6 +5,7 @@ import type { Attributes, RTEAnchorAttrs, RTEAssetAttrs, + RTEImageVaultAttrs, RTELinkAttrs, } from "./attrs" import type { RenderOptions } from "./option" @@ -36,6 +37,11 @@ export interface RTEReferenceLinkNode extends RTEDefaultNode { attrs: RTELinkAttrs } +export interface RTEImageVaultNode extends RTEDefaultNode { + attrs: RTEImageVaultAttrs + type: RTETypeEnum.ImageVault +} + export enum RTEMarkType { bold = "bold", break = "break", @@ -58,9 +64,11 @@ export type RTETextNode = RTETextNodeOptionalKeys & { text: string } -export type RTERegularNode = RTEDefaultNode | RTEAnchorNode +export type RTERegularNode = RTEDefaultNode | RTEAnchorNode | RTEImageVaultNode -export type RTEReferenceNode = RTEDefaultNode | RTEAnchorNode +export type RTEImageNode = RTEDefaultNode | RTEImageVaultNode + +export type RTEReferenceNode = RTEAnchorNode export type RTENode = RTERegularNode | RTEReferenceNode | RTETextNode From 55a71f001f514fcb7f38220df3e420eced80fa9f Mon Sep 17 00:00:00 2001 From: Christel Westerberg Date: Thu, 4 Jul 2024 07:59:03 +0200 Subject: [PATCH 2/4] fix: change name of myPages link vaariant to underscored --- .../Loyalty/Sidebar/JoinLoyalty/Contact/ContactRow/index.tsx | 2 +- components/TempDesignSystem/Link/link.module.css | 2 +- components/TempDesignSystem/Link/variants.ts | 2 +- components/TempDesignSystem/LoyaltyCard/index.tsx | 2 +- components/TempDesignSystem/Text/Title/variants.ts | 1 - 5 files changed, 4 insertions(+), 5 deletions(-) diff --git a/components/Loyalty/Sidebar/JoinLoyalty/Contact/ContactRow/index.tsx b/components/Loyalty/Sidebar/JoinLoyalty/Contact/ContactRow/index.tsx index 827153aa1..ee9f95ac1 100644 --- a/components/Loyalty/Sidebar/JoinLoyalty/Contact/ContactRow/index.tsx +++ b/components/Loyalty/Sidebar/JoinLoyalty/Contact/ContactRow/index.tsx @@ -44,7 +44,7 @@ export default async function ContactRow({ contact }: ContactRowProps) { diff --git a/components/TempDesignSystem/Link/link.module.css b/components/TempDesignSystem/Link/link.module.css index bcf90ec33..94a3c22ec 100644 --- a/components/TempDesignSystem/Link/link.module.css +++ b/components/TempDesignSystem/Link/link.module.css @@ -20,7 +20,7 @@ gap: var(--Spacing-x-half); } -.myPage { +.underscored { font-family: var(--typography-Body-Underlined-fontFamily); font-size: var(--typography-Body-Underlined-fontSize); font-weight: var(--typography-Body-Underlined-fontWeight); diff --git a/components/TempDesignSystem/Link/variants.ts b/components/TempDesignSystem/Link/variants.ts index cffb3dda4..df9d2c52f 100644 --- a/components/TempDesignSystem/Link/variants.ts +++ b/components/TempDesignSystem/Link/variants.ts @@ -23,7 +23,7 @@ export const linkVariants = cva(styles.link, { breadcrumb: styles.breadcrumb, default: styles.default, icon: styles.icon, - myPage: styles.myPage, + underscored: styles.underscored, myPageMobileDropdown: styles.myPageMobileDropdown, shortcut: styles.shortcut, sidebar: styles.sidebar, diff --git a/components/TempDesignSystem/LoyaltyCard/index.tsx b/components/TempDesignSystem/LoyaltyCard/index.tsx index db060ef42..b6dbd0008 100644 --- a/components/TempDesignSystem/LoyaltyCard/index.tsx +++ b/components/TempDesignSystem/LoyaltyCard/index.tsx @@ -49,7 +49,7 @@ export default function LoyaltyCard({ color="burgundy" href={link.href} target={link.openInNewTab ? "_blank" : undefined} - variant="myPage" + variant="underscored" > Date: Thu, 4 Jul 2024 10:33:49 +0200 Subject: [PATCH 3/4] fix: add imageContainer reference in rte --- .../ImageContainer/imageContainer.module.css | 23 ++++ components/ImageContainer/index.tsx | 36 +++++ components/JsonToHtml/index.tsx | 1 - components/JsonToHtml/jsontohtml.module.css | 6 +- components/JsonToHtml/renderOptions.tsx | 128 +++++++++++++++--- components/JsonToHtml/utils.tsx | 7 +- lib/graphql/Query/LoyaltyPage.graphql | 15 ++ .../contentstack/loyaltyPage/output.ts | 19 ++- types/components/imageContainer.ts | 6 + types/requests/embeds.ts | 3 +- types/requests/imageContainer.ts | 14 ++ types/requests/rte.ts | 6 + types/requests/utils/embeds.ts | 4 + types/rte/enums.ts | 9 ++ 14 files changed, 252 insertions(+), 25 deletions(-) create mode 100644 components/ImageContainer/imageContainer.module.css create mode 100644 components/ImageContainer/index.tsx create mode 100644 types/components/imageContainer.ts create mode 100644 types/requests/imageContainer.ts create mode 100644 types/requests/rte.ts diff --git a/components/ImageContainer/imageContainer.module.css b/components/ImageContainer/imageContainer.module.css new file mode 100644 index 000000000..bde762010 --- /dev/null +++ b/components/ImageContainer/imageContainer.module.css @@ -0,0 +1,23 @@ +.container { + display: grid; + gap: var(--Spacing-x2); + width: 100%; + grid-template-columns: auto; +} + +.image { + max-width: 100%; + height: 365px; + object-fit: cover; + border-radius: var(--Corner-radius-Medium); +} + +@media screen and (min-width: 768px) { + .container { + grid-template-columns: 1fr 1fr; + } + + .image { + margin: var(--Spacing-x1) var(--Spacing-x0); + } +} diff --git a/components/ImageContainer/index.tsx b/components/ImageContainer/index.tsx new file mode 100644 index 000000000..c7e23d621 --- /dev/null +++ b/components/ImageContainer/index.tsx @@ -0,0 +1,36 @@ +import Image from "../Image" +import Caption from "../TempDesignSystem/Text/Caption" + +import styles from "./imageContainer.module.css" + +import type { ImageContainerProps } from "@/types/components/imageContainer" + +export default function ImageContainer({ + leftImage, + rightImage, +}: ImageContainerProps) { + return ( +
    +
    + {leftImage.meta.alt + {leftImage.meta.caption} +
    +
    + {rightImage.meta.alt + {leftImage.meta.caption} +
    +
    + ) +} diff --git a/components/JsonToHtml/index.tsx b/components/JsonToHtml/index.tsx index 689bd0460..48ab55c93 100644 --- a/components/JsonToHtml/index.tsx +++ b/components/JsonToHtml/index.tsx @@ -10,7 +10,6 @@ export default function JsonToHtml({ if (!Array.isArray(nodes) || !nodes.length) { return null } - console.log({ nodes }) return (
    {nodesToHtml(nodes, embeds, renderOptions).filter(Boolean)} diff --git a/components/JsonToHtml/jsontohtml.module.css b/components/JsonToHtml/jsontohtml.module.css index 178802905..25263c850 100644 --- a/components/JsonToHtml/jsontohtml.module.css +++ b/components/JsonToHtml/jsontohtml.module.css @@ -4,5 +4,9 @@ height: 365px; object-fit: cover; border-radius: var(--Corner-radius-Medium); - padding: var(--Spacing-x1) var(--Spacing-x0); + margin: var(--Spacing-x1) var(--Spacing-x0); +} + +.li { + margin-left: var(--Spacing-x3); } diff --git a/components/JsonToHtml/renderOptions.tsx b/components/JsonToHtml/renderOptions.tsx index cd748e58e..70cd1f40a 100644 --- a/components/JsonToHtml/renderOptions.tsx +++ b/components/JsonToHtml/renderOptions.tsx @@ -2,25 +2,33 @@ import Image from "@/components/Image" import Link from "@/components/TempDesignSystem/Link" import { insertResponseToImageVaultAsset } from "@/utils/imageVault" +import ImageContainer from "../ImageContainer" import Divider from "../TempDesignSystem/Divider" import BiroScript from "../TempDesignSystem/Text/BiroScript" import Body from "../TempDesignSystem/Text/Body" import Caption from "../TempDesignSystem/Text/Caption" +import Footnote from "../TempDesignSystem/Text/Footnote" import Subtitle from "../TempDesignSystem/Text/Subtitle" import Title from "../TempDesignSystem/Text/Title" +import { hasAvailableFormat } from "./utils" import styles from "./jsontohtml.module.css" import type { EmbedByUid } from "@/types/components/jsontohtml" import { EmbedEnum } from "@/types/requests/utils/embeds" import type { Attributes, RTEImageVaultAttrs } from "@/types/rte/attrs" -import { RTEItemTypeEnum, RTETypeEnum } from "@/types/rte/enums" +import { + AvailableFormatEnum, + RTEItemTypeEnum, + RTETypeEnum, +} from "@/types/rte/enums" import type { RTEDefaultNode, RTEImageNode, RTENext, RTENode, RTERegularNode, + RTETextNode, } from "@/types/rte/node" import { RTEMarkType } from "@/types/rte/node" import type { RenderOptions } from "@/types/rte/option" @@ -57,14 +65,16 @@ export const renderOptions: RenderOptions = { if (node.attrs.url) { const props = extractPossibleAttributes(node.attrs) return ( - {next(node.children, embeds, fullRenderOptions)} - + ) } return null @@ -217,7 +227,7 @@ export const renderOptions: RenderOptions = { ) => { const props = extractPossibleAttributes(node.attrs) return ( -
  • +
  • {next(node.children, embeds, fullRenderOptions)}
  • ) @@ -244,6 +254,21 @@ export const renderOptions: RenderOptions = { fullRenderOptions: RenderOptions ) => { const props = extractPossibleAttributes(node.attrs) + + const hasFormat = node.children.some((item) => + hasAvailableFormat((item as RTETextNode).classname) + ) + + // If a child node has an available format as className, we wrap it in a + // span and render the children with the correct component + if (hasFormat) { + return ( + + {next(node.children, embeds, fullRenderOptions)} + + ) + } + return ( {next(node.children, embeds, fullRenderOptions)} @@ -264,11 +289,11 @@ export const renderOptions: RenderOptions = { if (image?.node.__typename === EmbedEnum.SysAsset) { const alt = image?.node?.title ?? node.attrs.alt const props = extractPossibleAttributes(node.attrs) + props.className = styles.image return ( {alt} ) } - } else { - const props = extractPossibleAttributes(node.attrs) - const href = node.attrs?.locale - ? `/${node.attrs.locale}${node.attrs.href}` - : node.attrs.href - return ( - - {next(node.children, embeds, fullRenderOptions)} - - ) + } else if (type === RTEItemTypeEnum.entry) { + const entry = embeds?.[node?.attrs?.["entry-uid"]] + + if (entry?.node.__typename === EmbedEnum.ImageContainer) { + const leftImage = insertResponseToImageVaultAsset( + entry.node.image_left + ) + const rightImage = insertResponseToImageVaultAsset( + entry.node.image_right + ) + return ( + + ) + } else { + // If entry is not an ImageContainer, it is a page and we return it as a link + const props = extractPossibleAttributes(node.attrs) + const href = node.attrs?.locale + ? `/${node.attrs.locale}${node.attrs.href}` + : node.attrs.href + return ( + + {next(node.children, embeds, fullRenderOptions)} + + ) + } } } @@ -300,7 +346,6 @@ export const renderOptions: RenderOptions = { const image = insertResponseToImageVaultAsset(attrs) const alt = image.meta.alt ?? image.title - const height = parseInt(attrs.height.replaceAll("px", "")) const width = parseInt(attrs.width.replaceAll("px", "")) const props = extractPossibleAttributes(attrs) return ( @@ -308,7 +353,7 @@ export const renderOptions: RenderOptions = { {alt} + {children} + + ) + } + + if (className === AvailableFormatEnum.caption) { + return ( + + {children} + + ) + } + + if (className === AvailableFormatEnum["script-1"]) { + return ( + + {children} + + ) + } + + if (className === AvailableFormatEnum["script-2"]) { + return ( + + {children} + + ) + } + + if (className === AvailableFormatEnum["subtitle-1"]) { + return ( + + {children} + + ) + } + if (className === AvailableFormatEnum["subtitle-2"]) { + return ( + + {children} + + ) + } return ( {children} diff --git a/components/JsonToHtml/utils.tsx b/components/JsonToHtml/utils.tsx index f368e380c..bf798829b 100644 --- a/components/JsonToHtml/utils.tsx +++ b/components/JsonToHtml/utils.tsx @@ -3,7 +3,7 @@ import { renderOptions } from "./renderOptions" import type { EmbedByUid } from "@/types/components/jsontohtml" import type { Embeds } from "@/types/requests/embeds" import type { Node } from "@/types/requests/utils/edges" -import { RTETypeEnum } from "@/types/rte/enums" +import { AvailableFormatEnum, RTETypeEnum } from "@/types/rte/enums" import type { RTENode, RTERenderOptionComponent, @@ -74,7 +74,6 @@ export function textNodeToHtml( if (node.bold) { text = (fullRenderOptions[RTEMarkType.bold] as RTERenderMark)(text) } - return text } @@ -86,6 +85,10 @@ function next( return nodeChildrenToHtml(nodes, embeds, fullRenderOptions) } +export function hasAvailableFormat(className?: string) { + return className && Object.keys(AvailableFormatEnum).includes(className) +} + export function nodeToHtml( node: RTENode, embeds: EmbedByUid, diff --git a/lib/graphql/Query/LoyaltyPage.graphql b/lib/graphql/Query/LoyaltyPage.graphql index 25a577afb..5ef8479f8 100644 --- a/lib/graphql/Query/LoyaltyPage.graphql +++ b/lib/graphql/Query/LoyaltyPage.graphql @@ -70,6 +70,15 @@ query GetLoyaltyPage($locale: String!, $uid: String!) { __typename ...LoyaltyPageLink ...ContentPageLink + ...Image + ... on ImageContainer { + title + image_left + image_right + system { + uid + } + } } } totalCount @@ -223,6 +232,12 @@ query GetLoyaltyPageRefs($locale: String!, $uid: String!) { ...System } } + ... on ImageContainer { + __typename + system { + ...System + } + } } } } diff --git a/server/routers/contentstack/loyaltyPage/output.ts b/server/routers/contentstack/loyaltyPage/output.ts index 0f2196b76..8c1374ff2 100644 --- a/server/routers/contentstack/loyaltyPage/output.ts +++ b/server/routers/contentstack/loyaltyPage/output.ts @@ -13,6 +13,7 @@ import { } from "@/types/components/loyalty/enums" import { Embeds } from "@/types/requests/embeds" import { PageLinkEnum } from "@/types/requests/pageLinks" +import { RTEEmbedsEnum } from "@/types/requests/rte" import { EdgesWithTotalCount } from "@/types/requests/utils/edges" import { RTEDocument } from "@/types/rte/node" @@ -272,6 +273,20 @@ const pageConnectionRefs = z.object({ ), }) +const rteConnectionRefs = z.object({ + edges: z.array( + z.object({ + node: z.object({ + __typename: z.nativeEnum(RTEEmbedsEnum), + system: z.object({ + content_type_uid: z.string(), + uid: z.string(), + }), + }), + }) + ), +}) + const cardBlockRefs = z.object({ __typename: z.literal(LoyaltyCardsGridEnum.Card), primary_button: z @@ -349,7 +364,7 @@ const loyaltyPageBlockTextContentRefs = z.object({ __typename: z.literal(LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksContent), content: z.object({ content: z.object({ - embedded_itemsConnection: pageConnectionRefs, + embedded_itemsConnection: rteConnectionRefs, }), }), }) @@ -365,7 +380,7 @@ const loyaltyPageSidebarTextContentRef = z.object({ __typename: z.literal(SidebarTypenameEnum.LoyaltyPageSidebarContent), content: z.object({ content: z.object({ - embedded_itemsConnection: pageConnectionRefs, + embedded_itemsConnection: rteConnectionRefs, }), }), }) diff --git a/types/components/imageContainer.ts b/types/components/imageContainer.ts new file mode 100644 index 000000000..6f8e75393 --- /dev/null +++ b/types/components/imageContainer.ts @@ -0,0 +1,6 @@ +import type { ImageVaultAsset } from "./imageVaultImage" + +export type ImageContainerProps = { + leftImage: ImageVaultAsset + rightImage: ImageVaultAsset +} diff --git a/types/requests/embeds.ts b/types/requests/embeds.ts index 11e863fd5..714c8746f 100644 --- a/types/requests/embeds.ts +++ b/types/requests/embeds.ts @@ -1,3 +1,4 @@ +import type { ImageContainer } from "./imageContainer" import type { SysAsset } from "./utils/asset" -export type Embeds = SysAsset +export type Embeds = SysAsset | ImageContainer diff --git a/types/requests/imageContainer.ts b/types/requests/imageContainer.ts new file mode 100644 index 000000000..3eb85023c --- /dev/null +++ b/types/requests/imageContainer.ts @@ -0,0 +1,14 @@ +import { InsertResponse } from "../components/imageVaultImage" +import { EmbedEnum } from "./utils/embeds" +import { Typename } from "./utils/typename" + +export type ImageContainer = Typename< + { + image_left: InsertResponse + image_right: InsertResponse + system: { + uid: string + } + }, + EmbedEnum.ImageContainer +> diff --git a/types/requests/rte.ts b/types/requests/rte.ts new file mode 100644 index 000000000..f6e18b41a --- /dev/null +++ b/types/requests/rte.ts @@ -0,0 +1,6 @@ +export enum RTEEmbedsEnum { + AccountPage = "AccountPage", + ContentPage = "ContentPage", + LoyaltyPage = "LoyaltyPage", + ImageContainer = "ImageContainer", +} diff --git a/types/requests/utils/embeds.ts b/types/requests/utils/embeds.ts index 8cdb3fcaa..527564882 100644 --- a/types/requests/utils/embeds.ts +++ b/types/requests/utils/embeds.ts @@ -1,6 +1,10 @@ export enum EmbedEnum { CurrentBlocksPage = "CurrentBlocksPage", SysAsset = "SysAsset", + ImageContainer = "ImageContainer", + LoyaltyPage = "LoyaltyPage", + AccountPage = "AccountPage", + ContentPage = "ContentPage", } export type Embed = keyof typeof EmbedEnum diff --git a/types/rte/enums.ts b/types/rte/enums.ts index 271c800aa..feb7834da 100644 --- a/types/rte/enums.ts +++ b/types/rte/enums.ts @@ -47,3 +47,12 @@ export enum RTEItemTypeEnum { } export type RTEItemType = keyof typeof RTEItemTypeEnum + +export enum AvailableFormatEnum { + "script-1" = "script-1", + "script-2" = "script-2", + "footnote" = "footnote", + "caption" = "caption", + "subtitle-1" = "subtitle-1", + "subtitle-2" = "subtitle-2", +} From 17bc18ce2bf2a61e423ccaaf1827eaa58eed01a8 Mon Sep 17 00:00:00 2001 From: Christel Westerberg Date: Fri, 5 Jul 2024 10:32:08 +0200 Subject: [PATCH 4/4] fix: add stylings for list --- .../LoyaltyPage/loyaltyPage.module.css | 1 + components/Current/Aside/Puff/index.tsx | 6 +- components/Current/Preamble/index.tsx | 4 +- .../ImageContainer/imageContainer.module.css | 1 + components/JsonToHtml/index.tsx | 4 +- components/JsonToHtml/jsontohtml.module.css | 52 +++++++++- components/JsonToHtml/renderOptions.tsx | 96 +++++++++++++------ components/JsonToHtml/utils.tsx | 20 +++- components/Section/Link/index.tsx | 2 +- public/_static/icons/check-ring.svg | 8 ++ public/_static/icons/heart.svg | 8 ++ types/rte/enums.ts | 8 +- 12 files changed, 167 insertions(+), 43 deletions(-) create mode 100644 public/_static/icons/check-ring.svg create mode 100644 public/_static/icons/heart.svg diff --git a/components/ContentType/LoyaltyPage/loyaltyPage.module.css b/components/ContentType/LoyaltyPage/loyaltyPage.module.css index 203e19793..b20fa33a6 100644 --- a/components/ContentType/LoyaltyPage/loyaltyPage.module.css +++ b/components/ContentType/LoyaltyPage/loyaltyPage.module.css @@ -4,6 +4,7 @@ padding-left: var(--Spacing-x0); padding-right: var(--Spacing-x0); position: relative; + justify-content: center; } .blocks { diff --git a/components/Current/Aside/Puff/index.tsx b/components/Current/Aside/Puff/index.tsx index a08f99605..bfb8f0843 100644 --- a/components/Current/Aside/Puff/index.tsx +++ b/components/Current/Aside/Puff/index.tsx @@ -3,10 +3,10 @@ import { useRouter } from "next/navigation" import { Button } from "@scandic-hotels/design-system/current" +import { renderOptions as currentRenderOptions } from "@/components/Current/currentRenderOptions" import Image from "@/components/Image" import JsonToHtml from "@/components/JsonToHtml" -import { renderOptions as currentRenderOption } from "./../../currentRenderOptions" import { renderOptions } from "./renderOptions" import styles from "./puff.module.css" @@ -45,7 +45,7 @@ export default function Puff({
    @@ -74,7 +74,7 @@ export default function Puff({
    diff --git a/components/Current/Preamble/index.tsx b/components/Current/Preamble/index.tsx index ef0dc682a..bd0c7adc4 100644 --- a/components/Current/Preamble/index.tsx +++ b/components/Current/Preamble/index.tsx @@ -1,6 +1,6 @@ import JsonToHtml from "@/components/JsonToHtml" -import { renderOptions as currentRenderOption } from "./../currentRenderOptions" +import { renderOptions as currentRenderOptions } from "./../currentRenderOptions" import Breadcrumbs from "./Breadcrumbs" import { renderOptions } from "./renderOptions" @@ -28,7 +28,7 @@ export default function Preamble({ ) : null} diff --git a/components/ImageContainer/imageContainer.module.css b/components/ImageContainer/imageContainer.module.css index bde762010..3f61b2506 100644 --- a/components/ImageContainer/imageContainer.module.css +++ b/components/ImageContainer/imageContainer.module.css @@ -7,6 +7,7 @@ .image { max-width: 100%; + width: 100%; height: 365px; object-fit: cover; border-radius: var(--Corner-radius-Medium); diff --git a/components/JsonToHtml/index.tsx b/components/JsonToHtml/index.tsx index 48ab55c93..501e394e0 100644 --- a/components/JsonToHtml/index.tsx +++ b/components/JsonToHtml/index.tsx @@ -1,5 +1,7 @@ import { nodesToHtml } from "./utils" +import styles from "./jsontohtml.module.css" + import type { JsonToHtmlProps } from "@/types/components/jsontohtml" export default function JsonToHtml({ @@ -11,7 +13,7 @@ export default function JsonToHtml({ return null } return ( -
    +
    {nodesToHtml(nodes, embeds, renderOptions).filter(Boolean)}
    ) diff --git a/components/JsonToHtml/jsontohtml.module.css b/components/JsonToHtml/jsontohtml.module.css index 25263c850..700de51bb 100644 --- a/components/JsonToHtml/jsontohtml.module.css +++ b/components/JsonToHtml/jsontohtml.module.css @@ -7,6 +7,54 @@ margin: var(--Spacing-x1) var(--Spacing-x0); } -.li { - margin-left: var(--Spacing-x3); +.ul, +.ol { + padding: var(--Spacing-x2) var(--Spacing-x0); + display: grid; + gap: var(--Spacing-x1); +} + +.ol:has(li:nth-last-child(n + 4)), +.ul:has(li:nth-last-child(n + 4)) { + grid-template-columns: 1fr 1fr; + grid-auto-flow: column; +} + +.ol > li::marker { + color: var(--Primary-Light-On-Surface-Accent); +} + +.ul:has(.heart), +.ul:has(.check) { + list-style: none; +} +.li:has(.heart), +.li:has(.check) { + display: flex; +} + +.li:not(:has(.heart), :has(.check)) { + margin-left: var(--Spacing-x2); +} + +.li:has(.heart):before { + content: url("/_static/icons/heart.svg"); + position: relative; + margin-right: var(--Spacing-x1); + height: 8px; + top: 3px; +} + +.li:has(.check)::before { + content: url("/_static/icons/check-ring.svg"); + position: relative; + margin-right: var(--Spacing-x1); + height: 8px; + top: 3px; +} + +.container { + display: "grid"; + gap: var(--Spacing-x3); + max-width: 1197px; } diff --git a/components/JsonToHtml/renderOptions.tsx b/components/JsonToHtml/renderOptions.tsx index 70cd1f40a..f585dc768 100644 --- a/components/JsonToHtml/renderOptions.tsx +++ b/components/JsonToHtml/renderOptions.tsx @@ -10,7 +10,7 @@ import Caption from "../TempDesignSystem/Text/Caption" import Footnote from "../TempDesignSystem/Text/Footnote" import Subtitle from "../TempDesignSystem/Text/Subtitle" import Title from "../TempDesignSystem/Text/Title" -import { hasAvailableFormat } from "./utils" +import { hasAvailableParagraphFormat, hasAvailableULFormat } from "./utils" import styles from "./jsontohtml.module.css" @@ -18,7 +18,7 @@ import type { EmbedByUid } from "@/types/components/jsontohtml" import { EmbedEnum } from "@/types/requests/utils/embeds" import type { Attributes, RTEImageVaultAttrs } from "@/types/rte/attrs" import { - AvailableFormatEnum, + AvailableParagraphFormatEnum, RTEItemTypeEnum, RTETypeEnum, } from "@/types/rte/enums" @@ -201,20 +201,6 @@ export const renderOptions: RenderOptions = { ) }, - [RTETypeEnum.h6]: ( - node: RTEDefaultNode, - embeds: EmbedByUid, - next: RTENext, - fullRenderOptions: RenderOptions - ) => { - const props = extractPossibleAttributes(node.attrs) - return ( - -
    {next(node.children, embeds, fullRenderOptions)}
    -
    - ) - }, - [RTETypeEnum.hr]: () => { return }, @@ -240,8 +226,26 @@ export const renderOptions: RenderOptions = { fullRenderOptions: RenderOptions ) => { const props = extractPossibleAttributes(node.attrs) + + // Set the number of rows dynamically to create even rows for each column. We want the li:s + // to flow with the column, so therefore this is needed. + let numberOfRows: number | undefined + if (node.children.length > 4) { + const half = node.children.length / 2 + numberOfRows = Math.ceil(half) + } + return ( -
      +
        {next(node.children, embeds, fullRenderOptions)}
      ) @@ -256,17 +260,13 @@ export const renderOptions: RenderOptions = { const props = extractPossibleAttributes(node.attrs) const hasFormat = node.children.some((item) => - hasAvailableFormat((item as RTETextNode).classname) + hasAvailableParagraphFormat((item as RTETextNode)?.classname) ) // If a child node has an available format as className, we wrap it in a // span and render the children with the correct component if (hasFormat) { - return ( - - {next(node.children, embeds, fullRenderOptions)} - - ) + return next(node.children, embeds, fullRenderOptions) } return ( @@ -423,6 +423,15 @@ export const renderOptions: RenderOptions = { ) }, + [RTETypeEnum.fragment]: ( + node: RTEDefaultNode, + embeds: EmbedByUid, + next: RTENext, + fullRenderOptions: RenderOptions + ) => { + return <>{next(node.children, embeds, fullRenderOptions)} + }, + [RTETypeEnum.tr]: ( node: RTEDefaultNode, embeds: EmbedByUid, @@ -472,8 +481,26 @@ export const renderOptions: RenderOptions = { fullRenderOptions: RenderOptions ) => { const props = extractPossibleAttributes(node.attrs) + + // Set the number of rows dynamically to create even rows for each column. We want the li:s + // to flow with the column, so therefore this is needed. + let numberOfRows: number | undefined + if (node.children.length > 4) { + const half = node.children.length / 2 + numberOfRows = Math.ceil(half) + } + return ( -
        +
          {next(node.children, embeds, fullRenderOptions)}
        ) @@ -533,7 +560,16 @@ export const renderOptions: RenderOptions = { delete props.id } - if (className === AvailableFormatEnum.footnote) { + if (className) { + if (hasAvailableULFormat(className)) { + // @ts-ignore: We want to set css modules classNames even if it does not correspond + // to an existing class in the module style sheet. Due to our css modules plugin for + // typescript, we cannot do this without the ts-ignore + props.className = styles[className] + } + } + + if (className === AvailableParagraphFormatEnum.footnote) { return ( {children} @@ -541,7 +577,7 @@ export const renderOptions: RenderOptions = { ) } - if (className === AvailableFormatEnum.caption) { + if (className === AvailableParagraphFormatEnum.caption) { return ( {children} @@ -549,7 +585,7 @@ export const renderOptions: RenderOptions = { ) } - if (className === AvailableFormatEnum["script-1"]) { + if (className === AvailableParagraphFormatEnum["script-1"]) { return ( {children} @@ -557,7 +593,7 @@ export const renderOptions: RenderOptions = { ) } - if (className === AvailableFormatEnum["script-2"]) { + if (className === AvailableParagraphFormatEnum["script-2"]) { return ( {children} @@ -565,14 +601,14 @@ export const renderOptions: RenderOptions = { ) } - if (className === AvailableFormatEnum["subtitle-1"]) { + if (className === AvailableParagraphFormatEnum["subtitle-1"]) { return ( {children} ) } - if (className === AvailableFormatEnum["subtitle-2"]) { + if (className === AvailableParagraphFormatEnum["subtitle-2"]) { return ( {children} diff --git a/components/JsonToHtml/utils.tsx b/components/JsonToHtml/utils.tsx index bf798829b..496b9f9e4 100644 --- a/components/JsonToHtml/utils.tsx +++ b/components/JsonToHtml/utils.tsx @@ -3,7 +3,11 @@ import { renderOptions } from "./renderOptions" import type { EmbedByUid } from "@/types/components/jsontohtml" import type { Embeds } from "@/types/requests/embeds" import type { Node } from "@/types/requests/utils/edges" -import { AvailableFormatEnum, RTETypeEnum } from "@/types/rte/enums" +import { + AvailableParagraphFormatEnum, + AvailableULFormatEnum, + RTETypeEnum, +} from "@/types/rte/enums" import type { RTENode, RTERenderOptionComponent, @@ -85,8 +89,18 @@ function next( return nodeChildrenToHtml(nodes, embeds, fullRenderOptions) } -export function hasAvailableFormat(className?: string) { - return className && Object.keys(AvailableFormatEnum).includes(className) +export function hasAvailableParagraphFormat(className?: string) { + if (!className) { + return false + } + return Object.keys(AvailableParagraphFormatEnum).includes(className) +} + +export function hasAvailableULFormat(className?: string) { + if (!className) { + return false + } + return Object.keys(AvailableULFormatEnum).includes(className) } export function nodeToHtml( diff --git a/components/Section/Link/index.tsx b/components/Section/Link/index.tsx index 924e81620..c8b27aedd 100644 --- a/components/Section/Link/index.tsx +++ b/components/Section/Link/index.tsx @@ -18,7 +18,7 @@ export default function SectionLink({ link, variant }: SectionLinkProps) { className={classNames} color="burgundy" href={link.href} - variant="myPage" + variant="underscored" > {link.text} diff --git a/public/_static/icons/check-ring.svg b/public/_static/icons/check-ring.svg new file mode 100644 index 000000000..c08dd0661 --- /dev/null +++ b/public/_static/icons/check-ring.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/public/_static/icons/heart.svg b/public/_static/icons/heart.svg new file mode 100644 index 000000000..e46e94905 --- /dev/null +++ b/public/_static/icons/heart.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/types/rte/enums.ts b/types/rte/enums.ts index feb7834da..f4d6bd86c 100644 --- a/types/rte/enums.ts +++ b/types/rte/enums.ts @@ -37,6 +37,7 @@ export enum RTETypeEnum { tr = "tr", ul = "ul", ImageVault = "ImageVault", + fragment = "fragment", } export type RTEType = keyof typeof RTETypeEnum @@ -48,7 +49,7 @@ export enum RTEItemTypeEnum { export type RTEItemType = keyof typeof RTEItemTypeEnum -export enum AvailableFormatEnum { +export enum AvailableParagraphFormatEnum { "script-1" = "script-1", "script-2" = "script-2", "footnote" = "footnote", @@ -56,3 +57,8 @@ export enum AvailableFormatEnum { "subtitle-1" = "subtitle-1", "subtitle-2" = "subtitle-2", } + +export enum AvailableULFormatEnum { + "heart" = "heart", + "check" = "check", +}