{\r\n public render(): JSX.Element {\r\n const editableLinks = this._mapEditableLinks(this.props.links);\r\n return (\r\n \r\n {editableLinks && editableLinks.length ? (\r\n \r\n ) : null}\r\n
\r\n );\r\n }\r\n\r\n private _mapEditableLinks = (linkdata: ILinksData[]): Msdyn365.ILinksData[] | null => {\r\n if (!linkdata || linkdata.length === 0) {\r\n return null;\r\n }\r\n const editableLinks: Msdyn365.ILinksData[] = [];\r\n linkdata.forEach((link, index) => {\r\n // Construct telemetry attribute to render\r\n const payLoad = getPayloadObject('click', this.props.telemetryContent, '', '');\r\n const linkText = link.linkText ? link.linkText : '';\r\n payLoad.contentAction.etext = linkText;\r\n const attributes = getTelemetryAttributes(this.props.telemetryContent, payLoad);\r\n const btnClass = index === 0 ? 'msc-cta__primary' : 'msc-cta__secondary';\r\n const editableLink: Msdyn365.ILinksData = {\r\n ariaLabel: link.ariaLabel,\r\n className: btnClass,\r\n linkText: link.linkText,\r\n linkUrl: link.linkUrl.destinationUrl,\r\n openInNewTab: link.openInNewTab,\r\n role: 'button',\r\n additionalProperties: attributes,\r\n onClick: onTelemetryClick(this.props.telemetryContent, payLoad, linkText)\r\n };\r\n editableLinks.push(editableLink);\r\n });\r\n\r\n return editableLinks;\r\n };\r\n}\r\nexport default ContentCardLinks;\r\n","/*---------------------------------------------------------------------------------------------\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License. See License.txt in the project root for license information.\r\n *--------------------------------------------------------------------------------------------*/\r\nimport {\r\n CacheType,\r\n createObservableDataAction,\r\n IAction,\r\n IActionContext,\r\n IActionInput,\r\n IAny,\r\n ICreateActionContext,\r\n IGeneric\r\n} from '@msdyn365-commerce/core';\r\n/* tslint:disable: no-duplicate-imports */\r\nimport { ProductRefinerValue, ProductSearchResult } from '@msdyn365-commerce/retail-proxy';\r\nimport { observable } from 'mobx';\r\n\r\nexport type listPageType = 'Category' | 'Search' | 'Unknown';\r\n\r\n/**\r\n * ListPageState class\r\n */\r\nexport class ListPageState {\r\n @observable public activeFilters: ProductRefinerValue[] | null = null;\r\n @observable public activeProducts: ProductSearchResult[] = [];\r\n}\r\n\r\n/**\r\n * ListPageStateInput - action input\r\n */\r\nexport class ListPageStateInput implements IActionInput {\r\n public getCacheKey = () => `ListPageState`;\r\n public getCacheObjectType = () => 'ListPageState';\r\n public dataCacheType = (): CacheType => 'application';\r\n}\r\n\r\nexport async function listPageStateAction(\r\n input: ListPageStateInput,\r\n ctx: IActionContext\r\n): Promise {\r\n return new ListPageState();\r\n}\r\n\r\n/**\r\n * create new input for create action\r\n */\r\nexport const createListPageInput = (\r\n inputData: ICreateActionContext>\r\n): IActionInput => {\r\n return new ListPageStateInput();\r\n};\r\n\r\n/**\r\n * ListPageState - create action\r\n */\r\nexport default createObservableDataAction({\r\n action: >listPageStateAction,\r\n input: createListPageInput\r\n});\r\n","/**\r\n * Copyright (c) Microsoft Corporation\r\n * All rights reserved. See License.txt in the project root for license information.\r\n * ISingleCategoryBanner contentModule Interface Properties\r\n * THIS FILE IS AUTO-GENERATED - MANUAL MODIFICATIONS WILL BE LOST\r\n */\r\n\r\nimport * as Msdyn365 from '@msdyn365-commerce/core';\r\n\r\nexport const enum imagePosition {\r\n left = 'left',\r\n center = 'center',\r\n right = 'right'\r\n}\r\n\r\nexport const enum actionableRegion {\r\n imageAndLinks = 'imageAndLinks',\r\n linksOnly = 'linksOnly'\r\n}\r\n\r\nexport const enum enhancedEcommTracking {\r\n promotion = 'promotion'\r\n}\r\n\r\nexport interface ISingleCategoryBannerConfig extends Msdyn365.IModuleConfig {\r\n useSeoData?: boolean;\r\n useDynamicImages?: boolean;\r\n dynamicImages?: IDynamicImagesData;\r\n heading?: IHeadingData;\r\n paragraph?: Msdyn365.RichText;\r\n image?: Msdyn365.IImageData;\r\n links?: ILinksData[];\r\n imagePosition?: imagePosition;\r\n actionableRegion?: actionableRegion;\r\n imageLink?: Msdyn365.ILinkData;\r\n imageAriaLabel?: string;\r\n className?: string;\r\n categoryRecordId?: string;\r\n enhancedEcommTracking?: enhancedEcommTracking;\r\n tealiumEvent?: ITealiumEventData;\r\n tealiumPromotion?: ITealiumPromotionData;\r\n}\r\n\r\nexport interface IDynamicImagesData {\r\n desktopImage?: Msdyn365.IImageData;\r\n tabletImage?: Msdyn365.IImageData;\r\n mobileImage?: Msdyn365.IImageData;\r\n}\r\n\r\nexport const enum HeadingTag {\r\n h1 = 'h1',\r\n h2 = 'h2',\r\n h3 = 'h3',\r\n h4 = 'h4',\r\n h5 = 'h5',\r\n h6 = 'h6'\r\n}\r\n\r\nexport interface IHeadingData {\r\n text: string;\r\n tag?: HeadingTag;\r\n}\r\n\r\nexport interface ILinksData {\r\n linkText?: string;\r\n linkUrl: Msdyn365.ILinkData;\r\n ariaLabel?: string;\r\n openInNewTab?: boolean;\r\n}\r\n\r\nexport interface ITealiumEventData {\r\n event?: string;\r\n event_category?: string;\r\n event_action?: string;\r\n event_label?: string;\r\n}\r\n\r\nexport interface ITealiumPromotionData {\r\n promotion_name?: string;\r\n promotion_id?: string;\r\n promotion_creative_version?: string;\r\n promotion_position?: string;\r\n}\r\n\r\nexport interface ISingleCategoryBannerProps extends Msdyn365.IModule {\r\n config: ISingleCategoryBannerConfig;\r\n}\r\n","/*---------------------------------------------------------------------------------------------\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License. See License.txt in the project root for license information.\r\n *--------------------------------------------------------------------------------------------*/\r\n/* eslint-disable no-duplicate-imports */\r\nimport { getTelemetryObject, IModuleProps, INodeProps, ITelemetryContent } from '@msdyn365-commerce-modules/utilities';\r\nimport * as Msdyn365 from '@msdyn365-commerce/core';\r\nimport MsDyn365 from '@msdyn365-commerce/core';\r\nimport classnames from 'classnames';\r\nimport * as React from 'react';\r\nimport { IDynamicImagesData } from '../../themes/mattressfirm/definition-extensions/content-block.ext.props.autogenerated';\r\nimport LinksComponent from './components/links';\r\nimport { ISingleCategoryBannerData } from './single-category-banner.data';\r\nimport { actionableRegion as region, ILinksData, ISingleCategoryBannerProps } from './single-category-banner.props.autogenerated';\r\n\r\nexport interface IContentBlockViewProps extends ISingleCategoryBannerProps<{}> {\r\n title?: React.ReactNode;\r\n text?: React.ReactNode;\r\n image?: React.ReactNode;\r\n links?: ILinksData[];\r\n className?: string;\r\n contentBlockContainer: IModuleProps;\r\n imageContainer: INodeProps;\r\n detailsContainer: INodeProps;\r\n unbxdBannerHTML?: string;\r\n unbxdImageURL?: string;\r\n contentBlockAnchorTag?: INodeProps;\r\n useSeoData?: boolean;\r\n seoData?: any,\r\n useDynamicImages?: boolean;\r\n dynamicImages?: IDynamicImagesData;\r\n imageLink?: string;\r\n imageAriaLabel?: string;\r\n showServerSideBanner: boolean;\r\n telemetryContent?: ITelemetryContent;\r\n handleTextChange?(): (event: Msdyn365.ContentEditableEvent) => string;\r\n}\r\n\r\ninterface ISingleCategoryBannerState {\r\n showServerSideBanner: boolean;\r\n}\r\n\r\n/**\r\n *\r\n * ContentCard component\r\n * @extends {React.PureComponent}\r\n */\r\n\r\nclass ContentBlock extends React.PureComponent, ISingleCategoryBannerState> {\r\n private telemetryContent: ITelemetryContent = getTelemetryObject(this.props.context.request.telemetryPageName!,\r\n this.props.friendlyName,\r\n this.props.telemetry);\r\n\r\n constructor(props: ISingleCategoryBannerProps) {\r\n super(props);\r\n this.state = {\r\n showServerSideBanner: false\r\n };\r\n }\r\n private handleSkeletonLoading = () => {\r\n if (MsDyn365.isBrowser) {\r\n try {\r\n const bannerImage: HTMLCollectionOf = document.getElementsByClassName(\"single-category-banner-image\");\r\n const bannerImagesSkeleton: HTMLElement | null = document.querySelector(\".single-category-banner-skeleton\");\r\n const bannerImageSelector: HTMLElement | null = document.querySelector(\".single-category-banner-image\");\r\n if (bannerImagesSkeleton && bannerImageSelector && bannerImage[0]?.complete && bannerImage[0]?.naturalHeight !== 0) {\r\n bannerImagesSkeleton.style.display = 'none';\r\n bannerImageSelector.style.display = 'block';\r\n } else if (bannerImagesSkeleton) {\r\n bannerImagesSkeleton.style.display = 'none';\r\n if (bannerImageSelector) {\r\n bannerImageSelector.style.display = 'block';\r\n }\r\n }\r\n } catch (error) {\r\n console.error('error[handleSkeletonLoading]', error);\r\n }\r\n }\r\n\r\n };\r\n public componentDidMount(): void {\r\n const activeProducts = (this.props.data?.listPageState?.result && this.props.data?.listPageState?.result?.activeProducts) || [];\r\n const extProperties = activeProducts && activeProducts.length > 0 && activeProducts[0]?.ExtensionProperties;\r\n const unbxdImageURL = extProperties && extProperties?.find(obj => obj?.Key === 'ImageURL')?.Value?.StringValue;\r\n const unbxdBannerHTMLRaw = extProperties && extProperties?.find(obj => obj?.Key === 'BannerHTML')?.Value?.StringValue;\r\n if (!(unbxdBannerHTMLRaw && unbxdImageURL)) {\r\n this.setState({ showServerSideBanner: true });\r\n }\r\n }\r\n\r\n // tslint:disable-next-line: cyclomatic-complexity max-func-body-length\r\n public render(): JSX.Element | null {\r\n const {\r\n heading,\r\n paragraph,\r\n image,\r\n links,\r\n className,\r\n useDynamicImages,\r\n dynamicImages,\r\n imageAriaLabel,\r\n useSeoData\r\n } = this.props.config;\r\n const activeProducts = (this.props.data?.listPageState?.result && this.props.data?.listPageState?.result?.activeProducts) || [];\r\n const activeFilters = (this.props.data?.listPageState?.result && this.props.data?.listPageState?.result?.activeFilters) || [];\r\n const isShowUnbxdBanner = activeFilters?.length > 1 ? false : true;\r\n const extProperties = activeProducts && activeProducts.length > 0 && activeProducts[0]?.ExtensionProperties;\r\n const unbxdImageURL = extProperties && extProperties?.find(obj => obj?.Key === 'ImageURL')?.Value?.StringValue;\r\n const unbxdLandingURL = extProperties && extProperties?.find(obj => obj?.Key === 'LandingURL')?.Value?.StringValue;\r\n const unbxdBannerHTMLRaw = extProperties && extProperties?.find(obj => obj?.Key === 'BannerHTML')?.Value?.StringValue;\r\n this.handleSkeletonLoading();\r\n const contentBlockTitle = heading && (\r\n \r\n );\r\n const imageProps = {\r\n gridSettings: this.props.context.request.gridSettings || {},\r\n imageSettings: image && image.imageSettings\r\n };\r\n const contentBlockLinks = links && links.length > 0 && (\r\n \r\n );\r\n const contentBlockText = paragraph && (\r\n \r\n );\r\n const contentBlockImage = image && (\r\n \r\n );\r\n if (\r\n !contentBlockTitle &&\r\n !contentBlockText &&\r\n !contentBlockImage &&\r\n !contentBlockLinks\r\n ) {\r\n this.props.context.telemetry.warning(\r\n 'Content block content is empty, module wont render.'\r\n );\r\n return null;\r\n }\r\n\r\n const contentBlockviewProps = {\r\n ...this.props,\r\n title: contentBlockTitle,\r\n text: contentBlockText,\r\n image: contentBlockImage,\r\n links: links,\r\n useSeoData: useSeoData,\r\n seoData: this.props.data.seoData?.result,\r\n useDynamicImages: useDynamicImages,\r\n dynamicImages: dynamicImages,\r\n moduleClass: this.props.config.className,\r\n contentBlockContainer: {\r\n moduleProps: this.props,\r\n className: classnames('ms-content-block', className)\r\n },\r\n imageContainer: { className: 'ms-content-block__image' },\r\n detailsContainer: { className: 'ms-content-block__details' },\r\n contentBlockAnchorTag: {\r\n tag: 'a',\r\n className: 'ms-content-block__link',\r\n role: 'link'\r\n },\r\n imageLink: unbxdImageURL && unbxdLandingURL ? unbxdLandingURL : this._getImageLink(),\r\n imageAriaLabel,\r\n telemetryContent: this.telemetryContent,\r\n handleTextChange: this.handleLinkTextChange,\r\n unbxdBannerHTML: unbxdBannerHTMLRaw,\r\n unbxdImageURL: unbxdImageURL,\r\n showServerSideBanner: this.state.showServerSideBanner\r\n };\r\n\r\n let isUnbxdBannerExist = false;\r\n if (unbxdBannerHTMLRaw || unbxdImageURL) {\r\n isUnbxdBannerExist = true;\r\n }\r\n let showBanner = false;\r\n if (!isUnbxdBannerExist && this.props.config.categoryRecordId !== undefined && this.props.config.categoryRecordId !== '') {\r\n const splitCategoryId = this.props.config.categoryRecordId.split(',');\r\n if (splitCategoryId.length > 0) {\r\n splitCategoryId.map((item: string) => {\r\n if (this.props.context.actionContext.requestContext.url.requestUrl.pathname.includes(item)) {\r\n showBanner = true;\r\n }\r\n });\r\n }\r\n }\r\n\r\n if (isShowUnbxdBanner && (showBanner || isUnbxdBannerExist)) {\r\n return this.props.renderView(contentBlockviewProps) as React.ReactElement;\r\n } else {\r\n return null;\r\n }\r\n }\r\n public handleTextChange = (event: Msdyn365.ContentEditableEvent) => (this.props.config.heading!.text = event.target.value);\r\n public handleParagraphChange = (event: Msdyn365.ContentEditableEvent) => (this.props.config.paragraph = event.target.value);\r\n /* Handle link text change*/\r\n public handleLinkTextChange = (linkIndex: number) => (event: Msdyn365.ContentEditableEvent) => {\r\n if (this.props.config.links && this.props.config.links[linkIndex]) {\r\n this.props.config.links[linkIndex].linkText = event.target.value;\r\n }\r\n };\r\n private _getImageLink(): string | null {\r\n const { imageLink, links, actionableRegion } = this.props.config;\r\n if (actionableRegion === region.imageAndLinks) {\r\n if (imageLink && imageLink.destinationUrl) {\r\n return imageLink.destinationUrl;\r\n } else if (links && links.length && links[0].linkUrl) {\r\n return links[0].linkUrl.destinationUrl;\r\n } else {\r\n return null;\r\n }\r\n } else {\r\n return null;\r\n }\r\n }\r\n}\r\n\r\nexport default ContentBlock;\r\n","/*---------------------------------------------------------------------------------------------\r\n * Copyright (c) Microsoft Corporation. All rights reserved.\r\n * Licensed under the MIT License. See License.txt in the project root for license information.\r\n *--------------------------------------------------------------------------------------------*/\r\n/* tslint:disable: no-duplicate-imports */\r\nimport { Module, Node } from '@msdyn365-commerce-modules/utilities';\r\nimport MsDyn365, { IImageData } from '@msdyn365-commerce/core';\r\nimport * as Msdyn365 from '@msdyn365-commerce/core';\r\nimport * as React from 'react';\r\nimport { useInView } from 'react-intersection-observer';\r\nimport { getPromoAnalyticsConfig } from '../../themes/mattressfirm/views/tealiumAnalytics/analytics';\r\nimport { fireAnalyticsLink, IAnalyticsConfiguration } from '../../Utilities/analytics/clickTrack';\r\nimport { htmltoText } from '../../Utilities/analytics/htmlToText';\r\nimport { firePromotionClick, firePromotionImpression } from '../../Utilities/analytics/promotionClickTrack';\r\nimport { getDynamicImageSettings, getResponsiveImage, getResponsiveFromSeoData } from '../../Utilities/get-dynamic-image';\r\nimport _getViewPort from '../../Utilities/get-view-port';\r\nimport LinksComponent from './components/links';\r\nimport { IContentBlockViewProps } from './single-category-banner';\r\nimport CustomSkeleton from '../../themes/mattressfirm/custom-components/CustomSkeleton';\r\n// tslint:disable-next-line: max-func-body-length cyclomatic-complexity\r\nconst ContentBlockView: React.FC = (props) => {\r\n const {\r\n contentBlockContainer,\r\n imageContainer,\r\n detailsContainer,\r\n title,\r\n text,\r\n links,\r\n image,\r\n contentBlockAnchorTag,\r\n imageLink,\r\n useSeoData,\r\n seoData,\r\n useDynamicImages,\r\n dynamicImages,\r\n imageAriaLabel,\r\n unbxdBannerHTML,\r\n unbxdImageURL\r\n } = props;\r\n const { tealiumEvent, enhancedEcommTracking, tealiumPromotion, heading, paragraph } = props.config;\r\n\r\n const isPromotion = enhancedEcommTracking === 'promotion';\r\n const pagePath = MsDyn365.isBrowser ? (window.location.href?.split(location.host)[1]?.includes('?') ? window.location.href.split(location.host)[1].split('?')[0] : window.location.href.split(location.host)[1]) : '';\r\n const paragraphText = paragraph ? htmltoText(paragraph.toString()).trim() : '';\r\n let promoAnalyticsConfig = getPromoAnalyticsConfig(props.config.image, imageLink || links && links[0]?.linkUrl?.destinationUrl, pagePath, paragraphText, tealiumPromotion, true, heading?.text);\r\n\r\n const [ref, inView] = useInView({\r\n triggerOnce: true,\r\n rootMargin: '25px'\r\n });\r\n\r\n const handleAnalytics = (isImageClick?: boolean, ctaUrl?: string) => {\r\n if (MsDyn365.isBrowser) {\r\n const eventActionDefault = isImageClick ? 'image click' : 'CTA click';\r\n const categoryBannerAnalyticsConfig: IAnalyticsConfiguration = {\r\n eventName: tealiumEvent?.event || 'category-banner',\r\n eventCategory: tealiumEvent?.event_category || 'category page banner',\r\n eventAction: tealiumEvent?.event_action || eventActionDefault,\r\n eventLabel: tealiumEvent?.event_label || heading?.text\r\n };\r\n fireAnalyticsLink({ ...categoryBannerAnalyticsConfig });\r\n if (isPromotion) {\r\n if (!isImageClick) {\r\n promoAnalyticsConfig = getPromoAnalyticsConfig(props.config.image, ctaUrl, pagePath, paragraphText, tealiumPromotion, true, heading?.text);\r\n }\r\n promoAnalyticsConfig && firePromotionClick({ ...promoAnalyticsConfig });\r\n }\r\n\r\n if (imageLink) {\r\n window.location.href = imageLink;\r\n } else if (!isImageClick && ctaUrl) {\r\n window.location.href = ctaUrl;\r\n }\r\n }\r\n };\r\n\r\n React.useEffect(() => {\r\n if (MsDyn365.isBrowser && isPromotion && inView) {\r\n promoAnalyticsConfig && firePromotionImpression({ ...promoAnalyticsConfig });\r\n }\r\n }, [inView]);\r\n\r\n let currentImage = image;\r\n\r\n if (useSeoData) {\r\n if (seoData && seoData['Banner State'].includes('Active')) {\r\n const desktopImage: IImageData = {\r\n src: seoData['Desktop Banner URL'],\r\n altText: seoData['H1 Tag'],\r\n title: seoData['H1 Tag']\r\n };\r\n const tabletImage: IImageData = {\r\n src: seoData['Tablet Banner URL'],\r\n altText: seoData['H1 Tag'],\r\n title: seoData['H1 Tag']\r\n };\r\n const mobileImage: IImageData = {\r\n src: seoData['Mobile Banner URL'],\r\n altText: seoData['H1 Tag'],\r\n title: seoData['H1 Tag']\r\n };\r\n\r\n currentImage = getResponsiveFromSeoData({\r\n desktop: desktopImage,\r\n tablet: tabletImage,\r\n mobile: mobileImage,\r\n imageSettingViewports: getDynamicImageSettings({ moduleName: 'mfrm-category-banner' })\r\n });\r\n }\r\n\r\n return (\r\n <>\r\n \r\n {currentImage}\r\n\r\n
\r\n {seoData && seoData['Banner State'].includes('Active') && }\r\n >\r\n\r\n );\r\n } else if (unbxdImageURL || unbxdBannerHTML) {\r\n const unbxdImage = unbxdImageURL && (\r\n <>\r\n \r\n \r\n >\r\n\r\n );\r\n return (\r\n \r\n \r\n \r\n {unbxdBannerHTML ? unbxdBannerHTML : unbxdImage}\r\n \r\n \r\n \r\n );\r\n // Only use Responsive Image if Dynamic Images are defined\r\n } else if (dynamicImages && useDynamicImages) {\r\n currentImage = getResponsiveImage({\r\n desktop: dynamicImages?.desktopImage,\r\n tablet: dynamicImages?.tabletImage,\r\n mobile: dynamicImages?.mobileImage,\r\n defaultImg: props.config.image,\r\n imageSettingViewports: getDynamicImageSettings({ moduleName: 'mfrm-category-banner' })\r\n });\r\n }\r\n if (useDynamicImages) {\r\n return (\r\n <>\r\n {currentImage}
\r\n {currentImage && }\r\n >\r\n\r\n );\r\n }\r\n\r\n if (imageLink) {\r\n return (\r\n \r\n \r\n ) => {\r\n event.preventDefault();\r\n handleAnalytics(true, undefined);\r\n }}\r\n >\r\n {image}\r\n \r\n \r\n \r\n {title}\r\n {text}\r\n {links}\r\n \r\n \r\n );\r\n } else {\r\n return (\r\n \r\n {image}\r\n \r\n {title}\r\n {text}\r\n {props.links && props.links.length > 0 && props.handleTextChange && props.telemetryContent &&\r\n , ctaUrl: string) => {\r\n event.preventDefault();\r\n handleAnalytics(false, ctaUrl);\r\n }\r\n }}\r\n />}\r\n \r\n \r\n );\r\n }\r\n};\r\n\r\nexport default ContentBlockView;\r\n","import React, { FunctionComponent } from 'react';\r\n\r\n\r\ninterface Props {\r\n /** Sets the skeleton-pulse style */\r\n type?: 'text' | 'image' | 'button' | 'button-secondary';\r\n /** Sets the width of the skeleton. Default unit is px. */\r\n width?: number | string;\r\n /** Sets the height of the skeleton. Default unit is px. */\r\n height?: number | string;\r\n /** Makes the skeleton look like a circle */\r\n circle?: boolean;\r\n /** Override classNames on wrapper */\r\n className?: string;\r\n /** Override styles on wrapper */\r\n style?: object;\r\n [rest: string]: unknown; // ...rest property\r\n}\r\n\r\nconst getValidCSSInput = (input: string | number) => {\r\n switch (typeof input) {\r\n case 'undefined':\r\n case 'boolean':\r\n return null;\r\n case 'number':\r\n return `${input}px`;\r\n default:\r\n const parsedInput = parseFloat(input);\r\n const unit = input.match(/%|em/);\r\n return isNaN(parsedInput) ? '' : unit ? `${parsedInput}${unit}` : `${parsedInput}px`;\r\n }\r\n};\r\n\r\nconst CustomSkeleton: FunctionComponent = ({\r\n width,\r\n height,\r\n circle,\r\n type = 'text',\r\n className = '',\r\n style = {},\r\n ...rest\r\n}) => {\r\n const isTextType = type === 'text';\r\n const classNames = `pulse ${!className ? type : ``} ${isTextType ? 'transform' : ''} ${type === 'button-secondary' && !className ? 'button' : ''} ${circle ? 'circle' : ''} ${className}`;\r\n\r\n return (\r\n \r\n );\r\n};\r\n\r\nexport default CustomSkeleton;\r\n","import { IImageData } from '@msdyn365-commerce/core';\r\nimport { ITealiumEventData, ITealiumPromotionData } from '../../definition-extensions/content-block.ext.props.autogenerated';\r\n\r\nexport const getPromoAnalyticsConfig = (image: IImageData | undefined, link: string | undefined, pagePath: string, paragraphText: string, tealiumPromotion: ITealiumPromotionData | undefined, isCategoryBanner?: boolean, headerText?: string) => {\r\n // Use Configured Paragraph text as Promotion Name\r\n let promoName;\r\n if (isCategoryBanner) {\r\n promoName = tealiumPromotion?.promotion_name || headerText || image?.title || image?.altText || '';\r\n } else {\r\n promoName = tealiumPromotion?.promotion_name || paragraphText;\r\n }\r\n // Use Configured Link as Promotion ID\r\n const promoID = tealiumPromotion?.promotion_id || link || '';\r\n // Use Configured Image URL as default Creative\r\n const promoCreative = tealiumPromotion?.promotion_creative_version || image?.title || image?.altText || '';\r\n const promoPosition = tealiumPromotion?.promotion_position || (isCategoryBanner ? '1' : undefined);\r\n\r\n return {\r\n eventLabel: `${promoName} from ${pagePath}`,\r\n promotionName: [promoName],\r\n promotionId: [promoID],\r\n promotionCreative: [promoCreative],\r\n promotionPosition: [promoPosition]\r\n };\r\n};\r\n\r\nexport const getAnalyticsConfig = (pagePath: string, heading: string | undefined, imageAriaLabel: string | undefined, tealiumEvent: ITealiumEventData | undefined) => {\r\n return {\r\n eventName: tealiumEvent?.event || 'content-block',\r\n eventCategory: tealiumEvent?.event_category || `${heading ? heading : imageAriaLabel} container`,\r\n eventType: tealiumEvent?.event_type || '',\r\n eventAction: tealiumEvent?.event_action || `${heading ? heading : imageAriaLabel} click`,\r\n eventLabel: tealiumEvent?.event_label || pagePath\r\n };\r\n};","const binding = { modules: {}, dataActions: {} };\n\n const registerActionId = (actionPath) => {\n if (binding.dataActions[actionPath] &&\n binding.dataActions[actionPath].default &&\n binding.dataActions[actionPath].default.prototype &&\n binding.dataActions[actionPath].default.prototype.id) {\n binding.dataActions[binding.dataActions[actionPath].default.prototype.id] = binding.dataActions[actionPath];\n } else {\n Object.keys(binding.dataActions[actionPath] || {}).forEach(exportName => {\n if (binding.dataActions[actionPath][exportName] &&\n binding.dataActions[actionPath][exportName].prototype &&\n binding.dataActions[actionPath][exportName].prototype.Action) {\n binding.dataActions[binding.dataActions[actionPath][exportName].prototype.id] = binding.dataActions[actionPath][exportName];\n }\n })\n }\n };\n\n const registerSanitizedActionPath = (sanitizedActionPath, dataAction) => {\n if (process.env.NODE_ENV === 'development') {\n if (!dataAction.default) {\n throw new Error('Data action path does not have a default export');\n }\n if (!(dataAction.default.prototype.id && binding.dataActions[dataAction.default.prototype.id]) || !binding.dataActions[sanitizedActionPath]) {\n binding.dataActions[sanitizedActionPath] = dataAction;\n }\n } else {\n binding.dataActions[sanitizedActionPath] = dataAction;\n if (!binding.dataActions[sanitizedActionPath].default) {\n throw new Error('Data action path ' + sanitizedActionPath + ' does not have a default export');\n }\n binding.dataActions[sanitizedActionPath].default.prototype.RegistrationId = sanitizedActionPath;\n if (binding.dataActions[sanitizedActionPath].default.prototype.id) {\n binding.dataActions[binding.dataActions[sanitizedActionPath].default.prototype.id] = sanitizedActionPath;\n }\n }\n };\n \n\n (binding.modules['single-category-banner'] = {\n c: () => require('partner/modules/single-category-banner/single-category-banner.tsx'),\n $type: 'contentModule',\n da: [{name:'listPageState', path:'modules/single-category-banner/list-page-state', runOn: 0},{name:'seoData', path:'data-actions/get-seo-data.action', runOn: 0}],\n \n iNM: false,\n ns: '__local__',\n n: 'single-category-banner',\n p: '__local__',\n \n pdp: '',\n \n \n md: 'src/modules/single-category-banner'\n });\n \n\n {\n const sanitizedActionPath = 'data-actions/get-seo-data.action';\n let dataAction = require('partner/data-actions/get-seo-data.action');\n registerSanitizedActionPath(sanitizedActionPath, dataAction);\n }\n \n\n {\n const sanitizedActionPath = 'modules/single-category-banner/list-page-state';\n let dataAction = require('partner/modules/single-category-banner/list-page-state');\n registerSanitizedActionPath(sanitizedActionPath, dataAction);\n }\n \n\n \n window.__bindings__ = window.__bindings__ || {};\n window.__bindings__.modules = {\n ...window.__bindings__.modules || {},\n ...binding.modules\n };\n \n window.__bindings__.dataActions = {\n ...window.__bindings__.dataActions || {},\n ...binding.dataActions\n };\n export const viewDictionary = {};\n viewDictionary['__local__|__local__|modules|single-category-banner|single-category-banner'] = {\n c: () => require('partner/modules/single-category-banner/single-category-banner.view.tsx'),\n cn: '__local__-__local__-single-category-banner'\n };\nwindow.__bindings__ = window.__bindings__ || {};\nwindow.__bindings__.viewDictionary = {\n ...window.__bindings__.viewDictionary || {},\n ...viewDictionary\n };","'use strict';\nvar call = require('../internals/function-call');\nvar fixRegExpWellKnownSymbolLogic = require('../internals/fix-regexp-well-known-symbol-logic');\nvar anObject = require('../internals/an-object');\nvar isNullOrUndefined = require('../internals/is-null-or-undefined');\nvar toLength = require('../internals/to-length');\nvar toString = require('../internals/to-string');\nvar requireObjectCoercible = require('../internals/require-object-coercible');\nvar getMethod = require('../internals/get-method');\nvar advanceStringIndex = require('../internals/advance-string-index');\nvar regExpExec = require('../internals/regexp-exec-abstract');\n\n// @@match logic\nfixRegExpWellKnownSymbolLogic('match', function (MATCH, nativeMatch, maybeCallNative) {\n return [\n // `String.prototype.match` method\n // https://tc39.es/ecma262/#sec-string.prototype.match\n function match(regexp) {\n var O = requireObjectCoercible(this);\n var matcher = isNullOrUndefined(regexp) ? undefined : getMethod(regexp, MATCH);\n return matcher ? call(matcher, regexp, O) : new RegExp(regexp)[MATCH](toString(O));\n },\n // `RegExp.prototype[@@match]` method\n // https://tc39.es/ecma262/#sec-regexp.prototype-@@match\n function (string) {\n var rx = anObject(this);\n var S = toString(string);\n var res = maybeCallNative(nativeMatch, rx, S);\n\n if (res.done) return res.value;\n\n if (!rx.global) return regExpExec(rx, S);\n\n var fullUnicode = rx.unicode;\n rx.lastIndex = 0;\n var A = [];\n var n = 0;\n var result;\n while ((result = regExpExec(rx, S)) !== null) {\n var matchStr = toString(result[0]);\n A[n] = matchStr;\n if (matchStr === '') rx.lastIndex = advanceStringIndex(S, toLength(rx.lastIndex), fullUnicode);\n n++;\n }\n return n === 0 ? null : A;\n }\n ];\n});\n","'use strict';\nvar apply = require('../internals/function-apply');\nvar call = require('../internals/function-call');\nvar uncurryThis = require('../internals/function-uncurry-this');\nvar fixRegExpWellKnownSymbolLogic = require('../internals/fix-regexp-well-known-symbol-logic');\nvar anObject = require('../internals/an-object');\nvar isNullOrUndefined = require('../internals/is-null-or-undefined');\nvar isRegExp = require('../internals/is-regexp');\nvar requireObjectCoercible = require('../internals/require-object-coercible');\nvar speciesConstructor = require('../internals/species-constructor');\nvar advanceStringIndex = require('../internals/advance-string-index');\nvar toLength = require('../internals/to-length');\nvar toString = require('../internals/to-string');\nvar getMethod = require('../internals/get-method');\nvar arraySlice = require('../internals/array-slice-simple');\nvar callRegExpExec = require('../internals/regexp-exec-abstract');\nvar regexpExec = require('../internals/regexp-exec');\nvar stickyHelpers = require('../internals/regexp-sticky-helpers');\nvar fails = require('../internals/fails');\n\nvar UNSUPPORTED_Y = stickyHelpers.UNSUPPORTED_Y;\nvar MAX_UINT32 = 0xFFFFFFFF;\nvar min = Math.min;\nvar $push = [].push;\nvar exec = uncurryThis(/./.exec);\nvar push = uncurryThis($push);\nvar stringSlice = uncurryThis(''.slice);\n\n// Chrome 51 has a buggy \"split\" implementation when RegExp#exec !== nativeExec\n// Weex JS has frozen built-in prototypes, so use try / catch wrapper\nvar SPLIT_WORKS_WITH_OVERWRITTEN_EXEC = !fails(function () {\n // eslint-disable-next-line regexp/no-empty-group -- required for testing\n var re = /(?:)/;\n var originalExec = re.exec;\n re.exec = function () { return originalExec.apply(this, arguments); };\n var result = 'ab'.split(re);\n return result.length !== 2 || result[0] !== 'a' || result[1] !== 'b';\n});\n\n// @@split logic\nfixRegExpWellKnownSymbolLogic('split', function (SPLIT, nativeSplit, maybeCallNative) {\n var internalSplit;\n if (\n 'abbc'.split(/(b)*/)[1] === 'c' ||\n // eslint-disable-next-line regexp/no-empty-group -- required for testing\n 'test'.split(/(?:)/, -1).length !== 4 ||\n 'ab'.split(/(?:ab)*/).length !== 2 ||\n '.'.split(/(.?)(.?)/).length !== 4 ||\n // eslint-disable-next-line regexp/no-empty-capturing-group, regexp/no-empty-group -- required for testing\n '.'.split(/()()/).length > 1 ||\n ''.split(/.?/).length\n ) {\n // based on es5-shim implementation, need to rework it\n internalSplit = function (separator, limit) {\n var string = toString(requireObjectCoercible(this));\n var lim = limit === undefined ? MAX_UINT32 : limit >>> 0;\n if (lim === 0) return [];\n if (separator === undefined) return [string];\n // If `separator` is not a regex, use native split\n if (!isRegExp(separator)) {\n return call(nativeSplit, string, separator, lim);\n }\n var output = [];\n var flags = (separator.ignoreCase ? 'i' : '') +\n (separator.multiline ? 'm' : '') +\n (separator.unicode ? 'u' : '') +\n (separator.sticky ? 'y' : '');\n var lastLastIndex = 0;\n // Make `global` and avoid `lastIndex` issues by working with a copy\n var separatorCopy = new RegExp(separator.source, flags + 'g');\n var match, lastIndex, lastLength;\n while (match = call(regexpExec, separatorCopy, string)) {\n lastIndex = separatorCopy.lastIndex;\n if (lastIndex > lastLastIndex) {\n push(output, stringSlice(string, lastLastIndex, match.index));\n if (match.length > 1 && match.index < string.length) apply($push, output, arraySlice(match, 1));\n lastLength = match[0].length;\n lastLastIndex = lastIndex;\n if (output.length >= lim) break;\n }\n if (separatorCopy.lastIndex === match.index) separatorCopy.lastIndex++; // Avoid an infinite loop\n }\n if (lastLastIndex === string.length) {\n if (lastLength || !exec(separatorCopy, '')) push(output, '');\n } else push(output, stringSlice(string, lastLastIndex));\n return output.length > lim ? arraySlice(output, 0, lim) : output;\n };\n // Chakra, V8\n } else if ('0'.split(undefined, 0).length) {\n internalSplit = function (separator, limit) {\n return separator === undefined && limit === 0 ? [] : call(nativeSplit, this, separator, limit);\n };\n } else internalSplit = nativeSplit;\n\n return [\n // `String.prototype.split` method\n // https://tc39.es/ecma262/#sec-string.prototype.split\n function split(separator, limit) {\n var O = requireObjectCoercible(this);\n var splitter = isNullOrUndefined(separator) ? undefined : getMethod(separator, SPLIT);\n return splitter\n ? call(splitter, separator, O, limit)\n : call(internalSplit, toString(O), separator, limit);\n },\n // `RegExp.prototype[@@split]` method\n // https://tc39.es/ecma262/#sec-regexp.prototype-@@split\n //\n // NOTE: This cannot be properly polyfilled in engines that don't support\n // the 'y' flag.\n function (string, limit) {\n var rx = anObject(this);\n var S = toString(string);\n var res = maybeCallNative(internalSplit, rx, S, limit, internalSplit !== nativeSplit);\n\n if (res.done) return res.value;\n\n var C = speciesConstructor(rx, RegExp);\n\n var unicodeMatching = rx.unicode;\n var flags = (rx.ignoreCase ? 'i' : '') +\n (rx.multiline ? 'm' : '') +\n (rx.unicode ? 'u' : '') +\n (UNSUPPORTED_Y ? 'g' : 'y');\n\n // ^(? + rx + ) is needed, in combination with some S slicing, to\n // simulate the 'y' flag.\n var splitter = new C(UNSUPPORTED_Y ? '^(?:' + rx.source + ')' : rx, flags);\n var lim = limit === undefined ? MAX_UINT32 : limit >>> 0;\n if (lim === 0) return [];\n if (S.length === 0) return callRegExpExec(splitter, S) === null ? [S] : [];\n var p = 0;\n var q = 0;\n var A = [];\n while (q < S.length) {\n splitter.lastIndex = UNSUPPORTED_Y ? 0 : q;\n var z = callRegExpExec(splitter, UNSUPPORTED_Y ? stringSlice(S, q) : S);\n var e;\n if (\n z === null ||\n (e = min(toLength(splitter.lastIndex + (UNSUPPORTED_Y ? q : 0)), S.length)) === p\n ) {\n q = advanceStringIndex(S, q, unicodeMatching);\n } else {\n push(A, stringSlice(S, p, q));\n if (A.length === lim) return A;\n for (var i = 1; i <= z.length - 1; i++) {\n push(A, z[i]);\n if (A.length === lim) return A;\n }\n q = p = e;\n }\n }\n push(A, stringSlice(S, p));\n return A;\n }\n ];\n}, !SPLIT_WORKS_WITH_OVERWRITTEN_EXEC, UNSUPPORTED_Y);\n","module.exports = React;","module.exports = ReactDOM;"],"names":["fireAnalyticsLink","_ref","searchTerm","searchType","eventName","eventCategory","eventAction","eventLabel","eventType","eventNoninteraction","enhancedAction","generalConfig","promoConfig","productConfig","customerConfig","productImpressionConfig","callUtagLink","_objectSpread","event","event_category","event_action","event_label","event_type","event_noninteraction","enhanced_action","search_term","search_type","htmltoText","html","MsDyn365","isBrowser","tempDivElement","document","createElement","innerHTML","textContent","innerText","firePromotionImpression","promotionName","promotionId","promotionCreative","promotionPosition","promotion_impression_name","promotion_impression_id","promotion_impression_creative","promotion_impression_position","firePromotionClick","_ref2","promotion_name","promotion_id","promotion_creative","promotion_position","callUtag","async","objToCall","Object","keys","forEach","key","utag","global","hasOwnProperty","link","e","console","log","callUtagView","view","getResponsiveFromSeoData","desktop","tablet","mobile","query","React","src","media","srcSet","className","alt","altText","getResponsiveImage","_defaultImg$imageSett","_defaultImg$imageSett2","defaultImg","lazyload","imageSettings","disableLazyLoad","defaultImgSrc","quality","getDynamicImageSettings","_ref3","_MsDyn365$themeSettin","moduleName","viewports","undefined","themeSettingsForModule","themeSettings","mattressfirm","modules","themeSettingsForLayout","properties","dynamic","imageViewportProperties","_get","_cloneDeep","canonicalURL","requestContext","_urlParts","requestUrl","url","origin","path","pathname","toLowerCase","urlParts","split","splice","match","removePipeSignValue","removeKeywords","join","filteredURL","_urlParts2","length","filter","urlPart","indexOf","removeKeywordFromUrl","app","config","removeKeywordFromUrlArray","trim","_part","removeKeyword","trimmedKeyword","indexOfValue","getSortedVirtualRefinerConfig","isMattressesCategory","appConfigSorted","getVirtualRefinerConfig","appConfig","enableForMattresses","enableForOtherCategories","sort","a","b","order","getVirtualRefinerNames","sortedVirtualRefinerConfig","appConfigRefinerNames","sortedConfig","push","refinerName","urlModifications","getVirtualRefinerValues","virtualRefiners","virtualRefinerValues","categoryIdToken","urlTokens","recordId","finalizedUrlParts","plainUrlPart","decodeURIComponent","part","filteredPart","mainRefiner","Values","refinerValue","_refinerValue$LeftVal","refinerValueKeyName","LeftValueBoundString","replace","regExSpecialChars","canonicalUrlspecialCharIncludeList","navLinkKeywordRemoval","_linkParams$map","_urlParts4","linkBase","linkParams","endsWith","linkParam","map","param","includeConfigList","includeConfig","_includeConfigList$tr","RegExp","GetSeoDataInput","Msdyn365","constructor","seoDataUrl","super","shouldCacheOutput","cacheObjectType","cacheKey","getSeoDataUrl","this","getCacheKey","getCacheObjectType","dataCacheType","id","action","input","ctx","jsonUrl","res","filteredUrlPath","seoData","data","inputData","ContentCardLinks","_mapEditableLinks","linkdata","editableLinks","index","payLoad","getPayloadObject","props","telemetryContent","linkText","contentAction","etext","attributes","getTelemetryAttributes","btnClass","editableLink","ariaLabel","linkUrl","destinationUrl","openInNewTab","role","additionalProperties","onClick","onTelemetryClick","render","links","editProps","onTextChange","ListPageState","activeFilters","activeProducts","__decorate","observable","ListPageStateInput","listPageStateAction","createListPageInput","createObservableDataAction","imagePosition","actionableRegion","enhancedEcommTracking","HeadingTag","ContentBlock","getTelemetryObject","context","request","telemetryPageName","friendlyName","telemetry","handleSkeletonLoading","_bannerImage$","_bannerImage$2","bannerImage","getElementsByClassName","bannerImagesSkeleton","querySelector","bannerImageSelector","complete","naturalHeight","style","display","error","handleTextChange","heading","text","target","value","handleParagraphChange","paragraph","handleLinkTextChange","linkIndex","state","showServerSideBanner","componentDidMount","_this$props$data","_this$props$data2","_activeProducts$","_extProperties$find","_extProperties$find2","listPageState","result","extProperties","ExtensionProperties","unbxdImageURL","find","obj","Key","Value","StringValue","setState","_this$props$data3","_this$props$data4","_this$props$data5","_this$props$data6","_activeProducts$2","_extProperties$find3","_extProperties$find4","_extProperties$find5","_this$props$data$seoD","image","useDynamicImages","dynamicImages","imageAriaLabel","useSeoData","isShowUnbxdBanner","unbxdLandingURL","unbxdBannerHTMLRaw","contentBlockTitle","tag","onEdit","imageProps","gridSettings","contentBlockLinks","LinksComponent","assign","contentBlockText","contentBlockImage","warning","contentBlockviewProps","title","moduleClass","contentBlockContainer","moduleProps","classnames","imageContainer","detailsContainer","contentBlockAnchorTag","imageLink","_getImageLink","unbxdBannerHTML","isUnbxdBannerExist","showBanner","categoryRecordId","splitCategoryId","item","actionContext","includes","renderView","region","imageAndLinks","_window$location$href","_links$","tealiumEvent","tealiumPromotion","isPromotion","pagePath","window","location","href","host","paragraphText","toString","promoAnalyticsConfig","getPromoAnalyticsConfig","ref","inView","useInView","triggerOnce","rootMargin","handleAnalytics","isImageClick","ctaUrl","eventActionDefault","categoryBannerAnalyticsConfig","currentImage","desktopImage","tabletImage","mobileImage","imageSettingViewports","CustomSkeleton","type","unbxdImage","Module","Node","preventDefault","onClickOverride","getValidCSSInput","parsedInput","parseFloat","unit","isNaN","_getValidCSSInput","_getValidCSSInput2","width","height","circle","rest","_objectWithoutProperties","_excluded","classNames","borderRadius","isCategoryBanner","headerText","promoName","promotion_creative_version","getAnalyticsConfig","binding","dataActions","registerSanitizedActionPath","sanitizedActionPath","dataAction","default","Error","prototype","RegistrationId","c","require","$type","da","name","runOn","iNM","ns","n","p","pdp","md","__bindings__","viewDictionary","cn","call","fixRegExpWellKnownSymbolLogic","anObject","isNullOrUndefined","toLength","requireObjectCoercible","getMethod","advanceStringIndex","regExpExec","MATCH","nativeMatch","maybeCallNative","regexp","O","matcher","string","rx","S","done","fullUnicode","unicode","lastIndex","A","matchStr","apply","uncurryThis","isRegExp","speciesConstructor","arraySlice","callRegExpExec","regexpExec","stickyHelpers","fails","UNSUPPORTED_Y","MAX_UINT32","min","Math","$push","exec","stringSlice","slice","SPLIT","nativeSplit","internalSplit","separator","limit","lim","lastLength","output","flags","ignoreCase","multiline","sticky","lastLastIndex","separatorCopy","source","splitter","C","unicodeMatching","q","z","i","re","originalExec","arguments","module","exports","ReactDOM"],"sourceRoot":""}