): JSX.Element {\n return (\n \n );\n}\n","import React from 'react';\nimport { FacebookIcon } from '@components/IconComponents/SocialIcons/FacebookIcon';\nimport { LinkedInIcon } from '@components/IconComponents/SocialIcons/LinkedInIcon';\nimport { MailIcon, v2Colors } from '@web-for-marketing/react-ui';\nimport { XIcon } from '@components/IconComponents/SocialIcons/XIcon';\nimport { useStaticValues } from '@stateManagement/StaticValuesContext';\nimport { getTranslation } from '@helpers/languageTranslations';\nimport { useTranslation } from '@stateManagement/TranslationContext';\n\nconst classes = {\n mailIcon: {\n '& path': {\n fill: 'currentColor',\n },\n },\n roundedShareBorder: {\n margin: '0 0.5rem',\n position: 'relative',\n border: `1px solid ${v2Colors.border.activePrimary}`,\n width: '4rem',\n height: '4rem',\n borderRadius: '50%',\n background: v2Colors.core.snow,\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n textDecoration: 'none',\n cursor: 'pointer',\n overflow: 'hidden',\n color: v2Colors.border.activePrimary,\n '& svg': {\n color: v2Colors.border.activePrimary,\n },\n '&:hover': {\n cursor: 'pointer',\n border: `1px solid ${v2Colors.core.snow}`,\n color: v2Colors.core.snow,\n backgroundColor: v2Colors.border.activePrimary,\n '& svg': {\n strokeWidth: 1.1,\n color: `${v2Colors.core.snow} !important`,\n backgroundColor: `${v2Colors.border.activePrimary} !important`,\n },\n },\n '&:focus-visible': {\n backgroundColor: `${v2Colors.border.activePrimary} !important`,\n color: v2Colors.core.snow,\n outline: 'none',\n '& svg': {\n strokeWidth: 1.1,\n color: `${v2Colors.core.snow} !important`,\n backgroundColor: `${v2Colors.border.activePrimary} !important`,\n },\n },\n '&:active': {\n backgroundColor: `${v2Colors.border.activePrimary} !important`,\n color: v2Colors.core.snow,\n outline: 'none',\n '& svg': {\n strokeWidth: 1.1,\n color: `${v2Colors.core.snow} !important`,\n backgroundColor: `${v2Colors.border.activePrimary} !important`,\n },\n },\n },\n} as const;\n\nfunction socialPopUpWindow(link: string | URL, socialType: string): void {\n const featureStyle = 'width=550,height=600,left=150,top=200,toolbar=0,status=0,';\n window.open(link, socialType, featureStyle);\n}\n\ninterface ShareSocialMediaButtonsProps {\n className?: string;\n}\n\nexport function ShareSocialMediaButtons({ className }: ShareSocialMediaButtonsProps): JSX.Element {\n const { fullUrl } = useStaticValues();\n const { selectedLanguageTranslation } = useTranslation();\n\n const socialPlatforms = [\n {\n socialType: 'facebook',\n link: `https://www.facebook.com/sharer/sharer.php?u=${fullUrl}&src=sdkpreparse`,\n icon: ,\n },\n {\n socialType: 'twitter',\n link: `https://twitter.com/intent/tweet?url=${fullUrl}`,\n icon: ,\n },\n {\n socialType: 'linkedIn',\n link: `https://www.linkedin.com/sharing/share-offsite/?url=${fullUrl}`,\n icon: ,\n },\n {\n socialType: 'mail',\n link: `mailto:?to=&subject=Sharing an article from Geotab&body=${fullUrl}`,\n icon: ,\n },\n ];\n\n return (\n \n {socialPlatforms.map(({ socialType, link, icon }, index) => (\n \n ))}\n
\n );\n}\n","import { colors, getRgbaColor, breakpoints, v2Colors } from '@web-for-marketing/react-ui';\nimport { typographyStyles } from '@web-for-marketing/react-ui';\nimport externalLinkWithBg from '@images/Blog/ExternalLinkWithBackground.svg';\nimport openInNewTab from '@images/Blog/OpenInNewTab.svg';\n\nexport const ckEditorHTMLStyles = {\n container: {\n marginBottom: '4rem',\n width: '100%',\n },\n articleStyles: {\n color: v2Colors.text.secondary,\n '& a': {\n transition: '200ms background-color ease',\n fontSize: 'inherit',\n fontWeight: 'inherit',\n lineHeight: 'inherit',\n textDecoration: 'underline',\n color: v2Colors.core.innovation,\n wordBreak: 'break-word',\n padding: '0.5rem 0.2rem',\n '&:hover': {\n backgroundColor: `${getRgbaColor(v2Colors.core.deepSpace, 0.03)} !important`,\n },\n '&:focus': {\n outlineColor: v2Colors.core.innovation,\n backgroundColor: `${getRgbaColor(v2Colors.core.deepSpace, 0.06)} !important`,\n },\n '&:active': {\n outline: 'none',\n backgroundColor: `${getRgbaColor(v2Colors.core.deepSpace, 0.05)} !important`,\n },\n '&[target=\"_blank\"]:not(figure *)::after': {\n content: '\"\"',\n height: '0.8em',\n width: '0.8em',\n marginLeft: '0.6rem',\n verticalAlign: 'baseline',\n display: 'inline-block',\n backgroundImage: `url(${openInNewTab})`,\n backgroundSize: 'contain',\n backgroundRepeat: 'no-repeat',\n },\n '&:not([href*=\"www.geotab.com\"]):not([href^=\"/\"]):not(figure *)::after': {\n content: '\"\"',\n height: '0.8em',\n width: '0.8em',\n marginLeft: '0.6rem',\n verticalAlign: 'baseline',\n display: 'inline-block',\n backgroundImage: `url(${openInNewTab})`,\n backgroundSize: 'contain',\n backgroundRepeat: 'no-repeat',\n },\n },\n '& quote': {\n fontSize: '3.2rem',\n color: v2Colors.text.secondary,\n fontStyle: 'oblique',\n margin: '0 1rem 2rem',\n [`@media (max-width: ${breakpoints.xl})`]: {\n fontSize: '2.8rem',\n },\n [`@media (max-width: ${breakpoints.lg})`]: {\n fontSize: '2.6rem',\n },\n [`@media (max-width: ${breakpoints.md})`]: {\n fontSize: '2.4rem',\n },\n },\n '& ul': {\n margin: '2rem 0 2.2rem',\n '& li::marker': {\n color: v2Colors.text.activePrimary,\n },\n '&:last-child': {\n marginBottom: 0,\n },\n },\n '& ol': {\n margin: '2rem 0 2.2rem',\n '&:last-child': {\n marginBottom: 0,\n },\n },\n '& li': {\n ...typographyStyles.body1,\n color: 'inherit',\n wordBreak: 'break-word',\n '&:not(:last-of-type)': {\n marginBottom: '1em',\n },\n '& ul,ol': {\n marginTop: '1em',\n marginBottom: 0,\n },\n },\n '& pre': {\n ...typographyStyles.body1,\n whiteSpace: 'pre-wrap',\n backgroundColor: v2Colors.core.cloud,\n fontFamily: '\"Inconsolata\", \"Menlo\", \"Consolas\", monospace',\n color: v2Colors.text.secondary,\n },\n '& code': {\n ...typographyStyles.body1,\n padding: '2rem',\n color: v2Colors.text.secondary,\n wordBreak: 'break-word',\n fontFamily: '\"source-code-pro\", \"Menlo\", \"Monaco\", \"Consolas\", \"Courier New\", \"monospace\"',\n },\n '& table, td': {\n ...typographyStyles.body1,\n color: v2Colors.text.secondary,\n border: `1px solid ${colors.core.mineral.main}`,\n borderCollapse: 'collapse',\n },\n '& table': {\n display: 'table',\n margin: 'auto',\n '& td': {\n padding: '0.72rem',\n },\n },\n '& img': {\n width: '100%',\n maxWidth: '100%',\n height: '100%',\n },\n '& figure': {\n display: 'block',\n width: 'auto',\n margin: 0,\n maxWidth: '100%',\n position: 'relative',\n },\n '& figure.media': {\n margin: 'auto',\n width: '100%',\n clear: 'both',\n '& > div > div': {\n paddingBottom: '56.25% !important',\n },\n },\n\n '& figure.image': {\n margin: '2rem 2rem 2rem 0',\n boxSizing: 'content-box !important' as 'content-box',\n '& a': {\n padding: 0,\n },\n '& a[target=\"_blank\"]::after': {\n content: `url(${externalLinkWithBg})`,\n position: 'absolute',\n left: 0,\n bottom: 0,\n },\n '& a[target=\"_blank\"]:hover::after': {\n content: `url(${externalLinkWithBg})`,\n position: 'absolute',\n left: 0,\n bottom: 0,\n },\n '& a[target=\"_blank\"]:focus::after': {\n content: `url(${externalLinkWithBg})`,\n position: 'absolute',\n left: 0,\n bottom: 0,\n },\n '& a[target=\"_blank\"]:hover::before': {\n content: 'linear-gradient(140deg, rgba(0, 120, 211, 0) 0%, rgba(0, 120, 211, 0.3) 100%)',\n position: 'absolute',\n left: 0,\n right: 0,\n bottom: '0.5rem',\n top: 0,\n },\n '& a[target=\"_blank\"]:focus::before': {\n content: 'linear-gradient(140deg, rgba(0, 120, 211, 0) 0%, rgba(0, 120, 211, 0.5) 100%)',\n position: 'absolute',\n left: 0,\n right: 0,\n },\n },\n '& figure.image-style-align-left': {\n float: 'left',\n margin: '2rem 2rem 2rem 0',\n },\n '& figure.image-style-align-center': {\n display: 'block',\n margin: '2rem auto',\n },\n '& figure.image-style-align-right': {\n float: 'right',\n margin: '2rem 0 2rem 2rem',\n },\n '& h1': {\n ...typographyStyles.header1,\n marginBottom: '0.3em',\n },\n '& h2': {\n ...typographyStyles.header3,\n marginBottom: '1.6rem',\n marginTop: '0.8em',\n },\n '& h3': {\n ...typographyStyles.header4,\n color: v2Colors.text.activePrimary,\n marginBottom: '1.6rem',\n marginTop: '1em',\n },\n '& h4, h6': {\n ...typographyStyles.body1,\n color: v2Colors.text.secondary,\n },\n '& h5': {\n ...typographyStyles.body2,\n color: v2Colors.text.secondary,\n },\n '& p': {\n ...typographyStyles.body1,\n color: v2Colors.text.secondary,\n wordBreak: 'break-word',\n },\n },\n} as const;\n","import { v2Colors, breakpoints } from '@web-for-marketing/react-ui';\n\nexport const blogCard2Styles = {\n cardContainer: {\n display: 'flex',\n flexDirection: 'row',\n width: '100%',\n '&:focus-within': {\n outline: `1px solid ${v2Colors.border.activePrimary}`,\n outlineOffset: '3px',\n borderRadius: '0.8rem',\n },\n '&:hover img': {\n transform: 'scale(1.05)',\n },\n },\n imageWrapper: {\n width: '25rem',\n height: '16rem',\n borderRadius: '8px',\n overflow: 'hidden',\n flexShrink: 0,\n [`@media (max-width: ${breakpoints.sm})`]: {\n width: '10rem',\n height: '10rem',\n },\n },\n cardContent: (hasCategoryPill?: boolean) =>\n ({\n padding: '1.6rem 2.4rem',\n [`@media (max-width: ${breakpoints.sm})`]: {\n padding: hasCategoryPill ? '0 1.6rem' : '1.6rem',\n },\n }) as const,\n categoryMargins: {\n margin: '0 0 8px 0',\n [`@media (max-width: ${breakpoints.sm})`]: {\n margin: '0 0 4px 0',\n },\n },\n textTruncate: {\n display: '-webkit-box',\n WebkitBoxOrient: 'vertical',\n WebkitLineClamp: 2,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n },\n title: {\n marginBottom: '0.8rem',\n '&:hover': {\n color: v2Colors.text.activePrimary,\n },\n [`@media (max-width: ${breakpoints.sm})`]: {\n fontSize: '1.6rem',\n marginBottom: '0.4rem',\n },\n },\n titleMargin: {\n marginTop: '1.6rem',\n },\n} as const;\n","import React from 'react';\nimport { useAtom } from 'jotai';\nimport { LinkOverlay, LinkOverlayContainer, Text } from '@web-for-marketing/react-ui';\nimport { selectedLanguageAtom } from '@atoms/appSettings';\nimport { BlogCardImage } from '@models/blogCards';\nimport { blogCard2Styles as blog2Classes } from './BlogCard2Style';\nimport { blogCardStyle as classes } from './BlogCardStyle';\nimport { isMobileAtom } from '@atoms/appSettings';\nimport { DateAndReadTime } from './DateAndReadTime';\nimport { CategoryPill } from './CategoryPill';\n\nexport interface BlogCard2Props {\n title: string;\n linkPath: string;\n ariaLabel?: string;\n image: BlogCardImage;\n category?: string;\n categoryLink?: string;\n publishedDateUtc: string | null;\n readMinutes?: number;\n className?: string;\n lazyLoad?: boolean;\n}\n\nexport function BlogCard2({\n title,\n linkPath,\n ariaLabel,\n image,\n category,\n categoryLink,\n publishedDateUtc,\n readMinutes,\n className,\n lazyLoad = false,\n}: BlogCard2Props): JSX.Element {\n const [selectedLanguage] = useAtom(selectedLanguageAtom);\n const [isMobile] = useAtom(isMobileAtom);\n const hasCategoryPill = category && categoryLink ? true : false;\n\n return (\n \n \n

\n
\n \n {category && categoryLink ? (\n \n ) : null}\n \n \n {title}\n \n \n {publishedDateUtc ? (\n \n ) : null}\n
\n \n );\n}\n","import { v2Colors, breakpoints } from '@web-for-marketing/react-ui';\nimport { typographyStyles } from '@web-for-marketing/react-ui';\n\nexport const blogCardStyle = {\n image: {\n width: '100%',\n height: '100%',\n objectFit: 'cover',\n transition: 'transform 0.3s ease-in-out',\n },\n cardContent: {\n padding: '0 1.6rem 1.6rem 1.6rem',\n },\n category: {\n display: 'inline-block',\n borderRadius: '2rem',\n padding: '4px 8px',\n border: '1px solid',\n borderColor: v2Colors.border.primary,\n backgroundColor: v2Colors.background.white,\n position: 'relative',\n outline: 'none',\n '&:focus-within': {\n outline: `1px solid ${v2Colors.border.activePrimary}`,\n outlineOffset: '3px',\n borderRadius: '2rem',\n },\n '& a': {\n textDecoration: 'none',\n outline: 'none',\n },\n '&:hover': {\n backgroundColor: v2Colors.action.active,\n },\n },\n description: {\n marginBottom: '0.8rem',\n },\n timeBlock: {\n display: 'flex',\n flexDirection: 'row',\n justifyContent: 'flex-start',\n width: '100%',\n },\n readMinutes: {\n display: 'flex',\n alignitems: 'center',\n },\n divider: {\n ...typographyStyles.body2,\n margin: '0 8px',\n [`@media (max-width: ${breakpoints.xs})`]: {\n display: 'none',\n },\n },\n} as const;\n","import React from 'react';\nimport { Text } from '@web-for-marketing/react-ui';\nimport { blogCardStyle as classes } from './BlogCardStyle';\n\ninterface PillProps {\n category: string;\n categoryLink: string;\n className?: string;\n}\n\nexport function CategoryPill({ category, categoryLink, className }: PillProps): JSX.Element {\n return (\n \n \n {category}\n \n
\n );\n}\n","import React from 'react';\nimport { PublicDateTime } from '@components/PublicDateTime';\nimport { getFormattedLocalDateTime } from '@helpers/dates';\nimport { blogCardStyle as classes } from './BlogCardStyle';\nimport { Text } from '@web-for-marketing/react-ui';\nimport { LanguageCode } from '@models/languageCode';\nimport { getTranslation } from '@helpers/languageTranslations';\nimport { useTranslation } from '@stateManagement/TranslationContext';\n\ninterface DateAndReadTimeProps {\n publishedDateUtc: string;\n selectedLanguage: LanguageCode | undefined;\n readMinutes?: number;\n}\n\nexport function DateAndReadTime({\n publishedDateUtc,\n selectedLanguage,\n readMinutes,\n}: DateAndReadTimeProps): JSX.Element {\n const { selectedLanguageTranslation } = useTranslation();\n\n const readMinuteText = getTranslation(selectedLanguageTranslation, 'blogInfo', 'readMinutes').replace(\n '5',\n readMinutes ? readMinutes : '~1'\n );\n\n return (\n \n
\n \n {getFormattedLocalDateTime(publishedDateUtc, 'LL', selectedLanguage)}\n \n \n
\n |\n
\n {readMinutes ? (\n
\n {readMinuteText}\n \n ) : null}\n
\n );\n}\n","import React from 'react';\nimport { Accordion, AccordionPanel, AccordionTrigger, Heading } from '@web-for-marketing/react-ui';\nimport { Stack } from '@mui/material';\nimport { RichTextContent } from '@components/RichTextContent';\nimport { breakpoints } from '@web-for-marketing/react-ui';\nimport { ArticleFAQType } from '@models/article';\n\ninterface ArticleFAQAccordionListProps {\n lists: ArticleFAQType[];\n title: string;\n className?: string;\n}\n\nconst classes = {\n title: {\n marginBottom: '3.2rem',\n [`@media (max-width: ${breakpoints.sm})`]: {\n marginBottom: '1.6rem',\n },\n },\n} as const;\n\nexport function ArticleFAQAccordionList({ lists, title, className }: ArticleFAQAccordionListProps): JSX.Element {\n return (\n \n {title ? (\n
\n {title}\n \n ) : null}\n
\n {lists.map(({ question, answer }, index) => (\n \n \n {question}\n \n \n \n \n \n ))}\n \n
\n );\n}\n","import React from 'react';\n\nexport function LightBulbIcon(props: React.SVGProps): JSX.Element {\n return (\n \n );\n}\n","import React, { useMemo } from 'react';\nimport { useTranslation } from '@stateManagement/TranslationContext';\nimport { getTranslation } from '@helpers/languageTranslations';\nimport { Grid2 } from '@mui/material';\nimport { breakpoints, space, Text } from '@web-for-marketing/react-ui';\nimport { RichTextContent } from '@components/RichTextContent';\nimport { ParseAbbreviations } from '@components/ParseAbbreviations';\nimport { LightBulbIcon } from '@components/IconComponents/LightBulbIcon';\nimport { v2Colors } from '@web-for-marketing/react-ui';\nimport { isMobileAtom } from '@atoms/appSettings';\nimport { useAtom } from 'jotai';\n\ninterface KeyTakeawaysProps {\n content: string;\n id?: string;\n mobileOffSetMargin?: string;\n}\n\nconst classes = {\n keyTakeAwayContainer: (mobileOffSetMargin?: string) => ({\n backgroundColor: v2Colors.background.light,\n padding: '3.2rem 3.2rem',\n borderRadius: '0.4rem',\n [`@media (max-width: ${breakpoints.sm})`]: {\n margin: mobileOffSetMargin ? `0 -${mobileOffSetMargin}` : `0 -${space.containerOuterPadding}`,\n padding: mobileOffSetMargin ? `0 ${mobileOffSetMargin}` : `0 ${space.containerOuterPadding}`,\n paddingTop: '2.4rem',\n borderRadius: '0',\n width: 'unset',\n },\n }),\n iconContainer: {\n marginRight: '2.4rem',\n },\n};\n\nexport const KeyTakeaways = ({ content, id, mobileOffSetMargin }: KeyTakeawaysProps): JSX.Element | null => {\n const { selectedLanguageTranslation } = useTranslation();\n const glossaryKeyTakeawayTranslation = useMemo(() => {\n return getTranslation(selectedLanguageTranslation, 'glossary', 'articleCard');\n }, [selectedLanguageTranslation]);\n const [isMobile] = useAtom(isMobileAtom);\n\n return (\n \n {!isMobile ? (\n \n \n
\n ) : null}\n \n \n {glossaryKeyTakeawayTranslation.keyTakeaways}\n \n \n
\n \n );\n};\n","import React from 'react';\n\nexport function DropdownIcon(props: React.SVGProps): JSX.Element {\n return (\n \n );\n}\n","import React from 'react';\n\nexport function FacebookIcon(props: React.SVGProps): JSX.Element {\n return (\n \n );\n}\n","import React from 'react';\n\nexport function LinkedInIcon(props: React.SVGProps): JSX.Element {\n return (\n \n );\n}\n","import React from 'react';\nimport { PropTypes } from 'prop-types';\n\nfunction checkAbbreviations(content, stringFormat) {\n let currentContent = null;\n\n if (content && content.length) {\n let abbreviations = content.split(/~!(.*?)!~/gm);\n currentContent = content;\n\n if (abbreviations.length > 1) {\n if (stringFormat) {\n currentContent = abbreviations\n .map((element) => {\n let newAbbrElement;\n\n if (element.indexOf('{') > -1 && element.indexOf('}') > -1) {\n let abbreviationContent = element.split(/{(.*?)}/gm);\n\n newAbbrElement = abbreviationContent.length\n ? `${addBreaks(\n abbreviationContent[1],\n stringFormat\n )}`\n : '';\n } else {\n newAbbrElement = addBreaks(element, stringFormat);\n }\n\n return newAbbrElement;\n })\n .join('');\n } else {\n currentContent = (\n <>\n {abbreviations.map((element, index) => {\n let newAbbrElement;\n if (element.indexOf('{') > -1 && element.indexOf('}') > -1) {\n let abbreviationContent = element.split(/{(.*?)}/gm);\n\n newAbbrElement = abbreviationContent.length ? (\n \n {addBreaks(abbreviationContent[1], stringFormat)}\n \n ) : null;\n } else {\n newAbbrElement = addBreaks(element, stringFormat, index);\n }\n return newAbbrElement;\n })}\n >\n );\n }\n } else {\n currentContent = addBreaks(currentContent, stringFormat);\n }\n }\n return currentContent;\n}\n\nfunction addBreaks(content, stringFormat, index = 0) {\n const contentWithNewline = content.replace(/
|
/gm, '\\n');\n let splitContent = contentWithNewline.split('\\n');\n let contentWithBreaks = [];\n\n if (splitContent.length > 1) {\n if (stringFormat) {\n for (let i = 0; i < splitContent.length - 1; i++) {\n contentWithBreaks.push(`${splitContent[i]}
`);\n }\n contentWithBreaks.push(splitContent[splitContent.length - 1]);\n splitContent = contentWithBreaks;\n } else {\n for (let i = 0; i < splitContent.length - 1; i++) {\n contentWithBreaks.push(\n \n {splitContent[i]}\n
\n \n );\n }\n contentWithBreaks.push(\n {splitContent[splitContent.length - 1]}\n );\n splitContent = {contentWithBreaks};\n }\n } else {\n if (!stringFormat) {\n splitContent = splitContent[0];\n }\n }\n\n return stringFormat ? splitContent.join('') : splitContent;\n}\n\nexport function ParseAbbreviations({ content, stringFormat }) {\n return checkAbbreviations(content, stringFormat);\n}\n\nParseAbbreviations.defaultProps = {\n content: '',\n};\n\nParseAbbreviations.propTypes = {\n content: PropTypes.string,\n stringFormat: PropTypes.bool,\n};\n","import React, { useEffect, useMemo, useState } from 'react';\nimport { useStaticValues } from '@stateManagement/StaticValuesContext';\nimport { breakpoints } from '@web-for-marketing/react-ui';\nimport { AspectRatio } from '@models/images';\nimport { Interpolation, Theme } from '@emotion/react';\nimport { PageHelmetPreloadLink } from '@components/PageHelmetPreloadLink';\n\ninterface BaseProps {\n imagePath?: string;\n lazyLoad?: boolean;\n mobilePath?: string;\n pictureProps?: React.HTMLAttributes & { css?: Interpolation };\n alt: string | undefined;\n mobileAlt?: string;\n fullWidth?: boolean;\n mobileQuery?: `${number}px`;\n aspectRatio?: AspectRatio;\n mobileAspectRatio?: AspectRatio;\n preload?: boolean;\n}\n\ninterface PictureStyleProps {\n aspectRatio?: AspectRatio;\n mobileAspectRatio?: AspectRatio;\n mobileQuery: string;\n imagePath?: string;\n mobilePath?: string;\n}\n\nexport type PictureProps = BaseProps & Omit, keyof BaseProps>;\n\nconst classes = {\n picture: {\n width: '100%',\n display: 'inline',\n height: '100%',\n },\n fullWidth: {\n width: '100%',\n },\n image: {\n objectFit: 'cover',\n },\n aspectRatio: ({ aspectRatio, mobileAspectRatio, mobileQuery, imagePath, mobilePath }: PictureStyleProps) => ({\n aspectRatio: imagePath ? aspectRatio : mobilePath ? mobileAspectRatio : undefined,\n [`@media (max-width: ${mobileQuery})`]: {\n aspectRatio: mobilePath ? mobileAspectRatio : imagePath ? aspectRatio : undefined,\n },\n }),\n} as const;\n\nexport function Picture({\n imagePath,\n mobilePath,\n alt,\n lazyLoad = false,\n mobileQuery = breakpoints.sm,\n fullWidth = true,\n className = '',\n pictureProps = {},\n aspectRatio,\n mobileAspectRatio,\n preload = false,\n mobileAlt,\n ...other\n}: PictureProps): JSX.Element {\n const [altText, setAltText] = useState(alt || '');\n const { prefixStringWithBaseUrl } = useStaticValues();\n const resolvedDesktopPath = useMemo(() => {\n return prefixStringWithBaseUrl(imagePath || mobilePath);\n }, [prefixStringWithBaseUrl, imagePath, mobilePath]);\n\n const resolvedMobilePath = useMemo(() => {\n return prefixStringWithBaseUrl(mobilePath || imagePath);\n }, [prefixStringWithBaseUrl, imagePath, mobilePath]);\n\n useEffect(() => {\n function updateAltText(): void {\n const isMobileWidth = window.innerWidth < parseInt(mobileQuery);\n const hasMobileImage = !!mobilePath;\n\n if (isMobileWidth && hasMobileImage) {\n setAltText(mobileAlt || '');\n } else {\n setAltText(alt || '');\n }\n }\n\n window.addEventListener('resize', updateAltText);\n\n // Initial call to set alt text on component mount\n updateAltText();\n\n return () => {\n window.removeEventListener('resize', updateAltText);\n };\n }, [mobileQuery, alt, mobileAlt, mobilePath]);\n\n return (\n <>\n {resolvedDesktopPath && preload ? : null}\n {resolvedMobilePath && preload ? : null}\n \n \n
\n \n >\n );\n}\n","import React from 'react';\nimport { isDateVisibleAtom } from '@atoms/date';\nimport { useAtom } from 'jotai';\nimport { Skeleton } from '@mui/material';\n\nexport function PublicDateTime({ children }: { children: JSX.Element }): JSX.Element {\n const [isDateVisibile] = useAtom(isDateVisibleAtom);\n\n if (isDateVisibile) {\n return children;\n } else {\n // we need to know the size of the text to render a skeleton with the correct size.\n // the datetime text causes hydration warnings, so we supress them while we hide the mismatched text with the skeleton\n const clonedElement = React.cloneElement(children, { suppressHydrationWarning: true });\n\n return {clonedElement};\n }\n}\n","import React from 'react';\nimport PropTypes from 'prop-types';\nimport { Navigate } from 'react-router-dom';\n\nexport function Redirect({ redirectUrl, statusCode }) {\n if (statusCode === 200 && typeof window !== 'undefined') {\n window.location.href = redirectUrl;\n }\n\n return ;\n}\n\nRedirect.propTypes = {\n redirectUrl: PropTypes.string.isRequired,\n statusCode: PropTypes.number.isRequired,\n};\n","import React from 'react';\nimport { DangerouslySetInnerHTML } from './SectionComponents/helpers/DangerouslySetInnerHTML';\nimport { DefaultTextProps } from '@web-for-marketing/react-ui';\nimport { richTextHtmlStyles } from './SectionComponents/styleObjects/richTextHtmlStyles';\nimport { RichTextListStyle } from '@models/richTextEditor';\n\ninterface RichTextContentProps extends DefaultTextProps {\n content: string;\n hideLinks?: boolean;\n listStyle?: RichTextListStyle;\n}\n\nexport function RichTextContent({ content, listStyle = 'default', ...other }: RichTextContentProps): JSX.Element {\n return (\n \n );\n}\n","import React, { useEffect } from 'react';\nimport { useStaticValues } from '@stateManagement/StaticValuesContext';\nimport { OverrideTextProps, Text } from '@web-for-marketing/react-ui';\nimport { getDangerouslySetInnerHTML, addScriptsToDOM, removeScriptTags } from './DangerouslySetInnerHTMLHelper';\n\ninterface BaseProps {\n html: string;\n parseLinks?: boolean;\n hideLinks?: boolean;\n}\n\ntype DangerouslySetInnerHTMLProps = BaseProps & OverrideTextProps;\n\nexport function DangerouslySetInnerHTML({\n html,\n parseLinks,\n hideLinks,\n ...other\n}: DangerouslySetInnerHTMLProps): JSX.Element {\n const { baseUrl } = useStaticValues();\n const { sanitizedHtml, scriptTags } = removeScriptTags(html);\n\n useEffect(() => {\n if (scriptTags) {\n addScriptsToDOM(scriptTags);\n }\n }, [scriptTags]);\n\n return (\n \n );\n}\n","import { isInternalOrBaseLink } from '@helpers/string';\n\nexport const getDangerouslySetInnerHTML = (\n html: string,\n baseUrl: string,\n parseLinks?: boolean,\n hideLinks?: boolean\n): string => {\n if (parseLinks) {\n const spliHtml = html.split(' {\n if (index === 0) {\n return str;\n }\n const match = str.match(/href=\"(.*?)\"/);\n if (match) {\n let linkAttributes = '';\n if (hideLinks) {\n linkAttributes += ' tabIndex=\"-1\"';\n }\n if (match[1] && !isInternalOrBaseLink(match[1], baseUrl)) {\n linkAttributes += ' target=\"_blank\" rel=\"noopener noreferrer\"';\n }\n return ` {\n const domParser = new DOMParser();\n const parsedScriptTags = domParser.parseFromString(scriptTags, 'text/html').querySelectorAll('script');\n\n parsedScriptTags.forEach((scriptTag) => {\n const newScriptTag = document.createElement('script');\n newScriptTag.innerHTML = scriptTag.innerHTML;\n const attributes = scriptTag.attributes;\n for (let i = 0; i < attributes.length; i++) {\n const { name, value } = attributes[i];\n newScriptTag.setAttribute(name, value);\n }\n document.body.appendChild(newScriptTag);\n });\n};\n\nexport const addLinksToDOM = (linkTags: string): void => {\n const domParser = new DOMParser();\n const parsedLinkTags = domParser.parseFromString(linkTags, 'text/html').querySelectorAll('link');\n\n parsedLinkTags.forEach((linkTag) => {\n const newLinkTag = document.createElement('link');\n newLinkTag.innerHTML = linkTag.innerHTML;\n const attributes = linkTag.attributes;\n for (let i = 0; i < attributes.length; i++) {\n const { name, value } = attributes[i];\n newLinkTag.setAttribute(name, value);\n }\n document.head.appendChild(newLinkTag);\n });\n};\n\nexport const removeScriptTags = (html: string): { sanitizedHtml: string; scriptTags: string } => {\n const scriptTags: string[] = [];\n\n const sanitizedHtml = html.replace(\n /