{"version":3,"sources":["webpack:///./src/Frontend/app/components/product-details/product-hero/product-hero.tsx","webpack:///./src/Frontend/app/components/product-image-modal/product-image-modal.tsx","webpack:///./src/Frontend/app/utils/theme-colors.ts","webpack:///./src/Frontend/app/utils/theming-utils.ts","webpack:///./src/Frontend/app/components/icons/icon.tsx","webpack:///./src/Frontend/app/components/arrow-link/arrow-link.tsx","webpack:///./src/Frontend/app/utils/breakpoint-utils.ts","webpack:///./src/Frontend/app/components/tag/tag.tsx","webpack:///./src/Frontend/app/utils/tracking-utils.ts","webpack:///./src/Frontend/app/components/product-image/product-image.tsx","webpack:///./src/Frontend/app/components/product-authors/product-authors.tsx","webpack:///./src/Frontend/app/components/show-more/show-more.tsx","webpack:///./src/Frontend/app/components/modal/modal.tsx","webpack:///./src/Frontend/app/components/input-select/input-select.tsx","webpack:///./src/Frontend/app/hooks/useShuffleIndex.ts","webpack:///./src/Frontend/app/components/tabs/tabs.tsx","webpack:///./src/Frontend/app/components/tabs/tab-menu/tab-menu.tsx","webpack:///./src/Frontend/app/components/tabs/tab-content-container/tab-content-container.tsx","webpack:///./src/Frontend/app/components/tabs/tab-content/tab-content.tsx","webpack:///./src/Frontend/app/components/icon-button/icon-button.tsx","webpack:///./src/Frontend/app/components/icon-link/icon-link.tsx","webpack:///./src/Frontend/app/components/specifications-list/specifications-list.tsx","webpack:///./src/Frontend/app/components/product-details/product-description/product-description.tsx","webpack:///./src/Frontend/app/components/work-details/work-variant-form/work-variant-form.tsx","webpack:///./src/Frontend/app/components/product-details/book-reading-modal/book-reading-modal.tsx","webpack:///./src/Frontend/app/components/product-details/audio-modal/audio-modal.tsx","webpack:///./src/Frontend/app/components/product-details/product-details.tsx"],"names":["state","isProductImageLoaded","isTimeoutOver","isModalOpen","requestAnimationFrameIndex","componentDidMount","this","window","requestAnimationFrame","setState","componentWillUnmount","cancelAnimationFrame","handleProductImageLoad","productImage","render","baseClass","productHeroClasses","graphicsClasses","className","global","currentSite","iconId","viewBox","props","imageSrcSet","alt","onClick","sizes","srcSet","fallbackSrc","imageFallbackSrc","onLoad","ref","node","crossOrigin","readBookLabel","readBookPlayerLink","listenToBookLabel","listenToBookPlayerLink","downloadCoverImageLabel","downloadCoverImageLink","innerClassName","onOpenBookModal","onOpenAudioModal","href","download","onRequestClose","isOpen","isZoomedIn","setIsZoomedIn","classes","event","stopPropagation","onClose","noContainerMarkup","type","rgbToHsl","r","g","b","max","Math","min","h","s","l","d","hue","saturation","lightness","findMatchingTheme","nums","target","closest","primaryThemeHues","map","color","Number","MAX_SAFE_INTEGER","reduce","indexOfClosest","number","index","dist","abs","img","colorThiefResult","getPalette","dominantColor","matchingThemeIndex","themeTarget","document","body","currentTheme","match","classList","remove","add","spriteUrl","preserveAspectRatio","xmlnsXlink","xlinkHref","link","componentClasses","dangerouslySetInnerHTML","__html","breakpoints","rat","rabbit","cat","dog","wolf","lion","horse","rhino","elephant","mediaQueries","Object","keys","queryStrings","key","currentMediaQueries","handleMediaMatch","isMatching","forEach","mediaQuery","matchMedia","matches","addListener","tagTypeClassMap","NEWS","SPOT","BESTSELLER","BOOK_OF_THE_MONTH","UPCOMING","classModifier","rootClasses","shape","children","EventTypes","CurrencyCodes","TrackingDimensions","ensureDataLayer","dataLayer","pushEcommerenceTrackingEvent","trackingEvent","push","pushTrackingEvent","pushClickTrackingEvent","trackingList","trackingPosition","productId","title","CLICK","ecommerce","click","actionField","list","products","id","name","position","pushDetailViewTrackingEvent","DETAIL_VIEW","detail","pushImpressionViewTrackingEvent","IMPRESSION_VIEW","impressions","product","ProductImage","loading","src","authors","maxLines","length","Wrapper","lines","author","url","showMoreHasOverflow","showMoreIsOpen","addEventListener","handleResize","bind","removeEventListener","disableOnBreakpoint","minHeight","disableOverflow","hasOverflow","childrenWrapper","clientHeight","toggleMore","btnLabelShowLess","btnLabelShowMore","containerClasses","setAnimateToMinHeight","btnText","height","duration","setAppElement","overlayClassName","options","label","touched","error","defaultLabel","excludeDefaultOption","readyForSorting","enableInlineError","forceErrorStyling","input","onChange","allOptions","value","inputHasError","dropdownVisible","setDropdownVisible","initial","currentIndex","setCurrentIndex","shuffleAction","useShuffleIndex","shuffle","dropdownRef","isAValueSelected","currentlySelectedOption","find","option","toggleDropdown","toggleState","onBlur","current","contains","relatedTarget","activeElement","htmlFor","onKeyPress","preventDefault","onKeyDown","supportsNativeSmoothScroll","documentElement","style","keyCode","nextIndex","currentElement","querySelector","scrollIntoView","behavior","block","navigator","userAgent","toLowerCase","indexOf","role","isOptionSelected","tabIndex","dataValue","getAttribute","parseInt","disabled","selectedTabKey","defaultTab","tabClickHandler","tabId","getRenderProps","renderProps","tabs","tab","btnClassName","selectedKey","e","isCurrent","isLarge","isInverted","isSecondary","renderedButton","renderedLink","header","specifications","item","valuesArray","subItem","subItemIndex","text","keyName","trim","replace","filter","str","productDescriptionTab","content","productDescriptionShowMoreButton","productDescriptionShowLessButton","productDescription","productSpecificationsTab","productSpecifications","productPressSpecificationsTab","productPressSpecifications","reduxForm","form","destroyOnUnmount","values","_","onVariantSelect","change","selectedVariant","variants","variantsLabel","undefined","materialType","String","Field","component","fieldName","playerLink","rest","controls","initialVariantIndex","vendorListTitle","vendorList","primaryPriceLabel","bookModalOpen","setBookModalOpen","audioModalOpen","setAudioModalOpen","hasSignupCta","productSignupCtaLink","productSignupCtaText","productSignupCtaTitle","hasVendorList","buyingSectionClasses","status","statusLabel","description","primaryPrice","initialValues","includes"],"mappings":"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","file":"4.62b9d38aa54bcb533271.js","sourcesContent":["import * as React from \"react\";\r\nimport classNames from \"classnames\";\r\nimport Icon from \"~/components/icons/icon\";\r\nimport setThemeFromImg from \"~/utils/theming-utils\";\r\nimport { IProduct } from \"~/types/product\";\r\n// import ProductDiscountSplash from \"~/components/product-discount-splash/product-discount-splash\";\r\nimport ProductImage from \"~/components/product-image/product-image\";\r\nimport ProductImageModal from \"~/components/product-image-modal/product-image-modal\";\r\nimport IconButton from \"~/components/icon-button/icon-button\";\r\nimport IconLink from \"~/components/icon-link/icon-link\";\r\n\r\nexport interface IProductHeroProps extends Pick<IProduct, \"imageFallbackSrc\" | \"imageSrcSet\"> {\r\n    // discount: IProduct[\"discount\"];\r\n    readBookLabel?: string;\r\n    readBookPlayerLink?: string;\r\n    listenToBookLabel?: string;\r\n    listenToBookPlayerLink?: string;\r\n    downloadCoverImageLabel?: string;\r\n    downloadCoverImageLink?: string;\r\n    onOpenAudioModal(): void;\r\n    onOpenBookModal(): void;\r\n}\r\n\r\nexport interface IProductHeroState {\r\n    isProductImageLoaded: boolean;\r\n    isTimeoutOver: boolean;\r\n    isModalOpen: boolean;\r\n}\r\n\r\nclass ProductHero extends React.Component<IProductHeroProps, IProductHeroState> {\r\n    private productImage: HTMLImageElement;\r\n    public state: IProductHeroState = {\r\n        isProductImageLoaded: false,\r\n        isTimeoutOver: false,\r\n        isModalOpen: false\r\n    };\r\n\r\n    private requestAnimationFrameIndex = 0;\r\n\r\n    public componentDidMount() {\r\n        this.requestAnimationFrameIndex = window.requestAnimationFrame(() =>\r\n            this.setState({ isTimeoutOver: true })\r\n        );\r\n    }\r\n\r\n    public componentWillUnmount() {\r\n        window.cancelAnimationFrame(this.requestAnimationFrameIndex);\r\n    }\r\n\r\n    private handleProductImageLoad() {\r\n        this.setState({ isProductImageLoaded: true });\r\n        setThemeFromImg(this.productImage);\r\n    }\r\n\r\n    public render() {\r\n        const baseClass = \"product-hero\";\r\n        const productHeroClasses = classNames(baseClass, {\r\n            [`${baseClass}--imageIsLoaded`]: this.state.isProductImageLoaded\r\n        });\r\n        const graphicsClasses = classNames(`${baseClass}__graphics`, {\r\n            [`${baseClass}__graphics--show`]: this.state.isProductImageLoaded\r\n        });\r\n\r\n        return (\r\n            <>\r\n                <div className={productHeroClasses}>\r\n                    <div className={`${baseClass}__image-container`}>\r\n                        <div className={`${baseClass}-background theme-bg-secondary`} />\r\n                        {/* Mobile icon */}\r\n                        <div className={graphicsClasses}>\r\n                            {this.state.isProductImageLoaded && (\r\n                                <>\r\n                                    {global.currentSite === \"ClubGyldendalDk\" ? null : (\r\n                                        <Icon\r\n                                            className=\"theme-color-primary\"\r\n                                            iconId=\"icon_80x48_quotation-mark\"\r\n                                            viewBox=\"0 0 80 48\"\r\n                                        />\r\n                                    )}\r\n                                </>\r\n                            )}\r\n                        </div>\r\n                        {this.state.isTimeoutOver && (\r\n                            <div className={`${baseClass}__image-wrapper`}>\r\n                                {this.props.imageSrcSet && (\r\n                                    <ProductImage\r\n                                        alt=\"Product image\"\r\n                                        onClick={() => this.setState({ isModalOpen: true })}\r\n                                        className={`${baseClass}__image`}\r\n                                        sizes=\"(max-width: 639px) calc((100vw - 48px) * 0.75), (max-width: 1039px) calc((100vw - 32px) * 0.2), 200px\"\r\n                                        srcSet={this.props.imageSrcSet}\r\n                                        fallbackSrc={this.props.imageFallbackSrc}\r\n                                        onLoad={() => this.handleProductImageLoad()}\r\n                                        ref={(node: any) => {\r\n                                            if (node) {\r\n                                                // Required for color sampling MMS images\r\n                                                node.crossOrigin = \"Anonymous\";\r\n                                                this.productImage = node;\r\n                                            }\r\n                                        }}\r\n                                    />\r\n                                )}\r\n                                {/* {this.props.discount && (\r\n                                    <ProductDiscountSplash discount={this.props.discount} />\r\n                                )} */}\r\n                                {((this.props.readBookLabel && this.props.readBookPlayerLink) ||\r\n                                    (this.props.listenToBookLabel && this.props.listenToBookPlayerLink) ||\r\n                                    (this.props.downloadCoverImageLabel &&\r\n                                        this.props.downloadCoverImageLink)) && (\r\n                                    <div className={`${baseClass}__actions`}>\r\n                                        {this.props.readBookLabel && this.props.readBookPlayerLink && (\r\n                                            <IconButton\r\n                                                className={`${baseClass}__play-button`}\r\n                                                innerClassName={`${baseClass}__inner-play-button`}\r\n                                                onClick={this.props.onOpenBookModal}\r\n                                                iconId=\"icon_read\"\r\n                                            />\r\n                                        )}\r\n                                        {this.props.listenToBookLabel &&\r\n                                            this.props.listenToBookPlayerLink && (\r\n                                                <IconButton\r\n                                                    className={`${baseClass}__play-button`}\r\n                                                    innerClassName={`${baseClass}__inner-play-button`}\r\n                                                    onClick={this.props.onOpenAudioModal}\r\n                                                    iconId=\"icon_listen\"\r\n                                                />\r\n                                            )}\r\n\r\n                                        {this.props.downloadCoverImageLabel &&\r\n                                            this.props.downloadCoverImageLink && (\r\n                                                <IconLink\r\n                                                    className={`${baseClass}__play-button`}\r\n                                                    innerClassName={`${baseClass}__inner-play-button`}\r\n                                                    href={this.props.downloadCoverImageLink}\r\n                                                    download\r\n                                                    iconId=\"icon_download\"\r\n                                                />\r\n                                            )}\r\n                                    </div>\r\n                                )}\r\n                            </div>\r\n                        )}\r\n                    </div>\r\n                    <div className={`${baseClass}__gallery-container`}>\r\n                        <div className={`${baseClass}-background theme-bg-tertiary`} />\r\n                        {/* Desktop icon */}\r\n                        <div className={graphicsClasses}>\r\n                            {this.state.isProductImageLoaded && (\r\n                                <>\r\n                                    {global.currentSite === \"ClubGyldendalDk\" ? null : (\r\n                                        <Icon\r\n                                            className=\"theme-color-primary\"\r\n                                            iconId=\"icon_80x48_quotation-mark\"\r\n                                            viewBox=\"0 0 80 48\"\r\n                                        />\r\n                                    )}\r\n                                </>\r\n                            )}\r\n                        </div>\r\n                    </div>\r\n                    <div className={`${baseClass}__box`}>\r\n                        <div className={`${baseClass}-background theme-bg-quaternary`} />\r\n                    </div>\r\n                </div>\r\n                <ProductImageModal\r\n                    onRequestClose={() => this.setState({ isModalOpen: false })}\r\n                    isOpen={this.state.isModalOpen}\r\n                    imageSrcSet={this.props.imageSrcSet}\r\n                    imageFallbackSrc={this.props.imageFallbackSrc}\r\n                />\r\n            </>\r\n        );\r\n    }\r\n}\r\n\r\nexport default ProductHero;\r\n","import * as React from \"react\";\r\nimport Modal, { IModalProps } from \"~/components/modal/modal\";\r\nimport ProductImage from \"~/components/product-image/product-image\";\r\nimport { IProduct } from \"~/types/product\";\r\nimport Icon from \"../icons/icon\";\r\nimport classNames from \"classnames\";\r\n\r\nexport interface ProductImageModalProps\r\n    extends Pick<IProduct, \"imageSrcSet\" | \"imageFallbackSrc\">,\r\n        Pick<IModalProps, \"isOpen\" | \"onRequestClose\"> {}\r\n\r\nconst ProductImageModal: React.FC<ProductImageModalProps> = props => {\r\n    const baseClass = \"product-image-modal\";\r\n    const [isZoomedIn, setIsZoomedIn] = React.useState(false);\r\n    const classes = classNames(baseClass, { [`${baseClass}--zoomed-in`]: isZoomedIn });\r\n\r\n    const onClick = React.useCallback(\r\n        (event: React.MouseEvent<HTMLImageElement, MouseEvent>) => {\r\n            event.stopPropagation();\r\n            setIsZoomedIn(!isZoomedIn);\r\n        },\r\n        [isZoomedIn]\r\n    );\r\n\r\n    if (!props.imageSrcSet) {\r\n        return null;\r\n    }\r\n\r\n    const onClose = () => {\r\n        props.onRequestClose?.();\r\n        setIsZoomedIn(false);\r\n    };\r\n\r\n    return (\r\n        <Modal className={classes} noContainerMarkup isOpen={props.isOpen}>\r\n            <div className={`${baseClass}__inner`} onClick={onClose}>\r\n                <ProductImage\r\n                    srcSet={props.imageSrcSet}\r\n                    fallbackSrc={props.imageFallbackSrc}\r\n                    sizes=\"100vw\"\r\n                    onClick={onClick}\r\n                />\r\n            </div>\r\n            <button type=\"button\" className=\"modal-close-button\" onClick={onClose}>\r\n                <Icon iconId=\"icon_28_close\" />\r\n            </button>\r\n        </Modal>\r\n    );\r\n};\r\n\r\nexport default ProductImageModal;\r\n","// The \"top\" colors of the themes – needs to correspond with the top theme colors in theming.scss\r\nconst primaryThemeColors: number[][] = [\r\n    [41, 60, 145],\r\n    [113, 191, 68],\r\n    [24, 171, 157],\r\n    [238, 64, 152],\r\n    [239, 72, 40],\r\n    [247, 150, 42],\r\n    [125, 105, 174],\r\n    [178, 210, 52],\r\n    [246, 213, 69]\r\n];\r\n\r\nexport default primaryThemeColors;\r\n","import ColorThief from \"colorthief\";\r\nimport primaryThemeColors from \"~/utils/theme-colors\";\r\n\r\ninterface IHslColor {\r\n    hue: number;\r\n    saturation: number;\r\n    lightness: number;\r\n}\r\n\r\n/**\r\n * Converts an RGB color value to HSL. Conversion formula\r\n * adapted from http://en.wikipedia.org/wiki/HSL_color_space.\r\n * Assumes r, g, and b are contained in the set [0, 255] and\r\n * returns h, s, and l in the set [0, 1].\r\n * Modified version from: https://stackoverflow.com/a/9493060\r\n */\r\nconst rgbToHsl = ([r, g, b]: number[]): IHslColor => {\r\n    r /= 255;\r\n    g /= 255;\r\n    b /= 255;\r\n\r\n    const max = Math.max(r, g, b);\r\n    const min = Math.min(r, g, b);\r\n    let h = (max + min) * 0.5;\r\n    let s = (max + min) * 0.5;\r\n    const l = (max + min) * 0.5;\r\n\r\n    if (max === min) {\r\n        h = s = 0; // achromatic\r\n    } else {\r\n        const d = max - min;\r\n        s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\r\n\r\n        switch (max) {\r\n            case r:\r\n                h = (g - b) / d + (g < b ? 6 : 0);\r\n                break;\r\n            case g:\r\n                h = (b - r) / d + 2;\r\n                break;\r\n            case b:\r\n                h = (r - g) / d + 4;\r\n                break;\r\n        }\r\n\r\n        h /= 6;\r\n    }\r\n\r\n    return { hue: h, saturation: s, lightness: l };\r\n};\r\n\r\n// Returns index of number in array closest to target\r\nconst findIndexOfClosest = (nums: number[], target: number) => {\r\n    let closest = Number.MAX_SAFE_INTEGER;\r\n    return nums.reduce((indexOfClosest, number, index) => {\r\n        const dist = Math.abs(target - number);\r\n        if (dist < closest) {\r\n            indexOfClosest = index;\r\n            closest = dist;\r\n        }\r\n        return indexOfClosest;\r\n    }, 0);\r\n};\r\n\r\nconst findMatchingTheme = (hue: number) => {\r\n    // Make array of the hue of the \"top/primary\" colors\r\n    const primaryThemeHues = primaryThemeColors.map(color => rgbToHsl(color).hue);\r\n\r\n    // Compare hue with theme hues and return index of closest match\r\n    return findIndexOfClosest(primaryThemeHues, hue);\r\n};\r\n\r\n/**\r\n * Adds a theme class to the body element matched to the\r\n * dominant color of the input image.\r\n * The comparison is solely based on hue.\r\n * Uses color-thief for getting the dominant color, see\r\n * https://github.com/lokesh/color-thief for docs.\r\n * @param img src of image or the HTML element itself\r\n */\r\nconst setThemeFromImg = (img: HTMLImageElement) => {\r\n    const colorThief = new ColorThief();\r\n    const GRAYSCALE_BOUNDARY = 0.15;\r\n    const GRAYSCALE_THEME_NAME = \"theme-10\";\r\n\r\n    const colorThiefResult = colorThief.getPalette(img, 2);\r\n    if (!colorThiefResult) {\r\n        // Silently fail getting a theme.\r\n        return;\r\n    }\r\n    const dominantColor = colorThiefResult[0];\r\n    const { hue, saturation } = rgbToHsl(dominantColor);\r\n    const matchingThemeIndex = findMatchingTheme(hue);\r\n\r\n    const themeContainer = img.closest(\"body\");\r\n    const themeTarget = themeContainer || document.body;\r\n\r\n    const currentTheme = themeTarget.className.match(/theme-\\d+/);\r\n    if (currentTheme) {\r\n        themeTarget.classList.remove(currentTheme[0]);\r\n    }\r\n\r\n    if (saturation < GRAYSCALE_BOUNDARY) {\r\n        themeTarget.classList.add(GRAYSCALE_THEME_NAME);\r\n        return;\r\n    }\r\n\r\n    themeTarget.classList.add(`theme-${matchingThemeIndex + 1}`);\r\n};\r\n\r\nexport default setThemeFromImg;\r\n","import * as React from \"react\";\r\nimport classNames from \"classnames\";\r\n\r\nexport type TIconNames =\r\n    | \"24_expand\"\r\n    | \"24_play\"\r\n    | \"24_star\"\r\n    | \"24_trash\"\r\n    | \"32_add-user\"\r\n    | \"32_basket\"\r\n    | \"32_checkmark-circle\"\r\n    | \"32_checkmark\"\r\n    | \"32_error\"\r\n    | \"32_information\"\r\n    | \"32_katalog\"\r\n    | \"32_search\"\r\n    | \"32_truck-in-motion\"\r\n    | \"32_user\"\r\n    | \"32_warning\"\r\n    | \"icon_16_arrow-down\"\r\n    | \"icon_16_arrow-left\"\r\n    | \"icon_16_arrow-right-bold\"\r\n    | \"icon_16_arrow-right\"\r\n    | \"icon_16_arrow-up\"\r\n    | \"icon_28_close\"\r\n    | \"icon_32_thumbs-up\"\r\n    | \"icon_80x41_quotation-mark-gyldendal-dk\"\r\n    | \"icon_80x48_quotation-mark\"\r\n    | \"icon_checkbox-black\"\r\n    | \"icon_checkmark-black\"\r\n    | \"icon_download\"\r\n    | \"icon_herringbone-narrow\"\r\n    | \"icon_herringbone-wide\"\r\n    | \"icon_placeholder-email\"\r\n    | \"icon_placeholder-lock\"\r\n    | \"icon_placeholder-phone-small\"\r\n    | \"icon_placeholder-vip-white\"\r\n    | \"icon_placeholder_basket\"\r\n    | \"icon_placeholder_checkmark\"\r\n    | \"icon_placeholder_eye-closed\"\r\n    | \"icon_placeholder_eye\"\r\n    | \"icon_placeholder_facebook\"\r\n    | \"icon_placeholder_filtering\"\r\n    | \"icon_placeholder_hamburger\"\r\n    | \"icon_placeholder_instagram\"\r\n    | \"icon_placeholder_phone\"\r\n    | \"icon_placeholder_user\"\r\n    | \"icon_read\"\r\n    | \"icon_listen\";\r\n\r\nexport interface IIconProps {\r\n    iconId: TIconNames;\r\n    spriteUrl?: string;\r\n    viewBox?: string;\r\n    className?: string;\r\n    onClick?: () => void;\r\n}\r\n\r\nconst Icon: React.FC<IIconProps> = props => {\r\n    const spriteUrl = props.spriteUrl || \"\";\r\n    const viewBox = props.viewBox || \"0 0 32 32\";\r\n\r\n    return (\r\n        <svg\r\n            viewBox={viewBox}\r\n            className={classNames(props.className, \"icon\", `icon-${props.iconId}`)}\r\n            preserveAspectRatio=\"xMidYMid\"\r\n            onClick={() => props.onClick && props.onClick()}\r\n        >\r\n            <use xmlnsXlink=\"http://www.w3.org/1999/xlink\" xlinkHref={`${spriteUrl}#${props.iconId}`} />\r\n        </svg>\r\n    );\r\n};\r\n\r\nexport default Icon;\r\n","import * as React from \"react\";\r\nimport classNames from \"classnames\";\r\nimport Icon from \"../icons/icon\";\r\n\r\nexport interface IArrowLinkProps {\r\n    className?: string;\r\n    link: string;\r\n}\r\n\r\nconst ArrowLink = ({ className, link }: IArrowLinkProps) => {\r\n    const baseClass = \"arrow-link\";\r\n    const componentClasses = classNames(baseClass, className);\r\n\r\n    return (\r\n        <div className={componentClasses}>\r\n            <Icon iconId=\"icon_16_arrow-right-bold\" />\r\n            <span dangerouslySetInnerHTML={{ __html: link }} />\r\n        </div>\r\n    );\r\n};\r\n\r\nexport default ArrowLink;\r\n","interface IBreakpoints {\r\n    [key: string]: number;\r\n}\r\n\r\ninterface IMediaQueryStrings {\r\n    [key: string]: string;\r\n}\r\n\r\nexport type IMatchingQueries = { [key in Breakpoints]?: boolean };\r\n\r\nexport type Breakpoints =\r\n    | \"ratMin\"\r\n    | \"ratMax\"\r\n    | \"rabbitMin\"\r\n    | \"rabbitMax\"\r\n    | \"catMin\"\r\n    | \"catMax\"\r\n    | \"dogMin\"\r\n    | \"dogMax\"\r\n    | \"wolfMin\"\r\n    | \"wolfMax\"\r\n    | \"lionMin\"\r\n    | \"horseMin\"\r\n    | \"horseMax\"\r\n    | \"rhinoMin\"\r\n    | \"rhinoMax\"\r\n    | \"elephantMin\"\r\n    | \"elephantMax\";\r\n\r\nexport const breakpoints: IBreakpoints = {\r\n    rat: 360,\r\n    rabbit: 480,\r\n    cat: 640,\r\n    dog: 768,\r\n    wolf: 1024,\r\n    lion: 1100,\r\n    horse: 1400,\r\n    rhino: 1520,\r\n    elephant: 1670\r\n};\r\n\r\nconst mediaQueries: IMediaQueryStrings = Object.keys(breakpoints).reduce(\r\n    (queryStrings: IMediaQueryStrings, key) => {\r\n        queryStrings[`${key}Min`] = `(min-width: ${breakpoints[key]}px)`;\r\n        queryStrings[`${key}Max`] = `(max-width: ${breakpoints[key] - 1}px)`;\r\n        return queryStrings;\r\n    },\r\n    {}\r\n);\r\n\r\nconst setupMediaQueryListeners = () => {\r\n    Object.keys(mediaQueries).forEach((key: string) => {\r\n        const mediaQuery = matchMedia(mediaQueries[key]);\r\n\r\n        handleMediaMatch(mediaQuery.matches, key as Breakpoints); // Initial values\r\n        mediaQuery.addListener(event => handleMediaMatch(event.matches, key as Breakpoints));\r\n    });\r\n};\r\n\r\nconst currentMediaQueries: IMatchingQueries = {};\r\nconst handleMediaMatch = (isMatching: boolean, key: Breakpoints) => (currentMediaQueries[key] = isMatching);\r\n\r\nif (!__SERVER__) {\r\n    setupMediaQueryListeners();\r\n}\r\n\r\nexport { currentMediaQueries };\r\n","import * as React from \"react\";\r\nimport classNames from \"classnames\";\r\nimport { ProductStatus } from \"~/types/product\";\r\n\r\nexport interface ITagProps {\r\n    type?: ProductStatus;\r\n    children: React.ReactNode;\r\n    className?: string;\r\n    shape?: \"pill\" | \"square\";\r\n}\r\n\r\nexport const tagTypeClassMap: { [key in ProductStatus]: string } = {\r\n    NEWS: \"news\",\r\n    SPOT: \"spot\",\r\n    BESTSELLER: \"bestseller\",\r\n    BOOK_OF_THE_MONTH: \"botm\",\r\n    UPCOMING: \"upcoming\"\r\n};\r\n\r\nconst Tag: React.FC<ITagProps> = props => {\r\n    const classModifier = props.type && tagTypeClassMap[props.type];\r\n    const rootClasses = classNames(\"tag\", props.className, `tag--shape-${props.shape || \"pill\"}`, {\r\n        [`tag--${classModifier}`]: props.type\r\n    });\r\n\r\n    return (\r\n        <div className={rootClasses}>\r\n            <span className=\"tag__label\">{props.children}</span>\r\n        </div>\r\n    );\r\n};\r\n\r\nexport default Tag;\r\n","import { MembershipType } from \"~/types/membership\";\r\nimport { IBasketProduct, IProduct } from \"~/types/product\";\r\n// import { IBasketSummationProps } from \"~/components/basket-summation/basket-summation\";\r\nimport { IProductTileProps } from \"~/components/product-tile/product-tile\";\r\n\r\nenum EventTypes {\r\n    SIGNUP = \"eec.signup\",\r\n    PURCHASE = \"eec.purchase\",\r\n    CHECKOUT = \"eec.checkout\",\r\n    ADD_TO_BASKET = \"eec.add\",\r\n    REMOVE_FROM_BASKET = \"eec.remove\",\r\n    CLICK = \"eec.impressionClick\",\r\n    DETAIL_VIEW = \"eec.detail\",\r\n    IMPRESSION_VIEW = \"eec.impressionView\",\r\n    PROMO_VIEW = \"eec.promotionView\",\r\n    PROMO_CLICK = \"eec.promotionClick\",\r\n    VOUCHER = \"eec.voucher\"\r\n}\r\n\r\nenum CurrencyCodes {\r\n    DKK = \"DKK\"\r\n}\r\n\r\nenum TrackingDimensions {\r\n    CAMPAIGN_ID = \"dimension2\",\r\n    MEMBERSHIP_TYPE = \"dimension3\",\r\n    PAYMENT_PERIOD = \"dimension4\",\r\n    DISCOUNT_SPLASH = \"dimension5\"\r\n}\r\n\r\ninterface ITrackingProduct {\r\n    name?: string;\r\n    id?: string;\r\n    price?: number;\r\n    quantity?: number;\r\n    [TrackingDimensions.MEMBERSHIP_TYPE]?: MembershipType | string;\r\n    [TrackingDimensions.PAYMENT_PERIOD]?: string;\r\n    [TrackingDimensions.DISCOUNT_SPLASH]?: string;\r\n}\r\n\r\ninterface IProductImpression extends ITrackingProduct {\r\n    list?: string;\r\n    position: number | undefined;\r\n}\r\n\r\ninterface ICheckoutActionField {\r\n    step: string;\r\n    [TrackingDimensions.CAMPAIGN_ID]?: string;\r\n    option?: string;\r\n    coupon?: string;\r\n}\r\n\r\ninterface IEcommerceTrackingEvent<T> {\r\n    event: EventTypes;\r\n    ecommerce: T & { currencyCode?: CurrencyCodes };\r\n}\r\n\r\ninterface ITrackingEvent {\r\n    event: \"trackEvent\";\r\n    eventData: {\r\n        category: string;\r\n        action: string;\r\n        label: string;\r\n    };\r\n}\r\n\r\nconst mapProductsToTrackingProducts = (\r\n    { title, primaryPriceNumber, productId, quantityNumber, discounts }: IBasketProduct,\r\n    membershipType?: MembershipType,\r\n    paymentPeriod?: string\r\n): ITrackingProduct => {\r\n    const product: ITrackingProduct = {\r\n        name: title,\r\n        price: primaryPriceNumber,\r\n        quantity: quantityNumber || 1,\r\n        [TrackingDimensions.MEMBERSHIP_TYPE]: membershipType || \"\",\r\n        [TrackingDimensions.PAYMENT_PERIOD]: paymentPeriod || \"\",\r\n        [TrackingDimensions.DISCOUNT_SPLASH]: discounts?.map(discount => discount.label).join(\" | \") || \"\"\r\n    };\r\n\r\n    if (productId) {\r\n        product.id = productId;\r\n    }\r\n\r\n    return product;\r\n};\r\n\r\nexport interface ISignupTrackingParams {\r\n    campaignId?: string;\r\n    membershipType?: MembershipType;\r\n    currentStepIndex: number;\r\n    paymentPeriod?: string;\r\n    miniBasketProducts?: IBasketProduct[];\r\n}\r\n\r\ninterface ISignupTrackingEvent\r\n    extends IEcommerceTrackingEvent<{\r\n        checkout: {\r\n            actionField: ICheckoutActionField;\r\n            products: ITrackingProduct[];\r\n        };\r\n    }> {}\r\n\r\nconst generateSignupTrackingEvent = ({\r\n    membershipType,\r\n    campaignId,\r\n    miniBasketProducts,\r\n    currentStepIndex,\r\n    paymentPeriod\r\n}: ISignupTrackingParams): ISignupTrackingEvent => {\r\n    const actionField: ICheckoutActionField = {\r\n        step: (currentStepIndex + 1).toString(),\r\n        option: currentStepIndex > 0 ? paymentPeriod : \"\"\r\n    };\r\n\r\n    actionField[TrackingDimensions.CAMPAIGN_ID] = campaignId || \"\";\r\n\r\n    const products: ITrackingProduct[] = miniBasketProducts\r\n        ? miniBasketProducts.map(product =>\r\n              mapProductsToTrackingProducts(product, membershipType, paymentPeriod)\r\n          )\r\n        : [];\r\n\r\n    const signupTrackingEvent = {\r\n        event: EventTypes.SIGNUP,\r\n        ecommerce: {\r\n            checkout: {\r\n                actionField,\r\n                products\r\n            }\r\n        }\r\n    };\r\n\r\n    return signupTrackingEvent;\r\n};\r\n\r\ninterface ICheckoutTrackingParams {\r\n    products?: IBasketProduct[];\r\n    paymentMethod?: string;\r\n    step: number;\r\n}\r\n\r\ninterface ICheckoutTrackingEvent\r\n    extends IEcommerceTrackingEvent<{\r\n        checkout: {\r\n            actionField: ICheckoutActionField;\r\n            products: ITrackingProduct[];\r\n        };\r\n    }> {}\r\n\r\nconst generateCheckoutTrackingEvent = ({\r\n    products,\r\n    step,\r\n    paymentMethod\r\n}: ICheckoutTrackingParams): ICheckoutTrackingEvent => {\r\n    const actionField: ICheckoutActionField = {\r\n        step: `${step}`\r\n    };\r\n\r\n    if (paymentMethod) {\r\n        actionField.option = paymentMethod;\r\n    }\r\n\r\n    const mappedProducts: ITrackingProduct[] = products\r\n        ? products.map(product => mapProductsToTrackingProducts(product))\r\n        : [];\r\n\r\n    return {\r\n        event: EventTypes.CHECKOUT,\r\n        ecommerce: {\r\n            checkout: {\r\n                actionField,\r\n                products: mappedProducts\r\n            }\r\n        }\r\n    };\r\n};\r\n\r\ninterface IPurchaseTrackingParams {\r\n    membershipType?: MembershipType;\r\n    miniBasketProducts?: IBasketProduct[];\r\n    // miniBasketSummation?: IBasketSummationProps;\r\n    orderId?: string;\r\n    campaignId?: string;\r\n}\r\n\r\ninterface IPurchaseActionField {\r\n    [TrackingDimensions.CAMPAIGN_ID]?: string;\r\n    coupon?: string;\r\n    revenue?: number;\r\n    shipping?: number;\r\n    tax?: number;\r\n    id?: string;\r\n}\r\n\r\ninterface IPurchaseTrackingEvent\r\n    extends IEcommerceTrackingEvent<{\r\n        purchase: {\r\n            actionField: IPurchaseActionField;\r\n            products: ITrackingProduct[];\r\n        };\r\n    }> {}\r\n\r\nconst generatePurchaseTrackingEvent = ({\r\n    membershipType,\r\n    miniBasketProducts,\r\n    // miniBasketSummation,\r\n    orderId,\r\n    campaignId\r\n}: IPurchaseTrackingParams): IPurchaseTrackingEvent => {\r\n    const actionField: IPurchaseActionField = {};\r\n\r\n    if (orderId) {\r\n        actionField.id = orderId;\r\n    }\r\n\r\n    actionField[TrackingDimensions.CAMPAIGN_ID] = campaignId || \"\";\r\n\r\n    // if (miniBasketSummation) {\r\n    //     actionField.tax = miniBasketSummation.vatNumber;\r\n    //     actionField.revenue = miniBasketSummation.totalPriceNumber;\r\n\r\n    //     if (miniBasketSummation.shippingFee) {\r\n    //         actionField.shipping = miniBasketSummation.shippingFeeNumber;\r\n    //     }\r\n    //     if (miniBasketSummation.voucherDiscount) {\r\n    //         actionField.coupon = miniBasketSummation.voucherDiscount;\r\n    //     }\r\n    // }\r\n\r\n    const products: ITrackingProduct[] = miniBasketProducts\r\n        ? miniBasketProducts.map(product => mapProductsToTrackingProducts(product, membershipType))\r\n        : [];\r\n\r\n    const purchaseTrackingEvent = {\r\n        event: EventTypes.PURCHASE,\r\n        ecommerce: {\r\n            currencyCode: CurrencyCodes.DKK,\r\n            purchase: {\r\n                actionField,\r\n                products\r\n            }\r\n        }\r\n    };\r\n\r\n    return purchaseTrackingEvent;\r\n};\r\n\r\ninterface IClickActionField {\r\n    list: string;\r\n}\r\n\r\ninterface IClickTrackingParams\r\n    extends Pick<IProductTileProps, \"trackingList\" | \"trackingPosition\" | \"productId\" | \"title\"> {}\r\n\r\ninterface IClickTrackingEvent\r\n    extends IEcommerceTrackingEvent<{\r\n        click: {\r\n            actionField: IClickActionField;\r\n            products: IProductImpression[];\r\n        };\r\n    }> {}\r\n\r\nconst generateClickTrackingEvent = ({\r\n    trackingList,\r\n    trackingPosition,\r\n    productId,\r\n    title\r\n}: IClickTrackingParams): IClickTrackingEvent => {\r\n    return {\r\n        event: EventTypes.CLICK,\r\n        ecommerce: {\r\n            click: {\r\n                actionField: {\r\n                    list: trackingList\r\n                },\r\n                products: [\r\n                    {\r\n                        id: productId,\r\n                        name: title,\r\n                        position: trackingPosition\r\n                    }\r\n                ]\r\n            }\r\n        }\r\n    };\r\n};\r\n\r\ninterface IDetailActionField {\r\n    list: string;\r\n}\r\n\r\ninterface IDetailViewTrackingParams extends Pick<IProduct, \"title\" | \"productId\"> {\r\n    trackingList: string;\r\n}\r\n\r\ninterface IDetailViewTrackingEvent\r\n    extends IEcommerceTrackingEvent<{\r\n        detail: {\r\n            actionField: IDetailActionField;\r\n            products: ITrackingProduct[];\r\n        };\r\n    }> {}\r\n\r\nconst generateDetailViewTrackingEvent = ({\r\n    title,\r\n    productId,\r\n    trackingList\r\n}: IDetailViewTrackingParams): IDetailViewTrackingEvent => {\r\n    return {\r\n        event: EventTypes.DETAIL_VIEW,\r\n        ecommerce: {\r\n            detail: {\r\n                actionField: {\r\n                    list: trackingList\r\n                },\r\n                products: [\r\n                    {\r\n                        id: productId,\r\n                        name: title\r\n                    }\r\n                ]\r\n            }\r\n        }\r\n    };\r\n};\r\n\r\ninterface IBasketTrackingParams {\r\n    products?: IBasketProduct[];\r\n    trackingList: string;\r\n}\r\n\r\ninterface IAddToBasketTrackingEvent\r\n    extends IEcommerceTrackingEvent<{\r\n        add: {\r\n            actionField: { list: string };\r\n            products: ITrackingProduct[] | undefined;\r\n        };\r\n    }> {}\r\n\r\nconst generateAddToBasketTrackingEvent = ({\r\n    products,\r\n    trackingList\r\n}: IBasketTrackingParams): IAddToBasketTrackingEvent => {\r\n    const basketProducts = products && products.map(product => mapProductsToTrackingProducts(product));\r\n\r\n    return {\r\n        event: EventTypes.ADD_TO_BASKET,\r\n        ecommerce: {\r\n            add: {\r\n                actionField: { list: trackingList },\r\n                products: basketProducts\r\n            }\r\n        }\r\n    };\r\n};\r\n\r\ninterface IRemoveFromBasketTrackingEvent\r\n    extends IEcommerceTrackingEvent<{\r\n        remove: {\r\n            actionField: { list: string };\r\n            products: ITrackingProduct[] | undefined;\r\n        };\r\n    }> {}\r\n\r\nconst generateRemoveFromBasketTrackingEvent = ({\r\n    products,\r\n    trackingList\r\n}: IBasketTrackingParams): IRemoveFromBasketTrackingEvent => {\r\n    const basketProducts = products && products.map(product => mapProductsToTrackingProducts(product));\r\n\r\n    return {\r\n        event: EventTypes.REMOVE_FROM_BASKET,\r\n        ecommerce: {\r\n            remove: {\r\n                actionField: { list: trackingList },\r\n                products: basketProducts\r\n            }\r\n        }\r\n    };\r\n};\r\n\r\ninterface IVoucherTrackingParams {\r\n    // summation?: IBasketSummationProps;\r\n    caller: string;\r\n    action: string;\r\n}\r\ninterface IVoucherTrackingEvent\r\n    extends IEcommerceTrackingEvent<{\r\n        // summation?: IBasketSummationProps;\r\n        caller: string;\r\n        action: string;\r\n    }> {}\r\n\r\nconst generateVoucherTrackingEvent = (props: IVoucherTrackingParams): IVoucherTrackingEvent => {\r\n    return {\r\n        event: EventTypes.VOUCHER,\r\n        ecommerce: {\r\n            // summation: props.summation,\r\n            caller: props.caller,\r\n            action: props.action\r\n        }\r\n    };\r\n};\r\n\r\ninterface IImpressionViewTrackingParams\r\n    extends Required<Pick<IProductTileProps, \"trackingList\" | \"trackingPosition\" | \"productId\" | \"title\">> {}\r\n\r\ninterface IImpressionViewTrackingEvent\r\n    extends IEcommerceTrackingEvent<{\r\n        impressions: IProductImpression[];\r\n    }> {}\r\n\r\nconst generateImpressionViewTrackingEvent = (\r\n    products: IImpressionViewTrackingParams[]\r\n): IImpressionViewTrackingEvent => {\r\n    return {\r\n        event: EventTypes.IMPRESSION_VIEW,\r\n        ecommerce: {\r\n            impressions: products.map(product => {\r\n                return {\r\n                    list: product.trackingList,\r\n                    position: product.trackingPosition,\r\n                    id: product.productId,\r\n                    name: product.title\r\n                };\r\n            })\r\n        }\r\n    };\r\n};\r\n\r\ninterface IPromoViewTrackingEvent\r\n    extends IEcommerceTrackingEvent<{\r\n        promoView: {\r\n            promotions: Array<{\r\n                id: string;\r\n                name: string;\r\n                creative: string;\r\n                position: string;\r\n            }>;\r\n        };\r\n    }> {}\r\n\r\nconst generatePromoViewTrackingEvent = (): IPromoViewTrackingEvent => {\r\n    return {\r\n        event: EventTypes.PROMO_VIEW,\r\n        ecommerce: {\r\n            promoView: {\r\n                promotions: [\r\n                    {\r\n                        id: \"\",\r\n                        name: \"Splash\",\r\n                        creative: \"\",\r\n                        position: \"\"\r\n                    }\r\n                ]\r\n            }\r\n        }\r\n    };\r\n};\r\n\r\ninterface IPromoClickTrackingEvent\r\n    extends IEcommerceTrackingEvent<{\r\n        promoClick: {\r\n            promotions: Array<{\r\n                id: string;\r\n                name: string;\r\n                creative: string;\r\n                position: string;\r\n            }>;\r\n        };\r\n    }> {}\r\n\r\nconst generatePromoClickTrackingEvent = (): IPromoClickTrackingEvent => {\r\n    return {\r\n        event: EventTypes.PROMO_CLICK,\r\n        ecommerce: {\r\n            promoClick: {\r\n                promotions: [\r\n                    {\r\n                        id: \"\",\r\n                        name: \"Splash\",\r\n                        creative: \"\",\r\n                        position: \"\"\r\n                    }\r\n                ]\r\n            }\r\n        }\r\n    };\r\n};\r\n\r\nconst ensureDataLayer = () => {\r\n    if (typeof window === \"undefined\") {\r\n        return false;\r\n    }\r\n\r\n    window.dataLayer = window.dataLayer || [];\r\n    return true;\r\n};\r\n\r\nconst pushEcommerenceTrackingEvent = (trackingEvent: IEcommerceTrackingEvent<unknown>) => {\r\n    if (ensureDataLayer()) window.dataLayer.push(trackingEvent);\r\n};\r\n\r\nexport const pushTrackingEvent = (trackingEvent: ITrackingEvent) => {\r\n    if (ensureDataLayer()) window.dataLayer.push(trackingEvent);\r\n};\r\n\r\nexport const pushAddToBasketTrackingEvent = (props: IBasketTrackingParams) =>\r\n    pushEcommerenceTrackingEvent(generateAddToBasketTrackingEvent(props));\r\n\r\nexport const pushRemoveFromBasketTrackingEvent = (props: IBasketTrackingParams) =>\r\n    pushEcommerenceTrackingEvent(generateRemoveFromBasketTrackingEvent(props));\r\n\r\nexport const pushSignupTrackingEvent = (props: ISignupTrackingParams) =>\r\n    pushEcommerenceTrackingEvent(generateSignupTrackingEvent(props));\r\n\r\nexport const pushCheckoutTrackingEvent = (props: ICheckoutTrackingParams) =>\r\n    pushEcommerenceTrackingEvent(generateCheckoutTrackingEvent(props));\r\n\r\nexport const pushPurchaseTrackingEvent = (props: IPurchaseTrackingParams) =>\r\n    pushEcommerenceTrackingEvent(generatePurchaseTrackingEvent(props));\r\n\r\nexport const pushClickTrackingEvent = (props: IClickTrackingParams) =>\r\n    pushEcommerenceTrackingEvent(generateClickTrackingEvent(props));\r\n\r\nexport const pushDetailViewTrackingEvent = (props: IDetailViewTrackingParams) =>\r\n    pushEcommerenceTrackingEvent(generateDetailViewTrackingEvent(props));\r\n\r\nexport const pushImpressionViewTrackingEvent = (props: IImpressionViewTrackingParams[]) =>\r\n    pushEcommerenceTrackingEvent(generateImpressionViewTrackingEvent(props));\r\n\r\nexport const pushPromoViewTrackingEvent = () =>\r\n    pushEcommerenceTrackingEvent(generatePromoViewTrackingEvent());\r\n\r\nexport const pushPromoClickTrackingEvent = () =>\r\n    pushEcommerenceTrackingEvent(generatePromoClickTrackingEvent());\r\n\r\nexport const pushVoucherTrackingEvent = (props: IVoucherTrackingParams) =>\r\n    pushEcommerenceTrackingEvent(generateVoucherTrackingEvent(props));\r\n","import * as React from \"react\";\r\n\r\nexport interface ProductImageProps extends Omit<React.ImgHTMLAttributes<HTMLImageElement>, \"src\" | \"srcSet\"> {\r\n    className?: string;\r\n    fallbackSrc?: string;\r\n    srcSet: string;\r\n    sizes?: string;\r\n    loading?: React.ImgHTMLAttributes<HTMLImageElement>[\"loading\"];\r\n    ref?: React.Ref<HTMLImageElement>;\r\n    width?: string | number;\r\n    height?: string | number;\r\n}\r\n\r\nconst ProductImage: React.FC<ProductImageProps> = React.forwardRef(\r\n    ({ fallbackSrc, loading = \"lazy\", ...props }, ref) => {\r\n        return <img ref={ref} src={fallbackSrc} loading={loading} {...props} />;\r\n    }\r\n);\r\n\r\nexport default ProductImage;\r\n","import * as React from \"react\";\r\nimport { IProductAuthor } from \"~/types/product\";\r\nimport TruncateMarkup from \"react-truncate-markup\";\r\nimport classNames from \"classnames\";\r\n\r\ninterface IProductAuthorProps {\r\n    authors?: IProductAuthor[];\r\n    maxLines?: number;\r\n    className?: string;\r\n}\r\n\r\nconst ProductAuthors: React.FC<IProductAuthorProps> = ({ authors, className, maxLines }) => {\r\n    if (!authors?.length) {\r\n        return null;\r\n    }\r\n\r\n    const baseClass = \"product-authors\";\r\n    const classes = classNames(baseClass, className);\r\n\r\n    const Wrapper: React.FC = ({ children }) =>\r\n        maxLines ? (\r\n            <TruncateMarkup lines={maxLines}>{children}</TruncateMarkup>\r\n        ) : (\r\n            <React.Fragment>{children}</React.Fragment>\r\n        );\r\n\r\n    return (\r\n        <Wrapper>\r\n            <ul className={classes}>\r\n                {authors.map((author, index) => {\r\n                    return (\r\n                        <li key={index} className={`${baseClass}__item`}>\r\n                            {author.url ? (\r\n                                <a href={author.url} title={author.name}>\r\n                                    {author.name}\r\n                                </a>\r\n                            ) : (\r\n                                <span>{author.name}</span>\r\n                            )}\r\n                        </li>\r\n                    );\r\n                })}\r\n            </ul>\r\n        </Wrapper>\r\n    );\r\n};\r\n\r\nexport default ProductAuthors;\r\n","import * as React from \"react\";\r\nimport classNames from \"classnames\";\r\nimport AnimateHeight from \"react-animate-height\";\r\nimport { currentMediaQueries, Breakpoints } from \"~/utils/breakpoint-utils\";\r\n\r\nexport interface IShowMoreProps {\r\n    minHeight: number;\r\n    btnLabelShowMore?: string;\r\n    btnLabelShowLess?: string;\r\n    className?: string;\r\n    disableOnBreakpoint?: Breakpoints;\r\n}\r\ninterface IShowMoreState {\r\n    showMoreHasOverflow: boolean;\r\n    showMoreIsOpen: boolean;\r\n}\r\n\r\nclass ShowMore extends React.Component<IShowMoreProps, IShowMoreState> {\r\n    private childrenWrapper: HTMLDivElement | null;\r\n\r\n    public state = {\r\n        showMoreHasOverflow: true,\r\n        showMoreIsOpen: false\r\n    };\r\n\r\n    public componentDidMount() {\r\n        window.addEventListener(\"resize\", this.handleResize.bind(this));\r\n        this.handleResize();\r\n    }\r\n\r\n    public componentWillUnmount() {\r\n        window.removeEventListener(\"resize\", this.handleResize.bind(this));\r\n    }\r\n\r\n    public handleResize() {\r\n        const { disableOnBreakpoint, minHeight } = this.props;\r\n        const disableOverflow = disableOnBreakpoint && currentMediaQueries[disableOnBreakpoint];\r\n        const hasOverflow = this.childrenWrapper && this.childrenWrapper.clientHeight > minHeight;\r\n\r\n        if (!disableOverflow && hasOverflow) {\r\n            this.setState({ showMoreHasOverflow: true });\r\n        } else {\r\n            this.setState({ showMoreHasOverflow: false });\r\n        }\r\n    }\r\n\r\n    private toggleMore() {\r\n        this.setState({ showMoreIsOpen: !this.state.showMoreIsOpen });\r\n    }\r\n\r\n    public render() {\r\n        const { className, minHeight, btnLabelShowLess, btnLabelShowMore, children } = this.props;\r\n        const baseClass = \"show-more\";\r\n        const containerClasses = classNames(className, baseClass, {\r\n            [`${baseClass}--hasOverflow`]: this.state.showMoreHasOverflow,\r\n            [`${baseClass}--isClosed`]: this.state.showMoreHasOverflow && !this.state.showMoreIsOpen\r\n        });\r\n        const setAnimateToMinHeight = this.state.showMoreHasOverflow && !this.state.showMoreIsOpen;\r\n        const btnText = this.state.showMoreIsOpen ? btnLabelShowLess : btnLabelShowMore;\r\n\r\n        return (\r\n            <div className={containerClasses}>\r\n                <AnimateHeight height={setAnimateToMinHeight ? minHeight : \"auto\"} duration={300}>\r\n                    <div ref={node => (this.childrenWrapper = node)}>{children}</div>\r\n                </AnimateHeight>\r\n\r\n                <button className=\"show-more-button\" onClick={() => this.toggleMore()}>\r\n                    {btnText}\r\n                </button>\r\n            </div>\r\n        );\r\n    }\r\n}\r\n\r\nexport default ShowMore;\r\n","import React from \"react\";\r\nimport ReactModal from \"react-modal\";\r\nimport Icon from \"~/components/icons/icon\";\r\nimport classNames from \"classnames\";\r\n\r\nexport interface IModalProps {\r\n    className?: string;\r\n    isOpen: boolean;\r\n    noContainerMarkup?: boolean;\r\n    onRequestClose?: () => void;\r\n}\r\n\r\nif (typeof window !== \"undefined\") {\r\n    ReactModal.setAppElement(\"body\");\r\n}\r\n\r\nconst Modal: React.FC<IModalProps> = ({ className, noContainerMarkup, children, ...props }) => {\r\n    const baseClass = \"modal\";\r\n    const rootClasses = classNames(baseClass, className);\r\n\r\n    const onClose = () => {\r\n        if (props.onRequestClose) {\r\n            props.onRequestClose();\r\n        }\r\n    };\r\n\r\n    return (\r\n        <ReactModal {...props} className={rootClasses} overlayClassName=\"modal-overlay\">\r\n            {noContainerMarkup ? (\r\n                children\r\n            ) : (\r\n                <div className=\"modal-content\">\r\n                    <button type=\"button\" className=\"modal-close-button\" onClick={onClose}>\r\n                        <Icon iconId=\"icon_28_close\" />\r\n                    </button>\r\n                    <div className=\"modal__content__inner\">{children}</div>\r\n                </div>\r\n            )}\r\n        </ReactModal>\r\n    );\r\n};\r\n\r\nexport default Modal;\r\n","import * as React from \"react\";\r\nimport { WrappedFieldProps } from \"redux-form\";\r\nimport Icon from \"../icons/icon\";\r\nimport classNames from \"classnames\";\r\nimport useShuffleIndex from \"~/hooks/useShuffleIndex\";\r\n\r\nexport interface IInputSelectProps {\r\n    fieldName: string;\r\n    label?: string;\r\n    disabled?: boolean;\r\n    className?: string;\r\n    type?: string;\r\n    required?: boolean;\r\n    options: Array<{\r\n        label: string;\r\n        value: string;\r\n    }>;\r\n    defaultLabel?: string;\r\n    enableInlineError?: boolean;\r\n    forceErrorStyling?: boolean;\r\n    excludeDefaultOption?: boolean;\r\n    readyForSorting?: boolean;\r\n}\r\n\r\nconst InputSelect: React.FC<IInputSelectProps & WrappedFieldProps> = props => {\r\n    const {\r\n        className,\r\n        options,\r\n        label,\r\n        meta: { touched, error },\r\n        defaultLabel,\r\n        excludeDefaultOption,\r\n        readyForSorting,\r\n        enableInlineError,\r\n        forceErrorStyling\r\n    } = props;\r\n    const DEFAULT_OPTION = \"\";\r\n    const { onChange, ...input } = props.input;\r\n    const allOptions =\r\n        defaultLabel && !excludeDefaultOption\r\n            ? [{ label: defaultLabel, value: DEFAULT_OPTION }, ...options]\r\n            : options;\r\n    const inputHasError = enableInlineError && touched && error;\r\n    const [dropdownVisible, setDropdownVisible] = React.useState(false);\r\n    const [currentIndex, shuffle] = useShuffleIndex(allOptions.length);\r\n    const dropdownRef = React.useRef<HTMLDivElement>(null);\r\n    const isAValueSelected = input.value !== DEFAULT_OPTION;\r\n    const currentlySelectedOption =\r\n        isAValueSelected &&\r\n        allOptions.find(option => {\r\n            return option.value === input.value;\r\n        });\r\n    const toggleDropdown = (toggleState = !dropdownVisible) => {\r\n        if (!toggleState) {\r\n            shuffle(\"reset\");\r\n        }\r\n        setDropdownVisible(toggleState);\r\n    };\r\n    const rootClasses = classNames(\"input-wrapper\", className, {\r\n        \"input-select-label--float\": isAValueSelected,\r\n        \"input-select--dropdownVisible\": dropdownVisible,\r\n        \"input-select--readyForSorting\": readyForSorting,\r\n        \"input-wrapper--hasError\": inputHasError || forceErrorStyling\r\n    });\r\n\r\n    return (\r\n        <div\r\n            className={rootClasses}\r\n            onBlur={(event: React.FocusEvent) => {\r\n                // Only close dropdown if focus moves to element outside component in order allow click events\r\n                if (!dropdownRef.current?.contains((event.relatedTarget || document.activeElement) as Node)) {\r\n                    toggleDropdown(false);\r\n                }\r\n            }}\r\n            ref={dropdownRef}\r\n        >\r\n            {label && (\r\n                <label className=\"input-select-label\" htmlFor={input.name}>\r\n                    {label}\r\n                </label>\r\n            )}\r\n            <button\r\n                id={input.name}\r\n                className=\"input-select\"\r\n                onClick={() => toggleDropdown()}\r\n                type=\"button\"\r\n                onKeyPress={(event: React.KeyboardEvent<HTMLButtonElement>) => {\r\n                    // Tab\r\n                    if (event.key !== \"Tab\") {\r\n                        event.preventDefault();\r\n                    }\r\n                    // Enter\r\n                    if (event.key === \"Enter\") {\r\n                        if (dropdownVisible) {\r\n                            // An option was selected\r\n                            onChange(allOptions[currentIndex].value);\r\n                        }\r\n                        toggleDropdown();\r\n                    }\r\n                }}\r\n                onKeyDown={(event: React.KeyboardEvent<HTMLButtonElement>) => {\r\n                    // ScrollIntoView with options does not work in all browsers.\r\n                    // Hence this check which means no support in IE/Edge/Safari.\r\n                    const supportsNativeSmoothScroll = \"scrollBehavior\" in document.documentElement.style;\r\n\r\n                    // Escape\r\n                    if (event.keyCode === 27) {\r\n                        toggleDropdown(false);\r\n                    }\r\n                    // ArrowDown\r\n                    if (event.keyCode === 40) {\r\n                        event.preventDefault();\r\n                        if (!dropdownVisible) {\r\n                            toggleDropdown(true);\r\n                        } else {\r\n                            shuffle(\"increment\");\r\n\r\n                            if (supportsNativeSmoothScroll) {\r\n                                const nextIndex = (currentIndex + 1) % allOptions.length;\r\n                                const currentElement = document.querySelector(\r\n                                    `[data-value=\"${allOptions[nextIndex].value}\"]`\r\n                                );\r\n                                currentElement?.scrollIntoView({ behavior: \"smooth\", block: \"nearest\" });\r\n                            }\r\n                        }\r\n                    }\r\n                    // ArrowUp\r\n                    if (event.keyCode === 38) {\r\n                        event.preventDefault();\r\n                        if (!dropdownVisible) {\r\n                            toggleDropdown(true);\r\n                        } else {\r\n                            shuffle(\"decrement\");\r\n\r\n                            if (supportsNativeSmoothScroll) {\r\n                                const nextIndex =\r\n                                    (currentIndex + (allOptions.length - 1)) % allOptions.length;\r\n                                const currentElement = document.querySelector(\r\n                                    `[data-value=\"${allOptions[nextIndex].value}\"]`\r\n                                );\r\n                                currentElement?.scrollIntoView({ behavior: \"smooth\", block: \"nearest\" });\r\n                            }\r\n                        }\r\n                    }\r\n\r\n                    // Space (Edge browser only): In Edge 'Space' does not trigger and onClick event\r\n                    // as it does in other browsers. Hence we need to add this specifically.\r\n                    const isBrowserEdge = navigator.userAgent.toLowerCase().indexOf(\"edge\") !== -1;\r\n                    if (isBrowserEdge && event.keyCode === 32) {\r\n                        if (dropdownVisible) {\r\n                            // An option was selected\r\n                            onChange(allOptions[currentIndex].value);\r\n                        }\r\n                        toggleDropdown();\r\n                    }\r\n                }}\r\n                role=\"button\"\r\n            >\r\n                {currentlySelectedOption && currentlySelectedOption.label}\r\n            </button>\r\n            {dropdownVisible && (\r\n                <ul className=\"input-select__dropdown\" id={`${input.name}-dropdown`}>\r\n                    {allOptions.map((option, index) => {\r\n                        const isOptionSelected = input.value === option.value;\r\n\r\n                        return (\r\n                            <li key={index} className=\"input-select__option\">\r\n                                <button\r\n                                    className=\"input-select__option-button reset-button\"\r\n                                    aria-label={option.label}\r\n                                    tabIndex={-1}\r\n                                    type=\"button\"\r\n                                    data-value={option.value}\r\n                                    onClick={(event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {\r\n                                        const { target } = event;\r\n                                        const dataValue = (target as Element).getAttribute(\"data-value\");\r\n                                        let value;\r\n                                        if (typeof option.value === \"number\") {\r\n                                            // Make sure that the value is parsed as number\r\n                                            // if that is what the options value is\r\n                                            value = dataValue && parseInt(dataValue, 10);\r\n                                        } else {\r\n                                            value = dataValue;\r\n                                        }\r\n                                        toggleDropdown(false);\r\n                                        onChange(value);\r\n                                    }}\r\n                                    data-active={currentIndex === index}\r\n                                    disabled={isOptionSelected}\r\n                                >\r\n                                    {option.label}\r\n                                </button>\r\n                            </li>\r\n                        );\r\n                    })}\r\n                </ul>\r\n            )}\r\n            <Icon iconId=\"icon_16_arrow-down\" className=\"input-select__icon\" />\r\n\r\n            {inputHasError && <div className=\"input__error\" dangerouslySetInnerHTML={{ __html: error }} />}\r\n        </div>\r\n    );\r\n};\r\n\r\nexport default InputSelect;\r\n","import * as React from \"react\";\r\n\r\ntype ShuffleAction = \"increment\" | \"decrement\" | \"reset\";\r\n\r\nexport default function useShuffleIndex(\r\n    length: number,\r\n    initial = 0\r\n): [number, (shuffleAction: ShuffleAction) => void] {\r\n    const [currentIndex, setCurrentIndex] = React.useState(initial);\r\n\r\n    const shuffle = (shuffleAction: ShuffleAction) => {\r\n        switch (shuffleAction) {\r\n            case \"increment\":\r\n                setCurrentIndex((currentIndex + 1) % length);\r\n                break;\r\n            case \"decrement\":\r\n                setCurrentIndex((currentIndex + (length - 1)) % length);\r\n                break;\r\n            case \"reset\":\r\n                setCurrentIndex(initial);\r\n                break;\r\n            default:\r\n                return;\r\n        }\r\n    };\r\n\r\n    return [currentIndex, shuffle];\r\n}\r\n","import * as React from \"react\";\r\nimport classNames from \"classnames\";\r\n\r\nexport interface ITab {\r\n    key: string;\r\n    label: string;\r\n    content: React.ReactNode;\r\n}\r\n\r\nexport interface ITabsProps {\r\n    render(state: ITabsRenderProps): React.ReactNode;\r\n    defaultTab: ITab;\r\n    className?: string;\r\n}\r\n\r\ninterface ITabsRenderProps {\r\n    readonly tabClickHandler: () => void;\r\n    readonly selectedTabKey: string;\r\n}\r\n\r\nclass Tabs extends React.Component<ITabsProps> {\r\n    public state = {\r\n        selectedTabKey: this.props.defaultTab.key\r\n    };\r\n\r\n    private tabClickHandler = (tabId: string) => {\r\n        this.setState({\r\n            selectedTabKey: tabId\r\n        });\r\n    };\r\n\r\n    public getRenderProps(): ITabsRenderProps {\r\n        return {\r\n            tabClickHandler: this.tabClickHandler.bind(this),\r\n            selectedTabKey: this.state.selectedTabKey\r\n        };\r\n    }\r\n\r\n    public render() {\r\n        const renderProps = this.getRenderProps();\r\n        const rootClasses = classNames(\"tabs\", this.props.className);\r\n\r\n        return <div className={rootClasses}>{this.props.render(renderProps)}</div>;\r\n    }\r\n}\r\n\r\nexport default Tabs;\r\n","import * as React from \"react\";\r\nimport classNames from \"classnames\";\r\nimport { ITab } from \"~/components/tabs/tabs\";\r\n\r\nexport interface ITabMenuProps {\r\n    tabs: ITab[];\r\n    selectedKey: string;\r\n    tabClickHandler: (tabkey: string) => void;\r\n    className?: string;\r\n}\r\n\r\nconst TabMenu: React.SFC<ITabMenuProps> = props => {\r\n    return (\r\n        <div className={classNames(\"tab-menu\", props.className)}>\r\n            {props.tabs.map(tab => {\r\n                const btnClassName = classNames(\"tab-menu__button\", {\r\n                    \"tab-menu__button--isSelected\": tab.key === props.selectedKey\r\n                });\r\n\r\n                return (\r\n                    <button\r\n                        className={btnClassName}\r\n                        key={tab.key}\r\n                        type=\"button\"\r\n                        onClick={(e: React.MouseEvent<HTMLButtonElement>) => {\r\n                            e.preventDefault();\r\n                            props.tabClickHandler(tab.key);\r\n                        }}\r\n                    >\r\n                        {tab.label}\r\n                    </button>\r\n                );\r\n            })}\r\n        </div>\r\n    );\r\n};\r\n\r\nexport default TabMenu;\r\n","import * as React from \"react\";\r\nimport classNames from \"classnames\";\r\n\r\ninterface ITabContentContainerProps {\r\n    className?: string;\r\n}\r\n\r\nconst TabContentContainer: React.SFC<ITabContentContainerProps> = props => {\r\n    const rootClasses = classNames(\"tab-content-container\", props.className);\r\n    return <div className={rootClasses}>{props.children}</div>;\r\n};\r\n\r\nexport default TabContentContainer;\r\n","import * as React from \"react\";\r\nimport classNames from \"classnames\";\r\n\r\ninterface ITabContentProps {\r\n    isCurrent: boolean;\r\n    className?: string;\r\n    children: React.ReactNode;\r\n}\r\n\r\nconst TabContent: React.SFC<ITabContentProps> = props => {\r\n    const rootClasses = classNames(\"tab-content\", props.className, {\r\n        \"tab-content--isCurrent\": props.isCurrent\r\n    });\r\n    return <div className={rootClasses}>{props.children}</div>;\r\n};\r\n\r\nexport default TabContent;\r\n","import * as React from \"react\";\r\nimport classNames from \"classnames\";\r\nimport Icon, { TIconNames } from \"../icons/icon\";\r\n\r\ntype IOnClickFunction = (e: React.MouseEvent<HTMLButtonElement>) => void;\r\n\r\nexport interface IIconButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\r\n    onClick?: IOnClickFunction;\r\n    className?: string;\r\n    innerClassName?: string;\r\n    iconId?: TIconNames;\r\n    isLarge?: boolean;\r\n    isInverted?: boolean;\r\n    isSecondary?: boolean;\r\n}\r\n\r\nconst IconButton: React.FC<IIconButtonProps> = props => {\r\n    const baseClass = \"button\";\r\n    const componentClasses = classNames(baseClass, `${baseClass}--round`, props.innerClassName, {\r\n        [`${baseClass}--large`]: props.isLarge,\r\n        [`${baseClass}--inverted`]: props.isInverted,\r\n        [`${baseClass}--secondary`]: props.isSecondary\r\n    });\r\n\r\n    const renderedButton = (\r\n        <button\r\n            className={componentClasses}\r\n            type={props.type || \"button\"}\r\n            disabled={!!props.disabled}\r\n            onClick={e => {\r\n                if (props.onClick) {\r\n                    props.onClick(e);\r\n                }\r\n            }}\r\n        >\r\n            {props.iconId && <Icon iconId={props.iconId} className={`${baseClass}__icon`} />}\r\n        </button>\r\n    );\r\n\r\n    return (\r\n        <div className={classNames(`${baseClass}__round-container`, props.className)}>\r\n            {renderedButton}\r\n            {props.children ? <div className={`${baseClass}__round-text`}>{props.children}</div> : null}\r\n        </div>\r\n    );\r\n};\r\nexport default IconButton;\r\n","import * as React from \"react\";\r\nimport classNames from \"classnames\";\r\nimport Icon, { TIconNames } from \"../icons/icon\";\r\n\r\nexport interface IIconLinkProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {\r\n    className?: string;\r\n    innerClassName?: string;\r\n    iconId?: TIconNames;\r\n    isLarge?: boolean;\r\n    isInverted?: boolean;\r\n    isSecondary?: boolean;\r\n}\r\n\r\nconst IconButton: React.FC<IIconLinkProps> = props => {\r\n    const baseClass = \"icon-link\";\r\n    const componentClasses = classNames(baseClass, \"button\", `${baseClass}--round`, props.innerClassName, {\r\n        [`${baseClass}--large`]: props.isLarge,\r\n        [`${baseClass}--inverted`]: props.isInverted,\r\n        [`${baseClass}--secondary`]: props.isSecondary\r\n    });\r\n\r\n    const renderedLink = (\r\n        <a\r\n            href={props.href}\r\n            className={componentClasses}\r\n            download={props.download}\r\n            target={props.download ? \"_blank\" : \"\"}\r\n        >\r\n            {props.iconId && <Icon iconId={props.iconId} className={`${baseClass}__icon`} />}\r\n        </a>\r\n    );\r\n\r\n    return (\r\n        <div className={classNames(`${baseClass}__round-container`, props.className)}>\r\n            {renderedLink}{\" \"}\r\n            {props.children ? <div className={`${baseClass}__round-text`}>{props.children}</div> : null}\r\n        </div>\r\n    );\r\n};\r\nexport default IconButton;\r\n","import * as React from \"react\";\r\nimport classNames from \"classnames\";\r\n\r\nexport interface ISpecificationItem {\r\n    url?: string;\r\n    text: string;\r\n}\r\n\r\nexport interface ISpecification {\r\n    key: string;\r\n    specifications: ISpecificationItem[];\r\n}\r\n\r\nexport interface ISpecificationsListProps {\r\n    specifications: ISpecification[];\r\n    header?: string;\r\n    className?: string;\r\n}\r\n\r\nconst SpecificationsList: React.FC<ISpecificationsListProps> = props => {\r\n    const { header, specifications, className } = props;\r\n    const rootClasses = classNames(\"specifications-list\", className);\r\n\r\n    return (\r\n        <div className={rootClasses}>\r\n            <ul className=\"specifications-list__list\">\r\n                {props.header && (\r\n                    <li className=\"specifications-list__header specifications-list__list-item\">{header}</li>\r\n                )}\r\n                {specifications.map((item, index) => {\r\n                    if (!item.specifications || !item.key || item.specifications.length === 0) {\r\n                        return;\r\n                    }\r\n\r\n                    const values = item.specifications.map((subItem, subItemIndex) => {\r\n                        if (!subItem || !subItem.text) {\r\n                            return \"\";\r\n                        }\r\n\r\n                        const keyName = `${item.key.trim().replace(/\\s/g, \"\")}-${subItemIndex}`;\r\n\r\n                        if (subItem.url) {\r\n                            return (\r\n                                <a href={subItem.url} data-key={`${keyName}`} key={keyName}>\r\n                                    {subItem.text}\r\n                                </a>\r\n                            );\r\n                        }\r\n                        return (\r\n                            <span data-key={`${keyName}`} key={keyName}>\r\n                                {subItem.text}\r\n                            </span>\r\n                        );\r\n                    });\r\n\r\n                    const valuesArray = values.map(value => value).filter(str => str !== \"\");\r\n\r\n                    if (!valuesArray || valuesArray.length === 0) {\r\n                        return;\r\n                    }\r\n\r\n                    return (\r\n                        <li key={index} className=\"specifications-list__list-item\">\r\n                            <span className=\"specifications-list__list-item-key\">{item.key}</span>\r\n                            <span className=\"specifications-list__list-item-value\">{valuesArray}</span>\r\n                        </li>\r\n                    );\r\n                })}\r\n            </ul>\r\n        </div>\r\n    );\r\n};\r\n\r\nexport default SpecificationsList;\r\n","import * as React from \"react\";\r\nimport SpecificationsList, {\r\n    ISpecification\r\n} from \"../../../components/specifications-list/specifications-list\";\r\nimport Tabs, { ITab } from \"../../../components/tabs/tabs\";\r\nimport TabMenu from \"../../../components/tabs/tab-menu/tab-menu\";\r\nimport TabContentContainer from \"../../../components/tabs/tab-content-container/tab-content-container\";\r\nimport TabContent from \"../../../components/tabs/tab-content/tab-content\";\r\nimport { IProduct } from \"../../../types/product\";\r\nimport ShowMore from \"../../../components/show-more/show-more\";\r\nimport { ProductSignupCtaProps } from \"../../../components/product-signup-cta/product-signup-cta\";\r\n\r\nexport interface IProductDescriptionProps {\r\n    productDescriptionShowMoreButton: string;\r\n    productDescriptionShowLessButton: string;\r\n\r\n    productDescriptionTab: string;\r\n    productDescription: IProduct[\"description\"];\r\n\r\n    productSpecificationsTab: string;\r\n    productSpecifications: ISpecification[];\r\n\r\n    productPressSpecificationsTab: string;\r\n    productPressSpecifications: ISpecification[];\r\n}\r\n\r\nconst enum tabTypes {\r\n    DESCRIPTION = \"description\",\r\n    SPECIFICATIONS = \"specifications\",\r\n    PRESS = \"press\"\r\n}\r\n\r\nconst ProductDescription: React.FC<IProductDescriptionProps & Partial<ProductSignupCtaProps>> = props => {\r\n    const baseClass = \"product-description\";\r\n\r\n    const tabs: ITab[] = [\r\n        {\r\n            key: tabTypes.DESCRIPTION,\r\n            label: props.productDescriptionTab,\r\n            content: (\r\n                <ShowMore\r\n                    className={`${baseClass}__container`}\r\n                    minHeight={335}\r\n                    btnLabelShowMore={props.productDescriptionShowMoreButton}\r\n                    btnLabelShowLess={props.productDescriptionShowLessButton}\r\n                >\r\n                    {props.productDescription && (\r\n                        <div\r\n                            className={`${baseClass}__rich-text content-rich-text`}\r\n                            dangerouslySetInnerHTML={{ __html: props.productDescription }}\r\n                        />\r\n                    )}\r\n                </ShowMore>\r\n            )\r\n        },\r\n        {\r\n            key: tabTypes.SPECIFICATIONS,\r\n            label: props.productSpecificationsTab,\r\n            content: <SpecificationsList specifications={props.productSpecifications} />\r\n        },\r\n        {\r\n            key: tabTypes.PRESS,\r\n            label: props.productPressSpecificationsTab,\r\n            content: <SpecificationsList specifications={props.productPressSpecifications} />\r\n        }\r\n    ];\r\n\r\n    // const { productSignupCtaTitle, productSignupCtaText, productSignupCtaLink } = props;\r\n\r\n    return (\r\n        <div className={baseClass}>\r\n            {/* {productSignupCtaTitle && productSignupCtaText && productSignupCtaLink && (\r\n                <ProductSignupCta\r\n                    productSignupCtaTitle={productSignupCtaTitle}\r\n                    productSignupCtaText={productSignupCtaText}\r\n                    productSignupCtaLink={productSignupCtaLink}\r\n                />\r\n            )} */}\r\n            <Tabs\r\n                className={`${baseClass}__tabs`}\r\n                defaultTab={tabs[0]}\r\n                render={({ tabClickHandler, selectedTabKey }) => (\r\n                    <>\r\n                        <TabMenu tabClickHandler={tabClickHandler} tabs={tabs} selectedKey={selectedTabKey} />\r\n                        <TabContentContainer>\r\n                            {tabs.map(tab => (\r\n                                <TabContent isCurrent={selectedTabKey === tab.key} key={tab.key}>\r\n                                    {tab.content}\r\n                                </TabContent>\r\n                            ))}\r\n                        </TabContentContainer>\r\n                    </>\r\n                )}\r\n            />\r\n        </div>\r\n    );\r\n};\r\n\r\nexport default ProductDescription;\r\n","import React from \"react\";\r\nimport { IProductDetailsProps } from \"~/components/product-details/product-details\";\r\nimport { Field, reduxForm, InjectedFormProps } from \"redux-form\";\r\nimport InputSelect from \"~/components/input-select/input-select\";\r\n\r\nexport interface WorkVariantProps {\r\n    variants: IProductDetailsProps[];\r\n    onVariantSelect: (selectedVariantIndex: string | undefined) => void;\r\n    variantsLabel?: string;\r\n}\r\n\r\ninterface WorkVariantFormProps {\r\n    selectedVariant: string;\r\n}\r\n\r\ntype WorkVariantFormPropsUnion = WorkVariantProps & InjectedFormProps<WorkVariantFormProps, WorkVariantProps>;\r\n\r\nconst WorkVariantSelect: React.FC<WorkVariantFormPropsUnion> = ({ variants, variantsLabel }) => {\r\n    const options = variants\r\n        .filter(({ product }) => product.materialType !== undefined)\r\n        .map(({ product }, index) => ({ label: product.materialType, value: String(index) }));\r\n\r\n    return (\r\n        <Field\r\n            className=\"work-variant-select\"\r\n            name=\"selectedVariant\"\r\n            component={InputSelect}\r\n            fieldName=\"selectedVariant\"\r\n            label={variantsLabel}\r\n            options={options}\r\n        />\r\n    );\r\n};\r\n\r\nconst WorkVariantForm = reduxForm<WorkVariantFormProps, WorkVariantProps>({\r\n    form: \"work-variant-form\",\r\n    destroyOnUnmount: false,\r\n    onChange: (values, _, props) => {\r\n        const { onVariantSelect, change } = props;\r\n\r\n        if (onVariantSelect) {\r\n            onVariantSelect(values.selectedVariant);\r\n        }\r\n        if (change) {\r\n            change(\"selectedVariant\", values.selectedVariant);\r\n        }\r\n    }\r\n})(WorkVariantSelect);\r\n\r\nexport default WorkVariantForm;\r\n","import * as React from \"react\";\r\nimport Modal, { IModalProps } from \"../../../components/modal/modal\";\r\n\r\nexport interface IBookReadingModalProps extends IModalProps {\r\n    playerLink?: string;\r\n}\r\n\r\nconst BookReadingModal: React.FC<IBookReadingModalProps> = ({ playerLink, ...rest }) => {\r\n    return (\r\n        <Modal className=\"book-reading-modal\" {...rest}>\r\n            <iframe src={playerLink} />\r\n        </Modal>\r\n    );\r\n};\r\n\r\nexport default BookReadingModal;\r\n","import * as React from \"react\";\r\nimport Modal, { IModalProps } from \"../../../components/modal/modal\";\r\n\r\nexport interface IAudioModalProps extends IModalProps {\r\n    title: string;\r\n    playerLink: string;\r\n}\r\n\r\nconst AudioModal: React.FC<IAudioModalProps> = ({ playerLink, title, ...rest }) => {\r\n    return (\r\n        <Modal className=\"audio-modal\" {...rest}>\r\n            <div className=\"audio-player-wrapper\">\r\n                <h1 className=\"audio-player-title\">{title}</h1>\r\n                <audio controls>\r\n                    <source src={playerLink} type=\"audio/mpeg\" />\r\n                </audio>\r\n            </div>\r\n        </Modal>\r\n    );\r\n};\r\n\r\nexport default AudioModal;\r\n","import * as React from \"react\";\r\nimport { IProduct } from \"../../types/product\";\r\nimport ProductHero from \"../../components/product-details/product-hero/product-hero\";\r\nimport ProductDescription, {\r\n    IProductDescriptionProps\r\n} from \"../../components/product-details/product-description/product-description\";\r\nimport Tag from \"../tag/tag\";\r\n// import { IButtonAddToBasketProps } from \"../button-add-to-basket/button-add-to-basket\";\r\n// import ButtonAddToBasket from \"~/components/button-add-to-basket/button-add-to-basket\";\r\n// import ProductPrice from \"../product-price/product-price\";\r\nimport { IButtonSkipBookOfTheMonthProps } from \"./button-skip-book-of-the-month/button-skip-book-of-the-month\";\r\nimport classNames from \"classnames\";\r\n// import CtaButton from \"../cta-button/cta-button\";\r\nimport { pushDetailViewTrackingEvent } from \"../../utils/tracking-utils\";\r\nimport { ProductSignupCtaProps } from \"../product-signup-cta/product-signup-cta\";\r\nimport WorkVariantForm, { WorkVariantProps } from \"../work-details/work-variant-form/work-variant-form\";\r\nimport ArrowLink from \"../arrow-link/arrow-link\";\r\nimport ProductAuthors from \"../product-authors/product-authors\";\r\n// import InfoSection from \"../info-section/info-section\";\r\n// import { useSelector } from \"react-redux\";\r\n// import { IRootState } from \"~/store/reducers\";\r\n// import { selectIsOutOfStock } from \"~/store/reducers/basket/basket-reducer\";\r\n// import ErrorMessage from \"../error-message/error-message\";\r\nimport BookReadingModal from \"./book-reading-modal/book-reading-modal\";\r\nimport IconButton from \"../icon-button/icon-button\";\r\nimport AudioModal from \"./audio-modal/audio-modal\";\r\nimport IconLink from \"../icon-link/icon-link\";\r\n// import { IDiscountOffer } from \"~/types/discount-offer\";\r\n// import DiscountModal from \"./discount-modal/discount-modal\";\r\n// import { hasDeclinedDiscountThisOffer } from \"~/utils/discount-utils\";\r\n\r\nexport interface IProductDetailsProps\r\n    extends Partial<\r\n            Pick<\r\n                IButtonSkipBookOfTheMonthProps,\r\n                \"skipBookOfTheMonthWebApiUrl\" | \"isSkipBookOfTheMonthAllowed\"\r\n            >\r\n        >,\r\n        Partial<Pick<WorkVariantProps, \"variants\" | \"variantsLabel\" | \"onVariantSelect\">>,\r\n        Partial<ProductSignupCtaProps>,\r\n        Pick<\r\n            IProductDescriptionProps,\r\n            | \"productDescriptionTab\"\r\n            | \"productDescriptionShowMoreButton\"\r\n            | \"productDescriptionShowLessButton\"\r\n            | \"productSpecificationsTab\"\r\n            | \"productSpecifications\"\r\n            | \"productPressSpecificationsTab\"\r\n            | \"productPressSpecifications\"\r\n        > {\r\n    product: IProduct;\r\n    initialVariantIndex?: number;\r\n    primaryPriceLabel: string;\r\n    // secondaryPriceLabel?: string;\r\n    addToBasketLabel?: string;\r\n    bookOfTheMonthAddToBasketLabel?: string;\r\n    bookOfTheMonthSkipLabel?: string;\r\n    ctaLink?: string;\r\n    className?: string;\r\n    vendorListTitle?: string;\r\n    vendorList?: string[];\r\n    readBookLabel?: string;\r\n    readBookPlayerLink?: string;\r\n    listenToBookLabel?: string;\r\n    listenToBookPlayerLink?: string;\r\n    downloadCoverImageLabel?: string;\r\n    downloadCoverImageLink?: string;\r\n    // disableDiscountOfferWebApiUrl: string;\r\n    // showDiscountOfferModal?: boolean;\r\n    // discountOffer?: IDiscountOffer;\r\n}\r\n\r\nconst ProductDetails: React.FC<IProductDetailsProps> = ({\r\n    product,\r\n    // addToBasketWebApiUrl,\r\n    // skipBookOfTheMonthWebApiUrl,\r\n    // isSkipBookOfTheMonthAllowed,\r\n    // addToBasketLabel,\r\n    // bookOfTheMonthAddToBasketLabel,\r\n    // bookOfTheMonthSkipLabel,\r\n    // ctaLink,\r\n    className,\r\n    variants,\r\n    variantsLabel,\r\n    onVariantSelect,\r\n    initialVariantIndex,\r\n    vendorListTitle,\r\n    vendorList,\r\n    readBookLabel,\r\n    listenToBookLabel,\r\n    readBookPlayerLink,\r\n    listenToBookPlayerLink,\r\n    downloadCoverImageLabel,\r\n    downloadCoverImageLink,\r\n    // showDiscountOfferModal = false,\r\n    // discountOffer,\r\n    // secondaryPriceLabel,\r\n    primaryPriceLabel,\r\n    ...props\r\n}) => {\r\n    const [bookModalOpen, setBookModalOpen] = React.useState(false);\r\n    const [audioModalOpen, setAudioModalOpen] = React.useState(false);\r\n    // const [discountModalOpen, setDiscountModalOpen] = React.useState(false);\r\n\r\n    React.useEffect(() => {\r\n        pushDetailViewTrackingEvent({ ...product, trackingList: \"Product Details\" });\r\n    }, []);\r\n\r\n    const baseClass = \"product-details\";\r\n    const rootClasses = classNames(baseClass, className);\r\n\r\n    const hasSignupCta =\r\n        props.productSignupCtaLink && props.productSignupCtaText && props.productSignupCtaTitle;\r\n    const hasVendorList = vendorListTitle && vendorList && vendorList.length > 0;\r\n\r\n    const buyingSectionClasses = classNames(`${baseClass}__buying-section`, {\r\n        [`${baseClass}__buying-section--hasSignupPadding`]: hasSignupCta\r\n        // [`${baseClass}__buying-section--hasVendorListAndBasketButton`]: hasVendorList && addToBasketWebApiUrl\r\n    });\r\n\r\n    // const isOutOfStock = useSelector((state: IRootState) => selectIsOutOfStock(state, product.productId));\r\n\r\n    // const onAddToBasket = () => {\r\n    //     if (!discountOffer) {\r\n    //         return;\r\n    //     }\r\n\r\n    //     if (hasDeclinedDiscountThisOffer(discountOffer)) {\r\n    //         return;\r\n    //     }\r\n\r\n    //     if (!showDiscountOfferModal) {\r\n    //         return;\r\n    //     }\r\n\r\n    //     setDiscountModalOpen(true);\r\n    // };\r\n\r\n    return (\r\n        <div className={rootClasses}>\r\n            <div className={`${baseClass}__hero-wrapper`}>\r\n                <ProductHero\r\n                    {...props}\r\n                    imageFallbackSrc={product.imageFallbackSrc}\r\n                    imageSrcSet={product.imageSrcSet}\r\n                    // discount={product.discount}\r\n                    onOpenAudioModal={() => setAudioModalOpen(true)}\r\n                    onOpenBookModal={() => setBookModalOpen(true)}\r\n                    readBookLabel={readBookLabel}\r\n                    readBookPlayerLink={readBookPlayerLink}\r\n                    listenToBookLabel={listenToBookLabel}\r\n                    listenToBookPlayerLink={listenToBookPlayerLink}\r\n                    downloadCoverImageLabel={downloadCoverImageLabel}\r\n                    downloadCoverImageLink={downloadCoverImageLink}\r\n                />\r\n            </div>\r\n\r\n            <div className={`${baseClass}__info-grid ${baseClass}__title-container`}>\r\n                <div className={`${baseClass}__action-wrapper`}></div>\r\n                <div className={`${baseClass}__title-wrapper ${baseClass}__info-wrapper`}>\r\n                    {product.status && <Tag type={product.status}>{product.statusLabel}</Tag>}\r\n                    <h1 className={`${baseClass}__title h1-style`}>{product.title}</h1>\r\n                    <ProductAuthors authors={product.authors} className={`${baseClass}__product-authors`} />\r\n                </div>\r\n            </div>\r\n\r\n            {readBookPlayerLink && (\r\n                <BookReadingModal\r\n                    playerLink={readBookPlayerLink}\r\n                    isOpen={bookModalOpen}\r\n                    onRequestClose={() => setBookModalOpen(false)}\r\n                />\r\n            )}\r\n\r\n            {listenToBookPlayerLink && (\r\n                <AudioModal\r\n                    title={product.title}\r\n                    playerLink={listenToBookPlayerLink}\r\n                    isOpen={audioModalOpen}\r\n                    onRequestClose={() => setAudioModalOpen(false)}\r\n                />\r\n            )}\r\n            <div className={`${baseClass}__info-grid ${baseClass}__content-container`}>\r\n                <div className={`${baseClass}__action-wrapper`}>\r\n                    <div className={`${baseClass}__action-button-wrapper`}>\r\n                        {readBookLabel && readBookPlayerLink && (\r\n                            <IconButton\r\n                                innerClassName={`${baseClass}__inner-play-button`}\r\n                                onClick={() => setBookModalOpen(true)}\r\n                                iconId=\"icon_read\"\r\n                            >\r\n                                {readBookLabel}\r\n                            </IconButton>\r\n                        )}\r\n\r\n                        {listenToBookLabel && listenToBookPlayerLink && (\r\n                            <IconButton\r\n                                innerClassName={`${baseClass}__inner-play-button`}\r\n                                onClick={() => setAudioModalOpen(true)}\r\n                                iconId=\"icon_listen\"\r\n                            >\r\n                                {listenToBookLabel}\r\n                            </IconButton>\r\n                        )}\r\n\r\n                        {downloadCoverImageLabel && downloadCoverImageLink && (\r\n                            <IconLink\r\n                                innerClassName={`${baseClass}__inner-play-button`}\r\n                                href={downloadCoverImageLink}\r\n                                iconId=\"icon_download\"\r\n                            >\r\n                                {downloadCoverImageLabel}\r\n                            </IconLink>\r\n                        )}\r\n                    </div>\r\n                </div>\r\n\r\n                <div className={`${baseClass}__info-wrapper`}>\r\n                    <div className={`${baseClass}__content-wrapper`}>\r\n                        <ProductDescription {...props} productDescription={product.description} />\r\n                        <div className={buyingSectionClasses}>\r\n                            {primaryPriceLabel && (\r\n                                <h3 className={`${baseClass}__vendor-list-title`}>{primaryPriceLabel}</h3>\r\n                            )}\r\n                            {product.primaryPrice && (\r\n                                <p className=\"product-price__primary-price\">{product.primaryPrice}</p>\r\n                            )}\r\n\r\n                            {variants &&\r\n                                variants.length > 0 &&\r\n                                onVariantSelect &&\r\n                                initialVariantIndex !== undefined && (\r\n                                    <WorkVariantForm\r\n                                        variants={variants}\r\n                                        variantsLabel={variantsLabel}\r\n                                        onVariantSelect={onVariantSelect}\r\n                                        initialValues={{\r\n                                            selectedVariant: String(initialVariantIndex)\r\n                                        }}\r\n                                    />\r\n                                )}\r\n\r\n                            {/* <ProductPrice\r\n                                {...props}\r\n                                priceType={product.priceType}\r\n                                primaryPrice={product.primaryPrice}\r\n                                secondaryPrice={product.secondaryPrice}\r\n                                isCurrentBookOfTheMonth={product.isCurrentBookOfTheMonth}\r\n                                bookOfTheMonthStatusLabel={product.bookOfTheMonthStatusLabel}\r\n                                status={product.status}\r\n                            >\r\n                                {ctaLink && <CtaButton isLarge link={ctaLink} />}\r\n                                {product.isCurrentBookOfTheMonth ? (\r\n                                    <>\r\n                                        {addToBasketWebApiUrl && (\r\n                                            <>\r\n                                                <ButtonAddToBasket\r\n                                                    className=\"product-price__buy-button\"\r\n                                                    addToBasketWebApiUrl={addToBasketWebApiUrl}\r\n                                                    productId={product.productId}\r\n                                                    trackingList=\"Product Details\"\r\n                                                    isLarge\r\n                                                    onAdd={onAddToBasket}\r\n                                                >\r\n                                                    {bookOfTheMonthAddToBasketLabel}\r\n                                                </ButtonAddToBasket>\r\n                                                {isOutOfStock.error && isOutOfStock.value && (\r\n                                                    <ErrorMessage\r\n                                                        errorSeverity=\"error\"\r\n                                                        errorMessage={isOutOfStock.error}\r\n                                                    />\r\n                                                )}\r\n                                            </>\r\n                                        )}\r\n                                        {skipBookOfTheMonthWebApiUrl && (\r\n                                            <ButtonSkipBookOfTheMonth\r\n                                                className=\"product-price__botm-skip-button\"\r\n                                                skipBookOfTheMonthWebApiUrl={skipBookOfTheMonthWebApiUrl}\r\n                                                isSkipBookOfTheMonthAllowed={isSkipBookOfTheMonthAllowed}\r\n                                                productId={product.productId}\r\n                                                isLarge\r\n                                                isInverted\r\n                                            >\r\n                                                {bookOfTheMonthSkipLabel}\r\n                                            </ButtonSkipBookOfTheMonth>\r\n                                        )}\r\n                                    </>\r\n                                ) : (\r\n                                    addToBasketWebApiUrl && (\r\n                                        <>\r\n                                            <ButtonAddToBasket\r\n                                                className=\"product-price__buy-button\"\r\n                                                addToBasketWebApiUrl={addToBasketWebApiUrl}\r\n                                                productId={product.productId}\r\n                                                trackingList=\"Product Details\"\r\n                                                isLarge\r\n                                                onAdd={onAddToBasket}\r\n                                            >\r\n                                                {addToBasketLabel}\r\n                                            </ButtonAddToBasket>\r\n                                            {isOutOfStock.error && isOutOfStock.value && (\r\n                                                <ErrorMessage\r\n                                                    errorSeverity=\"error\"\r\n                                                    errorMessage={isOutOfStock.error}\r\n                                                />\r\n                                            )}\r\n                                        </>\r\n                                    )\r\n                                )}\r\n                                {(product.stockStatusLabel || product.stockStatusDetails) && (\r\n                                    <InfoSection\r\n                                        iconId=\"32_information\"\r\n                                        label={product.stockStatusLabel}\r\n                                        details={product.stockStatusDetails}\r\n                                        status={\r\n                                            product.stockStatus\r\n                                                ? ProductStockStatusEnum[product.stockStatus]\r\n                                                : undefined\r\n                                        }\r\n                                    />\r\n                                )}\r\n                                {(product.deliveryLabel || product.deliveryDetails) && (\r\n                                    <InfoSection\r\n                                        iconId=\"32_truck-in-motion\"\r\n                                        label={product.deliveryLabel}\r\n                                        details={product.deliveryDetails}\r\n                                    />\r\n                                )}\r\n                            </ProductPrice> */}\r\n\r\n                            {/* {showDiscountOfferModal && discountOffer && (\r\n                                <DiscountModal\r\n                                    isOpen={discountModalOpen}\r\n                                    setOpen={setDiscountModalOpen}\r\n                                    addToBasketWebApiUrl={addToBasketWebApiUrl}\r\n                                    discount={discountOffer}\r\n                                    secondaryPriceLabel={secondaryPriceLabel}\r\n                                    {...props}\r\n                                />\r\n                            )} */}\r\n\r\n                            {hasVendorList && (\r\n                                <>\r\n                                    <h3 className={`${baseClass}__vendor-list-title`}>{vendorListTitle}</h3>\r\n                                    <ul className={`${baseClass}__vendor-list`}>\r\n                                        {vendorList?.map((item, index) => (\r\n                                            <li className={`${baseClass}__vendor`} key={index}>\r\n                                                {item.includes(\"</a>\") ? (\r\n                                                    <ArrowLink link={item} />\r\n                                                ) : (\r\n                                                    <span dangerouslySetInnerHTML={{ __html: item }} />\r\n                                                )}\r\n                                            </li>\r\n                                        ))}\r\n                                    </ul>\r\n                                </>\r\n                            )}\r\n                        </div>\r\n                    </div>\r\n                </div>\r\n            </div>\r\n        </div>\r\n    );\r\n};\r\n\r\nexport default ProductDetails;\r\n"],"sourceRoot":""}