From 511a192b6e9c57a659f61912892f456ba38159c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?ilyas=20St=C3=A9phane=20T=C3=BCrkben?= Date: Wed, 6 Dec 2023 17:36:39 +0100 Subject: [PATCH] MWPW-140042: Merch Card V3 (#1604) * MWPW-140042: Merch Card V3 Removed legacy merch-card No dependency on CaaS Accessible via arrow keys Co-authored-by: Mariia Lukianets Co-authored-by: Axel Cureno Basurto Co-authored-by: Honwai Wong --- CODEOWNERS | 3 +- libs/blocks/merch-card/legacy-merch-card.css | 352 ---------- libs/blocks/merch-card/legacy-merch-card.js | 207 ------ libs/blocks/merch-card/merch-card.css | 22 +- libs/blocks/merch-card/merch-card.js | 432 ++++++++---- libs/blocks/merch-card/merch-offer-select.js | 49 ++ libs/blocks/merch-offers/merch-offers.css | 3 + libs/blocks/merch-offers/merch-offers.js | 10 + libs/deps/merch-card.js | 629 +++++++++++------- libs/deps/merch-offer-select.js | 95 +++ libs/utils/utils.js | 1 + .../legacy-merch-card.test.js | 168 ----- .../legacy-merch-card/mocks/plans-card.html | 76 --- .../legacy-merch-card/mocks/segment-card.html | 24 - .../mocks/special-offers.html | 25 - .../legacy-merch-card/mocks/uar-card.html | 49 -- test/blocks/merch-card/merch-card.test.js | 456 +++++++------ .../merch-card/merch-offer-select.test.js | 70 ++ .../blocks/merch-card/mocks/acrobat-card.html | 63 ++ .../mocks/card-section-metadata.html | 52 ++ test/blocks/merch-card/mocks/catalog.html | 30 +- .../merch-card/mocks/intro-pricing.html | 23 + test/blocks/merch-card/mocks/plans-card.html | 56 +- .../merch-card/mocks/special-offers.html | 28 +- test/blocks/merch-card/mocks/uar-card.html | 4 +- 25 files changed, 1414 insertions(+), 1513 deletions(-) delete mode 100644 libs/blocks/merch-card/legacy-merch-card.css delete mode 100644 libs/blocks/merch-card/legacy-merch-card.js create mode 100644 libs/blocks/merch-card/merch-offer-select.js create mode 100644 libs/blocks/merch-offers/merch-offers.css create mode 100644 libs/blocks/merch-offers/merch-offers.js create mode 100644 libs/deps/merch-offer-select.js delete mode 100644 test/blocks/merch-card/legacy-merch-card/legacy-merch-card.test.js delete mode 100644 test/blocks/merch-card/legacy-merch-card/mocks/plans-card.html delete mode 100644 test/blocks/merch-card/legacy-merch-card/mocks/segment-card.html delete mode 100644 test/blocks/merch-card/legacy-merch-card/mocks/special-offers.html delete mode 100644 test/blocks/merch-card/legacy-merch-card/mocks/uar-card.html create mode 100644 test/blocks/merch-card/merch-offer-select.test.js create mode 100644 test/blocks/merch-card/mocks/acrobat-card.html create mode 100644 test/blocks/merch-card/mocks/card-section-metadata.html create mode 100644 test/blocks/merch-card/mocks/intro-pricing.html diff --git a/CODEOWNERS b/CODEOWNERS index 0db94fa3e5..7055a9bb70 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -32,7 +32,8 @@ /libs/blocks/marquee/ @ryanmparrish @Sartxi @auniverseaway /libs/blocks/media/ @ryanmparrish /libs/blocks/merch/ @3ch023 @honstar @VKniaz @npeltier @Axelcureno -/libs/blocks/merch-card/ @VKniaz @Axelcureno @ryanmparrish +/libs/blocks/merch-card/ @VKniaz @Axelcureno @ryanmparrish @yesil @3ch023 +/libs/blocks/merch-offers/ @yesil @vladen /libs/blocks/ost/ @Axelcureno @3ch023 @honstar @VKniaz @vladen @yesil @npeltier /libs/blocks/pdf-vewer/ @sanjayms01 /libs/blocks/quiz/ @colloyd @sabyamon @fullcolorcoder @JackySun9 @elaineskpt @echampio-at-adobe diff --git a/libs/blocks/merch-card/legacy-merch-card.css b/libs/blocks/merch-card/legacy-merch-card.css deleted file mode 100644 index 53271e27ea..0000000000 --- a/libs/blocks/merch-card/legacy-merch-card.css +++ /dev/null @@ -1,352 +0,0 @@ -/* stylelint-disable selector-class-pattern */ -.merch-card hr { - background-color: var(--color-gray-200); - border: none; - height: 1px; - width: 100%; - margin-bottom: var(--spacing-xs); -} - -.merch-card p { - font-size: var(--type-body-xs-size); - font-weight: 400; - line-height: 1.5; - margin-bottom: var(--spacing-xxs); - margin-top: 0; - color: var(--color-black); -} - -.merch-card h1, -.merch-card h2, -.merch-card h3, -.merch-card h4, -.merch-card h5, -.merch-card h6 { - line-height: 1.25; - margin-top: 0; - color: var(--color-black); -} - -.merch-card h2 { - font-size: var(--type-heading-l-size); - margin-bottom: var(--spacing-xxs); -} - -.merch-card h3, -.merch-card h4 { - font-size: var(--type-heading-xs-size); - margin-bottom: var(--spacing-xxs); -} - -.merch-card h5 { - font-size: var(--type-heading-xs-size); -} - -.merch-card .consonant-MerchCard-ProductIcon { - background-size: contain; - background-repeat: no-repeat; - position: relative; - margin-right: var(--spacing-xxs); - margin-bottom: var(--spacing-xxs); - display: block; - float: left; - width: 40px; - height: 40px; -} - -.merch-card div[class$="-title"] { - width: 100%; - font-size: var(--type-heading-xs-lh); - font-weight: var(--type-heading-all-weight); - align-self: flex-start; - max-height: max-content; - flex: none; -} - -.merch-card h4.consonant-SpecialOffers-title { - text-transform: uppercase; -} - -.merch-card h2.consonant-PlansCard-title { - font-size: var(--type-heading-m-size); - line-height: var(--type-heading-l-lh); -} - -.merch-card h3.consonant-SpecialOffers-title, -.merch-card h3.consonant-PlansCard-title { - margin-bottom: 0; -} - -.merch-card h3.consonant-PlansCard-title { - margin-bottom: var(--spacing-xxs); - line-height: var(--type-heading-s-lh); -} - -.merch-card h4.consonant-PlansCard-title { - font-size: var(--type-body-xxs-size); - font-style: italic; -} - -.merch-card h5[class$="-title"] { - font-size: var(--type-heading-xxs-size); - font-weight: 500; -} - -.merch-card.segment { - position: relative; - display: flex; - flex-direction: column; - min-height: 222px; - width: 100%; - flex: 1; - min-width: 378px; - max-width: 378px; -} - -.merch-card.special-offers, -.merch-card.segment, -.merch-card.plans { - border-radius: 16px; -} - -.merch-card.special-offers.full-width { - min-width: 100%; - max-width: 100%; - width: 1200px; -} - -.merch-card.special-offers.center { - text-align: center; -} - -.merch-card div[class$="-inner"] { - display: flex; - flex-direction: column; - flex-grow: 1; - padding: 16px 16px 20px; - border-radius: 4px; - background-color: var(--color-white); - text-decoration: none; -} - -.merch-card .consonant-PlansCard-inner { - padding: var(--spacing-xs); -} - -.merch-card div[class$="-prices"] { - font-size: var(--type-body-s-size); - line-height: 24px; - margin-bottom: var(--spacing-xxs); -} - -.merch-card div[class$="-description"] { - width: 100%; - font-size: var(--type-heading-xs-size); - line-height: 1.5; - margin-top: 0; - align-self: flex-start; - flex-grow: 1; -} - -.merch-card .consonant-SegmentBlade-description span.placeholder-resolved, -.merch-card .consonant-SpecialOffers-description span.placeholder-resolved, -.merch-card .consonant-PlansCard-description span.placeholder-resolved { - font-size: var(--type-heading-xs-size); -} - -.merch-card .consonant-SegmentBlade-description span.placeholder-resolved[data-template="strikethrough"], -.merch-card .consonant-SpecialOffers-description span.placeholder-resolved[data-template="strikethrough"], -.merch-card .consonant-PlansCard-description span.placeholder-resolved[data-template="strikethrough"] { - font-size: var(--type-body-xs-size); -} - -.merch-card.consonant-SpecialOffers-Card { - border-radius: 16px; -} - -.merch-card .consonant-SpecialOffers-img, -.merch-card .consonant-PlansCard-img { - flex-grow: 1; - position: relative; - width: 100%; - height: 213px; - background-color: var(--background-color); - background-position: 50% 50%; - background-repeat: no-repeat; - background-size: cover; -} - -.merch-card div[class$="-ribbon"] { - position: absolute; - top: 16px; - right: 0; - font-size: var(--type-heading-xxs-size); - font-weight: 500; - max-width: 150px; - line-height: 16px; - text-align: center; - padding: 8px 11px; - border-radius: 5px 0 0 5px; -} - -.merch-card .consonant-SpecialOffers-ribbon { - text-transform: uppercase; -} - -.merch-card .consonant-SpecialOffers-inner, -.merch-card .consonant-PlansCard-inner { - justify-content: center; - height: 100%; -} - -.merch-card.special-offers .consonant-SpecialOffers-description p, -.merch-card.special-offers .consonant-PlansCard-description p { - font-size: var(--type-body-xs-size); -} - -.merch-card .consonant-SpecialOffers-description em, -.merch-card .consonant-PlansCard-description em { - color: var(--color-gray-600); -} - -.merch-card.special-offers h4 { - font-size: var(--type-body-xxs-size); - text-transform: uppercase; - letter-spacing: 1px; -} - -.merch-card .checkbox-container { - cursor: pointer; - margin-bottom: var(--spacing-xs); -} - -.merch-card .checkbox-container, -.merch-card .secure-transaction-wrapper { - display: grid; - grid-template-columns: 12px auto; - gap: var(--spacing-xxs); -} - -.merch-card .checkbox-label, -.merch-card .secure-transaction-label { - font-size: var(--type-body-xxs-size); - line-height: 1.3; - color: var(--color-gray-600); -} - -.merch-card .secure-transaction-icon { - height: 15px; - width: 12px; - background: url('/libs/img/ui/secure-transaction.svg') no-repeat left center; -} - -.merch-card .secure-transaction-label { - white-space: nowrap; -} - -.merch-card .checkbox-container input[type="checkbox"] { - display: none; -} - -.merch-card .checkbox-container .checkmark { - position: relative; - display: inline-block; - width: 12px; - height: 12px; - border: 2px solid #757575; - background: #fff; - border-radius: 2px; - cursor: pointer; - margin-top: 2px; -} - -.merch-card .checkbox-container input[type="checkbox"]:checked + .checkmark { - background-color: var(--color-accent); - background-image: url('/libs/img/ui/checkmark-white-small.svg'); - border-color: var(--color-accent); -} - -.merch-card.has-divider hr { - margin: var(--spacing-xxs) 0; -} - -.merch-card.has-divider .consonant-CardFooter hr { - display: none; -} - -.merch-card.background-opacity-70 { - background-color: rgba(255 255 255 / 70%); -} - -.merch-card.background-opacity-70 div[class$="-inner"] { - background-color: transparent; -} - -.merch-card.inline-heading .consonant-SegmentBlade-inner { - display: grid; - column-gap: 12px; - align-items: center; - grid-template-columns: 40px 1fr; -} - -.merch-card ul[class$="-list"] { - list-style: none; - margin: 0; - padding-left: var(--spacing-xxs); - font-size: var(--type-body-xxs-size); - line-height: 1.5; - color: var(--color-black); -} - -.merch-card li[class$="-list-item"] { - position: relative; -} - -.merch-card li[class$="-list-item"]::before { - content: "\B7"; - position: absolute; - left: -0.4em; - font-size: 1.5em; - top: calc(0.5 * 1.5 * var(--type-body-xxs-size) - 0.05em); - transform: translateY(-50%); -} - -.merch-card.inline-heading .consonant-SegmentBlade-description, -.merch-card.inline-heading .consonant-CardFooter { - grid-column: span 2; -} - -.merch-card.special-offers .consonant-CardFooter { - margin-top: 0; - padding-top: 0; - justify-content: center; - box-sizing: border-box; - align-self: flex-end; - width: 100%; -} - -.merch-card .consonant-CardFooter .standard-wrapper { - display: flex; - flex-wrap: wrap; - gap: var(--spacing-xs); - align-items: center; -} - -.merch-card .consonant-CardFooter-row, -.merch-card .consonant-CardFooter-cell { - display: flex; - gap: var(--spacing-xs); - flex-wrap: wrap; - margin-left: auto; - height: auto; - width: auto; -} - -.merch-card .consonant-CardFooter-row .button--inactive { - display: none; -} - -.dark .merch-card .consonant-CardFooter .con-button.outline { - border-color: var(--color-black); - color: var(--color-black); -} diff --git a/libs/blocks/merch-card/legacy-merch-card.js b/libs/blocks/merch-card/legacy-merch-card.js deleted file mode 100644 index d8ba397264..0000000000 --- a/libs/blocks/merch-card/legacy-merch-card.js +++ /dev/null @@ -1,207 +0,0 @@ -/* eslint-disable prefer-destructuring */ -import { decorateButtons, decorateBlockHrs } from '../../utils/decorate.js'; -import { loadStyle, getConfig, createTag } from '../../utils/utils.js'; -import { addBackgroundImg, addWrapper, addFooter } from '../card/cardUtils.js'; -import { replaceKey } from '../../features/placeholders.js'; - -const { miloLibs, codeRoot } = getConfig(); -const base = miloLibs || codeRoot; - -const SEGMENT_BLADE = 'SegmentBlade'; -const SPECIAL_OFFERS = 'SpecialOffers'; -const PLANS_CARD = 'PlansCard'; -const cardTypes = { - segment: SEGMENT_BLADE, - 'special-offers': SPECIAL_OFFERS, - plans: PLANS_CARD, -}; -const getPodType = (styles) => { - const authoredType = styles?.find((style) => style in cardTypes); - - return cardTypes[authoredType] || SEGMENT_BLADE; -}; - -const decorateFooter = (el, altCtaMetaData, cardType) => { - const cardFooter = el.querySelector('.consonant-CardFooter'); - - const decorateWithSecureTransactionSign = () => { - const secureTransactionWrapper = createTag('div', { class: 'secure-transaction-wrapper' }); - const label = createTag('span', { class: 'secure-transaction-label' }); - const secureElement = createTag('span', { class: 'secure-transaction-icon' }); - secureTransactionWrapper.append(secureElement, label); - replaceKey('secure-transaction', getConfig()).then((replacedKey) => { - label.textContent = replacedKey; - }); - return secureTransactionWrapper; - }; - - const createCheckbox = (checkBoxText) => { - const container = createTag('label', { class: 'checkbox-container' }); - const input = createTag('input', { id: 'alt-cta', type: 'checkbox' }); - const checkmark = createTag('span', { class: 'checkmark' }); - const label = createTag('span', { class: 'checkbox-label' }, checkBoxText.innerHTML); - - container.append(input, checkmark, label); - return container; - }; - - const createSecureSign = () => { - const cardFooterRow = el.querySelector('.consonant-CardFooter-row'); - const standardWrapper = createTag('div', { class: 'standard-wrapper' }); - const secureTransactionWrapper = decorateWithSecureTransactionSign(); - - standardWrapper.append(secureTransactionWrapper, cardFooterRow); - cardFooter?.append(standardWrapper); - }; - - const decorateAlternativeCta = () => { - const altCtaRegex = /href=".*"/; - if (!altCtaRegex.test(altCtaMetaData[1]?.innerHTML)) return; - const cardFooterRow = el.querySelector('.consonant-CardFooter-row'); - const originalCtaButton = cardFooterRow.querySelector('.consonant-CardFooter-cell--right'); - const checkboxContainer = createCheckbox(altCtaMetaData[0]); - const altCtaButtonData = altCtaMetaData[1]; - decorateButtons(altCtaButtonData); - const altCtaButton = createTag( - 'div', - { class: originalCtaButton.classList }, - altCtaButtonData.innerHTML, - ); - altCtaButton.classList.add('button--inactive'); - checkboxContainer - .querySelector('input[type="checkbox"]') - .addEventListener('change', ({ target: { checked } }) => { - originalCtaButton.classList.toggle('button--inactive', checked); - altCtaButton.classList.toggle('button--inactive', !checked); - }); - cardFooterRow.append(altCtaButton); - cardFooter.prepend(checkboxContainer); - altCtaMetaData[0].parentNode.remove(); - }; - if (altCtaMetaData !== null) decorateAlternativeCta(); - if (el.classList.contains('secure')) createSecureSign(); - cardFooter.querySelectorAll('.consonant-CardFooter-cell').forEach( - (cell) => cell.classList.add(`consonant-${cardType}-cell`), - ); -}; - -const addInner = (el, altCta, cardType, merchCard) => { - const innerElements = [...el.querySelectorAll('h1, h2, h3, h4, h5, h6, p, ul')]; - const styles = [...el.classList]; - const merch = styles.includes('merch-card'); - const pElement = merch && el.querySelector(':scope > div > div > p:last-of-type'); - const links = pElement - ? pElement.querySelectorAll('a:not([data-dnd]), checkout-link') - : el.querySelectorAll('a:not([data-dnd]), checkout-link'); - const list = el.querySelector('ul'); - - const inner = el.querySelector(':scope > div:not([class])'); - inner.classList.add(`consonant-${cardType}-inner`); - - innerElements.forEach((element) => { - if (element.tagName.match(/^H[1-6]$/)) element.classList.add(`consonant-${cardType}-title`); - if (element.tagName.match(/^P$/)) element.classList.add(`consonant-${cardType}-description`); - if (element.tagName.match(/^UL$/)) { - list.classList.add(`consonant-${cardType}-list`); - list.querySelectorAll('li').forEach((li) => { - li.classList.add(`consonant-${cardType}-list-item`); - }); - } - }); - - inner.append(...innerElements); - addFooter(links, inner, cardType !== PLANS_CARD); - decorateFooter(el, altCta, cardType); - merchCard.append(inner); -}; - -const decorateRibbon = (el, ribbonMetadata, cardType) => { - const ribbonStyleRegex = /^#[0-9a-fA-F]+, #[0-9a-fA-F]+$/; - if (!ribbonStyleRegex.test(ribbonMetadata[0]?.innerText)) return; - const ribbonStyle = ribbonMetadata[0].innerText.trim(); - const [ribbonBgColor, ribbonTextColor] = ribbonStyle.split(', '); - const ribbonWrapper = ribbonMetadata[0].parentNode; - const ribbon = ribbonMetadata[1]; - ribbon.classList.add(`consonant-${cardType}-ribbon`); - const borderStyle = `1px solid ${ribbonBgColor}`; - if (el.classList.contains('evergreen')) { - ribbon.style.border = borderStyle; - ribbon.style.borderRight = 'none'; - } else { - ribbon.style.backgroundColor = ribbonBgColor; - el.style.border = borderStyle; - } - ribbon.style.color = ribbonTextColor; - const picture = el.querySelector(`.consonant-${cardType}-img`); - if (picture) { - picture.insertAdjacentElement('afterend', ribbon); - } else { - el.insertAdjacentElement('beforeend', ribbon); - } - ribbonWrapper.remove(); -}; - -const decorateIcon = (el, icons, cardType) => { - if (!icons) return; - const inner = el.querySelector(`.consonant-${cardType}-inner`); - const iconWrapper = createTag('div', { class: `consonant-${cardType}-iconWrapper` }); - icons.forEach((icon) => { - const url = icon.querySelector('img').src; - const iconDiv = createTag( - 'div', - { - class: 'consonant-MerchCard-ProductIcon', - style: `background-image: url(${url})`, - }, - ); - iconWrapper.appendChild(iconDiv); - icon.parentNode?.remove(); - }); - inner.prepend(iconWrapper); -}; - -export const initLegacyMerchCard = (el) => { - loadStyle(`${base}/blocks/merch-card/legacy-merch-card.css`); - loadStyle(`${base}/deps/caas.css`); - const section = el.closest('.section'); - section.classList.add('milo-card-section'); - const images = el.querySelectorAll('picture'); - let image; - const icons = []; - const rows = el.querySelectorAll(':scope > *'); - const ribbonMetadata = rows[0].children?.length === 2 ? rows[0].children : null; - const row = rows[ribbonMetadata === null ? 0 : 1]; - const altCta = rows[rows.length - 1].children?.length === 2 - ? rows[rows.length - 1].children : null; - const allPElems = row.querySelectorAll('p'); - const ctas = allPElems[allPElems.length - 1]; - const styles = [...el.classList]; - const cardType = getPodType(styles); - const merchCard = el; - decorateBlockHrs(el); - images.forEach((img) => { - const imgNode = img.querySelector('img'); - const { width, height } = imgNode; - const isSquare = Math.abs(width - height) <= 10; - if (img) { - if (isSquare) { - icons.push(img); - } else { - image = img; - } - } - }); - addWrapper(el, section, cardType); - merchCard.classList.add('consonant-Card', 'consonant-ProductCard', `consonant-${cardType}`); - if (image) addBackgroundImg(image, cardType, merchCard); - if (ribbonMetadata !== null) decorateRibbon(el, ribbonMetadata, cardType); - image?.parentElement.remove(); - if (ctas) decorateButtons(ctas); - addInner(el, altCta, cardType, merchCard); - decorateIcon(el, icons, cardType); - const inner = el.querySelector(`.consonant-${cardType}-inner`); - const innerCleanup = inner.querySelectorAll(':scope > div')[1]; - if (innerCleanup.classList.length === 0) innerCleanup.remove(); -}; - -export default initLegacyMerchCard; diff --git a/libs/blocks/merch-card/merch-card.css b/libs/blocks/merch-card/merch-card.css index 3ae881b0ce..f0500ae348 100644 --- a/libs/blocks/merch-card/merch-card.css +++ b/libs/blocks/merch-card/merch-card.css @@ -1,14 +1,20 @@ -main > div[class*="-merch-card"], -main > div[class*="-merch-cards"] { +main > div.section[class*="-merch-card"]:not([data-status='decorated']), +.fragment > div.section[class*="-merch-card"]:not([data-status='decorated']) { display: grid; + padding-bottom: var(--spacing-m); } - div[class*="-merch-card"] > div, +div[class*="-merch-card"] > div, div[class*="-merch-cards"] > div { - width: 100%; - grid-column: 1 / -1; -} + width: 100%; + grid-column: 1 / -1; + } -div[data-removed-manifest-id] { - display: none; + div[data-removed-manifest-id] { + display: none; + } + + .merch-card-price { + margin-top: 8px; + margin-bottom: 16px; } diff --git a/libs/blocks/merch-card/merch-card.js b/libs/blocks/merch-card/merch-card.js index b3b8e6a082..09eef6cd45 100644 --- a/libs/blocks/merch-card/merch-card.js +++ b/libs/blocks/merch-card/merch-card.js @@ -1,14 +1,109 @@ import { decorateButtons, decorateBlockHrs } from '../../utils/decorate.js'; -import { createTag, getConfig } from '../../utils/utils.js'; -import { getUpFromSectionMetadata } from '../card/cardUtils.js'; +import { getConfig, createTag } from '../../utils/utils.js'; +import { getMetadata } from '../section-metadata/section-metadata.js'; import { processTrackingLabels } from '../../martech/analytics.js'; import { replaceKey } from '../../features/placeholders.js'; -import '../../deps/commerce.js'; import '../../deps/merch-card.js'; -import { getMetadata } from '../section-metadata/section-metadata.js'; + +const PRODUCT_NAMES = [ + 'acrobat-pdf-pack', + 'acrobat-pro-2020', + 'acrobat-reader-dc-mobile', + 'acrobat-reader-dc', + 'acrobat-sign-solutions-mobile', + 'acrobat-sign-solutions', + 'acrobat-standard-2020', + 'acrobat-standard-dc', + 'acrobat', + 'adobe-connect', + 'adobe-export-pdf', + 'adobe-firefly', + 'adobe-scan', + 'advertising-cloud', + 'aero', + 'aftereffects', + 'analytics', + 'animate', + 'audience-manager', + 'audition', + 'behance', + 'bridge', + 'campaign', + 'captivate-prime', + 'captivate', + 'capture', + 'all-apps', + 'express', + 'character-animator', + 'cloud-service', + 'coldfusion-aws', + 'coldfusion-builder', + 'coldfusion-enterprise', + 'coldfusion', + 'color', + 'commerce-cloud', + 'content-server', + 'customer-journey-analytics', + 'design-to-print', + 'digital-editions', + 'dreamweaver', + 'embedded-print-engine', + 'experience-manager-assets', + 'experience-manager-forms', + 'experience-manager-sites', + 'experience-manager', + 'experience-platform', + 'fill-sign', + 'fonts', + 'frame', + 'framemaker-publishing-server', + 'framemaker', + 'fresco', + 'http-dynamic-streaming', + 'illustrator', + 'incopy', + 'indesign-server', + 'indesign', + 'intelligent-services', + 'journey-orchestration', + 'lightroom-classic', + 'lightroom', + 'magento', + 'marketo', + 'media-encoder', + 'media-server-aws', + 'media-server-extended', + 'media-server-professional', + 'media-server-standard', + 'mixamo', + 'pdf-print-engine', + 'pepe', + 'photoshop-elements', + 'photoshop-express', + 'photoshop', + 'portfolio', + 'postscript', + 'premiere-elements', + 'premierepro', + 'presenter-video-express', + 'real-time-customer-data-platform', + 'robohelp-server', + 'robohelp', + 'stock', + 'substance-3d-designer', + 'substance-3d-modeler', + 'substance-3d-painter', + 'substance-3d-sampler', + 'substance-3d-stager', + 'target', + 'technical-communication-suite', + 'type', + 'xml-documentation', +]; + +const TAG_PATTERN = /^[a-zA-Z0-9_-]+:[a-zA-Z0-9_-]+\/[a-zA-Z0-9_-].*$/; const CARD_TYPES = ['segment', 'special-offers', 'plans', 'catalog', 'product', 'inline-heading']; -const MERCH_CARD_GRIDS = ['one-merch-card', 'two-merch-cards', 'three-merch-cards', 'four-merch-cards']; const textStyles = { H5: 'detail-m', @@ -19,36 +114,23 @@ const textStyles = { const getPodType = (styles) => styles?.find((style) => CARD_TYPES.includes(style)); -const checkBoxLabel = (ctas, altCtaMetaData) => { - const altCtaRegex = /href=".*"/; - if (!altCtaRegex.test(altCtaMetaData[1]?.innerHTML)) return null; - const allButtons = ctas.querySelectorAll('a'); - const originalCtaButton = allButtons[allButtons.length - 1]; - const altCtaButtonData = altCtaMetaData[1]; - const altCtaButton = createTag('a', { class: [...originalCtaButton.classList, 'alt-cta', 'button--inactive'].join(' ') }, altCtaButtonData.textContent); - originalCtaButton.classList.add('active'); - decorateButtons(altCtaButton); - ctas.appendChild(altCtaButton); - return altCtaMetaData[0].textContent; -}; - -const isHeadingTag = (tagName) => /^H[1-5]$/.test(tagName); +const isHeadingTag = (tagName) => /^H[2-5]$/.test(tagName); const isParagraphTag = (tagName) => tagName === 'P'; -const createAndAppendTag = (tagName, attributes, content, parent) => { - const newTag = createTag(tagName, attributes, content); - parent.append(newTag); - return newTag; -}; - -const parseContent = (el, altCta, cardType, merchCard) => { - const innerElements = [...el.querySelectorAll('h1, h2, h3, h4, h5, h6, p, ul')]; +const parseContent = (el, merchCard) => { + const innerElements = [ + ...el.querySelectorAll('h2, h3, h4, h5, p, ul'), + ]; const bodySlot = createTag('div', { slot: 'body-xs' }); innerElements.forEach((element) => { const { tagName } = element; if (isHeadingTag(tagName)) { - createAndAppendTag(tagName, { slot: textStyles[tagName] }, element.innerHTML, merchCard); + const slotName = textStyles[tagName]; + if (slotName) { + element.setAttribute('slot', slotName); + merchCard.append(element); + } return; } if (isParagraphTag(tagName)) { @@ -58,49 +140,58 @@ const parseContent = (el, altCta, cardType, merchCard) => { merchCard.append(bodySlot); }; -const returnRibbonStyle = (ribbonMetadata) => { - const ribbonStyleRegex = /^#[0-9a-fA-F]+, #[0-9a-fA-F]+$/; - if (!ribbonStyleRegex.test(ribbonMetadata[0]?.innerText)) return null; - const style = ribbonMetadata[0].innerText; +const getBadgeStyle = (badgeMetadata) => { + const badgeStyleRegex = /^#[0-9a-fA-F]+, #[0-9a-fA-F]+$/; + if (!badgeStyleRegex.test(badgeMetadata[0]?.innerText)) return null; + const style = badgeMetadata[0].innerText; const badgeBackgroundColor = style.split(',')[0].trim(); const badgeColor = style.split(',')[1].trim(); - const ribbonWrapper = ribbonMetadata[0].parentNode; - const badgeText = ribbonMetadata[1].innerText; - ribbonWrapper.remove(); + const badgeWrapper = badgeMetadata[0].parentNode; + const badgeText = badgeMetadata[1].innerText; + badgeWrapper.remove(); return { badgeBackgroundColor, badgeColor, badgeText }; }; -const getActionMenuContent = (el, ribbonMetadata) => { - const index = ribbonMetadata !== null ? 1 : 0; - const expectedChildren = ribbonMetadata !== null ? 3 : 2; - if (el.childElementCount !== expectedChildren) { - return null; - } - const actionMenuContentWrapper = el.children[index]; - const actionMenuContent = actionMenuContentWrapper.children[0]; +const getActionMenuContent = (el) => { + const actionMenuContentWrapper = [...el.children].find((child) => child.querySelector('ul') && child.querySelector('h2') === null); + if (!actionMenuContentWrapper) return undefined; actionMenuContentWrapper.remove(); - return actionMenuContent; + return actionMenuContentWrapper?.firstElementChild; }; -function getMerchCardRows(rows, ribbonMetadata, cardType, actionMenuContent) { - const index = ribbonMetadata === null ? 0 : 1; - if (cardType === 'catalog') { - return actionMenuContent !== null ? rows[index + 1] : rows[index]; - } - return rows[index]; -} +const extractTags = (container) => [...container.querySelectorAll('p')] + .map((tag) => tag.innerText?.trim()) + .filter((item) => TAG_PATTERN.test(item)) + .reduce((acc, item) => { + const [, tag] = item.split(':'); + if (!tag) return acc; + const parts = tag.split('/'); + if (!acc[parts[0]]) return acc; + acc[parts[0]].push(parts.pop()); + return acc; + }, { categories: ['all'], types: [] }); -function addMerchCardGridsIfMissing(section) { - let styleClasses = []; - const el = section.querySelector('.section-metadata'); +const addMerchCardGridIfMissing = (section, cardType) => { + const el = section?.querySelector('.section-metadata'); + const directSection = section?.parentElement?.tagName === 'MAIN'; if (el) { const metadata = getMetadata(el); + let styleClasses = []; styleClasses = metadata?.style?.text?.split(',').map((token) => token.split(' ').join('-')) ?? []; + if (!styleClasses.some((styleClass) => /-merch-card/.test(styleClass))) { + if (styleClasses.some((styleClass) => /-up/.test(styleClass) || directSection)) { + section.classList.add('three-merch-cards', cardType); + } + } + section.classList.add(cardType); + return true; } - if (!MERCH_CARD_GRIDS.some((styleClass) => styleClasses.includes(styleClass))) { - section.classList.add('three-merch-cards'); + if (directSection) { + section.classList.add('three-merch-cards', cardType); } -} + + return false; +}; const decorateMerchCardLinkAnalytics = (el) => { [...el.querySelectorAll('a')].forEach((link, index) => { @@ -112,103 +203,156 @@ const decorateMerchCardLinkAnalytics = (el) => { }); }; -const init = (el) => { - let section = el.closest('.section'); - const upClass = getUpFromSectionMetadata(section); - if (upClass) { - import('./legacy-merch-card.js') - .then((module) => { - module.initLegacyMerchCard(el); - }); - } else { - if (section.parentElement.classList.contains('fragment')) { - const fragment = section.parentElement; - const fragmentParent = fragment.parentElement; - section.style.display = 'contents'; - fragment.style.display = 'contents'; - fragmentParent.style.display = 'contents'; - section = fragmentParent.parentElement; +const addStock = (merchCard, styles) => { + if (styles.includes('add-stock')) { + let stock; + const selector = styles.includes('edu') ? '.merch-offers.stock.edu > *' : '.merch-offers.stock > *'; + const [label, ...rest] = [...document.querySelectorAll(selector)]; + if (label) { + const offers = rest.filter(({ dataset: { wcsOsi } }) => wcsOsi); + stock = { label: label?.innerText, offers: offers?.map((offer) => offer.dataset.wcsOsi).join(',') }; } - addMerchCardGridsIfMissing(section); - const images = el.querySelectorAll('picture'); - let image; - const icons = []; - const rows = el.querySelectorAll(':scope > *'); - const styles = [...el.classList]; - const cardType = getPodType(styles); - const ribbonMetadata = rows[0].children?.length === 2 ? rows[0].children : null; - const actionMenuContent = cardType === 'catalog' ? getActionMenuContent(el, ribbonMetadata) : null; - const row = getMerchCardRows(rows, ribbonMetadata, cardType, actionMenuContent); - const altCta = rows[rows.length - 1].children?.length === 2 - ? rows[rows.length - 1].children : null; - const allPElems = row.querySelectorAll('p'); - const ctas = allPElems[allPElems.length - 1]; - images.forEach((img) => { - const imgNode = img.querySelector('img'); - const { width, height } = imgNode; - const isSquare = Math.abs(width - height) <= 10; - if (img) { - if (isSquare) { - icons.push(img); - } else { - image = img; - } - } - }); + if (stock !== undefined) { + merchCard.setAttribute('checkbox-label', stock.label); + merchCard.setAttribute('stock-offer-osis', stock.offers); + } + } +}; - const merchCard = createTag('merch-card', { class: el.className, variant: cardType, 'data-block': '' }); - if (ribbonMetadata !== null) { - const badge = returnRibbonStyle(ribbonMetadata); - if (badge !== null) { - merchCard.setAttribute('badge-background-color', badge.badgeBackgroundColor); - merchCard.setAttribute('badge-color', badge.badgeColor); - merchCard.setAttribute('badge-text', badge.badgeText); +const init = async (el) => { + const styles = [...el.classList]; + const lastClass = styles[styles.length - 1]; + const name = PRODUCT_NAMES.includes(lastClass) ? lastClass : undefined; + const cardType = getPodType(styles) || 'product'; + if (!styles.includes(cardType)) { + styles.push(cardType); + } + let section = el.closest('.section'); + if (section) { + const merchCards = addMerchCardGridIfMissing(section, cardType); + if (!merchCards) { + if (section?.parentElement.classList.contains('fragment')) { + const fragment = section.parentElement; + const fragmentParent = fragment.parentElement; + section.style.display = 'contents'; + fragment.style.display = 'contents'; + fragmentParent.style.display = fragmentParent.classList.contains('nested') + ? fragmentParent.style.display + : 'contents'; + section = fragmentParent.parentElement; + addMerchCardGridIfMissing(section, cardType); } } - if (actionMenuContent !== null) { - merchCard.setAttribute('action-menu', true); - merchCard.append(createTag('div', { slot: 'action-menu-content' }, actionMenuContent.innerHTML)); - } - if (image !== undefined) { - const imageSlot = createTag('div', { slot: 'bg-image' }); - imageSlot.appendChild(image); - merchCard.appendChild(imageSlot); - } - if (!icons || icons.length > 0) { - const iconImgs = Array.from(icons).map((icon) => { - const img = { - src: icon.querySelector('img').src, - alt: icon.querySelector('img').alt, - }; - return img; - }); - merchCard.setAttribute('icons', JSON.stringify(Array.from(iconImgs))); - icons.forEach((icon) => icon.remove()); - } - parseContent(el, altCta, cardType, merchCard); - const footer = createTag('div', { slot: 'footer' }); - if (ctas) { - decorateButtons(ctas); - footer.append(ctas); - merchCard.appendChild(footer); + } + const images = el.querySelectorAll('picture'); + let image; + const icons = []; + const merchCard = createTag('merch-card', { class: styles.join(' '), 'data-block': '' }); + merchCard.setAttribute('variant', cardType); + if (name) { + merchCard.setAttribute('name', name); + } + images.forEach((img) => { + const imgNode = img.querySelector('img'); + const { width, height } = imgNode; + const isSquare = Math.abs(width - height) <= 10; + if (img) { + if (isSquare) { + icons.push(img); + } else { + image = img; + } } - if (styles.includes('secure')) { - replaceKey('secure-transaction', getConfig()) - .then((key) => merchCard.setAttribute('secure-label', key)); + }); + let tags = {}; + if (el.lastElementChild) { + tags = extractTags(el.lastElementChild); + if (tags.categories?.length > 1 || tags.types?.length > 0) { + // this div contains tags, remove it from further processing. + el.lastElementChild.remove(); } - if (altCta) { - const label = checkBoxLabel(ctas, altCta); - if (label !== null) { - merchCard.setAttribute('checkbox-label', label); + } + const { categories = ['all'], types = [] } = tags; + if (el.firstElementChild) { + const badgeMetadata = el.firstElementChild.querySelector('ul,h2') === null + && el.firstElementChild.innerText.includes('#') ? el.firstElementChild : null; + if (badgeMetadata !== null) { + const badge = getBadgeStyle(badgeMetadata.children); + if (badge !== null) { + merchCard.setAttribute( + 'badge-background-color', + badge.badgeBackgroundColor, + ); + merchCard.setAttribute('badge-color', badge.badgeColor); + merchCard.setAttribute('badge-text', badge.badgeText); } } - decorateBlockHrs(merchCard); - if (merchCard.classList.contains('has-divider')) { - merchCard.setAttribute('custom-hr', true); + } + const actionMenuContent = cardType === 'catalog' + ? getActionMenuContent(el) + : null; + if (actionMenuContent) { + merchCard.setAttribute('action-menu', true); + merchCard.append( + createTag( + 'div', + { slot: 'action-menu-content' }, + actionMenuContent.innerHTML, + ), + ); + } + let ctas = el.querySelector('p > strong a, p > em a')?.closest('p'); + if (!ctas) { + const candidate = el.querySelector('p:last-of-type'); + if (candidate?.querySelector('a')) { + ctas = candidate; } - el.replaceWith(merchCard); - decorateMerchCardLinkAnalytics(merchCard); } + if (image !== undefined) { + const imageSlot = createTag('div', { slot: 'bg-image' }); + imageSlot.appendChild(image); + merchCard.appendChild(imageSlot); + } + if (!icons || icons.length > 0) { + const iconImgs = Array.from(icons).map((icon) => { + const img = { + src: icon.querySelector('img').src, + alt: icon.querySelector('img').alt, + }; + return img; + }); + merchCard.setAttribute( + 'icons', + JSON.stringify(Array.from(iconImgs)), + ); + icons.forEach((icon) => icon.remove()); + } + + addStock(merchCard, styles); + if (styles.includes('secure')) { + await replaceKey('secure-transaction', getConfig()).then((key) => merchCard.setAttribute('secure-label', key)); + } + merchCard.setAttribute('filters', categories.join(',')); + merchCard.setAttribute('types', types.join(',')); + parseContent(el, merchCard); + const footer = createTag('div', { slot: 'footer' }); + if (ctas) { + decorateButtons(ctas); + footer.append(ctas); + } + merchCard.appendChild(footer); + const offerSelection = cardType === 'plans' ? el.querySelector('ul') : null; + if (offerSelection) { + const { initOfferSelection } = await import('./merch-offer-select.js'); + initOfferSelection(merchCard, offerSelection); + } + decorateBlockHrs(merchCard); + if (merchCard.classList.contains('has-divider')) { + merchCard.setAttribute('custom-hr', true); + } + el.replaceWith(merchCard); + decorateMerchCardLinkAnalytics(merchCard); + return merchCard; }; export default init; diff --git a/libs/blocks/merch-card/merch-offer-select.js b/libs/blocks/merch-card/merch-offer-select.js new file mode 100644 index 0000000000..d765230225 --- /dev/null +++ b/libs/blocks/merch-card/merch-offer-select.js @@ -0,0 +1,49 @@ +import { createTag } from '../../utils/utils.js'; +import { decorateButtons } from '../../utils/decorate.js'; +import '../../deps/merch-offer-select.js'; + +function createDynamicSlots(el, bodySlot) { + const price = createTag('h5', { class: 'merch-card-price' }); + price.append(createTag('span', { slot: 'price', is: 'inline-price' })); + bodySlot.append(price); + + const p = createTag('p', { class: 'action-area' }); + p.append(createTag('a', { slot: 'cta', is: 'checkout-link' })); + const footer = el.querySelector('div[slot="footer"]'); + footer.append(p); + bodySlot.querySelector('p')?.setAttribute('slot', 'description'); +} +function createMerchOffer(option) { + const merchOffer = createTag('merch-offer', { text: option.childNodes[0].textContent.trim() }); + [...option.querySelector('ul').children].forEach((li, index) => { + const override = li.childNodes[0]; + if (override.nodeName === '#text') { + if (index === 0) { + merchOffer.setAttribute('badge-text', override.textContent.trim()); + } else { + const desc = createTag('p', { slot: 'description' }); + desc.textContent = override.textContent.trim(); + merchOffer.append(desc); + } + } else { + merchOffer.append(override); + } + }); + decorateButtons(merchOffer); + return merchOffer; +} + +export const initOfferSelection = (merchCard, offerSelection) => { + const bodySlot = merchCard.querySelector('div[slot="body-xs"]'); + if (!bodySlot) return; + createDynamicSlots(merchCard, bodySlot); + const merchOffers = createTag('merch-offer-select', { container: 'merch-card' }); + [...offerSelection.children].forEach((option) => { + merchOffers.append(createMerchOffer(option)); + }); + merchOffers.querySelectorAll('a[is="checkout-link"]').forEach((link) => { link.setAttribute('slot', 'cta'); }); + merchOffers.querySelectorAll('span[is="inline-price"]').forEach((price) => { price.setAttribute('slot', 'price'); }); + bodySlot.append(merchOffers); +}; + +export default initOfferSelection; diff --git a/libs/blocks/merch-offers/merch-offers.css b/libs/blocks/merch-offers/merch-offers.css new file mode 100644 index 0000000000..f6387c83f1 --- /dev/null +++ b/libs/blocks/merch-offers/merch-offers.css @@ -0,0 +1,3 @@ +.merch-offers { + display: none; +} diff --git a/libs/blocks/merch-offers/merch-offers.js b/libs/blocks/merch-offers/merch-offers.js new file mode 100644 index 0000000000..0e270e3666 --- /dev/null +++ b/libs/blocks/merch-offers/merch-offers.js @@ -0,0 +1,10 @@ +/** + * This block provides offers data like stock offers for re-using in cards or dialogs. + */ + +export default async function init(el) { + el.append(el.querySelector('p')); + el.append(...el.querySelectorAll('[data-wcs-osi]')); + el.firstElementChild.remove(); + return el; +} diff --git a/libs/deps/merch-card.js b/libs/deps/merch-card.js index 7014c1648c..1242b70f1a 100644 --- a/libs/deps/merch-card.js +++ b/libs/deps/merch-card.js @@ -1,5 +1,5 @@ -// Thu, 16 Nov 2023 19:37:46 GMT -import{html as a,LitElement as C}from"./lit-all.min.js";import{css as S,unsafeCSS as b}from"./lit-all.min.js";var p="(max-width: 899px)",l="(min-width: 700px) and (max-width: 1199px)",h="(min-width: 1200px)",x="(min-width: 1440px)";var f=S` +// Wed, 06 Dec 2023 15:56:55 GMT +import{html as n,LitElement as T}from"./lit-all.min.js";import{css as x,unsafeCSS as p}from"./lit-all.min.js";var s="(min-width: 768px)",c="(min-width: 1200px)",i="(min-width: 1600px)";var v=x` :host { position: relative; display: flex; @@ -9,7 +9,6 @@ import{html as a,LitElement as C}from"./lit-all.min.js";import{css as S,unsafeCS text-align: left; border-radius: var(--consonant-merch-spacing-xxxs); background-color: var(--consonant-merch-card-background-color); - overflow: auto; grid-template-columns: repeat(auto-fit, minmax(300px, max-content)); background-color: var(--consonant-merch-card-background-color); font-family: var(--body-font-family, 'Adobe Clean'); @@ -27,6 +26,11 @@ import{html as a,LitElement as C}from"./lit-all.min.js";import{css as S,unsafeCS cursor: pointer; } + .action-menu.always-visible { + visibility: visible; + background-image: var(--ellipsis-icon); + } + slot { display: block; } @@ -55,6 +59,7 @@ import{html as a,LitElement as C}from"./lit-all.min.js";import{css as S,unsafeCS } .body { + flex: 1; display: flex; flex-direction: column; justify-content: flex-start; @@ -64,17 +69,12 @@ import{html as a,LitElement as C}from"./lit-all.min.js";import{css as S,unsafeCS padding: var(--consonant-merch-spacing-xs); } - ::slotted([slot='footer']) { + footer { display: flex; justify-content: flex-end; - margin-top: auto; box-sizing: border-box; - align-self: flex-end; width: 100%; - padding-top: var(--consonant-merch-spacing-xs); - padding-bottom: var(--consonant-merch-spacing-xs); - pading-left: 0; - padding-left: var(--consonant-merch-spacing-xs); + padding: var(--consonant-merch-spacing-xs); } hr { @@ -88,7 +88,7 @@ import{html as a,LitElement as C}from"./lit-all.min.js";import{css as S,unsafeCS margin-right: var(--consonant-merch-spacing-xs); } - div[class$='-ribbon'] { + div[class$='-badge'] { position: absolute; top: 16px; right: 0; @@ -101,7 +101,7 @@ import{html as a,LitElement as C}from"./lit-all.min.js";import{css as S,unsafeCS border-radius: 5px 0 0 5px; } - .body .catalog-ribbon { + .body .catalog-badge { display: flex; height: fit-content; flex-direction: column; @@ -136,15 +136,6 @@ import{html as a,LitElement as C}from"./lit-all.min.js";import{css as S,unsafeCS visibility: hidden; } - .standard-wrapper { - display: flex; - flex-wrap: wrap; - gap: var(--spacing-xs); - align-items: center; - justify-content: space-between; - padding-left: var(--consonant-merch-spacing-xs); - } - #stock-checkbox, .secure-transaction-label { font-size: var(--consonant-merch-card-body-xxs-font-size); @@ -182,6 +173,7 @@ import{html as a,LitElement as C}from"./lit-all.min.js";import{css as S,unsafeCS display: inline-flex; gap: var(--consonant-merch-spacing-xxs); align-items: center; + flex: 1; } .secure-transaction-label::before { @@ -222,53 +214,37 @@ import{html as a,LitElement as C}from"./lit-all.min.js";import{css as S,unsafeCS margin-top: 2px; } - :host([type='super-wide']) { - grid-column: span 4; - } - - :host([type='wide']) { - grid-column: span 2; - } - - :host([variant='special-offers']) { - min-height: 438px; - } - :host([variant='special-offers'].center) { text-align: center; } - :host([variant='special-offers'].wide) { - grid-column: span 3; - width: auto; - } - - :host([variant='special-offers'].super-wide) { - grid-column: span 3; - width: auto; - } - - /* catalog */ - :host([variant='catalog']) { - min-height: 296px; - } - - :host([variant='catalog'][type='wide']) { - width: auto; - } - - :host([variant='catalog'][type='super-wide']) { - width: auto; - } - - /* Tablet */ - @media screen and ${b(l)} { - } - - /* Laptop */ - @media screen and ${b(h)} { - } -`;var[u,v,y,w]=["ArrowLeft","ArrowRight","ArrowUp","ArrowDown"];var k=document.createElement("style");k.innerHTML=` + /* plans */ + :host([variant='plans']) { + min-height: 348px; + } +`,y=()=>{let h=[x` + /* Tablet */ + @media screen and ${p(s)} { + :host([size='wide']), + :host([size='super-wide']) { + grid-column: span 2; + width: 100%; + } + } + + /* Laptop */ + @media screen and ${p(c)} { + :host([size='super-wide']) { + grid-column: span 3; + } + `];return h.push(x` + /* Large desktop */ + @media screen and ${p(i)} { + :host([size='super-wide']) { + grid-column: span 4; + } + } + `),h};var[u,f,w,k,z,$]=["ArrowLeft","ArrowRight","ArrowUp","ArrowDown","Enter","Tab"];var E=document.createElement("style");E.innerHTML=` :root { --consonant-merch-card-detail-font-size: 12px; @@ -292,6 +268,9 @@ import{html as a,LitElement as C}from"./lit-all.min.js";import{css as S,unsafeCS --consonant-merch-spacing-s: 24px; --consonant-merch-spacing-m: 32px; + /* cta */ + --consonant-merch-card-cta-font-size: 15px; + /* headings */ --consonant-merch-card-heading-xs-font-size: 18px; --consonant-merch-card-heading-xs-line-height: 22.5px; @@ -330,27 +309,29 @@ import{html as a,LitElement as C}from"./lit-all.min.js";import{css as S,unsafeCS /* colors */ --consonant-merch-card-border-color: #eaeaea; --color-accent: #1473E6; - --color-black: #000; - --color-grey-80: #2c2c2c; + --merch-color-grey-80: #2c2c2c; /* merch card generic */ - --consonant-merch-card-max-width: 378px; - - /* special offers mobile */ - --consonant-merch-card-special-offer-width: 300px; + --consonant-merch-card-max-width: 300px; + --transition: cmax-height 0.3s linear, opacity 0.3s linear; /* special offers */ --consonant-merch-card-special-offers-width: 378px; + /* image */ + --consonant-merch-card-image-width: 300px; + /* segment */ --consonant-merch-card-segment-width: 378px; /* inline-heading */ - --consonant-merch-card-inline-heading-width: 378px; + --consonant-merch-card-inline-heading-width: 300px; + + /* product */ + --consonant-merch-card-product-width: 300px; /* plans */ - --consonant-merch-card-plans-max-width: 302px; - --consonant-merch-card-plans-width: 276px; + --consonant-merch-card-plans-width: 300px; --consonant-merch-card-plans-icon-size: 40px; /* catalog */ @@ -360,7 +341,9 @@ import{html as a,LitElement as C}from"./lit-all.min.js";import{css as S,unsafeCS /* inline SVGs */ --checkmark-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' xml:space='preserve' viewBox='0 0 10 10'%3E%3Cpath fill='%23fff' d='M3.788 9A.999.999 0 0 1 3 8.615l-2.288-3a1 1 0 1 1 1.576-1.23l1.5 1.991 3.924-4.991a1 1 0 1 1 1.576 1.23l-4.712 6A.999.999 0 0 1 3.788 9z' class='spectrum-UIIcon--medium'/%3E%3C/svg%3E%0A"); - --secure-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' xml:space='preserve' width='10' height='10' fill='%23757575' viewBox='0 0 12 15'%3E%3Cpath d='M11.5 6H11V5A5 5 0 1 0 1 5v1H.5a.5.5 0 0 0-.5.5v8a.5.5 0 0 0 .5.5h11a.5.5 0 0 0 .5-.5v-8a.5.5 0 0 0-.5-.5ZM3 5a3 3 0 1 1 6 0v1H3Zm4 6.111V12.5a.5.5 0 0 1-.5.5h-1a.5.5 0 0 1-.5-.5v-1.389a1.5 1.5 0 1 1 2 0Z'/%3E%3C/svg%3E"); + --secure-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23757575' viewBox='0 0 12 15'%3E%3Cpath d='M11.5 6H11V5A5 5 0 1 0 1 5v1H.5a.5.5 0 0 0-.5.5v8a.5.5 0 0 0 .5.5h11a.5.5 0 0 0 .5-.5v-8a.5.5 0 0 0-.5-.5ZM3 5a3 3 0 1 1 6 0v1H3Zm4 6.111V12.5a.5.5 0 0 1-.5.5h-1a.5.5 0 0 1-.5-.5v-1.389a1.5 1.5 0 1 1 2 0Z'/%3E%3C/svg%3E"); + + --info-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 36 36'>'); @@ -370,25 +353,9 @@ merch-cards { display: contents; } -merch-cards > button { - grid-column: 1 / -1; - place-self: baseline; - background-color: transparent; - border-radius: 16px; - border: 2px solid var(--text-color, #2c2c2c); - color: var(--text-color, #2c2c2c); - display: inline-block; - font-size: 15px; - font-style: normal; - font-weight: 700; - line-height: 16px; - padding: 5px 14px; -} - -merch-cards > button:hover { - background-color: var(--color-black, #000); - border-color: var(--color-black, #000); - color: var(--color-white, #fff); +merch-cards > p[slot], +merch-cards > div[slot] p { + margin: 0; } .one-merch-card, @@ -397,131 +364,23 @@ merch-cards > button:hover { .four-merch-cards { display: grid; justify-content: center; - justify-items: center; - padding: var(--spacing-m); - gap: var(--spacing-m); -} - - -merch-card[variant="special-offers"] { - width: var(--consonant-merch-card-special-offers-width); -} - -merch-card[variant="segment"] { - width: var(--consonant-merch-card-segment-width); -} - -merch-card[variant="plans"] { - width: var(--consonant-merch-card-plans-width); -} - -merch-card[variant="inline-heading"] { - width: var(--consonant-merch-card-inline-heading-width); -} - -merch-card[variant="catalog"] { - width: var(--consonant-merch-card-catalog-width); + justify-items: stretch; + gap: var(--consonant-merch-spacing-m); } -@media screen and ${p} { - :root { - --consonant-merch-card-mobile-width: 300px; - } +@media screen and ${c} { .one-merch-card, .two-merch-cards, .three-merch-cards, .four-merch-cards { - grid-template-columns: fit-content(100%); - } - - merch-card[variant="special-offers"].merch-card, - merch-card[variant="segment"].merch-card, - merch-card[variant="plans"].merch-card, - merch-card[variant="catalog"].merch-card, - merch-card[variant="inline-heading"].merch-card { - width: var(--consonant-merch-card-mobile-width); - } -} - -/* Tablet */ -@media screen and ${l} { - :root { - --consonant-merch-card-special-offer-width: 302px; - --consonant-merch-card-catalog-width: 302px; - } - - .two-merch-cards, - .three-merch-cards, - .four-merch-cards { - grid-template-columns: repeat(2, fit-content(100%)); - } - -} - -/* desktop */ -@media screen and ${h} { - :root { - --consonant-merch-card-special-offer-width: 378px; - --consonant-merch-card-catalog-width: 276px; - } - - .three-merch-cards, - .four-merch-cards { - grid-template-columns: repeat(3, fit-content(100%)); - } -} - -/* Large desktop */ - @media screen and ${x} { - :root { - - } - - .four-merch-cards { - grid-template-columns: repeat(4, fit-content(100%)); + padding: var(--spacing-m); } } -[class*="-merch-cards"].m-gap { - gap: var(--consonant-merch-spacing-xs); - padding: var(--consonant-merch-spacing-xs); -} - -[class*="-merch-cards"].l-gap { - gap: var(--consonant-merch-spacing-s); - padding: var(--consonant-merch-spacing-s); -} - -[class*="-merch-cards"].xl-gap { - gap: var(--consonant-merch-spacing-m); - padding: var(--consonant-merch-spacing-m); -} - -div[class$='-badge'] { - position: absolute; - top: 16px; - right: 0; - font-size: var(--type-heading-xxs-size); - font-weight: 500; - max-width: 150px; - line-height: 16px; - text-align: center; - padding: 8px 11px; - border-radius: 5px 0 0 5px; -} - merch-card.background-opacity-70 { background-color: rgba(255 255 255 / 70%); } -merch-card hr { - background-color: var(--color-gray-200); - border: none; - height: 1px; - width: 100%; - margin-bottom: var(--consonant-merch-card-spacing-xs); -} - merch-card.has-divider hr { margin-bottom: var(--spacing-xxs); } @@ -543,35 +402,35 @@ merch-card [slot='heading-xs'] { line-height: var(--consonant-merch-card-heading-xs-line-height); margin: 0; margin-bottom: var(--consonant-merch-spacing-xxs); - color: var(--color-grey-80); + color: var(--merch-color-grey-80); } merch-card [slot='heading-s'] { font-size: var(--consonant-merch-card-heading-s-font-size); line-height: var(--consonant-merch-card-heading-s-line-height); margin: 0; - color: var(--color-grey-80); + color: var(--merch-color-grey-80); } merch-card [slot='heading-m'] { font-size: var(--consonant-merch-card-heading-m-font-size); line-height: var(--consonant-merch-card-heading-m-line-height); margin: 0; - color: var(--color-grey-80); + color: var(--merch-color-grey-80); } merch-card [slot='heading-l'] { font-size: var(--consonant-merch-card-heading-l-font-size); line-height: var(--consonant-merch-card-heading-l-line-height); margin: 0; - color: var(--color-grey-80); + color: var(--merch-color-grey-80); } merch-card [slot='heading-xl'] { font-size: var(--consonant-merch-card-heading-xl-font-size); line-height: var(--consonant-merch-card-heading-xl-line-height); margin: 0; - color: var(--color-grey-80); + color: var(--merch-color-grey-80); } merch-card [slot='detail-m'] { @@ -580,7 +439,7 @@ merch-card [slot='detail-m'] { font-weight: var(--consonant-merch-card-detail-m-font-weight); text-transform: uppercase; margin: 0; - color: var(--color-grey-80); + color: var(--merch-color-grey-80); } merch-card [slot="body-xxs"] { @@ -588,31 +447,35 @@ merch-card [slot="body-xxs"] { line-height: var(--consonant-merch-card-body-xxs-line-height); font-weight: normal; letter-spacing: var(--consonant-merch-card-body-xxs-letter-spacing); - color: var(--color-grey-80); + color: var(--merch-color-grey-80); } merch-card [slot="body-xs"] { font-size: var(--consonant-merch-card-body-xs-font-size); line-height: var(--consonant-merch-card-body-xs-line-height); - color: var(--color-grey-80); + color: var(--merch-color-grey-80); } merch-card [slot="body-m"] { font-size: var(--consonant-merch-card-body-m-font-size); line-height: var(--consonant-merch-card-body-m-line-height); - color: var(--color-grey-80); + color: var(--merch-color-grey-80); } merch-card [slot="body-l"] { font-size: var(--consonant-merch-card-body-l-font-size); line-height: var(--consonant-merch-card-body-l-line-height); - color: var(--color-grey-80); + color: var(--merch-color-grey-80); } merch-card [slot="body-xl"] { font-size: var(--consonant-merch-card-body-xl-font-size); line-height: var(--consonant-merch-card-body-xl-line-height); - color: var(--color-grey-80); + color: var(--merch-color-grey-80); +} + +merch-card[variant="plans"] [slot="description"] { + min-height: 84px; } merch-card[variant="catalog"] [slot="action-menu-content"] { @@ -655,12 +518,13 @@ merch-card[variant="catalog"] [slot="action-menu-content"] a { text-decoration: underline; } -.button--inactive { - display: none; +div[slot="footer"] a.con-button { + margin-left: var(--consonant-merch-spacing-xs); } -div[slot="footer"] a.con-button { - margin-right: var(--consonant-merch-spacing-xs); +div[slot="footer"] a:not([class]) { + font-weight: 700; + font-size: var(--consonant-merch-card-cta-font-size); } div[slot='bg-image'] img { @@ -669,52 +533,303 @@ div[slot='bg-image'] img { min-height: var(--consonant-merch-card-image-height); max-height: var(--consonant-merch-card-image-height); object-fit: cover; + border-top-left-radius: 16px; + border-top-right-radius: 16px; } -`;document.head.appendChild(k);var E="MERCH-CARD",$="merch-card",m=class extends C{static properties={name:{type:String},variant:{type:String},type:{type:String},badgeColor:{type:String,attribute:"badge-color"},badgeBackgroundColor:{type:String,attribute:"badge-background-color"},badgeText:{type:String,attribute:"badge-text"},icons:{type:Array},actionmenu:{type:Boolean,attribute:"action-menu"},actionMenuContent:{type:String,attribute:"action-menu-content"},title:{type:String},description:{type:String},customHr:{type:Boolean,attribute:"custom-hr"},detailBg:{type:String,attribute:"detail-bg"},secureLabel:{type:String,attribute:"secure-label"},checkboxLabel:{type:String,attribute:"checkbox-label"},stockOfferOsi:{type:String,attribute:"stock-offer-osi"},evergreen:{type:Boolean},filters:{type:String,reflect:!0,converter:{fromAttribute:e=>Object.fromEntries(e.split(",").map(n=>{let[t,o]=n.split(":"),r=Number(o);return[t,isNaN(r)?{}:r]})),toAttribute:e=>Object.entries(e).map(([n,t])=>isNaN(t)?n:`${n}:${t}`).join(",")}},types:{type:String,attribute:"types",reflect:!0}};static styles=[f];constructor(){super(),this.filters={},this.types=""}updated(e){e.has("badgeBackgroundColor")&&(this.style.border=`1px solid ${this.badgeBackgroundColor}`)}renderIcons(){return this.icons&&this.icons.length>0?a` + +/* Tablet */ +@media screen and ${s} { + :root { + --consonant-merch-card-catalog-width: 302px; + --consonant-merch-card-plans-width: 302px; + } +} + +/* desktop */ +@media screen and ${c} { + :root { + --consonant-merch-card-catalog-width: 276px; + --consonant-merch-card-plans-width: 276px; + --consonant-merch-card-inline-heading-width: 378px; + --consonant-merch-card-product-width: 378px; + --consonant-merch-card-image-width: 378px; + } +} + +/* supported cards */ +/* grid style for plans */ +.one-merch-card.plans, +.two-merch-cards.plans, +.three-merch-cards.plans, +.four-merch-cards.plans { + grid-template-columns: var(--consonant-merch-card-plans-width); +} + +/* Tablet */ +@media screen and ${s} { + .two-merch-cards.plans, + .three-merch-cards.plans, + .four-merch-cards.plans { + grid-template-columns: repeat(2, var(--consonant-merch-card-plans-width)); + } +} + +/* desktop */ +@media screen and ${c} { + .three-merch-cards.plans, + .four-merch-cards.plans { + grid-template-columns: repeat(3, var(--consonant-merch-card-plans-width)); + } +} + +/* Large desktop */ + @media screen and ${i} { + .four-merch-cards.plans { + grid-template-columns: repeat(4, var(--consonant-merch-card-plans-width)); + } +} + + +/* grid style for catalog */ +.one-merch-card.catalog, +.two-merch-cards.catalog, +.three-merch-cards.catalog, +.four-merch-cards.catalog { + grid-template-columns: var(--consonant-merch-card-catalog-width); +} + +/* Tablet */ +@media screen and ${s} { + .two-merch-cards.catalog, + .three-merch-cards.catalog, + .four-merch-cards.catalog { + grid-template-columns: repeat(2, var(--consonant-merch-card-catalog-width)); + } +} + +/* desktop */ +@media screen and ${c} { + .three-merch-cards.catalog, + .four-merch-cards.catalog { + grid-template-columns: repeat(3, var(--consonant-merch-card-catalog-width)); + } +} + +/* Large desktop */ + @media screen and ${i} { + .four-merch-cards.catalog { + grid-template-columns: repeat(4, var(--consonant-merch-card-catalog-width)); + } +} + + +/* grid style for special-offers */ +.one-merch-card.special-offers, +.two-merch-cards.special-offers, +.three-merch-cards.special-offers, +.four-merch-cards.special-offers { + grid-template-columns: minmax(300px, var(--consonant-merch-card-special-offers-width)); +} + +/* Tablet */ +@media screen and ${s} { + .two-merch-cards.special-offers, + .three-merch-cards.special-offers, + .four-merch-cards.special-offers { + grid-template-columns: repeat(2, minmax(300px, var(--consonant-merch-card-special-offers-width))); + } +} + +/* desktop */ +@media screen and ${c} { + .three-merch-cards.special-offers, + .four-merch-cards.special-offers { + grid-template-columns: repeat(3, minmax(300px, var(--consonant-merch-card-special-offers-width))); + } +} + +@media screen and ${i} { + .four-merch-cards.special-offers { + grid-template-columns: repeat(4, minmax(300px, var(--consonant-merch-card-special-offers-width))); + } +} + + +/* grid style for image */ +.one-merch-card.image, +.two-merch-cards.image, +.three-merch-cards.image, +.four-merch-cards.image { + grid-template-columns: var(--consonant-merch-card-image-width); +} + +/* Tablet */ +@media screen and ${s} { + .two-merch-cards.image, + .three-merch-cards.image, + .four-merch-cards.image { + grid-template-columns: repeat(2, var(--consonant-merch-card-image-width)); + } +} + +/* desktop */ +@media screen and ${c} { + .three-merch-cards.image, + .four-merch-cards.image { + grid-template-columns: repeat(3, var(--consonant-merch-card-image-width)); + } +} + +/* Large desktop */ + @media screen and ${i} { + .four-merch-cards.image { + grid-template-columns: repeat(4, var(--consonant-merch-card-image-width)); + } +} + + +/* grid style for segment */ +.one-merch-card.segment, +.two-merch-cards.segment, +.three-merch-cards.segment, +.four-merch-cards.segment { + grid-template-columns: minmax(276px, var(--consonant-merch-card-segment-width)); +} + +/* Tablet */ +@media screen and ${s} { + .two-merch-cards.segment, + .three-merch-cards.segment, + .four-merch-cards.segment { + grid-template-columns: repeat(2, minmax(276px, var(--consonant-merch-card-segment-width))); + } +} + +/* desktop */ +@media screen and ${c} { + .three-merch-cards.segment { + grid-template-columns: repeat(3, minmax(276px, var(--consonant-merch-card-segment-width))); + } + + .four-merch-cards.segment { + grid-template-columns: repeat(4, minmax(276px, var(--consonant-merch-card-segment-width))); + } +} + + +/* grid style for product */ +.one-merch-card.product, +.two-merch-cards.product, +.three-merch-cards.product, +.four-merch-cards.product { + grid-template-columns: var(--consonant-merch-card-product-width); +} + +/* Tablet */ +@media screen and ${s} { + .two-merch-cards.product, + .three-merch-cards.product, + .four-merch-cards.product { + grid-template-columns: repeat(2, var(--consonant-merch-card-product-width)); + } +} + +/* desktop */ +@media screen and ${c} { + .three-merch-cards.product, + .four-merch-cards.product { + grid-template-columns: repeat(3, var(--consonant-merch-card-product-width)); + } +} + +/* Large desktop */ + @media screen and ${i} { + .four-merch-cards.product { + grid-template-columns: repeat(4, var(--consonant-merch-card-product-width)); + } +} + + +/* grid style for inline-heading */ +.one-merch-card.inline-heading, +.two-merch-cards.inline-heading, +.three-merch-cards.inline-heading, +.four-merch-cards.inline-heading { + grid-template-columns: var(--consonant-merch-card-inline-heading-width); +} + +/* Tablet */ +@media screen and ${s} { + .two-merch-cards.inline-heading, + .three-merch-cards.inline-heading, + .four-merch-cards.inline-heading { + grid-template-columns: repeat(2, var(--consonant-merch-card-inline-heading-width)); + } +} + +/* desktop */ +@media screen and ${c} { + .three-merch-cards.inline-heading, + .four-merch-cards.inline-heading { + grid-template-columns: repeat(3, var(--consonant-merch-card-inline-heading-width)); + } +} + +/* Large desktop */ + @media screen and ${i} { + .four-merch-cards.inline-heading { + grid-template-columns: repeat(4, var(--consonant-merch-card-inline-heading-width)); + } +} + +`;document.head.appendChild(E);var C="MERCH-CARD",O="merch-card",b=class extends T{static properties={name:{type:String},variant:{type:String,reflect:!0},size:{type:String,attribute:"size",reflect:!0},badgeColor:{type:String,attribute:"badge-color"},badgeBackgroundColor:{type:String,attribute:"badge-background-color"},badgeText:{type:String,attribute:"badge-text"},icons:{type:Array},actionMenu:{type:Boolean,attribute:"action-menu"},actionMenuContent:{type:String,attribute:"action-menu-content"},title:{type:String},description:{type:String},customHr:{type:Boolean,attribute:"custom-hr"},detailBg:{type:String,attribute:"detail-bg"},secureLabel:{type:String,attribute:"secure-label"},checkboxLabel:{type:String,attribute:"checkbox-label"},stockOfferOsis:{type:Object,attribute:"stock-offer-osis",converter:{fromAttribute:e=>{let[t,r,a]=e.split(",");return{PUF:t,ABM:r,M2M:a}}}},filters:{type:String,reflect:!0,converter:{fromAttribute:e=>Object.fromEntries(e.split(",").map(t=>{let[r,a,o]=t.split(":"),d=Number(a);return[r,{order:isNaN(d)?void 0:d,size:o}]})),toAttribute:e=>Object.entries(e).map(([t,{order:r,size:a}])=>[t,r,a].filter(o=>o!=null).join(":")).join(",")}},types:{type:String,attribute:"types",reflect:!0}};static styles=[v,...y()];constructor(){super(),this.filters={},this.types=""}updated(e){e.has("badgeBackgroundColor")&&(this.style.border=`1px solid ${this.badgeBackgroundColor}`)}renderIcons(){return this.icons?this.icons&&this.icons.length>0?n`
- ${this.icons.map(e=>a`${e.alt}`)} + ${this.icons.map(e=>n`${e.alt}`)}
- `:""}get stockCheckbox(){return this.checkboxLabel?a``:""}get cardImage(){return n`
+ + ${this.badge} +
`}get plansFooter(){let e=this.secureLabel?n`${this.secureLabel}`:"";return n`
${e}
`}get badge(){let e;if(!(!this.badgeBackgroundColor||!this.badgeColor||!this.badgeText))return this.evergreen&&(e=`border: 1px solid ${this.badgeBackgroundColor}; border-right: none;`),n`
${this.badgeText}
- `}get headingmMSlot(){return this.shadowRoot.querySelector('slot[name="heading-m"]').assignedElements()[0]}get footerSlot(){return this.shadowRoot.querySelector('slot[name="footer"]').assignedElements()[0]}get price(){return this.headingmMSlot?.querySelector('span[is="inline-price"]')}get checkoutLinks(){return[...this.footerSlot?.querySelectorAll('a[is="checkout-link"]')??[]]}toggleStockOffer(e){this.stockOfferOsi&&this.toggleStock(this.checkoutLinks,e.target.checked)}toggleStock(e,n){e.length!==0&&e.forEach(t=>{let o=t.dataset.wcsOsi.split(",").filter(r=>r!==this.stockOfferOsi);n&&o.push(this.stockOfferOsi),t.dataset.wcsOsi=o.join(",")})}toggleActionMenu(e){let n=e?.type==="mouseleave"?!0:void 0,t=this.shadowRoot.querySelector('slot[name="action-menu-content"]');t&&t.classList.toggle("hidden",n)}get title(){return this.querySelector('[slot="heading-xs"]').textContent.trim()}updateFilters(e){let n={...this.filters};Object.keys(n).forEach(t=>{if(e){n[t]=Math.min(n[t],2);return}let o=n[t];o===1||isNaN(o)||(n[t]=Number(o)+1)}),this.filters=n}includes(e){return this.textContent.match(new RegExp(e,"i"))!==null}render(){switch(this.variant){case"special-offers":return this.renderSpecialOffer();case"segment":return this.renderSegment();case"plans":return this.renderPlans();case"catalog":return this.renderCatalog();case"inline-heading":return this.renderInlineHeading();default:return this.renderDefault()}}renderSpecialOffer(){return a`
- - ${this.decorateRibbon()} -
+ `}get headingmMSlot(){return this.shadowRoot.querySelector('slot[name="heading-m"]').assignedElements()[0]}get footerSlot(){return this.shadowRoot.querySelector('slot[name="footer"]')?.assignedElements()[0]}get price(){return this.headingmMSlot?.querySelector('span[is="inline-price"]')}get checkoutLinks(){return[...this.footerSlot?.querySelectorAll('a[is="checkout-link"]')??[]]}get isMobileOrTablet(){return window.matchMedia("(max-width: 1024px)").matches}async toggleStockOffer({target:e}){if(!this.stockOfferOsis)return;let t=this.checkoutLinks;if(t.length!==0)for(let r of t){await r.onceSettled();let a=r.value?.[0]?.planType;if(!a)return;let o=this.stockOfferOsis[a];if(!o)return;let d=r.dataset.wcsOsi.split(",").filter(m=>m!==o);e.checked&&d.push(o),r.dataset.wcsOsi=d.join(",")}}toggleActionMenu(e){let t=e?.type==="mouseleave"?!0:void 0,r=this.shadowRoot.querySelector('slot[name="action-menu-content"]');r&&r.classList.toggle("hidden",t)}get title(){return this.querySelector('[slot="heading-xs"]').textContent.trim()}updateFilters(e){let t={...this.filters};Object.keys(t).forEach(r=>{if(e){t[r].order=Math.min(t[r].order,2);return}let a=t[r].order;a===1||isNaN(a)||(t[r].order=Number(a)+1)}),this.filters=t}includes(e){return this.textContent.match(new RegExp(e,"i"))!==null}render(){switch(this.variant){case"special-offers":return this.renderSpecialOffer();case"segment":return this.renderSegment();case"plans":return this.renderPlans();case"catalog":return this.renderCatalog();case"image":return this.renderImage();case"product":case"inline-heading":return this.renderInlineHeading();default:return this.renderDefault()}}renderSpecialOffer(){return n`${this.cardImage}
- ${this.evergreen?a` + ${this.evergreen?n`
- `:a` + `:n`
- - `}`}renderSegment(){return a` ${this.decorateRibbon()} +
+ `}`}renderSegment(){return n` ${this.badge}

- `}renderPlans(){return a` ${this.decorateRibbon()} +
`}renderPlans(){return n` ${this.badge}
${this.renderIcons()} @@ -723,17 +838,20 @@ div[slot='bg-image'] img { ${this.stockCheckbox}
- ${this.plansFooter}`}renderCatalog(){return a`
+ ${this.plansFooter}`}renderCatalog(){return n`
- ${this.renderIcons()} ${this.decorateRibbon()} + ${this.renderIcons()} ${this.badge}
${this.actionMenuContent} @@ -741,8 +859,24 @@ div[slot='bg-image'] img {
- `}renderInlineHeading(){return a` - ${this.decorateRibbon()} +
`}renderImage(){return n`${this.cardImage} +
+ ${this.renderIcons()} + + + +
+ ${this.evergreen?n` +
+ +
+ `:n` +
+
+ `}`}renderInlineHeading(){return n` ${this.badge}
${this.renderIcons()} @@ -750,12 +884,11 @@ div[slot='bg-image'] img {
- ${this.customHr?"":a`
`} - - `}renderDefault(){return a` ${this.decorateRibbon()} + ${this.customHr?"":n`
`} ${this.plansFooter}`}renderDefault(){return n` ${this.badge}
${this.renderIcons()}
- `}connectedCallback(){super.connectedCallback(),this.setAttribute("tabindex","0"),this.addEventListener("keydown",this.keydownHandler),this.addEventListener("mouseleave",this.toggleActionMenu)}disconnectedCallback(){super.disconnectedCallback(),this.removeEventListener("keydown",this.keydownHandler)}keydownHandler(e){let n=document.activeElement;if(n&&n.tagName===E){let s=function(c){let i=o.indexOf(c);return{row:Math.floor(i/r),col:i%r}},t,o=Array.from(this.parentElement.querySelectorAll("merch-card")).filter(c=>window.getComputedStyle(c).display!=="none").sort((c,i)=>parseInt(window.getComputedStyle(c).order,0)-parseInt(window.getComputedStyle(i).order,0)),r=1,z=o[0].getBoundingClientRect().top;for(;r0&&(t=o[c.row*r+(c.col-1)]);break;case v:let i=s(n);i.col0&&(t=o[(g.row-1)*r+g.col]);break;case w:let d=s(n);d.rowd.col?0:1)&&(t=o[(d.row+1)*r+d.col]);break}t&&(t.focus(),e.preventDefault())}}};customElements.get($.toLowerCase())||customElements.define("merch-card",m);export{$ as MERCH_CARD,E as MERCH_CARD_NODE_NAME,m as MerchCard}; +
`}connectedCallback(){super.connectedCallback(),this.setAttribute("tabindex","0"),this.addEventListener("keydown",this.keydownHandler),this.addEventListener("mouseleave",this.toggleActionMenu)}disconnectedCallback(){super.disconnectedCallback(),this.removeEventListener("keydown",this.keydownHandler)}keydownHandler(e){let t=document.activeElement?.closest(C);if(!t)return;function r(S,A){let g=document.elementFromPoint(S,A)?.closest(C);g&&(e.preventDefault(),e.stopImmediatePropagation(),g.focus(),g.scrollIntoView({behavior:"smooth",block:"center"}))}let{x:a,y:o,width:d,height:m}=t.getBoundingClientRect(),l=64;switch(e.code===$?e.shiftKey?u:f:e.code){case u:r(a-l,o);break;case f:r(a+d+l,o);break;case w:r(a,o-l);break;case k:r(a,o+m+l);break;case z:this.footerSlot?.querySelector("a")?.click();break}}};customElements.define(O,b);export{O as MERCH_CARD,C as MERCH_CARD_NODE_NAME,b as MerchCard}; +//# sourceMappingURL=merch-card.js.map diff --git a/libs/deps/merch-offer-select.js b/libs/deps/merch-offer-select.js new file mode 100644 index 0000000000..76cb49c181 --- /dev/null +++ b/libs/deps/merch-offer-select.js @@ -0,0 +1,95 @@ +// Wed, 06 Dec 2023 11:00:21 GMT +import{html as d,LitElement as h}from"./lit-all.min.js";import{LitElement as c}from"./lit-all.min.js";var s=class extends c{static properties={offers:{type:Array},selectedOffer:{type:Object},defaults:{type:Object}};saveContainerDefaultValues(){let e=this.closest(this.getAttribute("container")),t=e?.querySelector('[slot="description"]:not(merch-offer > *)')?.cloneNode(!0),i=e?.badgeText;return{description:t,badgeText:i}}getSlottedElement(e,t){return(t||this.closest(this.getAttribute("container"))).querySelector(`[slot="${e}"]:not(merch-offer > *)`)}updateSlot(e,t){let i=this.getSlottedElement(e,t);if(!i)return;let o=this.selectedOffer.get(e)?this.selectedOffer.get(e):this.defaults[e];o&&i.replaceWith(o.cloneNode(!0))}updateBadgeText(e){this.selectedOffer.badgeText===""?e.badgeText=null:this.selectedOffer.badgeText?e.badgeText=this.selectedOffer.badgeText:e.badgeText=this.defaults.badgeText}updateContainer(){let e=this.closest(this.getAttribute("container"));!e||!this.selectedOffer||(this.updateSlot("cta",e),this.updateSlot("price",e),this.updateSlot("description",e),this.updateBadgeText(e))}selectOffer(e){let t=this.selectedOffer,i=e.detail;i&&(t&&(t.selected=!1),this.selectedOffer=i,this.updateContainer())}connectedCallback(){this.offers=[...this.querySelectorAll("merch-offer")],this.defaults=this.saveContainerDefaultValues(),this.addEventListener("offer-selected",this.selectOffer),this.offers[0].select(),this.selectedOffer=this.offers[0]}disconnectedCallback(){this.removeEventListener("offer-selected",this.selectOffer)}};customElements.define("merch-offer-select",s);import{css as l}from"./lit-all.min.js";var n=l` + :host { + --merch-radio: rgba(82, 88, 228); + --merch-radio-hover: rgba(64, 70, 202); + --merch-radio-down: rgba(50, 54, 168); + --merch-radio-selected: rgb(2, 101, 220); + align-items: flex-start; + display: flex; + max-inline-size: 100%; + min-block-size: 32px; + position: relative; + vertical-align: top; + } + + .merch-Radio-input { + block-size: 100%; + box-sizing: border-box; + cursor: pointer; + font-family: inherit; + font-size: 100%; + inline-size: 100%; + line-height: 1.3; + margin: 0; + opacity: 0; + overflow: visible; + padding: 0; + position: absolute; + z-index: 1; + } + + .merch-Radio-button { + block-size: 14px; + box-sizing: border-box; + flex-grow: 0; + flex-shrink: 0; + inline-size: 14px; + margin-block-start: 9px; + position: relative; + } + + .merch-Radio-button:before { + border-color: rgb(109, 109, 109); + border-radius: 50%; + border-style: solid; + border-width: 2px; + box-sizing: border-box; + content: ''; + display: block; + height: 14px; + position: absolute; + transition: border 0.13s ease-in-out, box-shadow 0.13s ease-in-out; + width: 14px; + z-index: 0; + } + + .merch-Radio-button:after { + border-radius: 50%; + content: ''; + display: block; + left: 50%; + position: absolute; + top: 50%; + transform: translateX(-50%) translateY(-50%); + transition: opacity 0.13s ease-out, margin 0.13s ease-out; + } + + :host(:active) .merch-Radio-button:before { + border-color: var(--merch-radio-down); + } + + :host(:hover) .merch-Radio-button:before { + border-color: var(--merch-radio-hover); + } + + :host([selected]) .merch-Radio-button::before { + border-color: var(--merch-radio-selected); + border-width: 5px; + } + + .merch-Radio-label { + color: rgb(34, 34, 34); + font-size: 14px; + line-height: 18.2px; + margin-block-end: 9px; + margin-block-start: 6px; + margin-inline-start: 10px; + text-align: start; + transition: color 0.13s ease-in-out; + } +`;var r=class extends h{static properties={text:{type:String},price:{type:Object},cta:{type:Object},osi:{type:String},selected:{type:Boolean,reflect:!0},badgeText:{type:String,attribute:"badge-text"},description:{type:Object}};static styles=[n];select(){this.selected||(this.selected=!0,this.parentElement.dispatchEvent(new CustomEvent("offer-selected",{detail:this})))}constructor(){super(),this.selected=!1,this.addEventListener("click",e=>{this.select()}),this.addEventListener("keyup",e=>{(e.key==="Enter"||e.key===" ")&&this.select()})}get(e){return this[e]||(this[e]=this.querySelector(`[slot="${e}"]`)),this[e]}connectedCallback(){super.connectedCallback(),this.hasAttribute("tabindex")||(this.tabIndex=0),this.hasAttribute("role")||(this.role="radio"),this.hasAttribute("aria-checked")||this.setAttribute("aria-checked",this.selected)}updated(e){e.has("selected")&&this.setAttribute("aria-checked",this.selected)}render(){return d` + + + ${this.text} + `}};customElements.define("merch-offer",r); diff --git a/libs/utils/utils.js b/libs/utils/utils.js index d1e9ae405d..cd4299b906 100644 --- a/libs/utils/utils.js +++ b/libs/utils/utils.js @@ -42,6 +42,7 @@ const MILO_BLOCKS = [ 'media', 'merch', 'merch-card', + 'merch-offers', 'modal', 'modal-metadata', 'pdf-viewer', diff --git a/test/blocks/merch-card/legacy-merch-card/legacy-merch-card.test.js b/test/blocks/merch-card/legacy-merch-card/legacy-merch-card.test.js deleted file mode 100644 index a2a7a06935..0000000000 --- a/test/blocks/merch-card/legacy-merch-card/legacy-merch-card.test.js +++ /dev/null @@ -1,168 +0,0 @@ -import { readFile } from '@web/test-runner-commands'; -import { expect } from '@esm-bundle/chai'; - -const { default: initLegacyMerchCard } = await import('../../../../libs/blocks/merch-card/legacy-merch-card.js'); - -describe('Merch Card', () => { - it('Shows segment card', async () => { - document.body.innerHTML = await readFile({ path: './mocks/segment-card.html' }); - await initLegacyMerchCard(document.querySelector('.merch-card')); - const inner = document.querySelector('.consonant-SegmentBlade-inner'); - const cardFooter = inner.querySelector('.consonant-CardFooter'); - const buttons = cardFooter.querySelectorAll('.con-button'); - - expect(document.querySelector('.consonant-ProductCard')).to.exist; - expect(inner.querySelector('.consonant-SegmentBlade-title')).to.exist; - expect(inner.querySelector('.consonant-SegmentBlade-description')).to.exist; - expect(cardFooter.querySelector('.con-button')).to.exist; - expect(buttons.length).to.be.equal(2); - expect(buttons[0].textContent).to.be.equal('Learn More'); - expect(buttons[1].textContent).to.be.equal('Save now'); - }); - - describe('Wrapper', async () => { - before(async () => { - document.body.innerHTML = await readFile({ path: './mocks/segment-card.html' }); - const merchCards = document.querySelectorAll('.segment'); - await initLegacyMerchCard(merchCards[0]); - await initLegacyMerchCard(merchCards[1]); - }); - - it('Has one per section', () => { - expect(document.querySelectorAll('.consonant-Wrapper').length).to.equal(1); - }); - - it('Is in correct position', async () => { - const wrapper = document.querySelector('.consonant-Wrapper'); - expect(wrapper.previousElementSibling).to.equal(document.querySelector('.before')); - expect(wrapper.nextElementSibling).to.equal(document.querySelector('.after')); - }); - }); - - it('Supports Special Offers card', async () => { - document.body.innerHTML = await readFile({ path: './mocks/special-offers.html' }); - await initLegacyMerchCard(document.querySelector('.special-offers')); - const inner = document.querySelector('.consonant-SpecialOffers-inner'); - const cardFooter = inner.querySelector('.consonant-CardFooter'); - const ribbon = document.querySelector('.consonant-SpecialOffers-ribbon'); - const buttons = cardFooter.querySelectorAll('.con-button'); - - expect(document.querySelector('.consonant-ProductCard')).to.exist; - expect(inner.querySelector('.consonant-SpecialOffers-title')).to.exist; - expect(inner.querySelector('.consonant-SpecialOffers-description')).to.exist; - expect(document.querySelector('.consonant-SpecialOffers-iconWrapper')).to.exist; - expect(ribbon).to.exist; - expect(ribbon.style.backgroundColor).to.be.equal(''); - expect(ribbon.style.color).to.be.equal('rgb(0, 0, 0)'); - expect(ribbon.textContent).to.be.equal('LOREM IPSUM DOLOR'); - expect(ribbon.style.borderLeft).to.be.equal('1px solid rgb(237, 204, 45)'); - expect(ribbon.style.borderRight).to.be.equal('none'); - expect(ribbon.style.borderTop).to.be.equal('1px solid rgb(237, 204, 45)'); - expect(ribbon.style.borderBottom).to.be.equal('1px solid rgb(237, 204, 45)'); - expect(buttons.length).to.be.equal(2); - expect(buttons[0].textContent).to.be.equal('Learn More'); - expect(buttons[1].textContent).to.be.equal('Save now'); - }); - - describe('Plans Card', () => { - before(async () => { - document.body.innerHTML = await readFile({ path: './mocks/plans-card.html' }); - }); - - it('Supports Plans card', async () => { - document.body.innerHTML = await readFile({ path: './mocks/plans-card.html' }); - await initLegacyMerchCard(document.querySelector('.plans.icons')); - const inner = document.querySelector('.consonant-PlansCard-inner'); - const cardFooter = inner.querySelector('.consonant-CardFooter'); - const ribbon = document.querySelector('.consonant-PlansCard-ribbon'); - const buttons = cardFooter.querySelectorAll('.con-button'); - const inactiveButton = cardFooter.querySelector('.button--inactive'); - const secureWrapper = cardFooter.querySelector('.secure-transaction-wrapper'); - const checkBoxContainer = cardFooter.querySelector('.checkbox-container'); - const plansCard = document.querySelector('.consonant-ProductCard'); - const iconsWrapper = document.querySelector('.consonant-PlansCard-iconWrapper'); - const icons = iconsWrapper.querySelectorAll('.consonant-MerchCard-ProductIcon'); - const list = document.querySelector('.consonant-PlansCard-list'); - const listItems = list.querySelectorAll('li'); - - expect(plansCard).to.exist; - expect(plansCard.style.border).to.be.equal('1px solid rgb(237, 204, 45)'); - expect(inner.querySelector('.consonant-PlansCard-title')).to.exist; - expect(inner.querySelector('.consonant-PlansCard-description')).to.exist; - expect(iconsWrapper).to.exist; - expect(icons.length).to.be.equal(2); - expect(ribbon).to.exist; - expect(ribbon.style.backgroundColor).to.be.equal('rgb(237, 204, 45)'); - expect(ribbon.style.color).to.be.equal('rgb(0, 0, 0)'); - expect(ribbon.textContent).to.be.equal('LOREM IPSUM DOLOR'); - expect(buttons.length).to.be.equal(2); - expect(buttons[0].textContent).to.be.equal('Learn More'); - expect(buttons[1].textContent).to.be.equal('Save now'); - expect(secureWrapper).to.exist; - expect(list).to.exist; - expect(list.classList.contains('consonant-PlansCard-list')).to.be.true; - expect(listItems.length).to.be.equal(2); - expect(listItems[0].textContent).to.be.equal('Maecenas porttitor congue massa'); - expect(listItems[1].textContent).to.be.equal('Nunc viverra imperdiet enim.'); - - expect(checkBoxContainer.querySelector('.checkMark')).to.exist; - expect(checkBoxContainer.querySelector('.checkbox-label').textContent).to.be.equal('Lorem ipsum dolor sit amet'); - expect(secureWrapper.querySelector('.secure-transaction-icon').classList).to.exist; - expect(secureWrapper.querySelector('.secure-transaction-label')).to.exist; - - expect(inactiveButton.classList.contains('button--inactive')).to.be.true; - checkBoxContainer.querySelector('.checkMark').click(); - expect(inactiveButton.classList.contains('button--inactive')).to.be.false; - checkBoxContainer.querySelector('.checkMark').click(); - expect(inactiveButton.classList.contains('button--inactive')).to.be.true; - }); - - it('should skip ribbon and altCta creation', async () => { - document.body.innerHTML = await readFile({ path: './mocks/plans-card.html' }); - await initLegacyMerchCard(document.querySelector('.plans.icons.skip-ribbon.skip-altCta')); - const inner = document.querySelector('.consonant-PlansCard-inner'); - const cardFooter = inner.querySelector('.consonant-CardFooter'); - const ribbon = document.querySelector('.consonant-PlansCard-ribbon'); - const buttons = cardFooter.querySelectorAll('.con-button'); - const inactiveButton = cardFooter.querySelectorAll('.button--inactiive'); - const secureWrapper = cardFooter.querySelector('.secure-transaction-wrapper'); - const checkBoxContainer = cardFooter.querySelector('.checkbox-container'); - const plansCard = document.querySelector('.consonant-ProductCard'); - const iconsWrapper = document.querySelector('.consonant-PlansCard-iconWrapper'); - const icons = iconsWrapper.querySelectorAll('.consonant-MerchCard-ProductIcon'); - - expect(plansCard).to.exist; - console.log(plansCard.style.border); - expect(inner.querySelector('.consonant-PlansCard-title')).to.exist; - expect(inner.querySelector('.consonant-PlansCard-description')).to.exist; - expect(iconsWrapper).to.exist; - expect(icons.length).to.be.equal(2); - expect(ribbon).to.not.exist; - expect(buttons.length).to.be.equal(2); - expect(buttons[0].textContent).to.be.equal('Learn More'); - expect(buttons[1].textContent).to.be.equal('Save now'); - expect(inactiveButton).to.exist; - expect(secureWrapper).to.not.exist; - expect(checkBoxContainer).to.not.exist; - }); - - it('does not display undefined if no content', async () => { - const el = document.querySelector('.merch-card.empty'); - await initLegacyMerchCard(el); - expect(el.outerHTML.includes('undefined')).to.be.false; - }); - }); - - describe('UAR Card', () => { - before(async () => { - document.body.innerHTML = await readFile({ path: './mocks/uar-card.html' }); - }); - it('handles decorated
', async () => { - const cards = document.querySelectorAll('.merch-card'); - cards.forEach((card) => { - initLegacyMerchCard(card); - }); - expect(cards[0].classList.contains('has-divider')).to.be.true; - }); - }); -}); diff --git a/test/blocks/merch-card/legacy-merch-card/mocks/plans-card.html b/test/blocks/merch-card/legacy-merch-card/mocks/plans-card.html deleted file mode 100644 index 490011c422..0000000000 --- a/test/blocks/merch-card/legacy-merch-card/mocks/plans-card.html +++ /dev/null @@ -1,76 +0,0 @@ -
-
-
-
-
-
-
-
-
#EDCC2D, #000000
-
LOREM IPSUM DOLOR
-
-
-
- - - - - - - - - - - - -

Lorem ipsum dolor sit amet

-

Lorem ipsum dolor

-

Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, - sit amet commodo magna eros quis urna. Nunc viverra imperdiet enim.

-

Maecenas

-
    -
  • Maecenas porttitor congue massa
  • -
  • Nunc viverra imperdiet enim.
  • -
-

See terms about lorem ipsum

-

Learn More Save now

-
-
-
-
Lorem ipsum dolor sit amet
- -
-
-
-
-
-
LOREM IPSUM DOLOR
-
-
-
- - - - - - - - - - - - -

Lorem ipsum dolor sit amet

-

Lorem ipsum dolor

-

Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, - sit amet commodo magna eros quis urna. Nunc viverra imperdiet enim.

-

See terms about lorem ipsum

-

Learn More Save now

-
-
-
-
Lorem ipsum dolor sit amet
-
-
-
-
diff --git a/test/blocks/merch-card/legacy-merch-card/mocks/segment-card.html b/test/blocks/merch-card/legacy-merch-card/mocks/segment-card.html deleted file mode 100644 index c816cac7f4..0000000000 --- a/test/blocks/merch-card/legacy-merch-card/mocks/segment-card.html +++ /dev/null @@ -1,24 +0,0 @@ -
-
-
-
-
-

Lorem ipsum dolor sit amet

-

Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis urna. Nunc viverra imperdiet enim.

-

See what's included | Learn more

-

Learn More Save now

-
-
-
-
-
-
-

Lorem ipsum dolor sit amet

-

Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis urna. Nunc viverra imperdiet enim.

-

See what's included | Learn more

-

Learn More Save now

-
-
-
-
-
diff --git a/test/blocks/merch-card/legacy-merch-card/mocks/special-offers.html b/test/blocks/merch-card/legacy-merch-card/mocks/special-offers.html deleted file mode 100644 index 9c48a9aaae..0000000000 --- a/test/blocks/merch-card/legacy-merch-card/mocks/special-offers.html +++ /dev/null @@ -1,25 +0,0 @@ -
-
-
-
#EDCC2D, #000000
-
LOREM IPSUM DOLOR
-
-
-
-

- - - - - - -

-

INDIVIDUALS

-

Get 10% off Photoshop.

-

Create gorgeous images, rich graphics, and incredible art. Save 10% for the first year. Ends Mar 20.

-

See terms

-

Learn More Save now

-
-
-
-
diff --git a/test/blocks/merch-card/legacy-merch-card/mocks/uar-card.html b/test/blocks/merch-card/legacy-merch-card/mocks/uar-card.html deleted file mode 100644 index 5955045e1d..0000000000 --- a/test/blocks/merch-card/legacy-merch-card/mocks/uar-card.html +++ /dev/null @@ -1,49 +0,0 @@ -
- -

UAR CARDS

- -
-
-
-

https://main--milo--adobecom.hlx.page/drafts/rparrish/assets/merch/photoshop.svg

-

Photoshop

-

PRICE - PUF - Photoshop with 2TB PRICE - ABM - Photoshop with 2TB

-

HR in between price and link? Variant UAR - Create gorgeous images, rich graphics, and incredible art.

-


--- #00ffff

-

See terms

-

Learn More Save now

-
-
-
- -

inline heading

-
-
-
-

https://main--milo--adobecom.hlx.page/drafts/rparrish/assets/merch/indesign.svg

-

InDesign

-

PRICE - PUF - Photoshop with 2TB PRICE - ABM - Photoshop with 2TB

-

--- #FF3266

-

Variant: ‘inline headline’ is used to keep the title inline w/ the icon.

-

See terms

-

Learn More Save now

-
-
-
- -

background opacity 70

-
-
-
-

https://main--milo--adobecom.hlx.page/drafts/rparrish/assets/merch/xd.svg

-

XD

-

PRICE - PUF - Photoshop with 2TB PRICE - ABM - Photoshop with 2TB

-

HR between link and ctas? Variant: ‘background opacity 70’ is used to have a 70% white bg.

-

See terms

-

See terms

-

Learn More Save now

-
-
-
- -
diff --git a/test/blocks/merch-card/merch-card.test.js b/test/blocks/merch-card/merch-card.test.js index 6f5991cb3d..1dc4accf2b 100644 --- a/test/blocks/merch-card/merch-card.test.js +++ b/test/blocks/merch-card/merch-card.test.js @@ -11,10 +11,7 @@ setConfig(conf); describe('Merch Card', () => { it('Shows segment card', async () => { document.body.innerHTML = await readFile({ path: './mocks/segment-card.html' }); - await init(document.querySelector('.segment')); - const merchCard = document.querySelector('merch-card'); - const fragment = document.querySelector('.fragment'); - const section = document.querySelector('.section'); + const merchCard = await init(document.querySelector('.segment')); const heading = merchCard.querySelector('h3[slot="heading-xs"]'); const body = merchCard.querySelector('div[slot="body-xs"]'); const footer = merchCard.querySelector('div[slot="footer"]'); @@ -28,18 +25,11 @@ describe('Merch Card', () => { expect(buttons.length).to.be.equal(2); expect(buttons[0].textContent).to.be.equal('Learn More'); expect(buttons[1].textContent).to.be.equal('Save now'); - - expect(fragment).to.exist; - expect(fragment.style.display).to.be.equal('contents'); - - expect(section).to.exist; - expect(section.style.display).to.be.equal('contents'); }); it('Supports Special Offers card', async () => { document.body.innerHTML = await readFile({ path: './mocks/special-offers.html' }); - await init(document.querySelector('.merch-card.special-offers')); - const merchCard = document.querySelector('merch-card'); + const merchCard = await init(document.querySelector('.special-offers')); const heading = merchCard.querySelector('h2[slot="heading-m"]'); const headingOne = merchCard.querySelector('h3[slot="heading-xs"]'); const body = merchCard.querySelector('div[slot="body-xs"]'); @@ -54,209 +44,281 @@ describe('Merch Card', () => { expect(merchCard.getAttribute('badge-background-color')).to.be.equal('#EDCC2D'); expect(merchCard.getAttribute('badge-color')).to.be.equal('#000000'); expect(merchCard.getAttribute('badge-text')).to.be.equal('LOREM IPSUM DOLOR'); - expect(body.textContent).to.be.equal('Create gorgeous images, rich graphics, and incredible art. Save 10% for the first year. Ends Mar 20.Best for:See terms'); + expect(body.textContent).to.be.equal('Create gorgeous images, rich graphics, and incredible art. Save 10% for the first year. Ends Mar 20.See terms'); expect(buttons.length).to.be.equal(2); expect(buttons[0].textContent).to.be.equal('Learn More'); expect(buttons[1].textContent).to.be.equal('Save now'); }); +}); - describe('Plans Card', () => { - before(async () => { - document.body.innerHTML = await readFile({ path: './mocks/plans-card.html' }); - }); +describe('Plans Card', () => { + it('Supports COM Plans card', async () => { + document.body.innerHTML = await readFile({ path: './mocks/plans-card.html' }); + const merchCard = await init(document.querySelector('.merch-card.plans.icons.secure')); + const heading = merchCard.querySelector('h2[slot="heading-m"]'); + const headingOne = merchCard.querySelector('h3[slot="heading-xs"]'); + const body = merchCard.querySelector('div[slot="body-xs"]'); + const detail = merchCard.querySelector('h5[slot="detail-m"]'); + const footer = merchCard.querySelector('div[slot="footer"]'); + const buttons = footer.querySelectorAll('.con-button'); - it('Supports Plans card', async () => { - document.body.innerHTML = await readFile({ path: './mocks/plans-card.html' }); - await init(document.querySelector('.merch-card.plans.icons.secure')); - const merchCard = document.querySelector('merch-card'); - const heading = merchCard.querySelector('h4[slot="body-xxs"]'); - const headingOne = merchCard.querySelector('h3[slot="heading-xs"]'); - const body = merchCard.querySelector('div[slot="body-xs"]'); - const detail = merchCard.querySelector('h5[slot="detail-m"]'); - const footer = merchCard.querySelector('div[slot="footer"]'); - const buttons = footer.querySelectorAll('.con-button'); + expect(merchCard).to.exist; + expect(heading).to.exist; + expect(headingOne).to.exist; + expect(body).to.exist; + expect(detail).to.exist; + expect(merchCard.getAttribute('variant')).to.be.equal('plans'); + expect(merchCard.getAttribute('badge-background-color')).to.be.equal('#EDCC2D'); + expect(merchCard.getAttribute('badge-color')).to.be.equal('#000000'); + expect(merchCard.getAttribute('badge-text')).to.be.equal('LOREM IPSUM DOLOR'); + expect(JSON.parse(merchCard.getAttribute('icons'))).to.have.lengthOf(2); + expect(merchCard.getAttribute('checkbox-label')).to.be.equal('Add a 30-day free trial of Adobe Stock.*'); + expect(body.textContent).to.be.equal('Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis urna. Nunc viverra imperdiet enim.MaecenasSee terms about lorem ipsum'); + expect(detail.textContent).to.be.equal('Maecenas porttitor enim.'); + expect(buttons.length).to.be.equal(2); + expect(buttons[0].textContent).to.be.equal('Learn More'); + expect(buttons[1].textContent).to.be.equal('Save now'); + }); - expect(merchCard).to.exist; - expect(heading).to.exist; - expect(headingOne).to.exist; - expect(body).to.exist; - expect(detail).to.exist; - expect(merchCard.getAttribute('variant')).to.be.equal('plans'); - expect(merchCard.getAttribute('badge-text')).to.be.equal('LOREM IPSUM DOLOR'); - expect(merchCard.getAttribute('badge-background-color')).to.be.equal('#EDCC2D'); - expect(merchCard.getAttribute('badge-color')).to.be.equal('#000000'); - expect(JSON.parse(merchCard.getAttribute('icons'))).to.have.lengthOf(2); - expect(merchCard.getAttribute('checkbox-label')).to.be.equal('Lorem ipsum dolor sit amet'); - expect(body.textContent).to.be.equal('Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis urna. Nunc viverra imperdiet enim.MaecenasSee terms about lorem ipsum'); - expect(detail.textContent).to.be.equal('Maecenas porttitor enim.'); - expect(buttons.length).to.be.equal(3); - expect(buttons[0].textContent).to.be.equal('Learn More'); - expect(buttons[1].textContent).to.be.equal('Save now'); - expect(buttons[2].textContent).to.be.equal('free-trial'); - }); + it('Supports EDU Plans card with stock', async () => { + document.body.innerHTML = await readFile({ path: './mocks/plans-card.html' }); + const merchCard = await init(document.querySelector('.merch-card.plans.edu.icons.secure')); + const heading = merchCard.querySelector('h2[slot="heading-m"]'); + const headingOne = merchCard.querySelector('h3[slot="heading-xs"]'); + const body = merchCard.querySelector('div[slot="body-xs"]'); + const detail = merchCard.querySelector('h5[slot="detail-m"]'); + const footer = merchCard.querySelector('div[slot="footer"]'); + const buttons = footer.querySelectorAll('.con-button'); - it('should skip ribbon and altCta creation', async () => { - document.body.innerHTML = await readFile({ path: './mocks/plans-card.html' }); - await init(document.querySelector('.plans.icons.skip-ribbon.skip-altCta')); - const merchCard = document.querySelector('merch-card'); - const heading = merchCard.querySelector('h3[slot=heading-xs]'); - const headingOne = merchCard.querySelector('h2[slot=heading-m]'); - const body = merchCard.querySelector('div[slot=body-xs]'); - const detail = merchCard.querySelector('h4[slot="body-xxs"]'); - const footer = merchCard.querySelector('div[slot="footer"]'); - const buttons = footer.querySelectorAll('.con-button'); + expect(merchCard).to.exist; + expect(heading).to.exist; + expect(headingOne).to.exist; + expect(body).to.exist; + expect(detail).to.exist; + expect(merchCard.getAttribute('variant')).to.be.equal('plans'); + expect(merchCard.getAttribute('badge-background-color')).to.be.equal('#EDCC2D'); + expect(merchCard.getAttribute('badge-color')).to.be.equal('#000000'); + expect(merchCard.getAttribute('badge-text')).to.be.equal('LOREM IPSUM DOLOR'); + expect(JSON.parse(merchCard.getAttribute('icons'))).to.have.lengthOf(2); + expect(merchCard.getAttribute('checkbox-label')).to.be.equal('Add a 30-day free trial of Adobe Stock.*'); + expect(body.textContent).to.be.equal('Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis urna. Nunc viverra imperdiet enim.MaecenasSee terms about lorem ipsum'); + expect(detail.textContent).to.be.equal('Maecenas porttitor enim.'); + expect(buttons.length).to.be.equal(2); + expect(buttons[0].textContent).to.be.equal('Learn More'); + expect(buttons[1].textContent).to.be.equal('Save now'); + }); - expect(merchCard).to.exist; - expect(heading).to.exist; - expect(headingOne).to.exist; - expect(body).to.exist; - expect(detail).to.exist; - expect(merchCard.getAttribute('variant')).to.be.equal('plans'); - expect(merchCard.getAttribute('badge')).to.not.exist; - expect(JSON.parse(merchCard.getAttribute('icons'))).to.have.lengthOf(2); - expect(body.textContent).to.be.equal('Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis urna. Nunc viverra imperdiet enim.See terms about lorem ipsum'); - expect(detail.textContent).to.be.equal('Lorem ipsum dolor sit'); - expect(buttons.length).to.be.equal(2); - expect(buttons[0].textContent).to.be.equal('Learn More'); - expect(buttons[1].textContent).to.be.equal('Save now'); - }); + it('should skip ribbon and altCta creation', async () => { + document.body.innerHTML = await readFile({ path: './mocks/plans-card.html' }); + const merchCard = await init(document.querySelector('.plans.icons.skip-ribbon.skip-altCta')); + const heading = merchCard.querySelector('h2[slot=heading-m]'); + const headingXs = merchCard.querySelector('h3[slot=heading-xs]'); + const body = merchCard.querySelector('div[slot=body-xs]'); + const detail = merchCard.querySelector('h5[slot=detail-m]'); + const footer = merchCard.querySelector('div[slot="footer"]'); + const buttons = footer.querySelectorAll('.con-button'); - it('does not display undefined if no content', async () => { - const el = document.querySelector('.merch-card.empty'); - await init(el); - expect(el.outerHTML.includes('undefined')).to.be.false; - }); + expect(merchCard).to.exist; + expect(heading).to.exist; + expect(headingXs).to.exist; + expect(body).to.exist; + expect(detail).to.exist; + expect(merchCard.getAttribute('variant')).to.be.equal('plans'); + expect(merchCard.getAttribute('badge')).to.not.exist; + expect(JSON.parse(merchCard.getAttribute('icons'))).to.have.lengthOf(2); + expect(body.textContent).to.be.equal('Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis urna. Nunc viverra imperdiet enim.See terms about lorem ipsum'); + expect(detail.textContent).to.be.equal('Maecenas porttitor enim.'); + expect(buttons.length).to.be.equal(2); + expect(buttons[0].textContent).to.be.equal('Learn More'); + expect(buttons[1].textContent).to.be.equal('Save now'); }); - describe('Catalog Card', () => { - it('Supports Catalog card', async () => { - document.body.innerHTML = await readFile({ path: './mocks/catalog.html' }); - await init(document.querySelector('.merch-card.ribbon')); - const merchCard = document.querySelector('merch-card'); - const heading = merchCard.querySelector('h4[slot="body-xxs"]'); - const headingOne = merchCard.querySelector('h3[slot="heading-xs"]'); - const detail = merchCard.querySelector('h5[slot="detail-m"]'); - const body = merchCard.querySelector('div[slot="body-xs"]'); - const actionMenu = merchCard.querySelector('div[slot="action-menu-content"]'); - const footer = merchCard.querySelector('div[slot="footer"]'); - const buttons = footer.querySelectorAll('.con-button'); + it('does not display undefined if no content', async () => { + document.body.innerHTML = await readFile({ path: './mocks/plans-card.html' }); + const el = document.querySelector('.merch-card.empty'); + await init(el); + expect(el.outerHTML.includes('undefined')).to.be.false; + }); +}); - expect(merchCard).to.exist; - expect(heading).to.exist; - expect(headingOne).to.exist; - expect(body).to.exist; - expect(actionMenu).to.exist; - expect(detail).to.exist; - expect(merchCard.getAttribute('variant')).to.be.equal('catalog'); - expect(merchCard.getAttribute('badge-text')).to.be.equal('LOREM IPSUM DOLOR'); - expect(merchCard.getAttribute('badge-background-color')).to.be.equal('#EDCC2D'); - expect(merchCard.getAttribute('badge-color')).to.be.equal('#000000'); - expect(merchCard.getAttribute('action-menu')).to.be.equal('true'); - // expect(merchCard.getAttribute('image')).to.exist; - expect(body.textContent).to.be.equal('Create gorgeous images, rich graphics, and incredible art. Save 10% for the first year. Ends Mar 20.See terms'); - expect(detail.textContent).to.be.equal('Desktop + Mobile'); - expect(buttons.length).to.be.equal(2); - expect(buttons[0].textContent).to.be.equal('Learn More'); - expect(buttons[1].textContent).to.be.equal('Save now'); - }); +describe('Catalog Card', () => { + it('Supports Catalog card', async () => { + document.body.innerHTML = await readFile({ path: './mocks/catalog.html' }); + const merchCard = await init(document.querySelector('.merch-card.ribbon')); + const heading = merchCard.querySelector('h2[slot="heading-m"]'); + const headingOne = merchCard.querySelector('h3[slot="heading-xs"]'); + const body = merchCard.querySelector('div[slot="body-xs"]'); + const actionMenu = merchCard.querySelector('div[slot="action-menu-content"]'); + const detail = merchCard.querySelector('h5[slot="detail-m"]'); + const footer = merchCard.querySelector('div[slot="footer"]'); + const buttons = footer.querySelectorAll('.con-button'); - it('Supports Catalog card without badge', async () => { - document.body.innerHTML = await readFile({ path: './mocks/catalog.html' }); - await init(document.querySelector('.merch-card.catalog.empty-badge')); - const merchCard = document.querySelector('merch-card'); - const heading = merchCard.querySelector('h3[slot="heading-xs"]'); - const headingM = merchCard.querySelector('h2[slot="heading-m"]'); - const detailM = merchCard.querySelector('h5[slot="detail-m"]'); - const body = merchCard.querySelector('div[slot="body-xs"]'); - const actionMenu = merchCard.querySelector('div[slot="action-menu-content"]'); - const footer = merchCard.querySelector('div[slot="footer"]'); - const buttons = footer.querySelectorAll('.con-button'); - console.log('MERCH_CARD-empty', merchCard); - expect(merchCard).to.exist; - expect(heading).to.exist; - expect(headingM).to.exist; - expect(body).to.exist; - expect(actionMenu).to.exist; - expect(merchCard.getAttribute('variant')).to.be.equal('catalog'); - expect(merchCard.getAttribute('badge')).to.not.exist; - expect(merchCard.getAttribute('action-menu')).to.be.equal('true'); - // expect(merchCard.getAttribute('image')).to.exist; - expect(body.textContent).to.be.equal('Create gorgeous images, rich graphics, and incredible art. Save 10% for the first year. Ends Mar 20.See terms'); - expect(detailM.textContent).to.be.equal('Desktop + Mobile'); - expect(buttons.length).to.be.equal(2); - expect(buttons[0].textContent).to.be.equal('Learn More'); - expect(buttons[1].textContent).to.be.equal('Save now'); - }); + expect(merchCard).to.exist; + expect(heading).to.exist; + expect(headingOne).to.exist; + expect(body).to.exist; + expect(detail).to.exist; + expect(actionMenu).to.exist; + expect(merchCard.getAttribute('variant')).to.be.equal('catalog'); + expect(merchCard.getAttribute('badge-background-color')).to.be.equal('#EDCC2D'); + expect(merchCard.getAttribute('badge-color')).to.be.equal('#000000'); + expect(merchCard.getAttribute('badge-text')).to.be.equal('LOREM IPSUM DOLOR'); + expect(merchCard.getAttribute('action-menu')).to.be.equal('true'); + expect(body.textContent).to.be.equal('Create gorgeous images, rich graphics, and incredible art. Save 10% for the first year. Ends Mar 20.See terms'); + expect(detail.textContent).to.be.equal('Desktop + Mobile'); + expect(buttons.length).to.be.equal(2); + expect(buttons[0].textContent).to.be.equal('Learn More'); + expect(buttons[1].textContent).to.be.equal('Save now'); + }); - it('Supports Catalog card without badge and action-menu', async () => { - document.body.innerHTML = await readFile({ path: './mocks/catalog.html' }); - await init(document.querySelector('.merch-card.catalog.empty-action-menu')); - const merchCard = document.querySelector('merch-card'); - const heading = merchCard.querySelector('h3[slot="heading-xs"]'); - const headingOne = merchCard.querySelector('h2[slot="heading-m"]'); - const body = merchCard.querySelector('div[slot="body-xs"]'); - const actionMenu = merchCard.querySelector('div[slot="action-menu-content"]'); - const detail = merchCard.querySelector('h5[slot="detail-m"]'); - const footer = merchCard.querySelector('div[slot="footer"]'); - const buttons = footer.querySelectorAll('.con-button'); - console.log('MERCH_CARD-empty-action', merchCard); - expect(merchCard).to.exist; - expect(heading).to.exist; - expect(headingOne).to.exist; - expect(body).to.exist; - expect(detail).to.exist; - expect(actionMenu).to.not.exist; - expect(merchCard.getAttribute('variant')).to.be.equal('catalog'); - expect(merchCard.getAttribute('badge')).to.not.exist; - expect(merchCard.getAttribute('action-menu')).to.not.exist; - // expect(merchCard.getAttribute('image')).to.exist; - expect(body.textContent).to.be.equal('Create gorgeous images, rich graphics, and incredible art. Save 10% for the first year. Ends Mar 20.See terms'); - expect(detail.textContent).to.be.equal('Desktop + Mobile'); - expect(buttons.length).to.be.equal(2); - expect(buttons[0].textContent).to.be.equal('Learn More'); - expect(buttons[1].textContent).to.be.equal('Save now'); - }); + it('Supports Catalog card without badge', async () => { + document.body.innerHTML = await readFile({ path: './mocks/catalog.html' }); + const merchCard = await init(document.querySelector('.merch-card.catalog.empty-badge')); + const heading = merchCard.querySelector('h2[slot="heading-m"]'); + const headingOne = merchCard.querySelector('h3[slot="heading-xs"]'); + const body = merchCard.querySelector('div[slot="body-xs"]'); + const actionMenu = merchCard.querySelector('div[slot="action-menu-content"]'); + const detail = merchCard.querySelector('h5[slot="detail-m"]'); + const footer = merchCard.querySelector('div[slot="footer"]'); + const buttons = footer.querySelectorAll('.con-button'); - it('Supports Catalog card with badge without action-menu', async () => { - document.body.innerHTML = await readFile({ path: './mocks/catalog.html' }); - await init(document.querySelector('.merch-card.catalog.empty-badge.action-menu-exist')); - const merchCard = document.querySelector('merch-card'); - const heading = merchCard.querySelector('h2[slot="heading-m"]'); - const headingOne = merchCard.querySelector('h3[slot="heading-xs"]'); - const body = merchCard.querySelector('div[slot="body-xs"]'); - const actionMenu = merchCard.querySelector('div[slot="action-menu-content"]'); - const detail = merchCard.querySelector('h5[slot="detail-m"]'); - const footer = merchCard.querySelector('div[slot="footer"]'); - const buttons = footer.querySelectorAll('.con-button'); - console.log('MERCH_CARD-action', merchCard); - expect(merchCard).to.exist; - expect(heading).to.exist; - expect(headingOne).to.exist; - expect(body).to.exist; - expect(detail).to.exist; - expect(actionMenu).to.not.exist; - expect(merchCard.getAttribute('variant')).to.be.equal('catalog'); - expect(merchCard.getAttribute('badge')).to.not.exist; - expect(merchCard.getAttribute('action-menu')).to.not.exist; - // expect(merchCard.getAttribute('image')).to.exist; - expect(body.textContent).to.be.equal('Create gorgeous images, rich graphics, and incredible art. Save 10% for the first year. Ends Mar 20.See terms'); - expect(detail.textContent).to.be.equal('Desktop + Mobile'); - expect(buttons.length).to.be.equal(2); - expect(buttons[0].textContent).to.be.equal('Learn More'); - expect(buttons[1].textContent).to.be.equal('Save now'); - }); + expect(merchCard).to.exist; + expect(heading).to.exist; + expect(headingOne).to.exist; + expect(body).to.exist; + expect(detail).to.exist; + expect(actionMenu).to.exist; + expect(merchCard.getAttribute('variant')).to.be.equal('catalog'); + expect(merchCard.getAttribute('badge')).to.not.exist; + expect(merchCard.getAttribute('action-menu')).to.be.equal('true'); + expect(body.textContent).to.be.equal('Create gorgeous images, rich graphics, and incredible art. Save 10% for the first year. Ends Mar 20.See terms'); + expect(detail.textContent).to.be.equal('Desktop + Mobile'); + expect(buttons.length).to.be.equal(2); + expect(buttons[0].textContent).to.be.equal('Learn More'); + expect(buttons[1].textContent).to.be.equal('Save now'); }); - describe('UAR Card', () => { - before(async () => { - document.body.innerHTML = await readFile({ path: './mocks/uar-card.html' }); - }); - it('handles decorated
', async () => { - const cards = document.querySelectorAll('.merch-card'); - cards.forEach((card) => { - init(card); - }); - expect(cards[0].classList.contains('has-divider')).to.be.true; + it('Supports Catalog card without badge and action-menu', async () => { + document.body.innerHTML = await readFile({ path: './mocks/catalog.html' }); + const merchCard = await init(document.querySelector('.merch-card.catalog.empty-action-menu')); + const heading = merchCard.querySelector('h2[slot="heading-m"]'); + const headingOne = merchCard.querySelector('h3[slot="heading-xs"]'); + const body = merchCard.querySelector('div[slot="body-xs"]'); + const actionMenu = merchCard.querySelector('div[slot="actionMenuContent"]'); + const detail = merchCard.querySelector('h5[slot="detail-m"]'); + const footer = merchCard.querySelector('div[slot="footer"]'); + const buttons = footer.querySelectorAll('.con-button'); + + expect(merchCard).to.exist; + expect(heading).to.exist; + expect(headingOne).to.exist; + expect(body).to.exist; + expect(detail).to.exist; + expect(actionMenu).to.not.exist; + expect(merchCard.getAttribute('variant')).to.be.equal('catalog'); + expect(merchCard.getAttribute('badge')).to.not.exist; + expect(merchCard.getAttribute('action-menu')).to.not.exist; + expect(body.textContent).to.be.equal('Create gorgeous images, rich graphics, and incredible art. Save 10% for the first year. Ends Mar 20.See terms'); + expect(detail.textContent).to.be.equal('Desktop + Mobile'); + expect(buttons.length).to.be.equal(2); + expect(buttons[0].textContent).to.be.equal('Learn More'); + expect(buttons[1].textContent).to.be.equal('Save now'); + }); + + it('Supports Catalog card with badge without action-menu', async () => { + document.body.innerHTML = await readFile({ path: './mocks/catalog.html' }); + const merchCard = await init(document.querySelector('.merch-card.catalog.empty-badge.action-menu-exist')); + const heading = merchCard.querySelector('h2[slot="heading-m"]'); + const headingOne = merchCard.querySelector('h3[slot="heading-xs"]'); + const body = merchCard.querySelector('div[slot="body-xs"]'); + const actionMenu = merchCard.querySelector('div[slot="actionMenuContent"]'); + const detail = merchCard.querySelector('h5[slot="detail-m"]'); + const footer = merchCard.querySelector('div[slot="footer"]'); + const buttons = footer.querySelectorAll('.con-button'); + + expect(merchCard).to.exist; + expect(heading).to.exist; + expect(headingOne).to.exist; + expect(body).to.exist; + expect(detail).to.exist; + expect(actionMenu).to.not.exist; + expect(merchCard.getAttribute('variant')).to.be.equal('catalog'); + expect(merchCard.getAttribute('badge-background-color')).to.be.equal('#EDCC2D'); + expect(merchCard.getAttribute('badge-color')).to.be.equal('#000000'); + expect(merchCard.getAttribute('badge-text')).to.be.equal('LOREM IPSUM DOLOR'); + expect(merchCard.getAttribute('action-menu')).to.not.exist; + expect(body.textContent).to.be.equal('Create gorgeous images, rich graphics, and incredible art. Save 10% for the first year. Ends Mar 20.See terms'); + expect(detail.textContent).to.be.equal('Desktop + Mobile'); + expect(buttons.length).to.be.equal(2); + expect(buttons[0].textContent).to.be.equal('Learn More'); + expect(buttons[1].textContent).to.be.equal('Save now'); + }); + + it('Parses the filters and types', async () => { + document.body.innerHTML = await readFile({ path: './mocks/catalog.html' }); + const merchCard = await init(document.querySelector('.merch-card.catalog.tags')); + expect(merchCard.filters).to.be.deep.equal({ + all: { order: undefined, size: undefined }, + 'creativity-design': { order: undefined, size: undefined }, + 'graphic-design': { order: undefined, size: undefined }, + photo: { order: undefined, size: undefined }, }); + expect(merchCard.types).to.equal('web,tablet,desktop'); + }); + + it('Supports intro-pricing card', async () => { + document.body.innerHTML = await readFile({ path: './mocks/intro-pricing.html' }); + const merchCard = await init(document.querySelector('.merch-card')); + const heading = merchCard.querySelector('h2[slot="heading-m"]'); + const headingXs = merchCard.querySelector('h3[slot="heading-xs"]'); + const body = merchCard.querySelector('div[slot="body-xs"]'); + const detailBg = merchCard.querySelector('h4[slot="body-xxs"]'); + const footer = merchCard.querySelector('div[slot="footer"]'); + const buttons = footer.querySelectorAll('.con-button'); + + expect(merchCard).to.exist; + expect(heading).to.exist; + expect(headingXs).to.exist; + expect(body).to.exist; + expect(detailBg).to.exist; + expect(merchCard.getAttribute('variant')).to.be.equal('catalog'); + expect(merchCard.getAttribute('badge-background-color')).to.be.equal('#EDCC2D'); + expect(merchCard.getAttribute('badge-color')).to.be.equal('#000000'); + expect(merchCard.getAttribute('badge-text')).to.be.equal('LOREM IPSUM DOLOR'); + expect(merchCard.classList.contains('intro-pricing')).to.be.true; + expect(body.textContent).to.be.equal('Create gorgeous images, rich graphics, and incredible art. Save 10% for the first year. Ends Mar 20.'); + expect(buttons.length).to.be.equal(2); + expect(buttons[0].textContent).to.be.equal('Learn More'); + expect(buttons[1].textContent).to.be.equal('Save now'); + }); +}); + +describe('UAR Card', () => { + it('handles decorated
', async () => { + document.body.innerHTML = await readFile({ path: './mocks/uar-card.html' }); + const cards = document.querySelectorAll('.merch-card'); + for (const card of cards) { + await init(card); + } + const merchCard = document.querySelector('merch-card'); + expect(merchCard.classList.contains('has-divider')).to.be.true; + }); +}); + +describe('Section metadata rules', async () => { + before(async () => { + document.body.innerHTML = await readFile({ path: './mocks/card-section-metadata.html' }); + }); + + it('should not add default merch-card grid styles', async () => { + const block = document.getElementById('with2ColumnsGrid'); + const merchCard = await init(block); + expect(merchCard.parentElement.className).to.not.match(/three-merch-cards/); + }); + + it('should add default merch-card grid styles', async () => { + const block = document.getElementById('withDefault3ColumnsGrid'); + const merchCard = await init(block); + expect(merchCard.parentElement.className).to.match(/three-merch-cards/); }); }); diff --git a/test/blocks/merch-card/merch-offer-select.test.js b/test/blocks/merch-card/merch-offer-select.test.js new file mode 100644 index 0000000000..cf3e85feb7 --- /dev/null +++ b/test/blocks/merch-card/merch-offer-select.test.js @@ -0,0 +1,70 @@ +import { readFile } from '@web/test-runner-commands'; +import { expect } from '@esm-bundle/chai'; + +const { default: initCard } = await import('../../../libs/blocks/merch-card/merch-card.js'); +const delay = (duration = 100) => new Promise((resolve) => { setTimeout(resolve, duration); }); + +describe('Merch Offer Select', () => { + before(async () => { + document.body.innerHTML = await readFile({ path: './mocks/acrobat-card.html' }); + await initCard(document.querySelector('.acrobat')); + await delay(); + }); + + function validateMerchOffer(offer, selected, text, badgeText, osi, description) { + expect(offer.hasAttribute('selected')).to.equal(selected === 'true'); + expect(offer.getAttribute('aria-checked')).to.equal(selected); + expect(offer.getAttribute('text')).to.equal(text); + expect(offer.getAttribute('badge-text')).to.equal(badgeText); + expect(offer.getAttribute('tabindex')).to.equal('0'); + const price = offer.get('price'); + expect(price.dataset.wcsOsi).to.equal(osi); + expect(price.getAttribute('slot')).to.equal('price'); + const cta = offer.get('cta'); + expect(cta.dataset.wcsOsi).to.equal(osi); + expect(cta.getAttribute('slot')).to.equal('cta'); + if (description) { + expect(offer.get('description').innerText).to.equal(description); + } else { + expect(offer.get('description')).not.to.exist; + } + } + + function validateMerchCard(card, badge, description, osi) { + if (badge) { + expect(card.shadowRoot.querySelector('div.plans-badge').innerText).to.equal(badge); + } else { + expect(card.shadowRoot.querySelector('div.plans-badge')).not.to.exist; + } + expect(card.querySelector('div[slot="body-xs"] p[slot="description"]').innerText).to.equal(description); + expect(card.querySelector('div[slot="footer"] a[is="checkout-link"]').dataset.wcsOsi).to.equal(osi); + expect(card.querySelector('div[slot="body-xs"] span[is="inline-price"]').dataset.wcsOsi).to.equal(osi); + } + + it('Should render offer select and inital card state', async () => { + const merchCard = document.querySelector('merch-card'); + const merchOffers = merchCard.querySelector('merch-offer-select').querySelectorAll('merch-offer'); + expect(merchOffers.length).to.equal(3); + validateMerchOffer(merchOffers[0], 'true', 'Annual, monthly payment', 'Recommended', '6WK1gybjBe2EKcq0HI0WvbsoiKOri2yRAwS9t_kGHoE', null); + validateMerchOffer(merchOffers[1], 'false', 'Annual, one-time payment', 'Best Offer', 'gr3e95wowwDvLJyphdXmBf9-vTub0fhbdxQfGJ7tdhA', 'New Description'); + validateMerchCard(merchCard, 'Recommended', 'Access advanced PDF.', '6WK1gybjBe2EKcq0HI0WvbsoiKOri2yRAwS9t_kGHoE'); + }); + + it('Should select and render second offer', async () => { + const merchCard = document.querySelector('merch-card'); + merchCard.querySelectorAll('merch-offer')[1].click(); + await delay(); + + const merchOffers = merchCard.querySelector('merch-offer-select').querySelectorAll('merch-offer'); + validateMerchOffer(merchOffers[0], 'false', 'Annual, monthly payment', 'Recommended', '6WK1gybjBe2EKcq0HI0WvbsoiKOri2yRAwS9t_kGHoE', null); + validateMerchOffer(merchOffers[1], 'true', 'Annual, one-time payment', 'Best Offer', 'gr3e95wowwDvLJyphdXmBf9-vTub0fhbdxQfGJ7tdhA', 'New Description'); + validateMerchCard(merchCard, 'Best Offer', 'New Description', 'gr3e95wowwDvLJyphdXmBf9-vTub0fhbdxQfGJ7tdhA'); + }); + + it('Should remove badge and set back description', async () => { + const merchCard = document.querySelector('merch-card'); + merchCard.querySelectorAll('merch-offer')[2].click(); + await delay(); + validateMerchCard(merchCard, null, 'Access advanced PDF.', 'BWGlzrQG6jgkf-_zPJm55M5QpAyb4skYi05BizQIJ3U'); + }); +}); diff --git a/test/blocks/merch-card/mocks/acrobat-card.html b/test/blocks/merch-card/mocks/acrobat-card.html new file mode 100644 index 0000000000..b1411306b5 --- /dev/null +++ b/test/blocks/merch-card/mocks/acrobat-card.html @@ -0,0 +1,63 @@ +
+
+
+
+
+
#EDCC2D, #000000
+
+
+
+
+

Acrobat Pro

+

Access advanced PDF.

+
    +
  • Annual, monthly payment +
      +
    • Recommended
    • +
    • + + US$ + + 19 + . + 99 + /mo + per license + + +
    • +
    • Buy now
    • +
    +
  • +
  • Annual, one-time payment +
      +
    • Best Offer
    • +
    • + + US$ + + 149 + . + 88 + /yr + per license + + +
    • +
    • Buy now
    • +
    • New Description
    • +
    +
  • +
  • Monthly, without commitment +
      +
    • US$29.99/moper license
    • +
    • try now
    • +
    +
  • +
+
+
+
+
+
+
diff --git a/test/blocks/merch-card/mocks/card-section-metadata.html b/test/blocks/merch-card/mocks/card-section-metadata.html new file mode 100644 index 0000000000..6d7a07f5fd --- /dev/null +++ b/test/blocks/merch-card/mocks/card-section-metadata.html @@ -0,0 +1,52 @@ + +
+
+
+
+
+ + + + + + +

INDIVIDUALS

+

Get 10% off Photoshop.

+
Desktop + Mobile
+

Create gorgeous images, rich graphics, and incredible art. Save 10% for the first year. Ends Mar 20.

+

See terms

+

Learn More Save now

+
+
+
+ +
+ +
+
+
+
+ + + + + + +

INDIVIDUALS

+

Get 10% off Photoshop.

+
Desktop + Mobile
+

Create gorgeous images, rich graphics, and incredible art. Save 10% for the first year. Ends Mar 20.

+

See terms

+

Learn More Save now

+
+
+
+
+
diff --git a/test/blocks/merch-card/mocks/catalog.html b/test/blocks/merch-card/mocks/catalog.html index 26468d66df..3dc6820f12 100644 --- a/test/blocks/merch-card/mocks/catalog.html +++ b/test/blocks/merch-card/mocks/catalog.html @@ -26,7 +26,7 @@ -

INDIVIDUALS

+

INDIVIDUALS

Get 10% off Photoshop.

Desktop + Mobile

Create gorgeous images, rich graphics, and incredible art. Save 10% for the first year. Ends Mar 20.

@@ -106,4 +106,32 @@
Desktop + Mobile
+
+
+
+ + + + + + +

Photoshop

+

US$79.99/mo

+
Desktop + Mobile
+

Create gorgeous images, rich graphics, and incredible art. Save 10% for the first year. Ends Mar 20.

+

See terms

+

Learn More Save now

+
+
+
+
+

catalog:categories/creativity-design

+

catalog:categories/creativity-design/graphic-design

+

catalog:categories/creativity-design/photo

+

catalog:types/web

+

catalog:types/tablet

+

catalog:types/desktop

+
+
+
diff --git a/test/blocks/merch-card/mocks/intro-pricing.html b/test/blocks/merch-card/mocks/intro-pricing.html new file mode 100644 index 0000000000..3f2b2720dd --- /dev/null +++ b/test/blocks/merch-card/mocks/intro-pricing.html @@ -0,0 +1,23 @@ +
+
+
+
#EDCC2D, #000000
+
LOREM IPSUM DOLOR
+
+
+
+ + + + + + +

Photoshop

+

US$79.99/mo

+

Desktop + Mobile

+

Create gorgeous images, rich graphics, and incredible art. Save 10% for the first year. Ends Mar 20.

+

Learn More Save now

+
+
+
+
diff --git a/test/blocks/merch-card/mocks/plans-card.html b/test/blocks/merch-card/mocks/plans-card.html index 6c270af50e..38c17af31a 100644 --- a/test/blocks/merch-card/mocks/plans-card.html +++ b/test/blocks/merch-card/mocks/plans-card.html @@ -1,10 +1,23 @@
+ +
+

Add a 30-day free trial of Adobe Stock.*

+ puf + abm + m2m +
+
+

Add a 30-day free trial of Adobe Stock.*

+ puf + abm +
+
-
+
#EDCC2D, #000000
LOREM IPSUM DOLOR
@@ -23,9 +36,8 @@ -

Lorem ipsum dolor sit amet

-

Lorem ipsum dolor

-

Lorem ipsum dolor sit

+

Lorem ipsum dolor sit amet

+

Lorem ipsum dolor

Maecenas porttitor enim.

Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis urna. Nunc viverra imperdiet enim.

Maecenas

@@ -33,9 +45,35 @@
Maecenas porttitor enim.

Learn More Save now

+
+ +
-
Lorem ipsum dolor sit amet
- +
#EDCC2D, #000000
+
LOREM IPSUM DOLOR
+
+
+
+ + + + + + + + + + + + +

Lorem ipsum dolor sit amet

+

Lorem ipsum dolor

+
Maecenas porttitor enim.
+

Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis urna. Nunc viverra imperdiet enim.

+

Maecenas

+

See terms about lorem ipsum

+

Learn More Save now

+
@@ -57,9 +95,9 @@
Maecenas porttitor enim.
-

Lorem ipsum dolor sit lorem-ipsum-dolor-sit-amet1

-

Lorem ipsum dolor

-

Lorem ipsum dolor sit

+

Lorem ipsum dolor sit amet

+

Lorem ipsum dolor

+
Maecenas porttitor enim.

Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis urna. Nunc viverra imperdiet enim.

See terms about lorem ipsum

Learn More Save now

diff --git a/test/blocks/merch-card/mocks/special-offers.html b/test/blocks/merch-card/mocks/special-offers.html index 4f9b337728..4ff855ea6e 100644 --- a/test/blocks/merch-card/mocks/special-offers.html +++ b/test/blocks/merch-card/mocks/special-offers.html @@ -12,11 +12,35 @@ -

INDIVIDUALS

-

Get 10% off Photoshop.

+

INDIVIDUALS

+

Get 10% off Photoshop.

+

Create gorgeous images, rich graphics, and incredible art. Save 10% for the first year. Ends Mar 20.

+

See terms

+

Learn More Save now

+
+
+ +
+
+
#EDCC2D, #000000
+
LOREM IPSUM DOLOR
+
+
+
+ + + + + + +

INDIVIDUALS

+

Get 10% off Photoshop.

Create gorgeous images, rich graphics, and incredible art. Save 10% for the first year. Ends Mar 20.

Best for:

See terms

+

/--#000000

+

Create gorgeous images, rich graphics, and incredible art. Save 10% for the first year. Ends Mar 20.

+

--/

Learn More Save now

diff --git a/test/blocks/merch-card/mocks/uar-card.html b/test/blocks/merch-card/mocks/uar-card.html index 07ff5177df..96d2e587c7 100644 --- a/test/blocks/merch-card/mocks/uar-card.html +++ b/test/blocks/merch-card/mocks/uar-card.html @@ -1,7 +1,7 @@
- +

UAR CARDS

- +