diff --git a/.eslintignore b/.eslintignore index f391acf72..685ba57c6 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,4 +1,8 @@ helix-importer-ui -tools/sitemap -solutions/plugins/experimentation -solutions/vendor +_src/scripts/lib-franklin-api.js +_src/scripts/vendor +_src/scripts/zuora.js +_src/vendor +_src/plugins +_src/scripts/libs/** +tools diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 000000000..3f4db9dbb --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,5 @@ +# These owners will be the default owners for everything in +# the repo. Unless a later match takes precedence, +# @global-owner1 and @global-owner2 will be requested for +# review when someone opens a pull request. +* @enake diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index bd93f8e30..5dc84d4e3 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -3,5 +3,5 @@ Please always provide the [GitHub issue(s)](../issues) your PR is for, as well a Fix # Test URLs: -- Before: https://main--bitdefender--hlxsites.hlx.page/solutions/ -- After: https://--bitdefender--hlxsites.hlx.page/solutions/ \ No newline at end of file +- Before: https://main--www-websites--bitdefender.hlx.page/zh-hk/ +- After: https://--www-websites--bitdefender.hlx.page/zh-hk/ diff --git a/.github/workflows/run-tests.yaml b/.github/workflows/run-tests.yaml index 0b534167e..24ae18ff2 100644 --- a/.github/workflows/run-tests.yaml +++ b/.github/workflows/run-tests.yaml @@ -16,20 +16,20 @@ jobs: - name: Use node.js uses: actions/setup-node@v3 with: - node-version: '16' #required for npm 8 or later. + node-version: '20' #required for npm 8 or later. - run: npm install - run: npm run lint env: CI: true - ghost_inspector_tests: - needs: linting - runs-on: ubuntu-latest - steps: - - name: execute Ghost Inspector test - uses: docker://ghostinspector/cli - with: - args: suite execute ${{ secrets.GI_SUITE }} \ - --apiKey ${{ secrets.GI_API_KEY }} \ - --branchName ${{ env.BRANCH_NAME }} \ - --errorOnFail \ - --errorOnScreenshotFail + # ghost_inspector_tests: + # needs: linting + # runs-on: ubuntu-latest + # steps: + # - name: execute Ghost Inspector test + # uses: docker://ghostinspector/cli + # with: + # args: suite execute ${{ secrets.GI_SUITE }} \ + # --apiKey ${{ secrets.GI_API_KEY }} \ + # --branchName ${{ env.BRANCH_NAME }} \ + # --errorOnFail \ + # --errorOnScreenshotFail diff --git a/404.html b/404.html index 165f8c43b..0691fefe3 100644 --- a/404.html +++ b/404.html @@ -9,12 +9,15 @@ - + - + + - + @@ -146,7 +149,7 @@

Page Not Found

The page you are looking for might have been removed, had its name changed, or is temporarily unavailable.

+
diff --git a/solutions/blocks/accordion/accordion.css b/_src/blocks/accordion/accordion.css similarity index 78% rename from solutions/blocks/accordion/accordion.css rename to _src/blocks/accordion/accordion.css index 758603d83..7916b0ba6 100644 --- a/solutions/blocks/accordion/accordion.css +++ b/_src/blocks/accordion/accordion.css @@ -2,13 +2,23 @@ padding: 0 var(--body-padding); } +.accordion-container > .default-content-wrapper:last-of-type p.info-button-container a { + display: flex; + text-align: center; + margin-top: 2em; +} + +.accordion-container > .default-content-wrapper:last-of-type p.info-button-container a::before { + margin-right: 5px; +} + .accordion { cursor: pointer; } .accordion .accordion-item { margin: 16px 0; - padding: 18px 54px; + padding: 1em 2em; border-radius: 10px; border-color: rgb(229 231 235); border-width: 0; @@ -82,6 +92,7 @@ .accordion-item-content ul { padding-left: 20px; + margin-top: 5px; } .accordion-item-content li { @@ -92,9 +103,15 @@ } .accordion-item-content p { - font-size: 16px; + color: #3c3c3c; + font-size: var(--body-font-size-m); word-break: break-word; max-width: 1110px; + margin-top: 5px; +} + +.accordion-item-content p strong { + color: #3c3c3c; } .accordion-item.expanded .accordion-item-content { @@ -108,9 +125,12 @@ } @media (min-width: 992px) { /* desktop */ - .accordion .accordion-item-header h3 { - font-size: var(--heading-font-size-s); + font-size: var(--body-font-size-xl); + } + + .accordion.smaller-text .accordion-item-content p { + font-size: var(--body-font-size-s)!important; } .accordion.terms-of-use .accordion-item-header h3 { @@ -129,7 +149,6 @@ max-width: var(--section-large-desktop-max-width); padding: 0 var(--section-large-desktop-padding); } - } .accordion.faq .accordion-item, @@ -162,3 +181,21 @@ margin-bottom: 0; } +@media (max-width: 500px) { + .accordion .accordion-item { + padding: 1em; + } +} + +@media (max-width: 768px) { + .accordion-item-content p { + font-size: var(--body-font-size-s); + } +} + +@media (max-width: 992px) { + .accordion-container .default-content-wrapper { + padding-top: 0; + padding-bottom: 0; + } +} \ No newline at end of file diff --git a/solutions/blocks/accordion/accordion.js b/_src/blocks/accordion/accordion.js similarity index 100% rename from solutions/blocks/accordion/accordion.js rename to _src/blocks/accordion/accordion.js diff --git a/solutions/blocks/awards-search/awards-search.css b/_src/blocks/awards-search/awards-search.css similarity index 98% rename from solutions/blocks/awards-search/awards-search.css rename to _src/blocks/awards-search/awards-search.css index d9fb85468..ec750ecad 100644 --- a/solutions/blocks/awards-search/awards-search.css +++ b/_src/blocks/awards-search/awards-search.css @@ -102,8 +102,8 @@ main .section .awards-search .awards-results-container .award-item-container h2 width: 1.5rem; height: 1.3125rem; /* stylelint-disable-next-line property-no-vendor-prefix */ - -webkit-mask: url('/solutions/icons/arrow-right.svg'); - mask: url('/solutions/icons/arrow-right.svg'); + -webkit-mask: url('/_src/icons/arrow-right.svg'); + mask: url('/_src/icons/arrow-right.svg'); background-color: var(--read-more-text-color); display: inline-block; opacity: 1; diff --git a/solutions/blocks/awards-search/awards-search.js b/_src/blocks/awards-search/awards-search.js similarity index 100% rename from solutions/blocks/awards-search/awards-search.js rename to _src/blocks/awards-search/awards-search.js diff --git a/_src/blocks/awards/awards.css b/_src/blocks/awards/awards.css new file mode 100644 index 000000000..9d0a150b5 --- /dev/null +++ b/_src/blocks/awards/awards.css @@ -0,0 +1,254 @@ +/* stylelint-disable no-descending-specificity */ +.awards-container { + display: flex; + justify-content: center; +} + +.awards-wrapper { + width: 100%; + display: flex; + flex-direction: column; + align-items: center; + max-width: 1300px; +} + +.awards-container .block.awards-component { + background-color: #edf9ff; + display: flex; + flex-direction: column; + align-items: center; + border-radius: 20px; +} + +.awards-container.we-container { + max-width: 100%; + padding-left: 20px; + padding-right: 20px; + margin-top: 15px; + margin-left: auto; + margin-right: auto; +} + +.awards-component { + display: flex; + justify-content: center; + align-items: center; + padding-top: 22px; + padding-bottom: 24px; + width: 100%; +} + +.awards-container h3 { + font-size: 32px; +} + +.awards-container h4 { + margin-bottom: 18px; + font-weight: normal; +} + +.awards-container .block.awards-component > div { + text-align: center; + display: flex; + align-items: center; + justify-content: center; +} + +.awards-component > div:nth-child(1) { + display: flex; + flex-direction: column; + align-items: center; + width: 85% !important; +} + +.awards-component > div:nth-child(2) { + display: flex; + flex-direction: column; + align-items: center; + width: 90%; +} + +.awards-component > div:nth-child(3) div { + display: flex; + flex-wrap: wrap; + justify-content: center; + width: 90%; + align-items: center; + gap: 4.5%; +} + + +.awards-component > div:nth-child(3) div img { + min-height: 56px; + height: auto; + max-width: 100%; + width: auto; + object-fit: contain; +} + +.awards-container .vsb picture{ + max-width: 90px; + min-width: 8%; +} + +.awards-container .vsb h3{ + margin-top: 0; + margin-bottom: 0; +} + +.awards-container .vsb p{ + margin-top: 0; + margin-bottom: 0; +} + +@media (min-width: 580px) { + .awards-component > div:nth-child(3) div { + max-width: 768px; + flex-wrap: nowrap; + } + + .vsb.awards-component > div:nth-child(3) div { + flex-wrap: wrap; + } +} + +@media (max-width: 768px) { + .awards-component > div:nth-child(3) div img { + min-height: auto; + margin: 5px 0; + } + + .awards-container h3 { + line-height: 38px; + } +} + +@media (min-width: 768px) { + .awards-component > div:nth-child(3) { + width: 95% !important; + } + + .awards-container .vsb picture{ + min-width: 100px; + } +} + +@media (min-width: 992px) { + .awards-component > div:nth-child(3) { + flex-wrap: nowrap; + justify-content: space-around; + width: 90%; + } + + .awards-wrapper .awards > div:nth-child(3) > div[data-valign="middle"] { + width: 100%; + display: flex; + justify-content: space-around; + align-items: center; + } + + .awards-component > div:nth-child(1) img { + width: 80px !important; + } + + .awards-component main .section.wide img { + height: auto; + object-fit: contain; + width: 70%; + } + + .awards-container .block.awards-component { + padding-bottom: 40px; + } + + .awards-container.we-container { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } + + .awards-container .vsb picture{ + min-width: 75px; + } + + .vsb.awards-component > div:nth-child(3) div { + flex-wrap: nowrap; + } +} + +@media (min-width: 1200px) { + .awards-component { + display: flex; + justify-content: center; + align-items: center; + padding-top: 32px; + padding-bottom: 24px; + } + + .awards-container .block.awards-component { + padding-bottom: 50px; + } + + .awards-component div[data-align="center"][data-valign="middle"] img { + width: 80px; + } + + .awards-container .block.awards-component > div { + text-align: center; + display: flex; + align-items: center; + } + + .awards-component > div:nth-child(1) { + display: flex; + flex-direction: column; + align-items: center; + width: 55%; + } + + .awards-component > div:nth-child(2) { + display: flex; + flex-direction: column; + align-items: center; + width: 50% !important; + } + + .awards-component > div:nth-child(3) { + display: flex; + flex-direction: row; + justify-content: space-around; + width: 70%; + } + + .awards-component h3 { + font: normal normal bold 32px/38px Arial, sans-serif; + max-width: 726px; + margin-bottom: 0; + } + + .awards-component h4 { + font-size: 18px; + font-weight: normal; + line-height: 25px; + margin-bottom: 35px; + margin-top: 14px; + } + + .awards-container.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + } + + .awards-container .vsb picture{ + min-width: 100px; +} +} + +@media (min-width: 1600px) { + .awards-containe.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + } +} diff --git a/_src/blocks/awards/awards.js b/_src/blocks/awards/awards.js new file mode 100644 index 000000000..58d8c2b72 --- /dev/null +++ b/_src/blocks/awards/awards.js @@ -0,0 +1,13 @@ +// eslint-disable-next-line no-unused-vars +export default function decorate(block, options) { + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + const blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + } + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); +} diff --git a/_src/blocks/banner-vsb/banner-vsb.css b/_src/blocks/banner-vsb/banner-vsb.css new file mode 100644 index 000000000..9150c61a2 --- /dev/null +++ b/_src/blocks/banner-vsb/banner-vsb.css @@ -0,0 +1,251 @@ +.banner-vsb-container, +.banner-vsb-container * { + box-sizing: border-box; +} + +.banner-vsb-container.section { + --gray-bg: rgb(246 246 246 / 100%); + --button-background-color: #eb0000; + --button-link-color: #fff; + --body-font-family: "Roboto", "roboto-normal-400-fallback", helvetica, ubuntu, roboto, noto, sans-serif; + --body-font-size-s: 16px; + --font-weight-bold: 500; + --button-hover-background-color: #d80000; + + padding: 0; +} + +/* imports from global */ +.banner-vsb-container a.button:any-link, input[type="submit"] { + font-family: var(--body-font-family); + font-size: var(--body-font-size-s); + font-style: normal; + font-weight: var(--font-weight-bold); + -webkit-font-smoothing: antialiased; + display: inline-flex; + align-items: center; + box-sizing: border-box; + text-decoration: none; + padding: 10px 26px 8px 28px; + text-align: center; + cursor: pointer; + color: var(--button-link-color); + background-color: var(--button-background-color); + border: 2px solid var(--button-background-color); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + border-radius: 8px; + height: fit-content; +} + +.banner-vsb-container a.button:hover, +.banner-vsb-container a.button:focus, +.banner-vsb-container input[type="submit"]:hover, +.banner-vsb-container input[type="submit"]:focus { + background-color: var(--button-hover-background-color); + border: 2px solid var(--button-hover-background-color); + cursor: pointer; +} + +.banner-vsb-container a.button span.button-text { + transition: transform .2s cubic-bezier(.4,0,.2,1); + transform: translate(0, 0); +} + +.banner-vsb-container a.button:hover span.button-text { + transform: translate(-10px, 0); +} + +.banner-vsb-container a.button::after, +.banner-vsb-container input[type="submit"]::after, +.banner-vsb-container main .section.link-right a::after { + content: ''; + width: 24px; + height: 24px; + /* stylelint-disable-next-line property-no-vendor-prefix */ + -webkit-mask:url('/_src/icons/arrow-right.svg'); + mask: url('/_src/icons/arrow-right.svg'); + background-color: var(--button-link-color); + display: inline-block; + transition: all .2s cubic-bezier(.4,0,.2,1); + transform: translateX(0); + opacity: 0; + margin-left: -10px; +} + +.banner-vsb-container a.button:hover::after, +.banner-vsb-container input[type="submit"]:hover::after { + transform: translateX(5px); + opacity: 1; +} + +.banner-vsb-container .banner-vsb-wrapper .block { + display: flex; + flex-direction: column; +} + +.banner-vsb-container h1 { + font: normal normal bold 32px / 36px "IBM Plex Sans", sans-serif; + color: #006EFF; +} + +.banner-vsb-container h2, +.banner-vsb-container h3, +.banner-vsb-container h4 { + font: normal normal bold 20px/24px "IBM Plex Sans", sans-serif; +} + +.banner-vsb-container p, +.banner-vsb-container div { + font: normal normal normal 20px/16px "IBM Plex Sans", sans-serif; +} + +.banner-vsb-container .rte-wrapper { + position: relative; + z-index: 4; +} + +.banner-vsb-container .video-wrapper { + height: 300px; + position: relative; +} + +.banner-vsb-container .video-wrapper video { + width: 100%; + height: 100%; + object-fit: cover; +} + +.banner-vsb-container .video-wrapper::before { + content: ''; + position: absolute; + width: 100%; + height: 100%; + background: linear-gradient(to bottom, var(--gray-bg), rgb(246 246 246 / 0%)); + z-index: 1; +} + +.banner-vsb-container .default-content-wrapper { + padding-top: 20px !important; + z-index: 4; + order: -1; +} + +.banner-vsb-container a.button:any-link:not(.modal, .primary) { + border: solid white 2px !important; + width: 100%; + justify-content: center; +} + +.banner-vsb-container.we-container { + margin: 0 auto; + max-width: 1332px; + padding: 0 20px; + position: relative; + width: 100% +} + +@media(max-width: 1599px) { + .banner-vsb-container.we-container { + max-width:1300px; + padding: 0 50px + } +} + +@media(max-width: 991px) { + .banner-vsb-container.we-container { + padding:0 20px + } +} + +.banner-vsb-container.we-container::after { + clear: both; + content: ""; + display: block +} + +.banner-vsb-container.we-container-fluid { + max-width: 100% +} + +@media (min-width: 768px) { + .banner-vsb-container.section { + border-radius: 20px; + overflow: hidden; + } + + .banner-vsb-container .video-wrapper, + .banner-vsb-container .default-content-wrapper { + width: 50%; + flex-shrink: 0; + } + + .banner-vsb-container .video-wrapper::before { + top: 0; + left: -1px; + background: linear-gradient(to right, var(--gray-bg), rgb(246 246 246 / 0%)); + } + + .banner-vsb-container .default-content-wrapper { + padding: 30px; + } + + .banner-vsb-container .banner-vsb-wrapper { + border-radius: 20px; + background: var(--gray-bg); + overflow: hidden; + } + + .banner-vsb-container .banner-vsb-wrapper .block { + flex-direction: row; + } + + .banner-vsb-container a.button:any-link:not(.modal, .primary) { + width: unset; + justify-content: unset; + display: inline-flex; + margin-right: 15px; + } +} + +@media (min-width: 992px) { + .banner-vsb-container h1 { + font: normal normal bold 48px/55px "IBM Plex Sans", sans-serif; + } + + .banner-vsb-container h2, + .banner-vsb-container h3, + .banner-vsb-container h4 { + font: normal normal bold 40px/52px "IBM Plex Sans", sans-serif; + } + + .banner-vsb-container { + height: 422px; + } + + .banner-vsb-container .banner-vsb-wrapper { + height: 100%; + } + + .banner-vsb-container .banner-vsb-wrapper .block { + height: 100%; + display: flex; + flex-direction: row; + } + + .banner-vsb-container .rte-wrapper { + width: 100%; + } + + .banner-vsb-container .video-wrapper { + height: 100%; + } + + .banner-vsb-container .default-content-wrapper { + padding-top: 0 !important; + height: 100%; + display: flex; + align-items: center; + } +} diff --git a/_src/blocks/banner-vsb/banner-vsb.js b/_src/blocks/banner-vsb/banner-vsb.js new file mode 100644 index 000000000..6b1a3b52a --- /dev/null +++ b/_src/blocks/banner-vsb/banner-vsb.js @@ -0,0 +1,74 @@ +import { decorateButtons } from '../../scripts/lib-franklin.js'; + +export default async function decorate(block, options) { + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + const blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + } + + const [rte, videoUrlEl] = [...block.children]; + + const videoUrl = videoUrlEl.textContent.trim(); + const videoFormat = videoUrl.split('.').pop(); + + // const blockDataset = getDatasetFromSection(block); + const { videoPlayerSettings, videoPlayerPoster } = block.closest('.section').dataset; + + function appendPreloadedVideo() { + const linkVideoEl = document.createElement('link'); + const linkVideoPosterEl = document.createElement('link'); + linkVideoEl.rel = 'preload'; + linkVideoEl.as = 'video'; + linkVideoEl.href = videoUrl; + linkVideoEl.type = `video/${videoFormat}`; + + linkVideoPosterEl.rel = 'preload'; + linkVideoPosterEl.as = 'image'; + linkVideoPosterEl.href = videoPlayerPoster; + + document.head.prepend(linkVideoPosterEl); + document.head.prepend(linkVideoEl); + } + + appendPreloadedVideo(); + + const formattedVideoSettings = videoPlayerSettings + .split(',') + .map((item) => { + let newStr = item; + if (newStr.includes('=')) { + newStr = item.replace('=', '="'); + newStr = `${newStr}"`; + + return newStr; + } + + return newStr.trim(); + }) + .join(' '); + + block.innerHTML = ` +
+ +
+
+ ${rte.innerHTML} +
+ `; + + block.querySelectorAll('.button-container > a').forEach((anchorEl) => { + anchorEl.target = '_blank'; + anchorEl.rel = 'noopener noreferrer'; + }); + + decorateButtons(block); + + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); +} diff --git a/solutions/blocks/barchart/barchart.css b/_src/blocks/barchart/barchart.css similarity index 70% rename from solutions/blocks/barchart/barchart.css rename to _src/blocks/barchart/barchart.css index 5564293f4..41fa391e8 100644 --- a/solutions/blocks/barchart/barchart.css +++ b/_src/blocks/barchart/barchart.css @@ -1,3 +1,7 @@ +.barchart-container .default-content-wrapper h2 { + font-size: var(--heading-font-size-l); +} + .barchart > ul { color: #3c3c3c; display: grid; @@ -19,25 +23,33 @@ box-shadow: 0 3px 8px 0 rgb(0 0 0 / 10%); display: flex; flex-direction: column; - padding: 30px 20px; + padding: 1em 2em; + margin: 7px; } .barchart.block h3 { line-height: 1.25; color: var(--text-color); - font-size: var(--body-font-size-m); - font-weight: 500; - margin-top: 0; + font-size: var(--body-font-size-xl); + font-weight: var(--font-weight-bold); + margin: 0; } - .barchart-body p { line-height: 1.25; - color: var(--text-color); + color: #3c3c3c; font-size: 14px; font-weight: 400; } +.barchart-body > p:first-of-type { + margin: 7px 0 2em; +} + +.barchart-body > p:last-of-type { + margin-top: 1.5em; +} + .barchart-body ul { display: flex; flex-wrap: wrap; @@ -58,14 +70,14 @@ font-weight: var(--font-weight-bold); } -.barchart-body li:nth-child(odd) { +.barchart-body li:nth-child(odd) { flex: 85%; line-height: 40px; position: relative; z-index: 1; } -.barchart-body li:nth-child(even) { +.barchart-body li:nth-child(even) { flex: 10%; text-align: right; padding: 0 10px 0 0; @@ -117,10 +129,9 @@ } @media (min-width: 990px) { /* desktop */ - .barchart-wrapper { max-width: var(--section-desktop-max-width); - padding: 0 var(--section-desktop-padding); + padding: 0 var(--section-desktop-padding-vertical); margin: 0 auto; } } @@ -131,3 +142,26 @@ padding: 0 var(--section-large-desktop-padding); } } + +@media (max-width: 990px) { /* desktop */ + .barchart.block h3 { + font-size: var(--body-font-size-m); + } + + .barchart > ul > li { + padding: 1em; + } +} + +@media (max-width: 768px) { + .barchart-container .default-content-wrapper h2 { + font-size: var(--heading-font-size-s); + } +} + +@media (max-width: 500px) { /* mobile */ + .barchart-container .default-content-wrapper { + padding-top: 0; + padding-bottom: 0; + } +} diff --git a/solutions/blocks/barchart/barchart.js b/_src/blocks/barchart/barchart.js similarity index 77% rename from solutions/blocks/barchart/barchart.js rename to _src/blocks/barchart/barchart.js index e866cb18d..7c51e1cf3 100644 --- a/solutions/blocks/barchart/barchart.js +++ b/_src/blocks/barchart/barchart.js @@ -10,7 +10,9 @@ export default function decorate(block) { ul.querySelectorAll('.barchart-body').forEach((container) => { const progressBars = container.querySelectorAll('ul li:nth-child(odd)'); progressBars.forEach((progressBar) => { - const value = (parseFloat(progressBar.nextElementSibling.textContent / 6) * 100).toFixed(2); + let valueAsString = progressBar.nextElementSibling.textContent; + valueAsString = valueAsString.replace(',', '.'); + const value = (parseFloat(valueAsString / 6) * 100).toFixed(2); progressBar.style.setProperty('--bar-width', `${value}%`); }); }); diff --git a/_src/blocks/big-teaser-section/big-teaser-section.css b/_src/blocks/big-teaser-section/big-teaser-section.css new file mode 100644 index 000000000..c2fd416b1 --- /dev/null +++ b/_src/blocks/big-teaser-section/big-teaser-section.css @@ -0,0 +1,119 @@ +.big-teaser-section-container { + background: white; + color: black; +} + +.big-teaser-section-container .default-content-wrapper { + display: flex; + flex-direction: column; +} + +.big-teaser-section-container .rte { + order: 1; + margin-top: 15px; +} + +.big-teaser-section-container .rte em { + color: #006EFF; + font-style: normal; +} + +.big-teaser-section-container .imgs-wrapper { + position: relative; + height: 300px; + border-radius: 15px; + overflow: hidden; +} + +.big-teaser-section-container .main-img { + width: 100%; + height: 100%; +} + + +.big-teaser-section-container .second-img { + position: absolute; + top: 0; + right: 0; + height: 100%; +} + + +@media screen and (min-width: 768px) { + .big-teaser-section-container.pb-0 { + padding-bottom: 0; + } + + .big-teaser-section-container.pt-1 { + padding-top: 1em; + } + + .big-teaser-section.block { + position: relative; + } + + .big-teaser-section-container .wrapper { + position: relative; + display: flex; + align-items: center; + } + + .big-teaser-section.reverted .wrapper { + flex-direction: row-reverse; + } + + .big-teaser-section-container .rte { + position: relative; + z-index: 1; + } + + .big-teaser-section.reverted .wrapper .rte { + margin-right: 60px; + } + + .big-teaser-section-container .imgs-wrapper { + width: 100%; + height: 450px; + top: 0; + margin: 0; + } + + .big-teaser-section-container .imgs-wrapper::before { + content: ''; + width: 100%; + height: 100%; + display: block; + position: absolute; + } +} + +@media screen and (min-width: 992px) { + .big-teaser-section-container p { + line-height: 1.3; + } + + .big-teaser-section-container .default-content-wrapper { + flex-direction: row; + align-items: unset; + } + + .big-teaser-section-container .default-content-wrapper > * { + width: calc(50% - 60px); + flex-shrink: 0; + } + + .big-teaser-section-container .default-content-wrapper > *:last-child { + margin-right: 60px; + } + + .big-teaser-section-container .imgs-wrapper { + height: 550px; + } + + .big-teaser-section-container .rte { + display: flex; + flex-direction: column; + justify-content: center; + margin-top: unset; + } +} diff --git a/_src/blocks/big-teaser-section/big-teaser-section.js b/_src/blocks/big-teaser-section/big-teaser-section.js new file mode 100644 index 000000000..a0cb5a757 --- /dev/null +++ b/_src/blocks/big-teaser-section/big-teaser-section.js @@ -0,0 +1,38 @@ +import { getDatasetFromSection } from '../../scripts/utils/utils.js'; + +export default async function decorate(block) { + const [richTextEl, imageOnTopEl] = [...block.children]; + + const blockDataset = getDatasetFromSection(block); + const { desktopPicture, mobilePicture } = blockDataset; + + const picture = document.createElement('picture'); + const img = document.createElement('img'); + img.setAttribute('src', `${mobilePicture}?format=webply&optimize=medium`); + img.setAttribute('alt', 'picture'); + + const desktopSource = document.createElement('source'); + desktopSource.setAttribute('media', '(min-width: 768px)'); + desktopSource.setAttribute('type', 'image/webp'); + desktopSource.setAttribute('srcset', `${desktopPicture}?format=webply&optimize=medium`); + + picture.prepend(img); + picture.prepend(desktopSource); + + block.innerHTML = ` +
+
${richTextEl.children[0].innerHTML}
+ +
+
+ ${picture.outerHTML} +
+ + ${imageOnTopEl.querySelector('picture')} +
+ ${imageOnTopEl.querySelector('picture')?.innerHTML} +
+
+
+ `; +} diff --git a/_src/blocks/bitdef-vs-brands/bitdef-vs-brands.css b/_src/blocks/bitdef-vs-brands/bitdef-vs-brands.css new file mode 100644 index 000000000..34e3f0635 --- /dev/null +++ b/_src/blocks/bitdef-vs-brands/bitdef-vs-brands.css @@ -0,0 +1,212 @@ +/* stylelint-disable no-descending-specificity */ +.bitdef-vs-brands { + display: flex; + flex-direction: column; + align-items: center; +} + +.bitdef-vs-brands .heading-container { + text-align: center; + max-width: 420px; +} + +.bitdef-vs-brands .new-container { + display: flex; + flex-direction: column; + align-items: center; +} + +.bitdef-vs-brands-container.we-container { + max-width: 100%; + padding-left: 20px; + padding-right: 20px; + margin-top: 15px; + margin-left: auto; + margin-right: auto; +} + +.bitdef-vs-brands-wrapper h2 { + font: normal normal bold 32px/37px Arial, sans-serif; +} + +.bitdef-vs-brands-wrapper h3 { + margin-bottom: 6px; + margin-top: 5px; + font: normal normal bold 24px Arial, sans-serif; +} + +.bitdef-vs-brands-wrapper .row-2 { + margin-bottom: 22px; + font-size: 14px; +} + +.bitdef-vs-brands-wrapper .table-container { + padding: 20px; + background-color: #f8f8f8; + border-radius: 16px; + max-width: 410px; + margin-bottom: 50px; +} + +.bitdef-vs-brands-wrapper table .blue-background p { + background-color: #005bd5; + color: white; + padding: 9px; + margin-top: 4px; + margin-bottom: 4px; + font: normal normal bold 14px/14px Arial, sans-serif; +} + +.bitdef-vs-brands-wrapper table .grey-background p { + background-color: #dedede; + padding: 9px; + margin-top: 4px; + margin-bottom: 4px; + font: normal normal normal 14px/14px Arial, sans-serif; +} + +.bitdef-vs-brands-wrapper table .blue-background p:nth-child(1) { + width: 100%; + border-radius: 8px 0 0 8px; +} + +.bitdef-vs-brands-wrapper table .blue-background p:nth-child(2) { + border-radius: 0 8px 8px 0; +} + +.bitdef-vs-brands-wrapper table .grey-background p:nth-child(1) { + width: 100%; + border-radius: 8px 0 0 8px; +} + +.bitdef-vs-brands-wrapper table .grey-background p:nth-child(2) { + border-radius: 0 8px 8px 0; +} + +.bitdef-vs-brands-wrapper table .same-line { + display: flex; + animation: increaseWidth 1s forwards; + width: 0; +} + +.bitdef-vs-brands-wrapper table .same-line:nth-child(1) { + margin-right: auto; +} + +.bitdef-vs-brands-wrapper .same-line { + animation: none; +} + +.bitdef-vs-brands-wrapper .same-line.animate { + animation: increaseWidth 1s forwards; +} + +.bitdef-vs-brands .row-2 > .column-0 { + padding-bottom: 14px; + font: normal normal normal 14px/18px Arial, sans-serif; +} + +.bitdef-vs-brands .row-6 > .column-0 { + padding-top: 14px; + font: normal normal normal 12px/14px Arial, sans-serif; +} + +@keyframes increase-width-row1 { + from { + width: 0; + } + + to { + width: 95%; + } +} + +/* Keyframes for the second row animation */ +@keyframes increase-width-row2 { + from { + width: 0; + } + + to { + width: 90%; + } +} + +/* Keyframes for the third row animation */ +@keyframes increase-width-row3 { + from { + width: 0; + } + + to { + width: 85%; + } +} + +/* Apply different animations to each row */ +.bitdef-vs-brands-wrapper table .row-3 .same-line.animate-row1 { + animation: increase-width-row1 1s forwards; +} + +.bitdef-vs-brands-wrapper table .row-4 .same-line.animate-row2 { + animation: increase-width-row2 1s forwards; +} + +.bitdef-vs-brands-wrapper table .row-5 .same-line.animate-row3 { + animation: increase-width-row3 1s forwards; +} + +.bitdef-vs-brands-wrapper img { + max-width: 32px; /* Adjust as needed */ + height: auto; /* Maintain aspect ratio */ +} + +@media (min-width: 768px) { + .bitdef-vs-brands-wrapper .heading-container { + max-width: 610px; + } + + .bitdef-vs-brands-wrapper .new-container { + flex-direction: row; + gap: 3%; + justify-content: center; + } + + .bitdef-vs-brands-wrapper .table-container { + width: 340px; + } +} + +@media (min-width: 990px) { + .bitdef-vs-brands-wrapper .new-container { + flex-direction: row; + gap: 3%; + justify-content: center; + } + + .bitdef-vs-brands-wrapper .table-container { + max-width: 410px; + } + + .bitdef-vs-brands-container.we-container { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } +} + +@media (min-width: 1200px) { + .bitdef-vs-brandss-container.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + } +} + +@media (min-width: 1600px) { + .bitdef-vs-brandss-container.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + } +} diff --git a/_src/blocks/bitdef-vs-brands/bitdef-vs-brands.js b/_src/blocks/bitdef-vs-brands/bitdef-vs-brands.js new file mode 100644 index 000000000..e42778bb7 --- /dev/null +++ b/_src/blocks/bitdef-vs-brands/bitdef-vs-brands.js @@ -0,0 +1,83 @@ +// eslint-disable-next-line no-unused-vars +export default function decorate(block, options) { + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + const blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + } + + const tables = block.querySelectorAll('.bitdef-vs-brands-wrapper table'); + + tables.forEach((table) => { + const parentDiv = table.closest('div'); + + parentDiv.classList.add('table-container'); + + table.querySelectorAll('tr').forEach((row, rowIndex) => { + row.classList.add(`row-${rowIndex}`); + + if (rowIndex >= 3 && rowIndex <= 5) { + if (rowIndex === 3) row.classList.add('blue-background'); + else row.classList.add('grey-background'); + row.querySelectorAll('td').forEach((td) => { + td.classList.add('same-line'); + }); + } + + row.querySelectorAll('td').forEach((cell, cellIndex) => { + cell.classList.add(`column-${cellIndex}`); + }); + }); + }); + // Select the first div within the .bitdef-vs-brands container + const firstDiv = block.querySelector('.bitdef-vs-brands > div'); + + // Add class 'heading-container' to the first div + firstDiv.classList.add('heading-container'); + + // Create a new container div + const newContainerDiv = document.createElement('div'); + newContainerDiv.classList.add('new-container'); + + // Move the second and third divs into the new container + while (firstDiv.nextSibling) { + newContainerDiv.appendChild(firstDiv.nextSibling); + } + + // Insert the new container after the first div + const bitdefContainer = block; + bitdefContainer.insertBefore(newContainerDiv, firstDiv.nextSibling); + + // Animation + const section = block; + + const threshold = { + threshold: 0.5, // Trigger animation when 50% of the section is visible + }; + + // eslint-disable-next-line no-unused-vars, no-shadow + const observer = new IntersectionObserver(((entries, observer) => { + entries.forEach((entry) => { + if (entry.isIntersecting && !entry.target.dataset.animationTriggered) { + // Add animation class to each row based on its index + // eslint-disable-next-line no-shadow + const tables = entry.target.querySelectorAll('table'); + tables.forEach((table) => { + const rows = table.querySelectorAll('.same-line'); + rows.forEach((row, index) => { + row.classList.add(`animate-row${index + 1}`); + }); + }); + // Set dataset attribute to indicate animation has been triggered + entry.target.dataset.animationTriggered = true; + } + }); + }), threshold); + + observer.observe(section); + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); +} diff --git a/_src/blocks/bitdefender-central/bitdefender-central.css b/_src/blocks/bitdefender-central/bitdefender-central.css new file mode 100644 index 000000000..580d5f3fa --- /dev/null +++ b/_src/blocks/bitdefender-central/bitdefender-central.css @@ -0,0 +1,476 @@ +.bitdefender-central-container { + --dark-background-color: #000; + --black-color: #000; + --white-color: #fff; + --background-color: #fff; + --link-color: #005ed9; + --link-hover-color: #00439c; + --button-link-color: #fff; + --button-background-color: #eb0000; + --button-hover-background-color: #d80000; + --button-primary-background-color: #000; + --button-primary-hover-background-color: #000; + --button-secondary-color: #000; + --button-secondary-hover-background-color: #000; + --overlay-background-color: #eee; + --highlight-background-color: #ccc; + --text-color: #000; + --text-error-color: #f00; + --color-highlight-blue: #006dff; + --color-dark-gray: #616161; + --checkbox-label: #3c3c3c; + --highlight-light-blue: #f3f7fe; + --text-dark-color: #fff; + --horizontal-separator-color: #dedede; + --modal-background-color: rgb(0 0 0 / 50%); + --background-color-light-sky-blue: #e4f2ff; + --icon-color: #205fff; + --background-light-blue: #d9eeff; + --background-blue: #005ed9; + --dark-blue-tag: #005eff; + --light-blue-tag: #13b0a7; + --green-tag: #218728; + --dark-shadow: #0000001a; + --background-checkmark: #61AF53; + --body-font-family: "Roboto", "roboto-normal-400-fallback", helvetica, ubuntu, roboto, noto, sans-serif; + --heading-font-family: var(--body-font-family); + --fixed-font-family: var(--body-font-family); + --font-weight-thin: 300; + --font-weight-regular: 400; + --font-weight-bold: 500; + --font-weight-bolder: 600; + --font-weight-boldest: 700; + --font-weight-heavy: 900; + --body-font-size-l: 22px; + --body-font-size-m: 18px; + --body-font-size-s: 16px; + --body-font-size-xs: 14px; + --body-font-size-xxs: 12px; + --body-font-size-xxxs: 10px; + --heading-font-size-xxxl: 60px; + --heading-font-size-xxl: 48px; + --heading-font-size-xl: 40px; + --heading-font-size-l: 32px; + --heading-font-size-m: 24px; + --heading-font-size-s: 20px; + --heading-font-size-xs: 18px; + --heading-font-size-xxs: 16px; + --nav-height: 63px; + --nav-height-desktop: 40px; + --body-max-width: 1920px; + --body-padding: 20px; + --section-desktop-max-width: 1290px; + --section-desktop-padding: 20px; + --section-desktop-padding-vertical: 48px; + --section-mobile-padding-vertical: 32px; + --cta-background-light-blue: var(--background-light-blue); +} + + +.bitdefender-central-wrapper { + max-width: var(--section-desktop-max-width); + padding: 0 var(--section-desktop-padding); + margin: 0 auto; +} + +.bitdefender-central.block > div { + display: grid; + grid-template-columns: 1fr; + grid-gap: 32px; +} + +.bitdefender-central-container.we-container { + max-width: 100%; + padding-left: 20px; + padding-right: 20px; + margin-top: 15px; + margin-left: auto; + margin-right: auto; +} + +.bitdefender-central.block > div > div { + background-color: #F8F8F8; + border-radius: 20px; + padding: 24px; +} + +.bitdefender-central.block > div > div:last-of-type { + background-color: transparent; + border-radius: 20px; + padding: 0; + display: flex; + align-items: stretch; +} + +.bitdefender-central.block > div > div:last-of-type p { + margin: 0; +} + +.bitdefender-central.block > div > div:first-of-type > p:nth-of-type(1) { + margin: 0; +} + +.bitdefender-central.block > div > div:first-of-type > p:nth-of-type(5) { + margin-bottom: 7px; +} + +.bitdefender-central.block > div > div:first-of-type h3 { + font: normal normal bold 32px/38px var(--body-font-family); + margin: 0; +} + +.bitdefender-central.block > div > div:first-of-type > p:nth-of-type(2) { + font: normal normal normal 20px/23px var(--body-font-family); + margin: 0; +} + +.bitdefender-central.block > div > div:first-of-type p.button-container { + display: inline-block; + padding-right: 24px; + margin: 0; +} + +.bitdefender-central.block > div > div:first-of-type a.button { + font: normal normal bold 16px/20px var(--body-font-family); + margin-top: 24px; + padding: 14px 28px; + color: #006EFF; + background: transparent; + border: 2px solid #006EFF; + border-radius: 10px; + display: inline-block; + position: relative; + min-width: 120px; + text-decoration: none; + text-align: center; +} + +.bitdefender-central.block > div > div:first-of-type p.button-container a.blue { + background-color: #006EFF; + color: white; +} + +.bitdefender-central.block > div > div:first-of-type p.button-container a:focus { + outline: 2px solid #48C1FF; + border-radius: 13px; + outline-offset: 2px; +} + +.bitdefender-central.block > div > div:first-of-type p.button-container a:hover { + padding: 14px 28px; + background: #006EFF; + color: #fff; +} + +.bitdefender-central.block > div > div:first-of-type p.button-container a.blue:hover { + background-color: #0A53C5; + border: 2px solid #0A53C5; + color: white; +} + +.bitdefender-central.block > div > div:first-of-type p.button-container a:active { + background: #0D499B; + order: 2px solid #0D499B; +} + +.bitdefender-central.block > div > div:first-of-type p.button-container a.blue:active { + background: #0A53C5; + order: 2px solid #0A53C5; +} + +.bitdefender-central.block > div > div:first-of-type p.button-container a:disabled { + background: transparent; + order: 2px solid #B7B7B7; + color: #B7B7B7; +} + +.bitdefender-central.block > div > div:first-of-type p.button-container a.blue:disabled { + background: #E7E7E7; + order: 2px solid #B7B7B7; + color: #B7B7B7; +} + +.bitdefender-central.block > div > div:first-of-type p.button-container a span { + transition: none; +} + +.bitdefender-central.block > div > div:first-of-type p.button-container a:hover span { + transform: none; +} + +.bitdefender-central.block > div > div:first-of-type p.button-container a::after { + content: ''; + width: 0; + height: 0; + margin: 0; + transition: none; +} + +.bitdefender-central.block > div > div:first-of-type ul { + list-style: none; + margin: 0; + padding: 22px 0 24px; + list-style-type: none; + border-bottom: 1px solid #D1D1D1; +} + +.bitdefender-central.block > div > div:first-of-type ul li { + margin: 0; + padding: 7px 0 0; + font: normal normal normal 16px/18px var(--body-font-family); +} + +.bitdefender-central.block img { + max-width: 100%; + width: auto; + height: auto; +} + +.modal-container .columns-wrapper img { + height: 225px; +} + +.bitdefender-central.block a.video-placeholder img { + object-fit: cover; + height: 100%; + border-radius: 20px; +} + +.bitdefender-central.block > div > div:first-of-type ul li::before { + content: url("/_src/icons/checkmark-green-circle.svg"); + display: inline-block; + width: 18px; + height: 18px; + position: relative; + top: 4px; + margin-right: 9px; +} + +.bitdefender-central.block > div > div:first-of-type .icon.icon-bd-round-thumb { + width: 64px; + height: 64px; + margin-bottom: 14px; + background-color: white; + padding: 6px; + border-radius: 16px; + display: block; +} + +.bitdefender-central.block > div > div:first-of-type .linked-image-container { + display: inline-block; + padding-right: 0; + margin: 0; +} + +.bitdefender-central.block > div > div:first-of-type .linked-image-container img { + width: 154px; + height: 46px; +} + +a.video-placeholder { + position: relative; + align-items: stretch; + display: flex; + color: var(--button-link-color); +} + +.video-placeholder .video-placeholder-play { + box-sizing: border-box; + position: absolute; + top: 50%; + left: 50%; + display: block; + transform: scale(3); + width: 1.375rem; + height: 1.375rem; + border: 0.125rem solid; + border-radius: 1.25rem; + padding: 0; + background-color: #2020e0; + border-color: #2020e0; + opacity: 0.8; + transition: opacity .3s ease-in-out; +} + +.video-placeholder:hover .video-placeholder-play { + opacity: 1; +} + +.video-placeholder .video-placeholder-play::before { + content: ''; + display: block; + box-sizing: border-box; + position: absolute; + width: 0; + height: 0.625rem; + border-top: 0.3125rem solid transparent; + border-bottom: 0.3125rem solid transparent; + border-left: 0.375rem solid; + top: 0.25rem; + left: 0.4375rem; +} + +/* modal */ +.modal-container { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: var(--modal-background-color); + z-index: 999; +} + +.modal-video-container { + display: flex; +} + +.modal-container .modal-content { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + background-color: transparent; + + /* padding: 20px 30px 30px; */ + border-radius: 8px; + + /* box-shadow: 0 3px 8px 0 rgb(0 0 0 / 10%); */ + + /* border: 1px solid #707070; */ + + /* width: 75%; */ + max-height: 90%; + overflow: visible; + opacity: 1; + animation: fade-in 0.5s ease-in-out forwards; +} + +.modal-container .modal-content .section:first-child { + border-bottom: 1px solid var(--horizontal-separator-color); + padding-bottom: 15px; +} + +.modal-container .modal-content .modal-close { + height: 30px; + width: 30px; + border: 0; + padding: 1px 1px 0 0; + border-radius: 50%; + position: absolute; + top: -20px; + right: -14px; + cursor: pointer; + transition: all .3s ease-in-out; + outline: none; +} + +.modal-container .modal-content .modal-close::before { + content: ""; + position: absolute; + top: 13px; + left: 4px; + width: 26px; + height: 2px; + background: #000; + transform: rotate(45deg); + transition: all .3s ease-in-out; +} + +.modal-container .modal-content .modal-close::after { + content: ""; + position: absolute; + top: 13px; + left: 4px; + width: 26px; + height: 2px; + background: #000; + transform: rotate(133deg); + transition: all .3s ease-in-out; +} + +.modal-container.video-modal .modal-content { + background-color: transparent; + border: none; + box-shadow: none; + padding-top: 40px; + width: 100%; + max-width: 900px; +} + +.modal-container.video-modal .modal-content .section:first-child { + border-bottom: none; +} + +.modal-container.video-modal .modal-content .modal-close { + position: absolute; + top: 0; + width: 32px; + height: 32px; + opacity: 0.3; + background-color: unset; +} + +.modal-container.video-modal .modal-content .modal-close:hover { + opacity: 1; +} + +.modal-container.video-modal .modal-content .modal-close::after, .modal-container.video-modal .modal-content .modal-close::before { + position: absolute; + content: ' '; + height: 33px; + width: 2px; + background-color: #040dfd; +} + +.modal-container.video-modal .modal-content .modal-close::after { + transform: rotate(45deg); +} + +.modal-container.video-modal .modal-content .modal-close::before { + transform: rotate(-45deg); +} + +@media (min-width: 992px) { + .bitdefender-central-container.we-container { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } + + .bitdefender-central.block > div { + grid-template-columns: 1fr 1fr; + } + + .video-placeholder .video-placeholder-play { + width: 2rem; + height: 2rem; + } + + .video-placeholder .video-placeholder-play::before { + height: 1rem; + top: 0.39rem; + left: 0.625rem; + border-top: 0.5rem solid transparent; + border-bottom: 0.5rem solid transparent; + border-left: 0.7rem solid; + } + + /* .modal-container .modal-content { + padding: 52px 62px 54px 55px; + max-width: 660px; + } */ + + .modal-container .modal-content .columns-wrapper { + padding-left: 0; + padding-right: 0; + } +} + +@media (min-width: 1200px) { + .bitdefender-central-container.we-container { + max-width: 1290px; + padding-left: 20px; + padding-right: 20px; + } +} diff --git a/_src/blocks/bitdefender-central/bitdefender-central.js b/_src/blocks/bitdefender-central/bitdefender-central.js new file mode 100644 index 000000000..b4ed63589 --- /dev/null +++ b/_src/blocks/bitdefender-central/bitdefender-central.js @@ -0,0 +1,186 @@ +function embedYoutube(url, autoplay) { + const usp = new URLSearchParams(url.search); + const suffix = autoplay ? '&muted=1&autoplay=0&enablejsapi=1' : ''; + let vid = usp.get('v') ? encodeURIComponent(usp.get('v')) : ''; + const embed = url.pathname; + if (url.origin.includes('youtu.be')) { + [, vid] = url.pathname.split('/'); + } + const modalContainer = document.createElement('dialog'); + modalContainer.classList.add('modal-container'); + + const modalContent = document.createElement('div'); + modalContent.classList.add('modal-content'); + modalContainer.appendChild(modalContent); + + const closeModal = () => modalContainer.close(); + const close = document.createElement('div'); + close.classList.add('modal-close'); + modalContent.append(close); + + const iframe = document.createElement('iframe'); + iframe.width = 783; + iframe.height = 440; + iframe.src = `https://www.youtube.com${vid ? `/embed/${vid}?rel=0&v=${vid}${suffix}` : embed}`; + iframe.title = 'YouTube video player'; + iframe.frameborder = 0; + iframe.allow = 'autoplay; fullscreen; accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture'; + iframe.allowFullscreen = true; + iframe.loading = 'lazy'; + modalContent.appendChild(iframe); + close.addEventListener('click', () => { + iframe.contentWindow.postMessage('{"event":"command","func":"stopVideo","args":""}', '*'); + closeModal(); + }); + return modalContainer; + // `
+ // + //
`; +} + +function decorateLinkedPictures(main) { + main.querySelectorAll('picture').forEach((picture) => { + // this condition checks if the picture is part of some content block ( rte ) + // and not a direct element in some DIV block + // that could have different behaviour for some blocks (ex: columns ) + if (picture.closest('div.block') && picture.parentElement.tagName !== 'DIV') { + const next = picture.parentNode.nextElementSibling; + if (next) { + const a = next.querySelector('a'); + const link = a?.textContent; + /* Modal video */ + if (a && link.startsWith('https://') && link.includes('fragments')) { + a.innerHTML = ''; + a.className = 'video-placeholder'; + a.appendChild(picture); + const overlayPlayButton = document.createElement('span'); + overlayPlayButton.className = 'video-placeholder-play'; + a.appendChild(overlayPlayButton); + a.addEventListener('click', async (event) => { + event.preventDefault(); + // eslint-disable-next-line no-use-before-define + }); + const up = a.parentElement; + if (up.childNodes.length === 1 && (up.tagName === 'P' || up.tagName === 'DIV')) { + up.classList.add('modal-video-container'); + } + return; + } + // Basic linked image + if (a && link.startsWith('https://')) { + a.innerHTML = ''; + a.className = 'linked-image'; + const pictureParent = picture.parentNode; + a.append(picture); + if (pictureParent.children.length === 0) { + pictureParent.parentNode.removeChild(pictureParent); + } + const up = a.parentElement; + if (up.childNodes.length === 1 && (up.tagName === 'P' || up.tagName === 'DIV')) { + up.classList.add('linked-image-container'); + } + } + } + } + }); +} + +function decorateButtons(element) { + const wrapButtonText = (a) => ((a.innerHTML.startsWith('<')) + ? `${a.querySelector('span.icon')?.outerHTML || ''}${a.textContent}` + : `${a.textContent}${a.querySelector('span.icon')?.outerHTML || ''}` + ); + element.querySelectorAll('a').forEach((a) => { + if (a.closest('.nav-brand') || a.closest('.nav-sections')) { + return; + } + a.title = a.title || a.textContent; + if (a.href !== a.textContent) { + const up = a.parentElement; + const twoup = a.parentElement.parentElement; + const threeup = a.parentElement.parentElement?.parentElement; + + if (!a.querySelector('img')) { + // Example:

Text

+ if (up.childNodes.length === 1 && up.tagName === 'STRONG' + && twoup.childNodes.length === 1 && twoup.tagName === 'P') { + a.className = 'button primary'; + twoup.classList.add('button-container'); + up.replaceWith(a); + a.innerHTML = wrapButtonText(a); + return; + } + if (up.childNodes.length === 1 && up.tagName === 'EM' + && twoup.childNodes.length === 1 && twoup.tagName === 'STRONG' + && threeup?.childNodes.length === 1 && threeup?.tagName === 'P') { + a.className = 'button secondary'; + threeup.classList.add('button-container'); + up.replaceWith(a); + a.innerHTML = wrapButtonText(a); + return; + } + // Example:

Text (example.com)

+ if (up.childNodes.length === 1 && up.tagName === 'P' && a.href.includes('/fragments/')) { + a.className = 'button modal'; + up.classList.add('button-container'); + return; + } + // Example:

Text 50% Discount

+ if (up.childNodes.length === 3 && up.tagName === 'P' && a.nextElementSibling?.tagName === 'EM') { + a.className = 'button'; + up.classList.add('button-container'); + a.innerHTML = wrapButtonText(a); + a.dataset.modal = a.nextSibling.textContent.trim().slice(1, -1); + a.nextSibling.remove(); + return; + } + // Example:

? Text

+ if (up.childNodes.length === 1 && up.tagName === 'P' && up.innerText.startsWith('?')) { + a.className = 'info-button modal'; + up.classList.add('info-button-container'); + a.textContent = a.textContent.slice(1).trim(); + a.title = a.title.slice(1).trim(); + return; + } + // Example:

Text

+ if (up.childNodes.length === 1 && (up.tagName === 'P' || up.tagName === 'DIV')) { + a.className = 'button'; // default + up.classList.add('button-container'); + a.innerHTML = wrapButtonText(a); + } + } + } + }); +} + +export default async function decorate(block, options) { + const { + // eslint-disable-next-line no-unused-vars + videoUrl, + } = block.closest('.section').dataset; + + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + decorateLinkedPictures(block); + decorateButtons(block); + + const wrapper = block.querySelector('.video-placeholder'); + block.appendChild(embedYoutube(new URL(videoUrl), true)); + const modalContainer = block.querySelector('dialog'); + wrapper.addEventListener('click', () => { + modalContainer.showModal(); + }); + } + const firstButton = block.querySelector('a.button'); + if (firstButton) { + firstButton.classList.add('blue'); + } + + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); +} diff --git a/_src/blocks/blog-insert/blog-insert.css b/_src/blocks/blog-insert/blog-insert.css new file mode 100644 index 000000000..689f9d1d1 --- /dev/null +++ b/_src/blocks/blog-insert/blog-insert.css @@ -0,0 +1,8 @@ +.blog-insert-container { + text-align: center; +} + +.blog-insert-container img { + width: 100%; + height: auto; +} \ No newline at end of file diff --git a/_src/blocks/blog-insert/blog-insert.js b/_src/blocks/blog-insert/blog-insert.js new file mode 100644 index 000000000..733a139fb --- /dev/null +++ b/_src/blocks/blog-insert/blog-insert.js @@ -0,0 +1,18 @@ +export default function decorate(block) { + const urlDiv = block.querySelector('div > div:nth-child(2) > div'); + const url = urlDiv.textContent.trim(); + + // Get the picture element + const pictureElement = block.querySelector('picture'); + + // Create a new anchor element + const anchorElement = document.createElement('a'); + anchorElement.href = url; + + // Wrap the picture element with the anchor element + pictureElement.parentNode.insertBefore(anchorElement, pictureElement); + anchorElement.appendChild(pictureElement); + + block.textContent = ''; + block.append(anchorElement); +} diff --git a/_src/blocks/box-carousel/box-carousel.css b/_src/blocks/box-carousel/box-carousel.css new file mode 100644 index 000000000..f561aeac0 --- /dev/null +++ b/_src/blocks/box-carousel/box-carousel.css @@ -0,0 +1,227 @@ +/* stylelint-disable no-descending-specificity */ +.box-carousel-container { + background: white; +} + +.box-carousel-container .carousel-header { + display: flex; + align-items: center; + justify-content: space; +} + +.box-carousel-container .carousel-header .title { + color: black; +} + +.box-carousel-container .carousel-header .title p { + margin: 0 0 16px; +} + +.box-carousel-container .carousel-header .left-arrow.disabled, +.box-carousel-container .carousel-header .right-arrow.disabled { + opacity: 0.3; +} + +.box-carousel-container .carousel-header .left-arrow, +.box-carousel-container .carousel-header .right-arrow { + color: black; +} + +.box-carousel-container .carousel-container { + width: 100%; + position: relative; + display: flex; + overflow: hidden; +} + +.box-carousel-container .carousel { + display: flex; + transition: transform 150ms cubic-bezier(0.165, 0.84, 0.44, 1) 0s; +} + +.box-carousel-container .block.scrollable .carousel { + overflow: auto; +} + +.box-carousel-container .block.scrollable .carousel::-webkit-scrollbar { + display: none; +} + +.box-carousel-container .carousel-item { + display: flex; + flex-direction: column; + width: 220px; + min-height: 220px; + margin: 10px; + box-sizing: border-box; + padding: 20px; + border-radius: 15px; + color: black; + font-size: 1em; + background: #eaf2ff; + flex-shrink: 0; + border: solid 1px black; +} + +.box-carousel-container.testimonials .carousel-item { + width: 300px; + height: 300px; + display: flex; + flex-direction: column; + border: solid 1px #ddd; + background: white; + position: relative; +} + +.box-carousel-container .carousel-item:first-child { + margin-left: 0; +} + +.box-carousel-container .carousel-item .title { + letter-spacing: 0; + overflow: hidden; + margin: 12px 0; +} + +.box-carousel-container.testimonials .carousel-item .title { + -webkit-line-clamp: 6; + line-clamp: 6; +} + +.box-carousel-container .carousel-item .subtitle { + font: normal normal normal 12px/15px "IBM Plex Sans", sans-serif; + letter-spacing: 0; + overflow: hidden; + margin-top: auto; + color: #242424; +} + +.box-carousel-container.testimonials .carousel-item .subtitle-secondary { + font: normal normal bold 14px/21px "IBM Plex Sans", sans-serif; + margin-top: auto; + position: relative; +} + +.box-carousel-container.testimonials .carousel-item .subtitle-secondary::before { + content: ''; + display: block; + position: absolute; + width: 40px; + height: 1px; + background: black; + top: -5px; +} + +.box-carousel-container.testimonials .carousel-item .subtitle { + margin-top: unset; + color: #242424; +} + +.box-carousel-container .left-arrow svg { + transform: rotate(180deg); +} + +.box-carousel-container .arrow { + width: 100px; +} + +.box-carousel-container .arrow svg { + width: 100%; + height: 50px; +} + +.box-carousel-container .arrow svg path { + fill: white; +} + +.box-carousel-container .arrow.disabled svg path { + fill: #a5a5a5; +} + +.box-carousel-container .carousel-item .icon { + width: 35px; + height: 35px; + margin: 0; +} + +.box-carousel-container svg path { + fill: black !important; +} + +.box-carousel-container.testimonials .img-container { + height: 60px; + width: 100%; +} + +.box-carousel-container.testimonials .img-container img { + object-fit: contain; + filter: grayscale(100%); + width: unset; +} + + +@media screen and (min-width: 768px) { + .box-carousel-container .carousel-header { + justify-content: space-between; + margin-bottom: 20px; + } + + .box-carousel-container.testimonials .img-container { + width: 60%; + } + + .box-carousel-container.testimonials .carousel-item { + width: calc((100% - 25px) / 2); + min-height: 390px; + } + + .box-carousel-container .carousel-item .subtitle { + font: normal normal normal 18px/23px "IBM Plex Sans", sans-serif; + } + + .box-carousel-container.testimonials .carousel-item .subtitle { + font: normal normal normal 12px/15px "IBM Plex Sans", sans-serif; + } +} + +@media screen and (min-width: 992px) { + .box-carousel-container .default-content-wrapper { + overflow: hidden; + } + + .box-carousel-container.testimonials .carousel-item { + width: calc((100% - 25px) / 3); + min-height: 390px; + } + + .box-carousel-container .carousel-item .title { + font-size: 22px; + color: #242424; + font-weight: 500; + } + + .box-carousel-container.testimonials .carousel-item .subtitle { + font-size: 17px; + } + + .box-carousel-container.testimonials .carousel-item .subtitle-secondary { + font-size: 18px; + } + + .box-carousel-container:not(.testimonials) .carousel-item:hover { + color: white; + background: #006dff; + box-shadow: 0 3px 40px #006EFFF2; + } + + .box-carousel-container .carousel-item:hover svg path { + fill: white !important; + } +} + +@media (min-width: 1600px) { + .box-carousel-container.testimonials .carousel-item { + width: calc(100% / 3); + } +} + diff --git a/_src/blocks/box-carousel/box-carousel.js b/_src/blocks/box-carousel/box-carousel.js new file mode 100644 index 000000000..25a290c95 --- /dev/null +++ b/_src/blocks/box-carousel/box-carousel.js @@ -0,0 +1,164 @@ +import { decorateIcons } from '../../scripts/lib-franklin.js'; +import { debounce, isView } from '../../scripts/utils/utils.js'; + +export default async function decorate(block) { + const [titleEl, ...slides] = [...block.children]; + let currentSlideIndex = 0; + + const isTestimonials = block.closest('.section').classList.contains('testimonials'); + + const carouselItemStyle = { + margin: 20, + }; + + function isFirstIndex() { + return currentSlideIndex === 0; + } + + function isLastIndex() { + return currentSlideIndex === slides.length - 3; + } + + function scrollCarousel(offset, carousel) { + const carouselItem = block.querySelector('.carousel-item'); + carousel.style.transform = `translateX(${-1 * offset * (carouselItem.offsetWidth + carouselItemStyle.margin)}px)`; + } + + function getCarousel() { + return block.querySelector('.carousel'); + } + + function updateDisabledArrow() { + const leftArrowEl = block.querySelector('.left-arrow'); + const rightArrowEl = block.querySelector('.right-arrow'); + + leftArrowEl.classList.remove('disabled'); + rightArrowEl.classList.remove('disabled'); + + if (isLastIndex()) { + block.querySelector('.right-arrow').classList.add('disabled'); + return; + } + + if (isFirstIndex()) { + block.querySelector('.left-arrow').classList.add('disabled'); + } + } + + function leftArrowHandler(e) { + e.preventDefault(); + if (isFirstIndex()) { + return; + } + currentSlideIndex -= 1; + scrollCarousel(currentSlideIndex, getCarousel()); + updateDisabledArrow(currentSlideIndex); + } + + function rightArrowHandler(e) { + e.preventDefault(); + if (isLastIndex()) { + return; + } + currentSlideIndex += 1; + scrollCarousel(currentSlideIndex, getCarousel()); + updateDisabledArrow(currentSlideIndex); + } + + function renderArrows() { + block.classList.remove('scrollable'); + + if (isView('desktop')) { + const cardsNotFullyVisible = window.innerWidth > 767; + return cardsNotFullyVisible ? ` + + + + + + + + + + + + + + + ` : ''; + } + + block.classList.add('scrollable'); + return ''; + } + + function render() { + block.classList.add('default-content-wrapper'); + + block.innerHTML = ` + + + + `; + + decorateIcons(block); + + const leftArrowEl = block.querySelector('.left-arrow'); + const rightArrowEl = block.querySelector('.right-arrow'); + + if (leftArrowEl && rightArrowEl) { + leftArrowEl.removeEventListener('click', leftArrowHandler); + rightArrowEl.removeEventListener('click', rightArrowHandler); + + leftArrowEl.addEventListener('click', leftArrowHandler); + rightArrowEl.addEventListener('click', rightArrowHandler); + } + } + + render(); + + window.addEventListener('resize', debounce(render, 250)); +} diff --git a/_src/blocks/box-image-round-card/box-image-round-card.css b/_src/blocks/box-image-round-card/box-image-round-card.css new file mode 100644 index 000000000..5ac577997 --- /dev/null +++ b/_src/blocks/box-image-round-card/box-image-round-card.css @@ -0,0 +1,109 @@ +.box-image-round-card-container .inner-wrapper { + display: flex; + background-color: #fff; + border-radius: 8px; + box-shadow: 0 3px 6px 0 rgb(0 0 0 / 8%); + position: relative; + overflow: hidden; + z-index: 2; + width: 100%; + margin: 10px 0; + padding: 40px 23px 2pc; +} + +/* .box-image-round-card-container .inner-wrapper > div:nth-child(1) { */ + +/* width: 50%; */ + +/* } */ + +/* .box-image-round-card-container .inner-wrapper > div:last-child { */ + +/* border-radius: 50%; */ + +/* position: absolute; */ + +/* right: -35px; */ + +/* top: -60px; */ + +/* width: 225px; */ + +/* height: 225px; */ + +/* overflow: hidden; */ + +/* } */ + +.box-image-round-card-container .icon-apple { + width: 60px; + transform: none; +} + +.box-image-round-card-container img { + width: 100%; + height: 100%; + object-fit: cover; + transition: transform .3s ease-in-out,-webkit-transform .3s ease-in-out; + transform: scale(1); +} + +.box-image-round-card-container .inner-wrapper > a:first-child { + position: absolute; + top: 0; + left: 0; + z-index: 2; + width: 100%; + height: 100%; + text-indent: -999999px; +} + +.box-image-round-card-container .inner-wrapper p.button-container { + display: inline-block; + margin-right: 10px; +} + +@media(min-width: 767px) { + /* tablet */ + .box-image-round-card-container .inner-wrapper p { + font-size: 18px; + } + + /* .box-image-round-card-container .inner-wrapper > div:last-child { */ + + /* width: 325px; */ + + /* height: 325px; */ + + /* } */ + .box-image-round-card-container .inner-wrapper > a:first-child:hover ~ div p.button-container > a::after { + transform: translateX(5px); + opacity: 1; + } + + .box-image-round-card-container .inner-wrapper > a:first-child:hover ~ div p.button-container > a span.button-text { + transform: translate(-10px, 0); + } + + .box-image-round-card-container .inner-wrapper > a:first-child:hover ~ div img { + transform: scale(1.1); + } + + .box-image-round-card-container .default-content-wrapper { + display: flex; + } + + .box-image-round-card-container .card-wrapper { + order: 2; + flex: 60%; + display: flex; + align-items: center; + } + + .box-image-round-card-container .picture-wrapper { + order: 1; + flex: 40%; + padding-right: 25px; + margin: 10px 0; + } +} diff --git a/_src/blocks/box-image-round-card/box-image-round-card.js b/_src/blocks/box-image-round-card/box-image-round-card.js new file mode 100644 index 000000000..36322492c --- /dev/null +++ b/_src/blocks/box-image-round-card/box-image-round-card.js @@ -0,0 +1,26 @@ +import { createOptimizedPicture } from '../../scripts/lib-franklin.js'; +import { getDatasetFromSection } from '../../scripts/utils/utils.js'; + +export default function decorate(block) { + const innerWrapper = block.children[0]; + innerWrapper.classList = 'inner-wrapper'; + + const defaultWrapper = document.createElement('div'); + defaultWrapper.classList = 'default-content-wrapper'; + + const carWrapper = document.createElement('div'); + carWrapper.classList = 'card-wrapper'; + + carWrapper.append(innerWrapper); + + const pictureWrapper = document.createElement('div'); + pictureWrapper.classList = 'picture-wrapper'; + + const blockDataset = getDatasetFromSection(block); + pictureWrapper.append(createOptimizedPicture(blockDataset.bgImage, 'title')); + + defaultWrapper.prepend(carWrapper); + defaultWrapper.append(pictureWrapper); + + block.prepend(defaultWrapper); +} diff --git a/solutions/blocks/cards/cards.css b/_src/blocks/cards/cards.css similarity index 100% rename from solutions/blocks/cards/cards.css rename to _src/blocks/cards/cards.css diff --git a/solutions/blocks/cards/cards.js b/_src/blocks/cards/cards.js similarity index 100% rename from solutions/blocks/cards/cards.js rename to _src/blocks/cards/cards.js diff --git a/_src/blocks/columns/columns.css b/_src/blocks/columns/columns.css new file mode 100644 index 000000000..db677b822 --- /dev/null +++ b/_src/blocks/columns/columns.css @@ -0,0 +1,1239 @@ +.columns-wrapper { + padding: 0 var(--body-padding); +} + +.columns-container.chat-options p { + font-size: var(--body-font-size-s) !important; +} + +.columns-container.linear-gradient h3 { + font-size: var(--heading-font-size-xl); + margin-bottom: 1em; +} + +.columns-container.linear-gradient p { + font-size: var(--body-font-size-m); +} + +.columns.benefits > p { + margin-bottom: 0; + margin-top: 0; +} + +.columns.benefits p { + font-size: var(--body-font-size-s); + line-height: 1.5; + letter-spacing: .006em; + font-weight: var(--font-weight-regular); +} + +.columns.new-v2 p { + font-size: 16px; + font-weight: 400; + line-height: 22px; +} + +.columns.awards > div > div > p { + margin: 0; + padding: 0 5px; + text-align: center; +} + +.columns.video-presentation > div > div > p { + font-size: var(--body-font-size-s); +} + +.columns.carousel > div > div > p { + width: inherit; + padding: 0 50px; + text-align: center; +} + +.columns-container.video-left .columns-right-col p { + margin: 1.5em 0; +} + +/* stylelint-disable-next-line selector-class-pattern */ +.v3_benefits .columns.benefits p { + font-size: var(--body-font-size-s); +} + +.columns-wrapper > div.grey-bck p:first-of-type { + margin: 1em 0; +} + +.v2 .columns.awards > div > div > p { + font-size: var(--body-font-size-s); +} + +.columns.awards > div > div > p:first-of-type { + margin-bottom: 24px; +} + +.section.subtitle-blue .columns.benefits p { + font-size: var(--body-font-size-s); + font-weight: 400; + letter-spacing: .006em; + line-height: 24px; +} + +.columns.awards.v2 > div > div > p:last-of-type { + margin-top: 10px; +} + +.columns.benefits h3 { + font-size: var(--heading-font-size-m); + font-weight: var(--font-weight-bold); + line-height: 1.25; +} + +.section.subtitle-blue h3 { + font-size: 1.25rem; + + --tw-text-opacity: 1; + + color: rgb(0 110 255 / var(--tw-text-opacity)); +} + +.creators .columns-container h3 { + font-weight: bold; +} + +.columns.new-v2 h3 { + font-family: "IBM Plex Sans" ,sans-serif; + font-size: 25px; + font-weight: 700; + line-height: 30px; + text-align: left; + color: #006EFF; +} + +.columns.video-presentation > div > div > h3 { + font-size: var(--heading-font-size-xl); +} + +.columns > div { + display: flex; + flex-direction: column; + justify-content: center; +} + +.columns > div > div { + order: 1; +} + +.text-over-image > div > div { + height: 600px; + border-radius: 12px; + display: flex; + flex-direction: column; + color: var(--white-color); + padding: 30px; + justify-content: flex-end; + background-size: cover; + background-repeat: no-repeat; +} + +.columns.carousel > div { + flex-direction: row; + justify-content: flex-start; + gap: 22px; + height: 15px; + top: 0; +} + +.columns.benefits > div { + align-items: flex-start; +} + +/* awards styling */ +.columns.awards > div { + gap:30px; + display: flex; + flex-flow: row wrap; + align-items: center; +} + +.columns img { + width: 100%; + +} + +.dlp.columns-container img{ + width: 67%; + margin-left: auto; +} + +.dlp.columns-container h2{ + color: #006DFF; +} + +.modal-container.get-bitdefender-familypack img { + height: auto; +} + +.columns.awards > div img { + display: block; + object-fit: contain; +} + +.columns > div > .columns-img-col img { + display: block; +} + +.grey-version .columns > div > div img, .small-icons .columns > div > div img { + height: 60px; + width: auto; +} + +.small-icons-v2 .columns > div > div img { + height: 120px; + width: auto; +} + +.columns.video-presentation .linked-image-container img { + width: 150px; + height: 44px; +} + +.columns.awards.smaller-icons > div img { + width: auto; + max-width: unset; + height: 100px; +} + +.grey-version .columns > div { + display: flex; + justify-content: space-between; +} + +.columns.carousel > div > div { + flex: 1 0 33%; + margin: 10px 5px; + width: 100%; + box-sizing: border-box; +} + +.grey-version .columns > div > div { + --tw-bg-opacity: 1; + + background-color: rgb(245 245 247 / var(--tw-bg-opacity)); + border-radius: 1rem; + padding: 3em; + margin-bottom: 1em; +} + +.text-over-image > div > div:first-child { + font-size: var(--heading-font-size-s); + margin-bottom: -10px; +} + +.percent-table .columns table tr { + align-items: center; + display: flex; + justify-content: space-between; +} + +.percent-table .columns table tr td:first-of-type { + font-size: var(--heading-font-size-l); + padding-right: 1.5em; +} + +.percent-table .columns table tr td:last-of-type { + width: 220px; +} + +.grey-version .columns > div > div h4 { + font-size: var(--heading-font-size-l); +} + +.creators .columns-container p.button-container { + text-align: center; +} + +.grey-version .columns > div > div p.button-container { + margin-bottom: auto; +} + +.columns-container.we-container { + max-width: 100%; + padding-left: 20px; + padding-right: 20px; + margin-top: 15px; + margin-left: auto; + margin-right: auto; +} + +.columns.highlight-text.black { + background-color: var(--black-color); + padding: 25px 2pc 20px 30px; + text-align: left; + position: absolute; + width: 100%; +} + +/* stylelint-disable-next-line selector-class-pattern */ +.v2_benefits .columns-container .default-content-wrapper { + margin-bottom: 3em; +} + +/* stylelint-disable-next-line selector-class-pattern */ +.bigger_title .columns.benefits h3 { + font-size: var(--heading-font-size-l); +} + +/* stylelint-disable-next-line selector-class-pattern */ +.v2_benefits .columns.benefits h3 { + font-size: var(--heading-font-size-l); +} + +.columns.video-presentation > div > div { + margin: 0 auto; +} + +.section.subtitle-blue h2 { + margin: 0 auto 3em; + width: 100%; + text-align: center; +} + +.columns.with-box-shadow > div > div { + padding: 0 20px; + border-right: none; + border-bottom: 2px solid var(--overlay-background-color); +} + +.columns-wrapper > div.grey-bck > div { + flex: 1; +} + +.columns-wrapper > div.grey-bck > div > div { + margin: 0!important; + flex: 0 0 50%; +} + +.columns.carousel > div:nth-child(1) { + position: relative; + left: 0; + gap: 0; + transition: transform 0.3s ease-in-out; + height: 200px; +} + +.creators .columns-container .columns > div { + justify-content: space-between; + margin-bottom: 3em; +} + +/* stylelint-disable-next-line selector-class-pattern */ +.v2_benefits .columns.benefits > div { + gap: 35px; +} + +.v2 .columns.awards > div { + align-items: flex-start; +} + +/* stylelint-disable-next-line selector-class-pattern */ +.v2_benefits .columns.benefits > div > div { + font-size: var(--body-font-size-m); + flex: 1; +} + +.columns.bg-image > div > div:first-child { + font-size: var(--heading-font-size-xl); + font-weight: bold; +} + +.columns.with-box-shadow > div > div:last-child { + border: none; +} + +.section.subtitle-blue .columns.benefits > div { + gap: 45px; + margin-bottom: 2em; +} + +.columns > div > .columns-img-col { + order: 0; + text-align: center; + margin-bottom: 2em; +} + +.creators .columns-container .columns > div:last-of-type { + margin-bottom: 0; +} + +.creators .columns-container h5 { + font-weight: bold; + color: #006DFF; +} + +.creators .columns-container.baby-blue-subtitles h3 { + color: #006DFF; +} + +.creators .columns-container.baby-blue-subtitles h3 br { + display: block; +} + +.creators .columns-container a.button { + height: auto; + background: #E72325 0% 0% no-repeat padding-box; + border-radius: 30px; + justify-content: center; + padding: 5px 10px; + font-size: 14px; +} + +.columns.bg-image a { + color: white +} + +.columns.new-v2 a { + color: #006EFF!important; + font-size: 18px; + text-decoration: none; + font-weight: 600; + transition: all .2s cubic-bezier(.4,0,.2,1); +} + +.green-button .button-container a { + background-color: #51a71d; + border: 2px solid #51a71d; + text-transform: uppercase; +} + +.green-button p:last-of-type a { + text-decoration: underline; + font-size: var(--body-font-size-xs); + margin: 0 10px; +} + +.columns.new-v2 a:hover { + color: #0A53C5; + transform: translateX(10px); +} + +.columns-container.chat-options p.button-container a { + background-color: transparent; + border: 2px solid black; + color: black; + white-space: normal; +} + +.columns-container.chat-options p.button-container a:hover { + background-color: black; + color: white; +} + +.columns-container.chat-options table { + width: 100%; +} + +.columns-container.chat-options table tr { + display: flex; + justify-content: space-between; +} + +.small-icons-v2 .columns > div > div.columns-img-col { + display: flex; + align-items: center; + justify-content: center; +} + +.columns.new-v2 > div > .columns-img-col img { + object-fit: contain; +} + +.columns-container.chat-options table tr td:first-of-type img { + height: 40px; +} + +.columns-container.chat-options table tr td:last-of-type img { + height: 133px; + display: none; +} + +.columns-wrapper > div.grey-bck { + background-color: #F5F5F7; + border-radius: 1em; + padding: 0; + display: flex; + overflow: hidden; +} + +.columns-wrapper > div.grey-bck h5 { + font-size: var(--heading-font-size-m); + line-height: var(--heading-font-size-l); +} + +.columns-wrapper > div.grey-bck div.columns-text-col { + padding-left: 4em; + padding-right: 1em; +} + +.section.baby-blue-bck .columns-wrapper { + background-color: #E4F2FF; +} + +.section.grey-bck .columns-wrapper { + background-color: #F5F5F7; +} + +.section.radius-corners .columns-wrapper { + border-radius: 1rem; + overflow: hidden; +} + +.section.radius-corners-10px .columns-wrapper { + border-radius: 10px; + overflow: hidden; +} + +.section.pl-0 .columns-wrapper { + padding-left: 0; +} + +.section.pr-0 .columns-wrapper { + padding-right: 0; +} + +.columns.new-v2 > div > .columns-img-col { + margin-bottom: 1em; +} + +.section.radius-corners .columns-wrapper .columns-img-col { + border-radius: 1rem; + overflow: hidden; + margin-bottom: 0; +} + +.section.radius-corners-10px .columns-wrapper .columns-img-col, +.section.radius-corners-10px .columns-wrapper .columns-img-col img { + margin-bottom: 0; + border-radius: 0; +} + +.columns .tag-dark-blue { + background-color: #007bff; + color: white; + font-size: 16px; + padding: 4px 15px; + border-radius: 16px; + display: inline-block; + vertical-align: middle; +} + +@media (min-width: 991px) { + .columns.benefits > div { + flex-direction: unset; + gap: 32px; + align-items: stretch; + } +} + +@media (min-width: 767px) { + .columns-container.chat-options .columns > div > div { + padding: 2em; + } + + .columns.highlight-text.black { + width: 520px; + right: 2.5%; + top: 15%; + border-radius: 5px; + } + + .columns.highlight-text.black.imageleft { + left: 2.5%; + } + + .percent-table .columns table tr td:first-of-type { + padding-right: 0.5em; + } +} + +@media (min-width: 992px) { /* desktop */ + .columns-container.we-container { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } + + .columns > div { + align-items: center; + flex-direction: unset; + gap: 32px; + } + + .columns > div > div { + flex: 1; + order: unset; + } + + + .columns-wrapper { + max-width: var(--section-desktop-max-width); + padding: 0 var(--section-desktop-padding); + margin: 0 auto; + } + + .columns.highlight-text.black { + right: 10%; + top: 10%; + } + + .columns.highlight-text.black.imageleft { + left: 10%; + } + + .section.subtitle-blue h2 { + margin: 0 auto 3em; + width: 630px; + } + + .section.subtitle-blue h3 { + font-size: 1.25rem; + } + + /* stylelint-disable-next-line selector-class-pattern */ + .section.b_mark > div { + padding: 5em 0 3em; + margin-top: 0; + } + + .columns.awards > div > div { + flex: 0; + } + + /* stylelint-disable-next-line selector-class-pattern */ + .section.b_mark .columns-img-col img { + margin-top: -200px; + margin-bottom: -3em; + } + + .columns-container.chat-options .columns > div > div { + padding: 2em; + } + + .section.subtitle-blue .columns.benefits > div { + margin-bottom: 0; + } + + /* stylelint-disable-next-line selector-class-pattern */ + .section.bd_woman { + margin-top: 2em; + } + + /* stylelint-disable-next-line selector-class-pattern */ + .section.bd_woman h2 { + font-weight: var(--font-weight-regular); + } + + .columns > div > .columns-img-col { + margin-bottom: 1em; + } + + /* stylelint-disable-next-line selector-class-pattern */ + .section.bd_woman .columns-img-col { + margin-top: -122px; + } + + /* stylelint-disable-next-line selector-class-pattern */ + .section.b_mark { + margin-bottom: 5em; + } + + .columns.screenshots { + margin-top: 4em; + } + + .v2 .columns > div > .columns-text-col { + flex: 0 0 40%; + } + + .v2 .columns > div > .columns-text-col.columns-right-col { + margin-left: 4em; + } + + .columns-container.chat-options table tr td:last-of-type img { + display: block; + } + + .creators .columns-container .columns > div > div.columns-left-col, .creators .columns-container .columns > div > div.columns-right-col { + width: 45%; + flex: none; + } + + .creators .columns-container .columns > div > div.columns-img-col { + width: 50%; + flex: none; + } + + .creators .columns-container h5 { + color: #006DFF; + font: normal normal bold 32px/45px "IBM Plex Sans", sans-serif; + } + + .creators .header-mobile.columns-container h1 { + font: normal normal bold 60px/70px "IBM Plex Sans", sans-serif; + } + + .creators .header-mobile.columns-container h2 { + color: #006DFF; + font: normal normal bold 32px/45px "IBM Plex Sans", sans-serif; + margin-bottom: 0; + } + + .creators .columns-container h3 { + font: normal normal bold 60px/70px "IBM Plex Sans", sans-serif; + } + + .creators .columns-container p { + font: normal normal normal 24px/33px Arial, sans-serif; + } + + .creators .columns-container.smaller-text p { + font: normal normal normal 18px / 27px Arial, sans-serif; + } + + .creators .columns-container p.button-container { + text-align: left; + } + + .creators .columns-container a.button { + min-width: 230px; + height: 48px; + padding: 10px 10px 10px 25px; + background: #E72325 0% 0% no-repeat padding-box; + border-radius: 40px; + justify-content: center; + font: normal normal 500 18px/24px Roboto, sans-serif; + } +} + +@media (max-width: 1200px) { + /* stylelint-disable-next-line selector-class-pattern */ + .v2_benefits .columns.benefits h3 { + font-size: var(--heading-font-size-m); + margin-bottom: 10px; + } +} + +@media (min-width: 1200px) { + .columns-container.we-container { + max-width: 1350px; + padding-left: 20px; + padding-right: 20px; + } + + .columns.awards > div > div { + flex: 1; + } + + .percent-table .columns table tr td:first-of-type { + padding-right: 1.5em; + } +} + +@media (min-width: 1600px) { /* large desktop */ + .columns-wrapper { + max-width: var(--section-large-desktop-max-width); + padding: 0 var(--section-large-desktop-padding); + } +} + +/* Benefits columns (icon, text, description) */ +.columns.benefits > .icon { + width: unset; + max-width: 66px; + margin-bottom: 16px; +} + +.columns-container.video-left video { + width: 100%; + border-radius: 10px; +} + +.columns-container.video-left .columns-right-col { + width: 100%; + flex: none; +} + +@media (min-width: 1271px) { + .columns.benefits p { + font-size: 18px; + } +} + +/* paragraph with image */ +.columns.video-presentation .button-container { + display: inline-block; + padding-right: 0; +} + +.columns.video-presentation .linked-image-container { + display: inline-block; + padding-right: 3px; + margin-top: 0; + margin-bottom: 0; +} + +.columns.video-presentation ul { + padding-top: 1px; +} + +.columns.vpn-presentation .button-container, +.columns.vpn-presentation .info-button-container{ + display: inline-block; + padding-right: 13px; + margin-top: 13px; +} + +.columns.vpn-presentation .left-col { + margin-bottom: 40px; +} + +@media (min-width: 992px) { + .columns.vpn-presentation .left-col { + margin-bottom: 0; + } +} + +.section.bullet-points.columns-container ul { + list-style: disc; +} + +.section.migration.columns-container ul { + padding: 0; +} + +.section.migration.columns-container ul li { + display: flex; + padding-left: 0; + margin-bottom: 1em; +} + +.section.migration.columns-container ul li::before { + content: url("/_src/icons/checkmark-light-green-circle.svg"); + display: inline-block; + width: 18px; + height: 18px; + position: relative; + top: 4px; + margin-right: 9px; + flex-shrink: 0; +} + +.section.migration.columns-container .columns-img-col img { + border-radius: 10px; +} + +.columns.carousel { + width: 100%; + margin-top: 0; + overflow: hidden; + height: auto; +} + +.section.migration .columns.carousel { + margin-top: 0; + height: auto; +} + +.carousel-buttons { + position: relative; + top: 30px; + display: flex; + justify-content: center; + align-items: center; + transition: all .4s ease-in-out; +} + +.section.migration .columns.carousel .carousel-buttons { + top: -10px; +} + +.columns.carousel button { + align-items: flex-start; + width: 10px; + height: 10px; + border-radius: 100%; + margin: 10px; + padding: 0; + background-color: var(--black-color); + border: none; + cursor: pointer; +} + +.columns.carousel button:hover { + background-color: var(--link-color); +} + +.section.wide.light-sky-blue.columns-container { + height: auto; +} + +.section.white.columns-container .columns.awards > div { + flex-direction: unset; + align-items: center; +} + +.section.white.columns-container .columns.awards > div img { + display: block; + height: 120px; + object-fit: contain; +} + +@media (min-width: 676px) and (max-width: 989px) { + .slide-left { + transform: translateX(-50%); + } +} + +@media (min-width: 990px) { + .columns.carousel button { + margin: -5px; + } + + .slide-left { + transform: translateX(-25%); + } + + .columns.with-box-shadow > div > div{ + border-bottom: none; + border-right: 2px solid var(--overlay-background-color); + min-height: 350px; + } + + .columns-container.video-left .columns-right-col { + width: 440px; + flex: none; + } +} + +.columns.carousel .active-button { + background-color: var(--link-color); +} + +.modal-container.get-bitdefender-familypack .columns.block.columns-2-cols > div { + display: flex; + flex-direction: column-reverse; + text-align: center; +} + +@media (min-width: 768px) { + .modal-container.get-bitdefender-familypack .columns.block.columns-2-cols > div { + display: flex; + flex: 1; + flex-direction: row; + order: unset; + justify-content: center; + align-items: center; + } +} + +.modal-container.modal-container.get-bitdefender-familypack .modal-content .section.columns-container { + border-bottom: none; + padding: 0; +} + +.columns-container[data-bg-image]{ + background-image: var(--bg-image-url); + background-size: cover; + background-position: center; + transition: padding-left 0.3s ease; + color: white; + text-align: center; + background-color: black; +} + +.linear-gradient.columns-container[data-bg-image]{ + background-size: cover; + background-position: center; + transition: padding-left 0.3s ease; + color: white; + background-image: none; + background-color: black; +} + +.columns.new-v2 h2 { + font-family: "IBM Plex Sans" ,sans-serif; + font-size: 25px; + font-weight: 600; + line-height: 32px; + text-align: center; + margin: 1em auto; +} + + + +@media (min-width: 768px) { + .linear-gradient.columns-container[data-bg-image]{ + background-image: linear-gradient(to right, rgb(39 1 107 / 100%) 20%, rgb(0 0 0 / 0%)), var(--bg-image-url); + } + + .columns-container[data-bg-image]{ + background-image: var(--bg-image-url); + } + + .linear-gradient.columns.bg-image > div { + width: calc(100% - 30%)!important; + } + + .columns.new-v2 h2 { + font-family: "IBM Plex Sans" ,sans-serif; + font-size: 32px; + font-weight: 600; + line-height: 36px; + text-align: center; + width: 600px; + margin: 2em auto; + } + + .columns.new-v2 h3 { + font-family: "IBM Plex Sans" ,sans-serif; + font-size: 32px; + font-weight: 700; + line-height: 37px; + text-align: left; + color: #006EFF; + } + + .columns.new-v2 p { + font-size: 16px; + font-weight: 400; + line-height: 22px; + } + + .columns.new-v2 div.columns-text-col { + padding: 2em; + } + + .columns.new-v2 div.columns-right-col { + margin-left: 5em; + margin-right: 5em; + } + + .columns.new-v2 div.columns-left-col { + margin-left: 5em; + margin-right: 5em; + } +} + +@media (min-width: 1024px) { + .columns.new-v2 div.columns-left-col { + margin-right: 10em; + margin-left: 0; + } +} + +.columns.bg-image > div > div > h4 { + padding: 0 0 50px; + font-size: var(--heading-font-size-m); + font-style: bold; +} + +.columns.bg-image .button-container { + padding: 10px 0 0; +} + +.columns.bg-image svg { + filter: invert(1) grayscale(1) brightness(100); +} + +.columns.with-box-shadow { + box-shadow: 0 3px 8px 0 rgb(0 0 0 / 20%); + border-radius: 5px; + padding: 35px 0; + color: var(--checkbox-label); +} + +.columns.highlight-text.black.block > div > div:first-child { + font-size: var(--heading-font-size-l); +} + + +main .section.two-columns .right-col .products.plans a.button:any-link { + background-color: var(--button-background-color); + border: 2px solid var(--button-background-color); +} + +.two-columns .left-col p a.info-button.modal { + color: var(--white-color); + display: flex; + font-weight: var(--font-weight-regular); + align-items: baseline; +} + +.two-columns .left-col p a.info-button.modal:hover { + opacity: .8; +} + +.two-columns .left-col p a.info-button.modal::before { + content: url("/_src/icons/user-guide-white.svg"); + color: white; + padding-right: 8px; +} + +.columns.new-v2 a::after { + content: '\2192'; + width: 24px; + height: 24px; + display: inline-block; + transition: all .2s cubic-bezier(.4,0,.2,1); + transform: translateX(0); + margin-left: 2px; +} + +.columns.new-v2 a:hover::after { + transform: translateX(5px); +} + +.columns.carousel > div.carousel-buttons { + justify-content: center; +} + +@media (max-width: 1399px) { + .columns-wrapper { + padding: 0 var(--section-large-desktop-padding); + } + + /* stylelint-disable-next-line selector-class-pattern */ + .v2_benefits .columns-wrapper { + padding: var(--section-mobile-padding-vertical); + } + + .columns.video-presentation .button-container { + margin-right: 10px; + } + + .columns.screenshots > div { + justify-content: space-evenly; + } +} + +@media (max-width: 992px) { + .columns.carousel > div { + gap: 0; + } + + .creators .columns > div > div { + text-align: center; + } + + .columns.video-presentation > div > div { + width: 520px; + } + + .columns-wrapper > div.grey-bck > div > div { + flex: 1; + } + + .creators .header-mobile.columns-container div { + text-align: center; + } + + .creators .header-mobile h1 { + font-size: 32px; + line-height: 1.2; + } + + .creators .header-mobile h2 { + font-size: 16px; + line-height: 1.2; + color: #006DFF; + font-weight: bold; + margin-bottom: 0; + } + + .creators .header-mobile h3 { + font-size: var(--heading-font-size-l); + line-height: 1.2; + } + + .creators .columns-container h3, .creators .columns-container h5, .creators .columns-container h2, .creators .columns-container h1 { + font-family: "IBM Plex Sans", sans-serif; + } + + .creators .default-content-wrapper h2 { + font-family: "IBM Plex Sans", sans-serif; + } + + .creators .image-position.columns-container div.columns-img-col { + display: none; + } + + .creators .image-position.columns-container .columns > div > div { + text-align: center; + } + + .creators .no-space-top .default-content-wrapper h2 { + padding-top: 23px; + } + + .section.wide.light-sky-blue.columns-container.awards.v2 { + width: 100%; + padding: 0; + margin: 4em 0 2em; + } + + .columns-wrapper > div.grey-bck div.columns-text-col { + padding: 2em; + } +} + +@media (min-width: 768px) { + .v2 .columns > div { + flex-direction: row; + } + + .v2 .columns.awards .columns-wrapper { + padding: 0 10px 5em; + } + + .v2 .columns.awards > div > div > p:last-of-type { + max-width: 325px; + margin: 10px auto 0; + } + + .columns.screenshots > div { + flex-direction: row; + } + + .columns.screenshots > div > .columns-img-col { + flex: 0 0 230px; + } +} + +@media (max-width: 768px) { + .columns-wrapper { + padding: var(--body-padding) var(--body-padding) 0; + } + + .cta .columns-img-col picture { + width: 345px; + } + + .columns.video-presentation > div > div > h3 { + font-size: var(--heading-font-size-l); + } + + .columns.carousel > div > div { + flex: 0 0 98%; + } +} + +@media (max-width: 500px) { + .columns.video-presentation > div > div { + width: 100%; + } + + .columns.carousel > div > div { + width: 100%; + flex: 1 0 100%; + box-sizing: border-box; + margin: 0; + } +} diff --git a/_src/blocks/columns/columns.js b/_src/blocks/columns/columns.js new file mode 100644 index 000000000..08de58fb9 --- /dev/null +++ b/_src/blocks/columns/columns.js @@ -0,0 +1,180 @@ +import { debounce, matchHeights } from '../../scripts/utils/utils.js'; + +function getItemsToShow() { + const width = window.innerWidth; + return width <= 767 ? 1 : 3; // 1 item for mobile, 2 for tablet, 3 for desktop +} + +function countSlides(carouselContent) { + return Math.ceil(carouselContent.children.length / getItemsToShow()); +} + +function showSlides(carousel, slideNumber) { + const carouselContent = carousel.querySelector('.columns.carousel > div:first-child'); + const itemsToShow = getItemsToShow(); + const translateXValue = -(carousel.clientWidth * slideNumber) / itemsToShow; + + carouselContent.style.transform = `translateX(${translateXValue}px)`; + carouselContent.style.transition = 'transform 0.5s ease'; +} + +function hideExcessElements(carousel) { + showSlides(carousel, 0); // Always show the first set initially +} + +function setActiveButton(button, buttonsWrapper) { + buttonsWrapper.querySelector('.active-button')?.classList.remove('active-button'); + button.classList.add('active-button'); +} + +function createNavigationButtons(numberOfSlides, carousel) { + const buttonsWrapper = document.createElement('div'); + buttonsWrapper.className = 'carousel-buttons'; + + Array.from({ length: numberOfSlides }, (_, i) => { + const button = document.createElement('button'); + button.setAttribute('aria-label', `Slide ${i + 1}`); + button.addEventListener('click', () => { + if (!button.classList.contains('active-button')) { + showSlides(carousel, i); + setActiveButton(button, buttonsWrapper); + } + }); + buttonsWrapper.appendChild(button); + return button; + }); + + buttonsWrapper.firstChild?.classList.add('active-button'); // Set first button as active + return buttonsWrapper; +} + +function setupCarousel(carousel, resetSlidePosition = false) { + const carouselContent = carousel.querySelector('.columns.carousel > div'); + if (resetSlidePosition) carouselContent.style.transform = 'translateX(0px)'; + + const buttonsWrapper = createNavigationButtons(countSlides(carouselContent), carousel); + carousel.querySelector('.carousel-buttons')?.remove(); // Remove existing buttons + carousel.appendChild(buttonsWrapper); + hideExcessElements(carousel); +} + +function setImageAsBackgroundImage() { + const columns = document.querySelectorAll('.columns.text-over-image > div > div'); + + columns.forEach((column) => { + const image = column.querySelector('img'); + + if (image) { + const src = image.getAttribute('src'); + + column.style.backgroundImage = `url(${src})`; + + // remove the p tag that contains the picture element + const pContainer = image.closest('p'); + if (pContainer) { + pContainer.remove(); + } + } + }); +} + +export default function decorate(block, options) { + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + const blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + } + + const { linksOpenInNewTab, type } = block.closest('.section').dataset; + const cols = [...block.firstElementChild.children]; + block.classList.add(`columns-${cols.length}-cols`); + + // setup image columns + [...block.children].forEach((row) => { + [...row.children].forEach((col) => { + const pic = col.querySelector('picture'); + if (pic) { + const picWrapper = pic.closest('div'); + if (picWrapper && picWrapper.children.length === 1) { + // picture is only content in column + picWrapper.classList.add('columns-img-col'); + } + } else { + const children = [...row.children]; + + if (children.length === 1) { + col.closest('div').classList.add('columns-title-col'); + } else { + const firstParentIndex = children.indexOf(col.closest('div')); + + col.closest('div').classList.add('columns-text-col'); + if (firstParentIndex) { + col.closest('div').classList.add('columns-right-col'); + } else { + col.closest('div').classList.add('columns-left-col'); + } + } + } + }); + }); + + if (linksOpenInNewTab === 'true') { + block.querySelectorAll('.button-container > a').forEach((anchorEl) => { + anchorEl.target = '_blank'; + anchorEl.rel = 'noopener noreferrer'; + }); + } + + if (block.classList.contains('text-over-image')) { + setImageAsBackgroundImage(); + } + + // If it has the carousel class, then setup the carousel + if (block.classList.contains('carousel')) { + setupCarousel(block); + } + + window.addEventListener('resize', debounce(() => { + // Check if the block still has the carousel class before resetting + if (block.classList.contains('carousel')) { + setupCarousel(block, true); // Pass true to reset the slide position + } + }, 250)); + window.dispatchEvent(new Event('resize')); // trigger resize to give width to columns + + const sectionDiv = document.querySelector('.columns-container[data-bg-image]'); + if (sectionDiv) { + const bgImageUrl = sectionDiv.getAttribute('data-bg-image'); + if (bgImageUrl) { + sectionDiv.style.setProperty('--bg-image-url', `url(${bgImageUrl})`); + } + } + + // This allows the event to cross the shadow DOM boundary + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, + }); + + if (type && type === 'video_left') { + block.closest('.section').classList.add('video-left'); + const leftCol = block.querySelector('.columns-img-col'); + const videoPath = leftCol.querySelector('tr:last-of-type').innerText.trim(); + const videoImg = leftCol.querySelector('img').getAttribute('src'); + + leftCol.innerHTML = ``; + } + + const chatOptions = document.querySelector('.chat-options'); + if (chatOptions) { + const cardButtons = chatOptions.querySelectorAll('.button-container'); + cardButtons.forEach((button) => { + button.previousElementSibling.classList.add('chat-options-text'); + }); + matchHeights(chatOptions, '.chat-options-text'); + matchHeights(chatOptions, 'table'); + } + matchHeights(block, 'h3'); + matchHeights(block, 'h4'); +} diff --git a/_src/blocks/creators-block/creators-block.css b/_src/blocks/creators-block/creators-block.css new file mode 100644 index 000000000..4286944c2 --- /dev/null +++ b/_src/blocks/creators-block/creators-block.css @@ -0,0 +1,184 @@ +@media (min-width: 992px) { + /* desktop */ + .creators-block-wrapper { + max-width: var(--section-desktop-max-width); + padding: 0 var(--section-desktop-padding); + margin: 0 auto; + } +} + +@media (min-width: 1600px) { + /* large desktop */ + .creators-block-wrapper { + max-width: var(--section-large-desktop-max-width); + padding: 0 var(--section-large-desktop-padding); + } +} + +.creators-block-wrapper { + border-radius: 20px; +} + +.creators-block.block>div { + position: relative; + padding-top: 40px; +} + +.creators-block.block>div:first-of-type img { + position: absolute; + right: 0; + top: 40px; +} + +.creators-block.block>div h3 { + text-align: left; + font-size: 60px; + line-height: 70px; + font-family: "IBM Plex Sans", sans-serif; + font-weight: normal; + letter-spacing: 0; + color: #FFF; +} + +.creators-block.block>div p { + text-align: left; + font-size: 28px; + line-height: 32px; + font-family: "IBM Plex Sans", sans-serif; + font-weight: bold; + letter-spacing: 0; + color: #FFF; +} + +.creators-block.block>div:nth-child(3) { + display: flex; + align-items: center; + justify-content: center; +} + +.creators-block.block>div:nth-child(3) a.button:any-link { + min-width: 230px; + height: 48px; + padding: 10px 10px 10px 25px; + background: #E72325 0% 0% no-repeat padding-box; + border-radius: 40px; + justify-content: center; + font: normal normal 500 18px / 24px Roboto, sans-serif; + margin-bottom: 35px; + color: white; +} + +.creators-block.block>div:nth-child(2)>div { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); + grid-gap: 30px; +} + +.creators-block.block>div:nth-child(2) .creator-box { + display: flex; + position: relative; + width: 220px; + height: 310px; + padding: 16px 23px; + border-radius: 20px; +} + +.creators-block.block>div:nth-child(2) .creator-box>div:nth-child(3) { + position: absolute; + color: #fff; + text-align: left; + font-size: 12px; + line-height: 16px; + font-family: Roboto, sans-serif; + font-weight: normal; + bottom: 16px; +} + +.creators-block.block>div:nth-child(2) .creator-box>div:nth-child(2) { + position: absolute; + color: #016DFF; + text-align: left; + font-size: 12px; + line-height: 16px; + font-family: Roboto, sans-serif; + font-weight: normal; + bottom: 33px; +} + +.creators-block.block>div:nth-child(2) .creator-box>div:nth-child(1) { + position: absolute; + color: #fff; + text-align: left; + font-size: 12px; + line-height: 16px; + font-family: Roboto, sans-serif; + font-weight: bold; + bottom: 64px; +} + +.creators-block.block>div:nth-child(2) .creator-box>div:nth-child(1) img { + position: relative; + top: 10px; + width: 30px; +} + +@media (max-width: 1320px) { + .creators-block-wrapper { + max-width: var(--section-desktop-max-width); + padding: 0 var(--section-desktop-padding); + margin: 8px; + } +} + +@media (max-width: 990px) { + .creators-block-wrapper { + max-width: var(--section-desktop-max-width); + padding: 0 var(--section-desktop-padding); + margin: 8px; + } +} + +@media (max-width: 768px) { + .creators.creators-block-container .creators-block-wrapper { + margin: 0 8px; + } + + .creators.creators-block-container >div h3 { + font-size: var(--heading-font-size-l); + line-height: 1.2; + } + + .creators-block.block>div { + padding: 30px 0; + } + + .creators-block.block>div:first-of-type { + padding: 30px 0 0; + } + + .creators-block.block>div:last-of-type { + padding: 0; + } + + .creators-block.block>div p { + font-size: 22px; + line-height: 26px; + } + + .creators-block.block>div p:first-of-type { + margin: 0; + } + + .creators-block.block>div:first-of-type img { + position: relative; + width: 60px; + top: 0; + } +} + +@media (max-width: 525px) { + .creators-block.block>div:nth-child(2) .creator-box { + width: 100%; + height: 120vw; + } +} \ No newline at end of file diff --git a/_src/blocks/creators-block/creators-block.js b/_src/blocks/creators-block/creators-block.js new file mode 100644 index 000000000..23f8a405d --- /dev/null +++ b/_src/blocks/creators-block/creators-block.js @@ -0,0 +1,57 @@ +export default function decorate(block) { + const parentBlockStyle = block.closest('.section > div').style; + const { + // eslint-disable-next-line no-unused-vars + backgroundColor, + } = block.closest('.section').dataset; + + if (backgroundColor) parentBlockStyle.backgroundColor = backgroundColor; + + block.querySelectorAll('table').forEach((table) => { + const newDiv = document.createElement('div'); + newDiv.classList.add('creator-box'); + + const linkToCreator = table.querySelector('tr:nth-child(4) td'); + const creatorLink = linkToCreator ? linkToCreator.textContent.trim() : ''; + + // Find the image from the last row + const lastRow = table.querySelector('tr:last-child'); + const img = lastRow.querySelector('img'); + let backgroundImage = ''; + + if (img) { + backgroundImage = `url(${img.src})`; + } + + table.querySelectorAll('tr').forEach((tr, rowIndex) => { + // Skip the last row since we've already processed the image + if (rowIndex === table.rows.length - 1) return; + + tr.querySelectorAll('td').forEach((td) => { + const innerDiv = document.createElement('div'); + innerDiv.innerHTML = td.innerHTML; + newDiv.style.background = `linear-gradient(to bottom, rgba(0, 0, 0, 0) 60%, #000 100%), ${backgroundImage}`; + newDiv.style.backgroundSize = 'cover'; // Cover the whole div + newDiv.style.backgroundPosition = 'center'; // Center the image + newDiv.appendChild(innerDiv); + }); + }); + + // Remove the 4th div from creator-box + const fourthDiv = newDiv.querySelectorAll('div:nth-child(4)'); + if (fourthDiv.length > 0) { + newDiv.removeChild(fourthDiv[0]); + } + + // Wrap the newDiv in an anchor element if a link is found + if (creatorLink) { + const anchor = document.createElement('a'); + anchor.href = creatorLink; + anchor.target = '_blank'; + anchor.appendChild(newDiv); + table.parentNode.replaceChild(anchor, table); + } else { + table.parentNode.replaceChild(newDiv, table); + } + }); +} diff --git a/_src/blocks/dropdown-box/dropdown-box.css b/_src/blocks/dropdown-box/dropdown-box.css new file mode 100644 index 000000000..ea4fd0a2d --- /dev/null +++ b/_src/blocks/dropdown-box/dropdown-box.css @@ -0,0 +1,619 @@ +.dropdown-box-container .block img { + width: 20px; +} + +.dropdown-box-container .block>div { + padding: 15px 30px; +} + +/* blue tbs */ +.dropdown-box-container .block>div>div { + border-bottom: 1px solid #D6D6D6; +} + +.dropdown-box-container .block>div:not(:first-child) { + padding: 0; + font-weight: 500; + display: flex; +} + +.dropdown-box-container .block>div:nth-child(1) { + color: #fff; + background-color: #006eff; + padding: 0; +} + +.dropdown-box-container .block>div:first-of-type>div, +.dropdown-box-container .block>div:last-of-type>div { + border-bottom: 0 none; +} + +.dropdown-box-container .block>div:nth-child(1)>div { + font-weight: bold; + cursor: pointer; + padding: 15px 30px; +} + +.dropdown-box-container .block>div:not(:first-child)>div { + flex: 1; + padding: 15px 2%; + display: inline-block; +} + +.dropdown-box-container .block>div>div strong em { + color: red; + font-style: normal; +} + +.dropdown-box-container .block.hide-title>div:nth-child(1)>div, +.dropdown-box-container.hide-title .block>div:nth-child(1)>div { + display: none; +} + +.dropdown-box-container .block:not(.selected-2)>div>div:nth-child(2), +.dropdown-box-container .block.selected-1>div>div:nth-child(2), +.dropdown-box-container .block.selected-2>div>div:nth-child(3), +.dropdown-box-container .block.selected-3>div>div:nth-child(4) { + background-color: #f6f6f6; +} + +.dropdown-box-container.selected-1 .block>div>div:nth-child(2), +.dropdown-box-container.selected-2 .block>div>div:nth-child(3), +.dropdown-box-container.selected-3 .block>div>div:nth-child(4) { + background-color: #f6f6f6; +} + +.dropdown-box-container.selected-2 .block>div>div:nth-child(2), +.dropdown-box-container.selected-3 .block>div>div:nth-child(2) { + background-color: white; +} + +.dropdown-box-container .block>div:not(:first-child)>div:first-child { + display: block; + align-items: center; +} + +.dropdown-box-container .block>div:not(:first-child)>div:first-child p { + margin: 0; +} + +.dropdown-box-container .block>div:not(:first-child)>div:first-child span { + margin-left: 10px; +} + +.dropdown-box-container .block.has2divs>div>div:nth-child(2) { + width: 66%; + background-color: white; +} + +.dropdown-box-container .block.inactive>div:not(:first-child)>div, +.dropdown-box-container .block.closed>div:not(:first-child)>div, +.dropdown-box-container.inactive .block>div:not(:first-child)>div, +.dropdown-box-container.closed .block>div:not(:first-child)>div { + display: none; +} + +.dropdown-box-container .block.baby-blue>div:not(:first-child)>div:first-child, +.dropdown-box-container.baby-blue .block>div:not(:first-child)>div:first-child { + background-color: #e3f2ff; +} + +.dropdown-box-container .block.closed.inactive>div:not(:first-child)>div, +.dropdown-box-container.closed .block.inactive>div:not(:first-child)>div { + display: inline-block; +} + +.dropdown-box-container .block.has2divs>div>div:nth-child(2) img { + width: 400px; +} + +.dropdown-box-container.awards90 .block.has2divs>div>div:nth-child(2) img { + width: 90%; +} + +.dropdown-box-container .block.inactive>div:nth-child(1)>div::before, +.dropdown-box-container .block.closed>div:nth-child(1)>div::before { + width: 10px; + height: 10px; + float: left; + content: ""; + margin-right: 10px; + margin-top: 10px; + border: solid white; + border-width: 0 2px 2px 0; + transform: rotate(-135deg); +} + +.dropdown-box-container.arrow-dark .block.inactive>div:nth-child(1)>div::before, +.dropdown-box-container.arrow-dark .block.closed>div:nth-child(1)>div::before { + width: 10px; + height: 10px; + float: left; + content: ""; + margin-right: 10px; + margin-top: 10px; + border: solid black; + border-width: 0 2px 2px 0; + transform: rotate(-135deg); +} + +/* handling - arrow down/up */ +/* stylelint-disable no-descending-specificity */ +.dropdown-box-container .block>div:nth-child(1)>div::before, +.dropdown-box-container .block.closed.inactive>div:nth-child(1)>div::before { + width: 10px; + height: 10px; + float: left; + content: ""; + margin-right: 10px; + margin-top: 4px; + border: solid white; + border-width: 0 2px 2px 0; + transform: rotate(45deg); +} + +.dropdown-box-container.arrow-dark .block>div:nth-child(1)>div::before, +.dropdown-box-container.arrow-dark .block.closed.inactive>div:nth-child(1)>div::before { + width: 10px; + height: 10px; + float: left; + content: ""; + margin-right: 10px; + margin-top: 4px; + border: solid black; + border-width: 0 2px 2px 0; + transform: rotate(45deg); +} + +.dropdown-box-container .default-content-wrapper h5 { + font-size: 40px; + line-height: 1.2; + font-weight: 500; + color: #000; + font-family: roboto, sans-serif; + margin-bottom: 22px; + text-align: left; +} + +.dropdown-box-container .new, +.dropdown-box-container.new .block { + padding: 0 0 2em 2em; + cursor: pointer; + box-shadow: 0 3px 8px 0 #E5E5E5; + position: relative; + border-radius: 10px; + margin-bottom: 1em; + z-index: 3; +} + +.dropdown-box-container .dropdown-box-wrapper { + position: relative; +} + +.dropdown-box-container>div:nth-child(2) .new::after, +.dropdown-box-container.new>div:nth-child(2) .block::after { + content: ""; + position: absolute; + top: -60px; + right: 0; + width: 196px; + height: 90pt; + background: url("../../images/patter_grid_blue.png") no-repeat; + z-index: -1; +} + +.dropdown-box-container .new div:nth-child(1), +.dropdown-box-container.new .block div:nth-child(1) { + background-color: white; + padding-top: 2em; + padding-right: 2em; +} + +.dropdown-box-container .new>div:not(:first-child), +.dropdown-box-container.new .block>div:not(:first-child) { + display: block; +} + +.dropdown-box-container .new.inactive>div:not(:first-child), +.dropdown-box-container.new .block.inactive>div:not(:first-child) { + display: none; +} + +.dropdown-box-container .new.closed>div:not(:first-child), +.dropdown-box-container.new.closed .block.inactive>div:not(:first-child) { + display: none; +} + +.dropdown-box-container .new.closed.inactive>div:not(:first-child), +.dropdown-box-container.new.closed .block>div:not(:first-child) { + display: block; +} + +.dropdown-box-container .new>div:nth-child(1)>div, +.dropdown-box-container.new .block>div:nth-child(1)>div { + background: transparent; + font-size: 24px; + line-height: 1.25; + font-weight: 600; + color: #000; + padding: 0; + position: relative; +} + +.dropdown-box-container .new>div:nth-child(1)>div::before, +.dropdown-box-container.new .block>div:nth-child(1)>div::before { + display: none; +} + +.dropdown-box-container .new>div:nth-child(1)>div::after, +.dropdown-box-container.new .block>div:nth-child(1)>div::after { + content: ""; + position: absolute; + display: block; + top: 0; + bottom: 0; + margin: auto 0; + right: 15px; + width: 10px; + height: 10px; + border: solid #c5c5c5; + border-width: 0 2px 2px 0; + transform: rotate(45deg); + transition: top 0.3s ease-in-out, -webkit-transform 0.3s ease-in-out; + transition: top 0.3s ease-in-out, transform 0.3s ease-in-out; + transition: top 0.3s ease-in-out, transform 0.3s ease-in-out, -webkit-transform 0.3s ease-in-out; +} + +.dropdown-box-container .new>div:not(:first-child)>div:first-child, +.dropdown-box-container.new .block>div:not(:first-child)>div:first-child { + padding: 0; + font-weight: 500; + display: block; + width: 100%; + font-size: 18px; + color: #3c3c3c; +} + +.dropdown-box-container .new>div:not(:first-child)>div:first-child a, +.dropdown-box-container.new .block>div:not(:first-child)>div:first-child a { + color: #006eff; +} + +.dropdown-box-container.slider .new>div:not(:first-child) p, +.dropdown-box-container.slider.new .block>div:not(:first-child) p { + text-align: center; +} + +.dropdown-box-container.slider .new>div:not(:first-child) p img, +.dropdown-box-container.slider.new .block>div:not(:first-child) p img { + width: 300px; +} + +.dropdown-box-container.dropdown-slider { + position: relative; + margin-bottom: 2em; +} + +.dropdown-box-container.dropdown-slider::after { + content: ""; + position: absolute; + top: 16px; + right: 0; + width: 196px; + height: 90pt; + background: url("../../images/patter_grid_blue.png") no-repeat; + z-index: 1; +} + +.dropdown-box-container.dropdown-slider .dropdown-box-wrapper { + display: none; +} + +.dropdown-box-container.dropdown-slider .slider-box { + position: initial; +} + +.dropdown-box-container.dropdown-slider .slider-box .title { + padding: 1em; + cursor: pointer; + box-shadow: 0 3px 8px 0 #E5E5E5; + position: relative; + border-radius: 10px; + margin-bottom: 1em; + z-index: 3; + font-size: 16px; + line-height: 1.25; + color: #000; +} + +.dropdown-box-container.dropdown-slider .slider-box .title::after { + content: ""; + position: absolute; + display: block; + top: 0; + bottom: 0; + margin: auto 0; + right: 15px; + width: 10px; + height: 10px; + border: solid #c5c5c5; + border-width: 0 2px 2px 0; + transform: rotate(45deg); + transition: top 0.3s ease-in-out, -webkit-transform 0.3s ease-in-out; + transition: top 0.3s ease-in-out, transform 0.3s ease-in-out; + transition: top 0.3s ease-in-out, transform 0.3s ease-in-out, -webkit-transform 0.3s ease-in-out; +} + +.dropdown-box-container.dropdown-slider.no-load-bar .slider-box .title { + cursor: default; +} + +.dropdown-box-container.dropdown-slider.no-load-bar .slider-box .title::after { + display: none; +} + +.dropdown-box-container.dropdown-slider .slider-box .title .loading-bar { + display: none; + position: absolute; + top: 0; + left: 0; + width: 0; + height: 4px; + background: #006eff; + font-size: 19px; + line-height: 22px; + margin-bottom: 1em; +} + +.dropdown-box-container.dropdown-slider .slider-box .description { + position: absolute; + top: 12em; + right: 0; + padding-left: 5%; + display: none; + background-color: white; + z-index: 2; +} + +.dropdown-box-container.dropdown-slider .slider-box .active .title::after { + border-color: #006eff; + transform: rotate(225deg); + top: 11px; +} + +.dropdown-box-container.dropdown-slider .slider-box .active .title .loading-bar { + display: block; +} + +.dropdown-box-container.dropdown-slider .slider-box .active .description { + display: block; +} + +.dropdown-box-container { + clear: both; + padding: 0 var(--body-padding); + + .row { + --bs-gutter-x: 1.5rem; + --bs-gutter-y: 0; + + display: flex; + flex-wrap: wrap; + margin-top: calc(-1* var(--bs-gutter-y)); + margin-right: calc(-.5* var(--bs-gutter-x)); + } + + .row>* { + flex-shrink: 0; + width: 100%; + max-width: 100%; + padding-right: calc(var(--bs-gutter-x)* .5); + padding-left: calc(var(--bs-gutter-x)* .5); + margin-top: var(--bs-gutter-y); + } + + .col-12 { + flex: 0 0 auto; + width: 100%; + } + + @media (min-width: 768px) { + .col-md-7 { + flex: 0 0 auto; + width: 58.3333%; + } + } + + @media (min-width: 768px) { + .col-md-5 { + flex: 0 0 auto; + width: 41.6667%; + } + } + + &.container { + --bs-gutter-x: 1.5rem; + --bs-gutter-y: 0; + + width: 100%; + padding-right: calc(var(--bs-gutter-x)* .5); + padding-left: calc(var(--bs-gutter-x)* .5); + margin-right: auto; + margin-left: auto; + + @media (min-width: 576px) { + max-width: 540px; + } + + @media (min-width: 768px) { + max-width: 720px; + } + + @media (min-width: 992px) { + max-width: 960px; + } + + @media (min-width: 1200px) { + max-width: 1140px; + } + + @media (min-width: 1400px) { + max-width: 1320px; + } + } + + @media (min-width: 990px) { + max-width: var(--section-desktop-max-width); + padding: 0 var(--section-desktop-padding); + margin: 0 auto; + } + + @media (min-width: 1600px) { + max-width: var(--section-large-desktop-max-width); + padding: 0 var(--section-large-desktop-padding); + } +} + + +@media (width <=991px) { + .dropdown-box-container .default-content-wrapper h5 { + font-size: 33px; + } +} + +/* for mobile */ +@media (width <=768px) { + .dropdown-box-container { + clear: both; + padding: 0 15px 5px; + } + + .dropdown-box-container.dropdown-slider .dropdown-box-wrapper { + display: block; + } + + .dropdown-box-container.dropdown-slider .dropdown-box-wrapper img { + width: 90%; + } + + .dropdown-box-container.dropdown-slider .slider-box { + display: none; + } + + .dropdown-box-container .block>div:not(:first-child) { + display: block; + } + + .dropdown-box-container .block>div:nth-child(1)>div::before, + .dropdown-box-container .block.closed.inactive>div:nth-child(1)>div::before { + margin-top: 1px !important; + } + + .dropdown-box-container .block>div:nth-child(1)>div { + padding: 10px 3% !important; + display: flex; + font-size: 15px; + line-height: 17px; + } + + .dropdown-box-container .new>div:nth-child(1)>div::after, + .dropdown-box-container.new .block>div:nth-child(1)>div::after { + position: static; + margin-left: 15px; + flex: 0 0 auto; + } + + .dropdown-box-container.no-dropdown-logic .block>div:nth-child(1)>div { + display: block; + } + + .dropdown-box-container.no-dropdown-logic .new>div:nth-child(1)>div::after, + .dropdown-box-container.no-dropdown-logic.new .block>div:nth-child(1)>div::after { + display: none; + } + + .dropdown-box-container>div:nth-child(2) .new::after { + top: -90px; + right: 0; + width: 135px; + height: 90pt; + display: none; + } + + .dropdown-box-container.dropdown-slider::after { + display: none; + } + + .dropdown-box-container .block>div:not(:first-child)>div { + padding: 8px 2% !important; + font-size: 15px; + } + + .dropdown-box-container .block img { + width: 15px; + } + + .dropdown-box-container .block>div:not(:first-child)>div:nth-child(1) { + width: 100%; + text-align: center; + } + + .dropdown-box-container .block>div:not(:first-child)>div:not(:first-child) { + width: 50%; + float: left; + } + + .dropdown-box-container .block.has4divs>div:not(:first-child)>div:not(:first-child) { + width: 33%; + min-height: 3em; + font-size: 13px; + line-height: 16px; + } + + .dropdown-box-container .block.has4divs>div:not(:first-child)>div:first-child p { + line-height: 17px; + } + + .dropdown-box-container .block.has3divs>div:not(:first-child)>div:not(:first-child) { + width: 50%; + min-height: 3em; + font-size: 13px; + line-height: 16px; + } + + .dropdown-box-container .block.has2divs>div:not(:first-child)>div:not(:first-child) { + width: 100%; + } + + .dropdown-box-container .default-content-wrapper h5 { + font-size: 30px; + line-height: 32px; + } + + .dropdown-box-container .new, + .dropdown-box-container.new .block { + padding: 15px; + } + + .dropdown-box-container .new p, + .dropdown-box-container.new .block p { + font-size: 15px; + } + + .dropdown-box-container .new div:nth-child(1), + .dropdown-box-container.new .block div:nth-child(1) { + padding-top: 0; + padding-right: 0; + } + + .dropdown-box-container .new div:nth-child(1)>div, + .dropdown-box-container.new .block div:nth-child(1)>div { + font-size: 18px; + line-height: 24px; + } + + .dropdown-box-container .new ul, + .dropdown-box-container.new .block ul { + text-align: left; + } +} \ No newline at end of file diff --git a/_src/blocks/dropdown-box/dropdown-box.js b/_src/blocks/dropdown-box/dropdown-box.js new file mode 100644 index 000000000..468c09a25 --- /dev/null +++ b/_src/blocks/dropdown-box/dropdown-box.js @@ -0,0 +1,82 @@ +/* + Information: + - the tab is open by default + - [add-on] - will be treated as green tag + + Parameters: + - (closed) : for tab to be closed by default +*/ +export default function decorate(block) { + const parentSelector = block.closest('.section'); + const { type, topBackgroundColor, topTextColor } = parentSelector.dataset; + + // search for [] to replace with span greeenTag class + const getFirstDivs = block.querySelectorAll('.dropdown-box-container .block > div > div:nth-child(1)'); + getFirstDivs.forEach((item) => { + item.innerHTML = item.innerHTML.replace('[', ''); + item.innerHTML = item.innerHTML.replace(']', ''); + }); + + // make slideUp slideDown functionality + const getFirstTabs = block.querySelectorAll('.dropdown-box-container .block > div:first-child'); + getFirstTabs.forEach((tab) => { + tab.parentNode.classList.remove('inactive'); + tab.addEventListener('click', () => { + tab.parentNode.classList.toggle('inactive'); + }); + }); + + if (block.children.length >= 2) { + const childrenNr = block.children[1].children.length; + block.classList.add(`has${childrenNr}divs`); + + if (topBackgroundColor) { + block.querySelector('div:nth-child(1) > div > div').style.backgroundColor = topBackgroundColor; + } + + if (topTextColor) { + block.querySelector('div:nth-child(1) > div').style.color = topTextColor; + } + } + + // if it's slider + if (type === 'slider') { + block.closest('.dropdown-box-container').classList.add('container', 'dropdown-slider'); + const sliderBox = document.createElement('div'); + sliderBox.className = 'slider-box'; + + const infoTextEl = block.children[0].children[0]; + const infoTextEl2 = block.children[1].children[0]; + sliderBox.innerHTML = ` +
+
+
+ ${infoTextEl.innerHTML} +
+
${infoTextEl2.innerHTML}
+
+ `; + + block.closest('.dropdown-box-container').appendChild(sliderBox); + } + + // if it's slider + if (type === 'slider-no-load-bar') { + block.closest('.dropdown-box-container').classList.add('container', 'dropdown-slider', 'no-load-bar'); + const sliderBox = document.createElement('div'); + sliderBox.className = 'slider-box'; + + const infoTextEl = block.children[0].children[0]; + const infoTextEl2 = block.children[1].children[0]; + sliderBox.innerHTML = ` +
+
+ ${infoTextEl.innerHTML} +
+
${infoTextEl2.innerHTML}
+
+ `; + + block.closest('.dropdown-box-container').appendChild(sliderBox); + } +} diff --git a/_src/blocks/dropdownbox-compare/dropdownbox-compare.css b/_src/blocks/dropdownbox-compare/dropdownbox-compare.css new file mode 100644 index 000000000..d6ec62f61 --- /dev/null +++ b/_src/blocks/dropdownbox-compare/dropdownbox-compare.css @@ -0,0 +1,302 @@ +/* b-boxes .dropdownbox-compare-container */ +.dropdownbox-compare-container { + clear: both; + padding: 0!important; +} + +.dropdownbox-compare-container .block img { + width: 20px; +} + +.dropdownbox-compare-container .block > div { + padding: 0; + font-weight: 500; + display: flex; +} + +/* blue tbs */ +.dropdownbox-compare-container .block > div > div { + border-bottom: 1px solid #e4f2ff; + border: 1px solid #e4f2ff; + flex: 1; + padding: 15px 20px; + display: inline-block; +} + +.dropdownbox-compare-container .block > div:nth-child(1) > div { + font-weight: bold; + cursor: pointer; +} + +.dropdownbox-compare-container .block > div > div strong em { + color: red; + font-style: normal; +} + +.dropdownbox-compare-container .block > div:first-of-type > div, .dropdownbox-compare-container .block > div:last-of-type > div { + border-bottom: 0 none; +} + +.dropdownbox-compare-container .block > div > div:not(:nth-child(1)) { + display: flex; + align-items: center; + justify-content: center; +} + +.dropdownbox-compare-container .block > div:nth-child(1) > div:nth-child(1) { + color: #fff; + background-color: #006eff; +} + +.dropdownbox-compare-container .block > div:not(:nth-child(1)) > div:nth-child(1) { + background: #e4f2ff; +} + +.dropdownbox-compare-container .block:not(.selected-2) > div > div:nth-child(2), .dropdownbox-compare-container .block.selected-1 > div > div:nth-child(2), .dropdownbox-compare-container .block.selected-2 > div > div:nth-child(3), .dropdownbox-compare-container .block.selected-3 > div > div:nth-child(4) { + background-color: #f6f6f6; +} + +.dropdownbox-compare-container.selected-1 .block > div > div:nth-child(2), .dropdownbox-compare-container.selected-2 .block > div > div:nth-child(3), .dropdownbox-compare-container.selected-3 .block > div > div:nth-child(4) { + background-color: #f6f6f6; +} + +.dropdownbox-compare-container.selected-2 .block > div > div:nth-child(2), .dropdownbox-compare-container.selected-3 .block > div > div:nth-child(2) { + background-color: white; +} + +.dropdownbox-compare-container .block > div:not(:first-child) > div:first-child { + display: block; + align-items: center; +} + +.dropdownbox-compare-container .block > div > div p { + font-family: roboto, sans-serif; + font-size: 14px; + font-weight: 400; +} + +.dropdownbox-compare-container .block > div:first-child > div p { + color: white; +} + +.dropdownbox-compare-container .block > div:not(:first-child) > div p { + color: #616161; +} + +.dropdownbox-compare-container .block > div > div:first-child p { + margin: 0; + margin-left: 26px; +} + +.dropdownbox-compare-container .block > div > div span.green-tag { + background: #2cb43d; + border-radius: 50px; + color: #3c3c3c; + color: #fff !important; + display: block; + font-family: roboto, sans-serif; + font-size: 10px !important; + font-style: normal; + font-weight: 700; + margin: -5px 0 6px; + padding: 0 20px; + padding: 3px 9px !important; + text-transform: uppercase; + width: fit-content; +} + + +.dropdownbox-compare-container .block > div > div strong { + font-size: 14px; + line-height: 1.5; + font-weight: normal; +} + +.dropdownbox-compare-container .block.closed > div:not(:first-child) > div, .dropdownbox-compare-container.closed .block > div:not(:first-child) > div { + display: none; +} + +.dropdownbox-compare-container .block.closed > div > div:not(:nth-child(1)) { + display: flex; + align-items: center; + justify-content: center; +} + +.dropdownbox-compare-container .block.closed > div:not(:first-child) > div:first-of-type, .dropdownbox-compare-container.closed .block.closed > div:not(:first-child) > div:first-of-type { + display: inline-block; +} + +.dropdownbox-compare-container .block.closed > div:nth-child(1) > div:nth-child(1)::before { + width: 10px; + height: 10px; + float: left; + content: ""; + margin-right: 10px; + margin-top: 10px; + border: solid white; + border-width: 0 2px 2px 0; + transform: rotate(-135deg); +} + +/* handling - arrow down/up */ +/* stylelint-disable no-descending-specificity */ +.dropdownbox-compare-container.no-arrow .block > div:nth-child(1) > div::before { + visibility: hidden; +} + +.dropdownbox-compare-container .block > div:nth-child(1) > div::before, +.dropdownbox-compare-container .block.closed > div:nth-child(1) > div::before { + width: 10px; + height: 10px; + float: left; + content: ""; + margin-right: 10px; + margin-top: 4px; + border: solid white; + border-width: 0 2px 2px 0; + transform: rotate(45deg); +} + +.dropdownbox-compare-container .dropdownbox-compare-wrapper { + position: relative; +} + +@media (width <= 991px) { + .dropdownbox-compare-container .default-content-wrapper h5 { + font-size: 33px; + } +} + +/* for mobile */ +@media (width <= 991px) { + .dropdownbox-compare-container .block > div { + display: block; + } + + .dropdownbox-compare-container .block > div > div:nth-child(1) { + width: 100%; + } + + .dropdownbox-compare-container .block > div > div:not(:nth-child(1)) { + width: 33%!important; + float: left; + } +} + +@media (width <= 768px) { + .dropdownbox-compare-container { + clear: both; + padding: 0 15px 5px; + } + + .dropdownbox-compare-container .block > div:not(:first-child) { + display: block; + } + + .dropdownbox-compare-container .block > div:nth-child(1) > div:nth-child(1)::before, .dropdownbox-compare-container .block.closed.close > div:nth-child(1) > div:nth-child(1)::before { + margin-top: 1px !important; + } + + .dropdownbox-compare-container .block > div:nth-child(1) > div { + padding: 10px 3% !important; + display: flex; + font-size: 15px; + line-height: 17px; + } + + .dropdownbox-compare-container .new > div:nth-child(1) > div:nth-child(1)::after, .dropdownbox-compare-container.new .block > div:nth-child(1) > div:nth-child(1)::after { + position: static; + margin-left: 15px; + flex: 0 0 auto; + } + + .dropdownbox-compare-container > div:nth-child(2) .new::after { + top: -90px; + right: 0; + width: 135px; + height: 90pt; + display: none; + } + + .dropdownbox-compare-container .block > div:not(:first-child) > div { + padding: 8px 2% !important; + font-size: 15px; + } + + .dropdownbox-compare-container .block img { + width: 15px; + } + + .dropdownbox-compare-container .block > div:not(:first-child) > div:nth-child(1) { + width: 100%; + text-align: center; + } + + .dropdownbox-compare-container .block > div:not(:first-child) > div:not(:first-child) { + width: 50%; + float: left; + } + + .dropdownbox-compare-container .default-content-wrapper h5 { + font-size: 30px; + line-height: 32px; + } + + .section.product-comparison-table-container.migration .old-price-box { + flex-direction: column; + } + + .section.product-comparison-table-container.migration .old-price-box span { + flex-direction: column; + justify-content: center; + align-items: center; + margin: 5px 0; + } + + .section.product-comparison-table-container.migration .old-price-box span del { + margin-left: 10px; + } + + .section.product-comparison-table-container.migration .new-price-box { + flex-direction: column; + align-items: center; + justify-content: center; + font-size: 22px; + } + + .section.product-comparison-table-container.migration .new-price-box span { + margin: 0 0 7px; + } + + .section.product-comparison-table-container.migration .product-comparison-price > p:last-of-type, .section.product-comparison-table-container.migration .product-comparison-header div[role="columnheader"] p { + text-align: center; + min-height: auto; + } + + .section.product-comparison-table-container.migration h3 { + font-size: 15px !important; + } + + .section.product-comparison-table-container.migration p.button-container { + margin-bottom: 1em; + } + + .section.product-comparison-table-container.migration .product-comparison-price { + margin: 3px; + } +} + +@media (min-width: 992px) { + .dropdownbox-compare-wrapper { + max-width: var(--section-desktop-max-width); + padding: 0 var(--section-desktop-padding); + } +} + +@media (min-width: 580px) { + .dropdownbox-compare-wrapper { + margin: 0 auto; + overflow-y: visible; + + } +} diff --git a/_src/blocks/dropdownbox-compare/dropdownbox-compare.js b/_src/blocks/dropdownbox-compare/dropdownbox-compare.js new file mode 100644 index 000000000..4566f113d --- /dev/null +++ b/_src/blocks/dropdownbox-compare/dropdownbox-compare.js @@ -0,0 +1,17 @@ +export default function decorate(block) { + // search for [] to replace with span greeenTag class + const getFirstDivs = block.querySelectorAll('.dropdownbox-compare-container .block > div > div:nth-child(1)'); + getFirstDivs.forEach((item) => { + item.innerHTML = item.innerHTML.replace('[', ''); + item.innerHTML = item.innerHTML.replace(']', ''); + }); + + // make slideUp slideDown functionality + const getFirstTabs = block.querySelectorAll('.dropdownbox-compare-container .block > div:first-child'); + getFirstTabs.forEach((tab) => { + tab.parentNode.classList.remove('closed'); + tab.addEventListener('click', () => { + tab.parentNode.classList.toggle('closed'); + }); + }); +} diff --git a/_src/blocks/dual-teaser/dual-teaser.css b/_src/blocks/dual-teaser/dual-teaser.css new file mode 100644 index 000000000..6825ab5c7 --- /dev/null +++ b/_src/blocks/dual-teaser/dual-teaser.css @@ -0,0 +1,148 @@ +/* stylelint-disable no-descending-specificity */ +.dual-teaser-container.section { + background: transparent linear-gradient(180deg, #006EFF 0%, #000 100%) 0 0 no-repeat padding-box; + overflow: unset; + padding-top: 0; +} + +.dual-teaser-container.section::before { + content: ''; + display: block; + width: 100%; + height: 200px; + background: #EFF6FF; + position: relative; + top: -1px; +} + +.dual-teaser-container .col-container { + width: 100%; +} + +.dual-teaser-container .col-container:first-child { + margin-bottom: 20px; +} + +.dual-teaser-container .col-container .card { + width: 100%; + height: 350px; + position: relative; + display: flex; + flex-direction: column; + justify-content: flex-end; + border-radius: 10px; + overflow: hidden; +} + +.dual-teaser-container .default-content-wrapper { + margin-top: -120px; +} + +.dual-teaser-container .img-container { + width: 100%; + height: 100%; + position: absolute; + overflow: hidden; + border-radius: inherit; +} + +.dual-teaser-container .col-container .box { + height: 190px; + padding: 10px; + background: #003b89a3 0 0 no-repeat padding-box; + backdrop-filter: blur(30px); + display: flex; + flex-direction: column; + border-bottom-right-radius: 10px; + border-bottom-left-radius: 10px; +} + +.dual-teaser-container .col-container .box h2, +.dual-teaser-container .col-container .box h3, +.dual-teaser-container .col-container .box h4, +.dual-teaser-container .col-container .box h5 { + color: white; + letter-spacing: 0; +} + +.dual-teaser-container .col-container .box p, +.dual-teaser-container .col-container .box div { + font: normal normal normal 14px/18px "IBM Plex Sans", sans-serif; + letter-spacing: 0; + margin: 0; +} + +.dual-teaser-container .col-container .box .button-container { + margin-top: auto; +} + +.dual-teaser-container .col-container .box a { + width: 100%; + justify-content: center; +} + +.dual-teaser-container .col-container span.icon { + display: none; +} + +@media (min-width: 768px) { + .dual-teaser-container .default-content-wrapper { + width: 100%; + display: flex; + margin-top: -180px; + } + + .dual-teaser-container .col-container:first-child { + margin-top: unset; + } + + .dual-teaser-container .col-container:first-child .card { + border-radius: 20px 0 0 20px; + } + + .dual-teaser-container .col-container:last-child .card { + border-radius: 0 20px 20px 0; + } + + .dual-teaser-container .col-container { + position: relative; + margin-bottom: 0; + } + + .dual-teaser-container .col-container .card { + height: 600px; + } + + .dual-teaser-container .col-container .box { + padding: 33px 7% 33px 33px; + height: 270px; + border-bottom-right-radius: unset; + border-bottom-left-radius: unset; + } + + .dual-teaser-container .col-container .box a { + width: unset; + } + + .dual-teaser-container .col-container .box p, + .dual-teaser-container .col-container .box div { + font: normal normal normal 18px/23px "IBM Plex Sans", sans-serif; + letter-spacing: 0; + } + + .dual-teaser-container .col-container .box h2, + .dual-teaser-container .col-container .box h3, + .dual-teaser-container .col-container .box h4, + .dual-teaser-container .col-container .box h5 { + margin-bottom: 16px; + } + + .dual-teaser-container .col-container span.icon { + display: block; + position: absolute; + width: 90px; + height: 90px; + top: 20%; + left: -45px; + } +} diff --git a/_src/blocks/dual-teaser/dual-teaser.js b/_src/blocks/dual-teaser/dual-teaser.js new file mode 100644 index 000000000..ea070b10a --- /dev/null +++ b/_src/blocks/dual-teaser/dual-teaser.js @@ -0,0 +1,34 @@ +import { decorateIcons } from '../../scripts/lib-franklin.js'; + +export default async function decorate(block) { + const cols = [...block.children[1].children]; + const middleSvgIcon = block.children[0].querySelector('span'); + + block.innerHTML = ` +
+ ${cols.map((col, idx) => { + const pictureEl = col.querySelector('picture'); + const richTextEls = [...col.children]; + richTextEls.shift(); + const [titleEl, subtitleEl, buttonEl] = richTextEls; + + return ` +
+
+
+ ${pictureEl.outerHTML} +
+
+ ${titleEl.outerHTML} +
${subtitleEl.innerHTML}
+ ${buttonEl.outerHTML} +
+
+ ${idx === 1 ? middleSvgIcon.outerHTML : ''} +
+ `; + }).join('')} + `; + + decorateIcons(block); +} diff --git a/solutions/blocks/embed/embed.css b/_src/blocks/embed/embed.css similarity index 100% rename from solutions/blocks/embed/embed.css rename to _src/blocks/embed/embed.css diff --git a/solutions/blocks/embed/embed.js b/_src/blocks/embed/embed.js similarity index 100% rename from solutions/blocks/embed/embed.js rename to _src/blocks/embed/embed.js diff --git a/_src/blocks/exit-popup/exit-popup.css b/_src/blocks/exit-popup/exit-popup.css new file mode 100644 index 000000000..f229f5ba8 --- /dev/null +++ b/_src/blocks/exit-popup/exit-popup.css @@ -0,0 +1,96 @@ +/* stylelint-disable no-descending-specificity */ +main .exit-popup-container { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.7); + z-index: 9999; + display: none; +} + +main .exit-popup-wrapper { + width: 460px; + position: fixed; + z-index: 999; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + border-radius: 10px; + background-color: white; + color: black; + padding: 0; + box-shadow: 0 3px 6px #00000029; + overflow: hidden; +} + +main .exit-popup-container #exit-action { + position: absolute; + top: 1em; + right: 1em; + width: 15px; + height: 15px; + cursor: pointer; +} + +main .exit-popup-container #exit-action:hover { + opacity: 0.6; +} + +main .exit-popup-container .block p { + margin: 5px 0; +} + +main .exit-popup-container .block > div { + padding: 1em; +} + +main .exit-popup-container .block > div:first-of-type { + background: #006DFF; + color: white; +} + +main .exit-popup-container .block > div:first-of-type p { + margin-top: 0; + font-family: roboto, sans-serif; + font-size: 24px; + line-height: 32px; + font-weight: 400; +} + +main .exit-popup-container .block > div:first-of-type h5 { + font-family: roboto, sans-serif; + font-size: 32px; + line-height: 35px; + font-weight: 500; +} + +main .exit-popup-container .block > div:last-of-type a:last-of-type { + width: 100%; + text-align: center; + display: flex; + align-items: center; + justify-content: center; + font-family: roboto, sans-serif; + font-size: 18px; + line-height: 24px; + font-weight: 500; + margin: 1em auto; +} + +main .exit-popup-container .block > div:last-of-type a:last-of-type:hover::after { + margin-left: 0; +} + +main .exit-popup-container .block > div:last-of-type p strong { + font-family: roboto, sans-serif; + font-size: 24px; + line-height: 32px; +} + +@media (max-width: 460px) { + main .exit-popup-container { + width: 90%; + } +} \ No newline at end of file diff --git a/_src/blocks/exit-popup/exit-popup.js b/_src/blocks/exit-popup/exit-popup.js new file mode 100644 index 000000000..bd31de628 --- /dev/null +++ b/_src/blocks/exit-popup/exit-popup.js @@ -0,0 +1,75 @@ +import { ProductInfo } from '../../scripts/libs/store/store.js'; +// eslint-disable-next-line no-unused-vars +export default async function decorate(block) { + const parentSelector = block.closest('.section'); + const { product, custompid } = parentSelector.dataset; + + if (product) { + const [alias, devices, years] = product.split(','); + // eslint-disable-next-line no-undef + const products = await Store.getProducts([new ProductInfo(alias, 'consumer', custompid)]); + const productItem = products[alias]; + const variation = productItem.getOption(Number(devices), Number(years)); + const percentPrice = variation.getDiscount('percentage'); + + // discount in the title + const tileDiscountEl = block.querySelector('h5'); + if (tileDiscountEl) tileDiscountEl.innerHTML = tileDiscountEl.innerHTML.replace('50%', `${percentPrice}%`); + + // buy button + const buyBtnEl = block.querySelector('p.button-container a'); + if (buyBtnEl) { + buyBtnEl.textContent = buyBtnEl.textContent.replace('50%', `${percentPrice}%`); + buyBtnEl.setAttribute('href', await variation.getStoreUrl()); + } + } + + // exit element: x + const exitEl = document.createElement('span'); + exitEl.id = 'exit-action'; + exitEl.innerHTML = 'Bitdefender'; + block.appendChild(exitEl); + + // popup configuration: + const POPUP_DISPLAY_LIMIT = 2; + const POPUP_TIMEOUT_DAYS = 30; + let popupDisplayCount = parseInt(localStorage.getItem('popupDisplayCount') || 0, 10); + const lastPopupDate = parseInt(localStorage.getItem('lastPopupDate') || 0, 10); + + // if 30 days have passed + function hasThirtyDaysPassed(lastDisplayDate) { + const thirtyDaysInMs = POPUP_TIMEOUT_DAYS * 24 * 60 * 60 * 1000; + const now = Date.now(); + return now - lastDisplayDate > thirtyDaysInMs; + } + + // reset count if 30 days have passed + if (lastPopupDate && hasThirtyDaysPassed(lastPopupDate)) { + localStorage.removeItem('popupDisplayCount'); + localStorage.removeItem('lastPopupDate'); + popupDisplayCount = 0; // Reset count for the session + } + + // event: mouseout -> display the popup + document.addEventListener('mouseout', (event) => { + if (popupDisplayCount < POPUP_DISPLAY_LIMIT && event.clientY < 0 && parentSelector) { + parentSelector.style.display = 'block'; + + // add to the count + popupDisplayCount += 1; + localStorage.setItem('popupDisplayCount', popupDisplayCount.toString()); + + // last display time + localStorage.setItem('lastPopupDate', Date.now().toString()); + } + }); + + // Close the popup: x-icon + background + const closePopup = () => { + const popup = document.querySelector('main .exit-popup-container'); + if (popup) popup.style.display = 'none'; + }; + + if (exitEl) exitEl.addEventListener('click', closePopup); + parentSelector.addEventListener('click', closePopup); +} diff --git a/solutions/blocks/features/features.css b/_src/blocks/features/features.css similarity index 88% rename from solutions/blocks/features/features.css rename to _src/blocks/features/features.css index 065dc557c..af7d37b1d 100644 --- a/solutions/blocks/features/features.css +++ b/_src/blocks/features/features.css @@ -11,7 +11,7 @@ .features { box-shadow: 0 3px 8px 0 var(--dark-shadow); border-radius: 8px; - padding: 40px 15px 20px; + padding: 3em 1em; } .features > div { @@ -21,7 +21,7 @@ } .features img { - width: 100%; + width: 56px; } .features > div > div { @@ -59,8 +59,18 @@ line-height: 1.5; } -.features p.features-tabs-hidden { - display: none; +.features p:nth-of-type(2) { + margin-top: 5px; +} + +.features > div > div > p:first-of-type { + height: 55px; +} + +.features h3 { + font-size: var(--heading-font-size-m); + font-weight: var(--font-weight-bold); + margin-bottom: 0; } .features ul { @@ -90,8 +100,8 @@ width: 14px; height: 8px; margin: 0 3px; - background: url("/solutions/icons/tabs_arrow.svg") no-repeat; - background-size: 100%;; + background: url("/_src/icons/tabs_arrow.svg") no-repeat; + background-size: 100%; transform: rotate(180deg); transition: all .3s linear; } @@ -191,5 +201,12 @@ .features-wrapper { max-width: var(--section-large-desktop-max-width); padding: 0 var(--section-large-desktop-padding); + margin-top: 3em; } } + +@media (max-width: 500px) { /* mobile */ + .features { + padding: 1em; + } +} \ No newline at end of file diff --git a/solutions/blocks/features/features.js b/_src/blocks/features/features.js similarity index 92% rename from solutions/blocks/features/features.js rename to _src/blocks/features/features.js index 3f31f678c..94d60841c 100644 --- a/solutions/blocks/features/features.js +++ b/_src/blocks/features/features.js @@ -1,3 +1,5 @@ +import { matchHeights } from '../../scripts/utils/utils.js'; + function expandItem(content) { content.style.height = `${content.scrollHeight}px`; const transitionEndCallback = () => { @@ -134,4 +136,13 @@ export default function decorate(block) { col.appendChild(extractFeatures(col)); }); }); + + const featuresList = block.querySelectorAll('ul'); + if (featuresList) { + featuresList.forEach((list) => { + const featureText = list.previousElementSibling; + featureText.classList.add('feature-text'); + }); + } + matchHeights(block, '.feature-text'); } diff --git a/_src/blocks/footer/footer.css b/_src/blocks/footer/footer.css new file mode 100644 index 000000000..402b2f809 --- /dev/null +++ b/_src/blocks/footer/footer.css @@ -0,0 +1,768 @@ +footer.landingpage { + background: #006EFF; + color: white; + font-weight: 400; + +a:any-link { + color: white; + text-decoration: none; +} + +img { + width: 300px; + height: auto; + margin-bottom: 10px; +} +} + +footer.default { + padding: 2.5rem 0 1.5rem; + background-color: #000; + font-size: var(--body-font-size-s); +} + +footer.default .footer a { + color: #fff; + cursor: pointer; + outline: 0; + font-family: var(--body-font-family),sans-serif; +} + +footer.default .footer ul { + list-style: none; + padding: 0 1.25rem; + margin: 0; + font-family: var(--body-font-family), sans-serif; +} + +footer.default .footer ul li { + font-size: var(--body-font-size-s); + line-height: 1.63; + font-family: var(--body-font-family),sans-serif; + margin: 0 0 0.4375rem; + padding-left: 0; +} + +footer.default .footer ul li a { + font: normal normal var(--font-weight-boldest) 10px/30px var(--body-font-family); +} + +footer.default .footer p { + margin: 0; + padding: 0 1.25rem; +} + +footer.default .footer .deactivated a { + color: #999 !important; + cursor: auto; + pointer-events: none; +} + +footer.default .footer a:hover { + text-decoration: underline; +} + +footer.default .footer .deactivated::before { + content: "•"; + color: #999; + font-weight: var(--font-weight-boldest); + display: inline-block; + width: 1rem; + position: absolute; + z-index: 1; + left: -1rem; + top: 0.125rem; +} + +footer.default .footer > div { + display: grid; + margin: 0 auto; + max-width: 81.25rem; +} + +footer.default .footer > div div { + margin: 0; + padding: 0; + border-bottom: 0.0625rem solid #9098a3; +} + +footer.default .footer > div p { + text-align: left; + font: normal normal var(--font-weight-boldest) 13px/24px var(--body-font-family); + letter-spacing: 0; + color: #9098a3; + opacity: 1; + position: relative; + margin: 0; + transition: transform .5s ease-in-out; + cursor: pointer; + padding: 0.625rem 1.25rem; +} + +footer.default .footer > div > :nth-child(1) > p { + width: 100%; + margin-bottom: 1.875rem; + display: flex; + overflow: hidden; + border: none; +} + +footer.default .footer > div > :nth-child(1) > p a { + height: 100%; +} + +footer.default .footer > div > :nth-child(1) > p picture { + width: 11.875rem; + height: 1.9375rem; + overflow: hidden; + display: flex; +} + +footer.default .footer > div > :nth-child(1) > p a img { + height: 1.5rem; + width: auto; + object-fit: contain; +} + +footer.default .footer > div > :nth-child(1) > ul { + margin: 0; + display: block; + column-count: 2; + list-style-type: none; + padding-bottom: 1.875rem; +} + +footer.default .footer > div > :nth-child(1) > ul li { + padding: 0; + margin: 0 0 0.4375rem; +} + +footer.default .footer > div > :nth-child(1) > ul li a { + text-align: left; + letter-spacing: .78pt; + text-transform: uppercase; + font: normal normal var(--font-weight-boldest) 11px/30px var(--body-font-family); +} + +footer.default .footer > div > :nth-child(2) { + order: 4; + margin-top: 0.6875rem; + margin-bottom: 1.5rem; + border: none; +} + +footer.default .footer > div > :nth-child(3) { + order: 2; + padding-bottom: 0.625rem; +} + +footer.default .footer > div > :nth-child(4) { + order: 3; + padding-bottom: 0.625rem; +} + +footer.default .footer > div > :nth-child(5) { + order: 5; + padding: 0; + border-bottom-width: 1px; + border-style: solid; + border-color: rgb(144 152 163); + margin-bottom: 1.5rem; +} + +footer.default .footer > div > :nth-child(6) { + order: 6; + border: none; +} + +footer.default .footer > div > :nth-child(3) > p::before, +footer.default .footer > div > :nth-child(4) > p::before { + transform: rotate(45deg); + border-color: #fff; + border-style: solid; + border-width: 0 0.1875rem 0.1875rem 0; + content: ""; + width: 0.5rem; + height: 0.5rem; + display: inline-block; + position: absolute; + right: 1.25rem; + top: 0.75rem; + left: auto; + transition: transform .5s ease-in-out; +} + +footer.default .footer > div > :nth-child(3) > ul, +footer.default .footer > div > :nth-child(4) > ul { + width: 100%; + max-height: 125rem; + margin-bottom: 0.625rem; + transition: transform .5s ease-in-out; +} + +footer.default .footer > div > :nth-child(3) > ul li, +footer.default .footer > div > :nth-child(4) > ul li { + margin: 0 0 0.625rem; + padding-left: 0; +} + +footer.default .footer > div > :nth-child(3) > ul li > a, +footer.default .footer > div > :nth-child(4) > ul li > a { + font: normal normal var(--font-weight-bold) 10px/30px var(--body-font-family); + letter-spacing: 0; + opacity: 1; +} + +footer.default .footer > div > :nth-child(2) > ul { + column-count: 2; + padding: 0 1.25rem 0.375rem; + margin-top: 0.6875rem; +} + +footer.default .footer > div > :nth-child(3) > p + ul, +footer.default .footer > div > :nth-child(4) > p + ul { + display: none; + max-height: 0; + overflow: hidden; + transition: max-height 0.5s ease-in-out; +} + +footer.default .footer > div > :nth-child(3) > p + ul.visible, +footer.default .footer > div > :nth-child(4) > p + ul.visible { + display: block; +} + +footer.default .footer > div > :nth-child(3) > p + ul.open, +footer.default .footer > div > :nth-child(4) > p + ul.open { + max-height: 400px; +} + +footer.default .footer > div > :nth-child(3) > p, +footer.default .footer > div > :nth-child(4) > p { + padding-bottom: 0; +} + +footer.default .footer > div > :nth-child(3) > p.active, +footer.default .footer > div > :nth-child(4) > p.active { + padding-bottom: 0.625rem; +} + +footer.default .footer > div > :nth-child(4) > p + ul { + display: none; +} + +footer.default .footer > div > :nth-child(3) > p.active + ul, +footer.default .footer > div > :nth-child(4) > p.active + ul { + display: inline-block; +} + +footer.default .footer > div > :nth-child(4) > p.active + ul { + column-count: 2; +} + +footer.default .footer > div > :nth-child(3) > p.active::before, +footer.default .footer > div > :nth-child(4) > p.active::before { + transform: rotate(225deg); + top: 1.0625rem; +} + +footer.default .footer > div > :nth-child(2) > p { + padding: 0 1.25rem; + margin-bottom: 1rem; +} + +footer.default .footer > div > :nth-child(5) > p { + font-size: var(--body-font-size-m); + padding: 0 1.375rem 1.5rem; + color: rgb(255 255 255); + letter-spacing: 0; + line-height: 1.5rem; + font-weight: var(--font-weight-boldest); + font-family: "IBM Plex Sans" ,sans-serif; +} + +footer.default .footer > div > :nth-child(6) > p { + font: normal normal normal 10px/13px var(--body-font-family); + width: 100%; + max-width: 100%; + margin-top: 1rem; + margin-bottom: 1.625rem; + position: relative; + text-align: left!important; + letter-spacing: 0; + color: #9098a3; + opacity: 1; + line-height: 1.14!important; + padding: 0 1.25rem; +} + +footer.default .footer > div > :nth-child(6) > ul li { + display: block; + margin-bottom: 0.625rem; + font: normal normal var(--font-weight-regular) 10px/30px var(--body-font-family); + width: 100%; + line-height: 1; + font-size: var(--body-font-size-xxs); +} + +footer.default .footer > div > :nth-child(6) > ul li > a { + display: inline-block; + font: normal normal var(--font-weight-bold) 10px/30px var(--body-font-family); +} + +@media(min-width: 480px) { + footer.default .footer > div > :nth-child(6) > ul li > a { + font: normal normal var(--font-weight-bold) 11px/30px var(--body-font-family); + } + + footer.default .footer > div > :nth-child(6) > p { + font: normal normal normal 11px/13px var(--body-font-family); + } +} + +@media(min-width: 767px) { /* tablet */ + footer.default { + padding: 3.625rem 0 2.6875rem; + } + + footer.default .footer > div > :nth-child(1) > ul li > a { + font: normal normal var(--font-weight-boldest) 9pt/30px var(--body-font-family); + } + + footer.default .footer > div > :nth-child(6) > ul li > a { + font: normal normal var(--font-weight-bold) 9pt/30px var(--body-font-family); + } + + footer.default .footer > div > :nth-child(6) > p { + font: normal normal normal 9pt/13px var(--body-font-family); + } + + footer.landingpage img { + width: 400px; + } +} + +@media(min-width: 990px) { /* desktop */ + footer.default .footer .deactivated { + position: relative; + } + + footer.default .footer > div { + grid-template-columns: [first-col] 25% [second-col] 75%; + } + + footer.default .footer > div div { + border: none; + } + + footer.default .footer > div p { + pointer-events: none; + } + + footer.default .footer > div > :nth-child(1) { + order: 1; + display: flex; + justify-content: center; + flex-flow: row wrap; + padding: 0 3.125rem; + margin-bottom: 4.0625rem; + grid-column: first-col / span 2; + } + + footer.default .footer > div > :nth-child(1) > p { + max-width: 25%; + padding: 0; + pointer-events: visible; + } + + footer.default .footer > div > :nth-child(1) > p a img { + height: 1.75rem; + } + + footer.default .footer > div > :nth-child(1) > ul { + width: 66%; + margin-left: 9%; + display: inline-block; + vertical-align: top; + border-bottom: none; + column-count: 1; + list-style-type: none; + padding: 0; + } + + footer.default .footer > div > :nth-child(1) > ul li > a { + font: normal normal var(--font-weight-boldest) 13px/30px var(--body-font-family); + } + + footer.default .footer > div > :nth-child(2) { + order: 2; + margin-top: 0; + grid-column: first-col / span 1; + padding-left: 3.125rem; + margin-bottom: 0; + } + + footer.default .footer > div > :nth-child(2) > p, + footer.default .footer > div > :nth-child(3) > p, + footer.default .footer > div > :nth-child(4) > p { + padding: 0; + font: normal normal var(--font-weight-boldest) 13px/24px var(--body-font-family); + letter-spacing: 0; + color: #9098a3; + opacity: 1; + border-bottom: 1px solid #3a4350; + padding-bottom: 0.9375rem; + text-transform: none; + width: 100%; + margin-bottom: 0; + } + + footer.default .footer > div > :nth-child(3) ul, + footer.default .footer > div > :nth-child(4) ul { + display: block !important; + margin-bottom: 0; + } + + footer.default .footer > div > :nth-child(3) > ul { + padding: 0; + display: grid; + grid-template-columns: 1fr; + margin-top: 0.9375rem; + list-style: none; + } + + footer.default .footer > div > :nth-child(3) > p { + width: 95%; + } + + footer.default .footer > div > :nth-child(2) > ul { + padding: 0; + column-count: 1; + display: grid; + grid-template-columns: 1fr; + margin-top: 0.9375rem; + list-style: none; + } + + footer.default .footer > div > :nth-child(3) ul { + column-count: 2; + } + + footer.default .footer > div > :nth-child(2) > ul li, + footer.default .footer > div > :nth-child(4) > ul li { + margin-bottom: 0.5rem; + width: 100%; + padding: 0; + } + + footer.default .footer > div > :nth-child(2) > ul li > a, + footer.default .footer > div > :nth-child(3) > ul li > a, + footer.default .footer > div > :nth-child(4) > ul li > a { + font: normal normal var(--font-weight-bold) 13px/30px var(--body-font-family); + display: inline-block; + position: relative; + } + + footer.default .footer > div > :nth-child(3) { + order: 3; + grid-column: second-col / span 1; + margin-left: 14%; + padding-bottom: 0; + } + + footer.default .footer > div > :nth-child(3) > p::before, + footer.default .footer > div > :nth-child(4) > p::before { + display: none; + } + + footer.default .footer > div > :nth-child(4) ul { + column-count: 3; + padding: 0; + margin-top: 0.9375rem; + } + + footer.default .footer > div > :nth-child(4) { + order: 4; + grid-column: first-col / span 2; + margin-top: 4.0625rem; + padding: 0 3.125rem; + } + + footer.default .footer > div > :nth-child(5) { + order: 5; + grid-column: first-col / span 2; + margin-top: 2.5rem; + border: none; + padding: 0 3.125rem; + margin-bottom: 0; + padding-bottom: 1rem; + } + + footer.default .footer > div > :nth-child(5) > p { + padding: 0; + } + + footer.default .footer > div > :nth-child(6) { + order: 6; + grid-column: first-col / span 2; + padding: 0 3.125rem; + } + + footer.default .footer > div > :nth-child(6) > ul { + border-top: 1px solid #3a4350; + padding: 1rem 0 0; + display: flex; + } + + footer.default .footer > div > :nth-child(6) > ul li { + display: inline-block; + list-style: none; + padding: 0; + margin: 0; + position: relative; + font-size: var(--body-font-size-xxs); + font-weight: var(--font-weight-regular); + line-height: 1.14; + width: auto; + } + + footer.default .footer > div > :nth-child(6) > ul li > a { + font: normal normal normal 13px/18px var(--body-font-family); + margin-right: 0.625rem; + padding-right: 1.25rem; + position: relative; + } + + footer.default .footer > div > :nth-child(6) > ul li > a::after { + content: ""; + position: absolute; + top: 0.125rem; + right: 0.1875rem; + width: 0.125rem; + height: 1rem; + background-color: #fff; + } + + footer.default .footer > div > :nth-child(6) > p { + padding: 0; + font: normal normal normal 13px/18px var(--body-font-family); + margin-top: 0.875rem; + margin-bottom: 0; + } + + footer.default .footer > div > :nth-child(3) > p + ul, + footer.default .footer > div > :nth-child(4) > p + ul { + overflow: visible; + max-height: 400px; + } + + footer.default .footer > div > :nth-child(4) > p.active + ul { + column-count: 3; + } +} + +#footer-ferrari { + background-color: #000; +} + +#footer-ferrari .section:nth-of-type(1) p { + width: 40%; +} + +#footer-ferrari ul { + margin-left: 0; + padding-left: 0; +} + +#footer-ferrari .section:nth-of-type(1) ul { + width: 60%; + display: flex; + justify-content: space-between; + padding-top: 0; + margin-top: 0; +} + +#footer-ferrari .section:nth-of-type(2) ul:nth-of-type(1) li:not(:first-of-type) { + float: left; +} + +#footer-ferrari .section:nth-of-type(2) ul:nth-of-type(1) li:not(:first-of-type) img { + width: 40px; + margin-right: 12px; +} + +#footer-ferrari .section:nth-of-type(2) ul:nth-of-type(2) li:first-of-type { + width: 100%; +} + +#footer-ferrari .section:nth-of-type(3) strong, +#footer-ferrari .section:nth-of-type(2) ul:nth-of-type(1) strong { + width: 100%; + margin-bottom: 10px; + font-size: 22px; + line-height: 27px; +} + +#footer-ferrari .section:nth-of-type(2) ul:nth-of-type(2) li:first-of-type strong { + width: 100%; + display: block; + font-size: 14px; + line-height: 1.71; + letter-spacing: 1.12px; + color: #fff; + padding-bottom: 13px; + border-bottom: 2px solid white; + margin-bottom: 25px; +} + +#footer-ferrari .section:nth-of-type(4) ul li a { + font-size: 14px; + font-weight: normal; + line-height: 1.14; + color: #fff; + position: relative; + margin-right: 10px; + padding-right: 20px; + margin-bottom: 10px; + border-right: 0 none; + display: inline-block; +} + +#footer-ferrari .section:nth-of-type(4) ul li:last-of-type a { + border-right: 0 none; +} + +#footer-ferrari .section:nth-of-type(2) ul:nth-of-type(2) li:not(:first-of-type) a { + font-size: 16px; + font-weight: 500; + line-height: 1.5; +} + +#footer-ferrari .section:nth-of-type(3) p { + border-bottom: 0 none; + margin-top: 1em; + padding-top: 10px; + font-size: 22px; + line-height: 27px; +} + +#footer-ferrari .section:nth-of-type(4) p { + text-align: right; + line-height: 17px; +} + +#footer-ferrari .section:nth-of-type(4) ul p { + font-size: 14px; + line-height: 1.14; +} + +#footer-ferrari .section:nth-of-type(1) { + display: none; +} + +#footer-ferrari .section:nth-of-type(4) ul { + width: 60%; + display: flex; + flex-direction: column; +} + +#footer-ferrari .section:nth-of-type(2) ul:nth-of-type(1) { + width: 100%; + margin-top: 0; +} + +#footer-ferrari .section:nth-of-type(4) { + padding-top: 0; +} + +#footer-ferrari .section:nth-of-type(4) div { + display: flex; + align-items: self-end; +} + +#footer-ferrari .section:nth-of-type(2) ul:nth-of-type(2) { + display: none; +} + +@media (min-width: 768px) { + footer.landingpage { + padding: 50px 0; + + .default-content-wrapper { + display: flex; + justify-content: space-between; + } + + p strong { + font-size: 32px; + font-weight: bold; + color: white; + } + } +} + +@media (min-width: 992px) { + #footer-ferrari .section:nth-of-type(1) { + display: block; + } + + #footer-ferrari .section:nth-of-type(4) ul { + display: flex; + flex-direction: row; + margin-top: 0; + margin-bottom: 0; + } + + + #footer-ferrari .section:nth-of-type(2) ul:nth-of-type(1) { + width: 40%; + } + + #footer-ferrari .section:nth-of-type(2) ul:nth-of-type(2) { + display: block; + width: 60%; + } + + #footer-ferrari .section:nth-of-type(3) p { + width: 100%; + border-bottom: 2px solid white; + margin-top: 100px; + padding-top: 10px; + line-height: 2; + } + + #footer-ferrari .section:nth-of-type(3) strong { + font-size: 31px; + } + + #footer-ferrari .section:nth-of-type(2) ul:nth-of-type(1) strong { + width: 120px; + display: block; + margin-bottom: 28px; + color: #fff; + font-size: 40px; + line-height: 45px; + } + + #footer-ferrari ul li { + list-style-type: none; + padding-left: 0; + } + + #footer-ferrari .section:nth-of-type(2) ul:nth-of-type(2) li:not(:first-of-type) { + width: 50%; + float: left; + margin-top: 0; + margin-bottom: 25px; + } +} + +@media(min-width: 1600px) { /* large desktop */ + footer.default .footer > div { + width: 100%; + margin: 0 auto; + padding: 0 1.25rem; + max-width: 83.25rem; + position: relative; + } +} diff --git a/_src/blocks/footer/footer.js b/_src/blocks/footer/footer.js new file mode 100644 index 000000000..2a1898aa2 --- /dev/null +++ b/_src/blocks/footer/footer.js @@ -0,0 +1,246 @@ +import { decorateIcons, getMetadata, loadBlocks } from '../../scripts/lib-franklin.js'; +import { adobeMcAppendVisitorId, getDomain } from '../../scripts/utils/utils.js'; +import { decorateMain } from '../../scripts/scripts.js'; + +function wrapImgsInLinks(container) { + const pictures = container.querySelectorAll('picture'); + pictures.forEach((pic) => { + const link = pic.nextElementSibling; + if (link && link.tagName === 'A' && link.href) { + link.innerHTML = pic.outerHTML; + pic.replaceWith(link); + } + }); +} + +function onFooterElementClick(evt) { + const header = evt.target; + const ul = header.nextElementSibling; + header.classList.toggle('active'); + + if (ul.classList.contains('open')) { + ul.addEventListener('transitionend', function callback() { + if (!ul.classList.contains('open')) { // Ensure the ul is still closed + ul.classList.remove('visible'); + } + ul.removeEventListener('transitionend', callback); + }); + ul.classList.remove('open'); + } else { + ul.classList.add('visible'); + setTimeout(() => { + ul.classList.add('open'); + }, 10); // slight delay to allow the browser to apply the "visible" class first + } +} + +function disableSelectedCountry(container) { + const listOfCountries = container.querySelectorAll('li'); + listOfCountries.forEach((countryLanguage) => { + if (countryLanguage.innerHTML.includes('selected')) { + countryLanguage.classList.add('deactivated'); + countryLanguage.innerHTML = countryLanguage.innerHTML.replace('(selected)', ''); + } + }); +} + +function setupPrivacyButton(container) { + const privacyButton = container.querySelector('a[href="#privacybutton"]'); + if (privacyButton) { + privacyButton.href = '#'; + privacyButton.addEventListener('click', (e) => { + e.preventDefault(); + if (window.UC_UI) { + window.UC_UI.showSecondLayer(); + } + }); + } +} + +async function runDefaultFooterLogic(block) { + // fetch footer content + const footerPath = getMetadata('footer') || '/footer'; + const resp = await fetch(`${footerPath}.plain.html`, window.location.pathname.endsWith('/footer') ? { cache: 'reload' } : {}); + + if (resp.ok) { + const html = await resp.text(); + + // decorate footer DOM + const footer = document.createElement('div'); + footer.innerHTML = html; + + wrapImgsInLinks(footer); + + const sectionHeaders = footer.querySelectorAll('div > div > p'); + sectionHeaders[2].addEventListener('click', onFooterElementClick); + sectionHeaders[3].addEventListener('click', onFooterElementClick); + + const sectionsData = footer.querySelectorAll('div > div > ul'); + disableSelectedCountry(sectionsData[3]); + + decorateIcons(footer); + block.append(footer); + + setupPrivacyButton(footer); + + adobeMcAppendVisitorId('footer'); + } +} + +async function runLandingpageLogic(block) { + const footerPath = getMetadata('footer') || '/footer'; + const resp = await fetch(`${footerPath}.plain.html`); + + const fragment = document.createElement('main'); + if (resp.ok) { + fragment.innerHTML = await resp.text(); + decorateMain(fragment); + await loadBlocks(fragment); + } + const footer = block.closest('.footer-wrapper'); + + if (window.location.href.indexOf('scuderiaferrari') !== -1 || window.location.href.indexOf('spurs') !== -1) { + block.closest('.footer-wrapper').id = 'footer-ferrari'; + } + + if (fragment) { + const fragmentSections = fragment.querySelectorAll(':scope .section'); + if (fragmentSections) { + footer.replaceChildren(...fragmentSections); + } + } + + const replacements = [ + [/\[year\]/g, new Date().getFullYear()], + [/>Twitter Bitdefenderx<'], + [/>Linkedin Bitdefenderlinkedin<'], + [/>Facebook Bitdefenderfacebook<'], + [/>Youtube Bitdefenderyoutube<'], + ]; + + replacements.forEach(([pattern, replacement]) => { + footer.innerHTML = footer.innerHTML.replace(pattern, replacement); + }); + + setupPrivacyButton(footer); + + adobeMcAppendVisitorId('footer'); +} + +async function runAemFooterLogic() { + // fetch footer content + const aemFooterHostname = window.location.hostname.includes('.hlx.') + || window.location.hostname.includes('localhost') + ? 'https://stage.bitdefender.com' + : ''; + + const websiteDomain = getDomain(); + let aemFetchDomain; + + if (websiteDomain === 'en-us') { + aemFetchDomain = 'en'; + } else if (websiteDomain.includes('-global')) { + const [singleDomain] = websiteDomain.split('-'); + aemFetchDomain = singleDomain; + } else { + aemFetchDomain = websiteDomain.split('-').join('_'); + } + + const aemFooterFetch = await fetch(`${aemFooterHostname}/content/experience-fragments/bitdefender/language_master/${aemFetchDomain}/footer-fragment-v1/master/jcr:content/root.html`); + if (!aemFooterFetch.ok) { + return; + } + + const aemFooterHtml = await aemFooterFetch.text(); + const footer = document.createElement('footer'); + const shadowRoot = footer.attachShadow({ mode: 'open' }); + const contentDiv = document.createElement('div'); + contentDiv.innerHTML = aemFooterHtml; + + const loadedLinks = []; + contentDiv.querySelectorAll('link').forEach((linkElement) => { + // update the links so that they work on all Franklin domains + linkElement.href = `${aemFooterHostname}${linkElement.getAttribute('href')}`; + linkElement.rel = 'stylesheet'; + + // add a promise for each link element in the code + // so that we can wait on all the CSS before displaying the component + loadedLinks.push(new Promise((resolve, reject) => { + linkElement.onload = () => { + resolve(); + }; + + linkElement.onerror = () => { + reject(); + }; + })); + }); + + // a list of all the components to be received from aem components + const aemComponents = ['footer']; + + // add logic so that every time an AEM function is fully loaded + // it is directly run using the shadow dom as parameter + aemComponents.forEach((aemComponentName) => { + window.addEventListener(aemComponentName, () => { + window[aemComponentName](shadowRoot); + }); + }); + + // select all the scripts from contet div and + const scripts = contentDiv.querySelectorAll('script'); + scripts.forEach((script) => { + // multiple reruns of runtime lead to all the scripts + // being run multiple times + if (!script.src.includes('runtime')) { + const newScript = document.createElement('script'); + newScript.src = `${aemFooterHostname}${script.getAttribute('src')}`; + newScript.defer = true; + shadowRoot.appendChild(newScript); + } + }); + + shadowRoot.appendChild(contentDiv); + document.querySelector('footer').replaceWith(footer); +} + +/** + * applies footer factory based on footer variation + * @param {String} footerMetadata The footer variation: landingpage' or none + * @param {Element} footer The footer element + */ +function applyFooterFactorySetup(footerMetadata, block) { + // TODO: please remove this if after creating the zh-hk and zh-tw + // headers in AEM + const regex = /\/(zh-hk|zh-tw)\//i; + const matches = window.location.href.match(regex); + if (matches) { + runDefaultFooterLogic(block); + return; + } + + switch (footerMetadata) { + case 'landingpage': + runLandingpageLogic(block); + break; + case 'franklinFooter': + runDefaultFooterLogic(block); + break; + default: + runAemFooterLogic(block); + break; + } +} + +/** + * loads and decorates the footer + * @param {Element} block The footer block element + */ +export default async function decorate(block) { + const footerMetadata = getMetadata('footer-type'); + block.parentNode.classList.add(footerMetadata || 'default'); + + block.textContent = ''; + + applyFooterFactorySetup(footerMetadata, block); +} diff --git a/_src/blocks/form-blog/form-blog.css b/_src/blocks/form-blog/form-blog.css new file mode 100644 index 000000000..0c949e408 --- /dev/null +++ b/_src/blocks/form-blog/form-blog.css @@ -0,0 +1,217 @@ +.form-blog { + --input-border: #d6d6d6; + } + + .form-blog-wrapper { + width: 100%; + margin: 0 auto; + max-width: var(--body-max-width); + padding: 0 var(--body-padding); + position: relative; + } + + .form-blog > div:first-child { + display: none; + } + + .form-blog input[type="email"] { + border: 1px solid var(--input-border); + border-radius: 5px; + transition: all 0.3s ease-in-out; + font-size: var(--body-font-size-s); + line-height: 50px; + padding: 0 15px; + margin-bottom: 15px; + width: 100%; + } + + .form-blog input[type="text"] { + border: 1px solid var(--input-border); + border-radius: 5px; + transition: all 0.3s ease-in-out; + font-size: var(--body-font-size-s); + line-height: 50px; + padding: 0 15px; + margin-bottom: 15px; + width: 100%; + } + + .checkbox { + display: flex; + align-items: flex-start; + color: var(--checkbox-label); + font-size: var(--body-font-size-xs); + margin: 15px 0; + } + + .checkbox input[type="checkbox"] { + margin: 5px 10px; + width: 25px; + height: auto; + zoom: 1.25; + + @media (min-width: 768px) { + zoom: 1; + } + } + + input[type="submit"] { + width: 100%; + justify-content: center; + } + + input[type="submit"]:disabled { + opacity: 0.5; + cursor: unset; + } + + input[type="submit"]:disabled::after { + display: none; + } + + input[type="submit"].disabled:hover .button-text { + transform: none; + } + + .form-blog-container > .default-content-wrapper:nth-child(3) { + display: flex; + justify-content: center; + } + + .form-blog-container > .default-content-wrapper:nth-child(3) > p strong { + color: var( --checkbox-label); + font-size: var(--body-font-size-xxs); + font-weight: var(--font-weight-bold); + } + + + .form-blog-container input[type="submit"] { + font-family: var(--body-font-family); + font-size: var(--body-font-size-s); + font-style: normal; + font-weight: var(--font-weight-bold); + -webkit-font-smoothing: antialiased; + display: inline-flex; + align-items: center; + box-sizing: border-box; + text-decoration: none; + padding: 10px 26px 8px 28px; + text-align: center; + cursor: pointer; + color: var(--button-link-color); + background-color: var(--button-background-color); + border: 2px solid var(--button-background-color); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + border-radius: 8px; + height: fit-content; + } + + .form-blog-container { + --dark-background-color: #000; + --black-color: #000; + --white-color: #fff; + --background-color: #fff; + --link-color: #005ed9; + --link-hover-color: #00439c; + --button-link-color: #fff; + --button-background-color: #eb0000; + --button-hover-background-color: #d80000; + --button-primary-background-color: #000; + --button-primary-hover-background-color: #000; + --button-secondary-color: #000; + --button-secondary-hover-background-color: #000; + --overlay-background-color: #eee; + --highlight-background-color: #ccc; + --text-color: #000; + --text-error-color: #f00; + --color-highlight-blue: #006dff; + --color-dark-gray: #616161; + --checkbox-label: #3c3c3c; + --highlight-light-blue: #f3f7fe; + --text-dark-color: #fff; + --horizontal-separator-color: #dedede; + --modal-background-color: rgb(0 0 0 / 50%); + --background-color-light-sky-blue: #e4f2ff; + --icon-color: #205fff; + --background-light-blue: #d9eeff; + --background-blue: #005ed9; + --dark-blue-tag: #005eff; + --light-blue-tag: #13b0a7; + --green-tag: #218728; + --dark-shadow: #0000001a; + --background-checkmark: #61AF53; + --body-font-family: "Roboto", "roboto-normal-400-fallback", helvetica, ubuntu, roboto, noto, sans-serif; + --heading-font-family: var(--body-font-family); + --fixed-font-family: var(--body-font-family); + --font-weight-thin: 300; + --font-weight-regular: 400; + --font-weight-bold: 500; + --font-weight-bolder: 600; + --font-weight-boldest: 700; + --font-weight-heavy: 900; + --body-font-size-l: 22px; + --body-font-size-m: 18px; + --body-font-size-s: 16px; + --body-font-size-xs: 14px; + --body-font-size-xxs: 12px; + --body-font-size-xxxs: 10px; + --heading-font-size-xxxl: 60px; + --heading-font-size-xxl: 48px; + --heading-font-size-xl: 40px; + --heading-font-size-l: 32px; + --heading-font-size-m: 24px; + --heading-font-size-s: 20px; + --heading-font-size-xs: 18px; + --heading-font-size-xxs: 16px; + --nav-height: 63px; + --nav-height-desktop: 40px; + --body-max-width: 1920px; + --body-padding: 20px; + --section-desktop-max-width: 1300px; + --section-desktop-padding: 20px; + --section-large-desktop-max-width: 1332px; + --section-large-desktop-padding: 50px; + --section-desktop-padding-vertical: 48px; + --section-mobile-padding-vertical: 32px; + } + +/* stylelint-disable-next-line no-duplicate-selectors */ +.form-blog-container{ + .form-blog-wrapper { + box-sizing: border-box; + + .form-blog.blog-template { + box-shadow: 0 5px 15px 5px rgb(0 0 0 / 10%); + max-width: 390px; + padding: 15px; + box-sizing: border-box; + + input[type="email"] { + box-sizing: border-box;; + } + + input[type="text"] { + box-sizing: border-box;; + } + + > div:first-child { + display: block; + + h2 { + font-size: 22px; + font-weight: bold; + } + + p { + font-size: 16px; + } + + p.button-container { + display: none; + } + } + } + } +} \ No newline at end of file diff --git a/_src/blocks/form-blog/form-blog.js b/_src/blocks/form-blog/form-blog.js new file mode 100644 index 000000000..85d359346 --- /dev/null +++ b/_src/blocks/form-blog/form-blog.js @@ -0,0 +1,168 @@ +import Cookie from '../../scripts/libs/cookie.js'; +import { AdobeDataLayerService, FormEvent } from '../../scripts/libs/data-layer.js'; + +function onChange(form) { + // Targeting the anchor inside .button-container + const submitButton = form.querySelector('input[type="submit"]'); + const emailInput = form.querySelector('input[type="email"]'); + + const allCheckboxesChecked = [...form.querySelectorAll('input[type="checkbox"]:required')].every((checkbox) => checkbox.checked); + const emailPopulated = emailInput.value.trim() !== ''; + + submitButton.disabled = !((allCheckboxesChecked && emailPopulated)); +} + +async function hashEmail(email) { + const encoder = new TextEncoder(); + const data = encoder.encode(email); + const hashBuffer = await crypto.subtle.digest('SHA-256', data); + const hashArray = Array.from(new Uint8Array(hashBuffer)); + const hashHex = hashArray.map((b) => b.toString(16).padStart(2, '0')).join(''); + return hashHex; +} + +async function handleSubmitNewsletter(e, form, flow, successMessage, failMessage, formType = 'newsletter') { + e.preventDefault(); + const formData = new FormData(form); + const email = formData.get('email'); + const name = formData.get('name'); + const firstName = name.split(' ')[0]; + const lastName = name.split(' ')[1] || ''; + const update = formData.get('checkbox'); + + const jsonObject = { + email, + flow, + first_name: firstName, + last_name: lastName, + update, + }; + + const response = await fetch('https://www.bitdefender.com/site/Store/offerSubscribe', { + method: 'POST', + body: JSON.stringify(jsonObject), + }); + const formParent = form.parentElement; + if (response.ok) { + const hashedEmail = await hashEmail(email); + AdobeDataLayerService.push(new FormEvent( + 'form completed', + { + form: formType, + formID: hashedEmail, + }, + )); + + formParent.innerHTML = ''; + formParent.appendChild(successMessage); + + Cookie.set('newsLetterIntentShown', '1'); + } else { + formParent.innerHTML = ''; + formParent.appendChild(failMessage); + } +} + +function parseHTML(html) { + // Regular expressions to match text inside curly braces and square brackets + const curlyRegex = /{{(.*?)}}/g; + const squareRegex = /\[\[(.*?)\]\]/g; + + const insideCurlyBrackets = []; + const insideSquareBrackets = []; + + // Match all occurrences of the curly braces regex + let match; + // eslint-disable-next-line no-cond-assign + while ((match = curlyRegex.exec(html)) !== null) { + insideCurlyBrackets.push(match[1].trim()); + } + + // Match all occurrences of the square brackets regex + // eslint-disable-next-line no-cond-assign + while ((match = squareRegex.exec(html)) !== null) { + insideSquareBrackets.push(match[1].trim()); + } + + return { + insideCurlyBrackets, + insideSquareBrackets, + }; +} + +// Function to create the form +async function createForm(types, labels, flow, successMessage, failMessage, formType) { + const form = document.createElement('form'); + form.setAttribute('method', 'post'); + + for (let i = 0; i < types.length; i += 1) { + const type = types[i].toLowerCase(); + const input = document.createElement('input'); + input.id = `form-${i}-${type}`; + input.addEventListener('change', () => onChange(form)); + input.addEventListener('input', () => onChange(form)); + + if (type === 'name') { + input.setAttribute('type', 'text'); + } else { + input.setAttribute('type', type); + } + + input.setAttribute('name', type); + input.setAttribute('placeholder', labels[i]); + input.setAttribute('required', ''); + input.setAttribute('aria-required', 'true'); + + form.append(input); + if (type === 'submit') { + input.classList.add('disabled'); + input.disabled = true; + } + + if (type === 'checkbox') { + const div = document.createElement('div'); + div.classList.add('checkbox'); + + const label = document.createElement('label'); + label.setAttribute('for', `form-${i}-${type}`); + label.innerHTML = labels[i]; + input.before(div); + div.append(input, label); + } + } + + form.addEventListener('submit', (e) => handleSubmitNewsletter(e, form, flow, successMessage, failMessage, formType)); + return form; +} + +export default async function decorate(block, options) { + const { + template, flow, + } = block.closest('.section').dataset; + + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + const blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + } + + const formDataHTML = block.children[1]; + const successMessage = block.children[2].children[1]; + const failMessage = block.children[3].children[1]; + const formData = parseHTML(formDataHTML.innerHTML); + const [types, labels] = [formData.insideCurlyBrackets, formData.insideSquareBrackets]; + const form = await createForm(types, labels, flow, successMessage, failMessage, options.formType); + if (form) block.append(form); + block.children[1].innerHTML = ''; + block.children[2].innerHTML = ''; + block.children[3].innerHTML = ''; + if (template === 'blog') { + block.classList.add('blog-template'); + } + + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); +} diff --git a/solutions/blocks/form/form.css b/_src/blocks/form/form.css similarity index 100% rename from solutions/blocks/form/form.css rename to _src/blocks/form/form.css diff --git a/_src/blocks/form/form.js b/_src/blocks/form/form.js new file mode 100644 index 000000000..0ed943ace --- /dev/null +++ b/_src/blocks/form/form.js @@ -0,0 +1,234 @@ +async function fetchData(url) { + const resp = await fetch(url); + const json = await resp.json(); + return json.data; +} + +/** + * + * @param {String} email + * @returns {Boolean} wether the email passed is valid or not + */ +const validateEmail = (email) => { + const re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; + return re.test(email.toLowerCase()); +}; + +/** + * + * @param {HTMLInputElement} inputElement + * @returns {Boolean} validation status of the field + */ +const checkInputValue = (inputElement) => { + // real time field validation for the email field (For DIP only) + switch (inputElement.type) { + case 'email': + // validate the email inputs using the validation function if there are error fields + if (!validateEmail(inputElement.value)) { + return false; + } + + break; + case 'checkbox': + if (!inputElement.checked && inputElement.required) { + return false; + } + + break; + default: + break; + } + + return true; +}; + +/** + * + * @param {HTMLInputElement} inputElement + */ +const displayInputError = (inputElement) => { + const inputElementError = inputElement.parentElement.querySelector('.input-error-field'); + if (inputElementError) { + inputElementError.classList.remove('global-display-none'); + } +}; + +/** + * + * @param {HTMLInputElement} inputElement + */ +const hideInputError = (inputElement) => { + const inputElementError = inputElement.parentElement.querySelector('.input-error-field'); + if (inputElementError) { + inputElementError.classList.add('global-display-none'); + } +}; + +/** + * + * @param {HTMLFormElement} form + * set the onChange function for all the form inputs + */ +function checkFormValues(form) { + const submitButton = form.querySelector('input[type="submit"]'); + + // Targeting the anchor inside .button-container + const allInputFields = form.querySelectorAll('input:not([type="hidden"])'); + let disabledStatus = false; + allInputFields.forEach((inputField) => { + if (!disabledStatus && !checkInputValue(inputField)) { + disabledStatus = true; + } + }); + + submitButton.disabled = disabledStatus; +} + +async function handleSubmit(e, handler) { + e.preventDefault(); + try { + const mod = await import(handler); + if (mod.default) await mod.default(e); + } catch (error) { + // eslint-disable-next-line no-console + console.log('failed to load module for lib-identity-exposed-onsubmit', error); + } +} + +/** + * + * @param {HTMLInputElement} input the input to be adde inside the div wrapper + * @param {HTMLDivElement} newDivParent the div wrapper to hold the input + */ +const wrapInputInsideDiv = (input, newDivParent) => { + const label = input.nextElementSibling; + + // if the input has a label, also add it inside the wrapper + if (label && label.tagName === 'LABEL') { + input.before(newDivParent); + newDivParent.append(input, label); + } else { + input.after(newDivParent); + newDivParent.append(input); + } +}; + +// Debounce function to improve performance of input calls +/** + * + * @param {Function} func + * @param {Number} wait + * @param {Boolean} immediate + */ +const debounce = (func, wait, immediate) => { + let timeout; + + return (...args) => { + const later = () => { + timeout = null; + if (!immediate) { + func(args); + } + }; + + const callNow = immediate && !timeout; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + if (callNow) { + func(args); + } + }; +}; + +/** + * + * @param {HTMLInputElement} input + * @param {HTMLFormElement} form + * add the validations which get triggered whenever an input is filled with data + */ +const addInputValidation = (input, form) => { + if (input.dataset.containsErrorField && checkInputValue(input)) { + hideInputError(input); + } else if (input.dataset.containsErrorField) { + displayInputError(input); + } + + checkFormValues(form); +}; + +/** + * + * @param {string} formURL url to form html + * @returns {Promise} returns the form + */ +export async function createForm(formURL) { + const { pathname, search } = new URL(formURL); + const data = await fetchData(`${pathname}${search}`); + const form = document.createElement('form'); + + form.setAttribute('method', 'post'); + + data.forEach((field, index) => { + const input = document.createElement('input'); + input.id = `form-${index}-${field.Field}`; + input.setAttribute('type', field.Type); + input.setAttribute('name', field.Field); + input.setAttribute('placeholder', field.Default); + input.setAttribute('value', field.Value); + input.setAttribute('data-contains-error-field', Boolean(field.Error)); + + // add event listeners to the fields + input.addEventListener('input', debounce(() => addInputValidation(input, form), 100, false)); + + if (field.Required && field.Required.toLowerCase() === 'true') { + input.setAttribute('required', ''); + input.setAttribute('aria-required', 'true'); + } + + form.append(input); + + // Only create a label if the field.Label is not null + if (field.Label) { + const label = document.createElement('label'); + label.setAttribute('for', input.id); + label.textContent = field.Label; + form.append(label); + } + + if (field.Type === 'submit') { + input.classList.add('disabled'); + input.disabled = true; + } + + if (field.Field === 'handler') { + form.addEventListener('submit', (e) => handleSubmit(e, field.Value)); + } + + if (field.Type === 'checkbox') { + const newDivWrapper = document.createElement('div'); + newDivWrapper.classList.add('checkbox'); + + wrapInputInsideDiv(input, newDivWrapper); + } + + if (field.Error) { + const newDivWrapper = document.createElement('div'); + newDivWrapper.classList.add('input-container-with-error'); + + // add the error field + const errorField = document.createElement('p'); + errorField.classList.add('input-error-field', 'global-display-none'); + errorField.textContent = field.Error; + newDivWrapper.appendChild(errorField); + input.classList.add('input-with-error-field'); + + wrapInputInsideDiv(input, newDivWrapper); + } + }); + return form; +} + +export default async function decorate(block) { + const form = await createForm(block.textContent.trim()); + if (form) block.append(form); +} diff --git a/_src/blocks/four-cards/four-cards.css b/_src/blocks/four-cards/four-cards.css new file mode 100644 index 000000000..dd509ce04 --- /dev/null +++ b/_src/blocks/four-cards/four-cards.css @@ -0,0 +1,315 @@ +.four-cards-container { + --dark-background-color: #000; + --black-color: #000; + --white-color: #fff; + --background-color: #fff; + --link-color: #005ed9; + --link-hover-color: #00439c; + --button-link-color: #fff; + --button-background-color: #eb0000; + --button-hover-background-color: #d80000; + --button-primary-background-color: #000; + --button-primary-hover-background-color: #000; + --button-secondary-color: #000; + --button-secondary-hover-background-color: #000; + --overlay-background-color: #eee; + --highlight-background-color: #ccc; + --text-color: #000; + --text-error-color: #f00; + --color-highlight-blue: #006dff; + --color-dark-gray: #616161; + --checkbox-label: #3c3c3c; + --highlight-light-blue: #f3f7fe; + --text-dark-color: #fff; + --horizontal-separator-color: #dedede; + --modal-background-color: rgb(0 0 0 / 50%); + --background-color-light-sky-blue: #e4f2ff; + --icon-color: #205fff; + --background-light-blue: #d9eeff; + --background-blue: #005ed9; + --dark-blue-tag: #005eff; + --light-blue-tag: #13b0a7; + --green-tag: #218728; + --dark-shadow: #0000001a; + --background-checkmark: #61AF53; + --body-font-family: "Roboto", "roboto-normal-400-fallback", helvetica, ubuntu, roboto, noto, sans-serif; + --heading-font-family: var(--body-font-family); + --fixed-font-family: var(--body-font-family); + --font-weight-thin: 300; + --font-weight-regular: 400; + --font-weight-bold: 500; + --font-weight-bolder: 600; + --font-weight-boldest: 700; + --font-weight-heavy: 900; + --body-font-size-l: 22px; + --body-font-size-m: 18px; + --body-font-size-s: 16px; + --body-font-size-xs: 14px; + --body-font-size-xxs: 12px; + --body-font-size-xxxs: 10px; + --heading-font-size-xxxl: 60px; + --heading-font-size-xxl: 48px; + --heading-font-size-xl: 40px; + --heading-font-size-l: 32px; + --heading-font-size-m: 24px; + --heading-font-size-s: 20px; + --heading-font-size-xs: 18px; + --heading-font-size-xxs: 16px; + --nav-height: 63px; + --nav-height-desktop: 40px; + --body-max-width: 1920px; + --body-padding: 20px; + --section-desktop-max-width: 1300px; + --section-desktop-padding: 20px; + --section-large-desktop-max-width: 1332px; + --section-large-desktop-padding: 50px; + --section-desktop-padding-vertical: 48px; + --section-mobile-padding-vertical: 32px; + --cta-background-light-blue: var(--background-light-blue); +} + +@media (min-width: 992px) { /* desktop */ + .four-cards-wrapper { + max-width: var(--section-desktop-max-width); + padding: 0 var(--section-desktop-padding); + margin: 0 auto; + } +} + +@media (min-width: 1600px) { /* large desktop */ + .four-cards-wrapper { + max-width: var(--section-large-desktop-max-width); + padding: 0 var(--section-large-desktop-padding); + } +} + +.creators .title-size .default-content-wrapper p { + font-size: 24px; +} + + +.creator-cards .four-cards.block { + display: flex; + justify-content: center; +} + +.creator-cards .four-cards.block ul li strong { + font-size: 22px; +} + +.four-cards .default-content-wrapper { + text-align: center; +} + +.creator-cards .default-content-wrapper { + text-align: center; +} + +.dlp.four-cards-container .default-content-wrapper{ + text-align: center; +} + +.four-cards-container h3 { + font: normal normal bold 32px/37px var(--body-font-family); + text-align: center; + margin-bottom: 56px; +} + +.creator-cards.four-cards-container h3 { + font: normal normal bold 60px/69px "IBM Plex Sans", sans-serif; + text-align: center; + margin-bottom: 28px; +} + +.creator-cards.four-cards-container h4 { + font: normal normal bold 22px/24px "IBM Plex Sans", sans-serif; + text-align: left; + +} + +.four-cards-container.we-container { + max-width: 100%; + padding-left: 20px; + padding-right: 20px; + margin-top: 15px; + margin-left: auto; + margin-right: auto; +} + +.four-cards-container .icon svg { + width: 48px; + height: 48px; + padding-right: 2px; + fill: #fff; +} + +.four-cards > ul { + list-style: none; + margin: 0; + padding: 0; + display: grid; + grid-template-columns: 1fr; + grid-gap: 24px; +} + +.four-cards > ul > li { + display: inline-block; + background-color: #f6f6f6; + padding: 24px; + margin: 0; + border-radius: 20px; + text-align: left; + font: normal normal normal 16px/24px var(--body-font-family); +} + +.creator-cards .four-cards > ul > li { + font-size: 18px; +} + +.creator-cards .default-content-wrapper:last-of-type { + padding-top: 0; +} + +.creator-cards .four-cards ul li div img { + height: 48px; + margin-bottom: 0; +} + +/* a/b test styles, should be deleted after */ +.four-cards-container.we-container .default-content-wrapper { + text-align: center; +} + +.four-cards-container a { + font: normal normal bold 16px/20px var(--body-font-family); + margin-top: 32px; + padding: 14px 28px; + color: #006EFF; + background: white; + border: 2px solid #006EFF; + border-radius: 10px; + display: inline-block; + position: relative; + min-width: 180px; +} + +.four-cards-container p a { + font-size: 16px; + font-style: normal; + font-weight: 500; + -webkit-font-smoothing: antialiased; + display: inline-flex; + align-items: center; + box-sizing: border-box; + text-decoration: none; + padding: 10px 26px 8px 28px; + text-align: center; + justify-content: center; + cursor: pointer; + color: #006DFF; + background-color: transparent; + border: 2px solid #006DFF; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + border-radius: 8px; + height: fit-content; + transition: all .2s cubic-bezier(.4,0,.2,1); +} + +.four-cards-container p a:hover { + color: white; + background-color: #006DFF; +} + +.four-cards-container p a:active { + background-color: #0D499B; +} + +.creator-cards .default-content-wrapper a.button:any-link { + min-width: 230px; + height: 48px; + padding: 10px 10px 10px 25px; + background: #E72325 0% 0% no-repeat padding-box; + border-radius: 40px; + justify-content: center; + font: normal normal 500 18px / 24px Roboto, sans-serif; + color: white; +} + +.creator-cards .default-content-wrapper a.button:hover { + color: white; + background-color: var(--button-background-color); +} + +.creator-cards .default-content-wrapper a.button:active { + color: white; + background-color: var(--button-background-color); + border: 0; +} + +.four-cards .icon { + width: 48px; + height: 48px; + margin-bottom: 16px; +} + +@media (max-width: 991px) { /* mobile/tablet */ + .four-cards-wrapper { + padding: var(--body-padding); + } + + .four-cards > ul > li { + margin: 0; + } +} + +@media (min-width: 768px) { + .four-cards > ul { + grid-template-columns: 1fr 1fr; + grid-gap: 14px; + } +} + +@media (min-width: 992px) { + .four-cards-container.we-container { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } + + .four-cards > ul { + grid-template-columns: 1fr 1fr 1fr 1fr; + grid-gap: 14px; + } + + .creator-cards .four-cards > ul { + grid-template-columns: 300px 300px 300px; + grid-gap: 14px; + } +} + +@media (min-width: 1200px) { + .four-cards-container.we-container { + max-width: 1350px; + padding-left: 20px; + padding-right: 20px; + } + +} + +@media (max-width: 991px) { + .creators .title-size .default-content-wrapper h2 { + font-size: 31px; + } + + .creators .title-size .default-content-wrapper p { + font-size: 18px; + line-height: 1.25; + margin-bottom: 9px; + } + + .creator-cards .default-content-wrapper a.button:any-link { + margin-top: 0; + } +} diff --git a/_src/blocks/four-cards/four-cards.js b/_src/blocks/four-cards/four-cards.js new file mode 100644 index 000000000..71922ba0c --- /dev/null +++ b/_src/blocks/four-cards/four-cards.js @@ -0,0 +1,50 @@ +export default async function decorate(block, options) { + const { + // eslint-disable-next-line no-unused-vars + margintop, + } = block.closest('.section').dataset; + + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + const blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + const fourCardsWrapper = block.closest('.four-cards-wrapper'); + if (fourCardsWrapper) { + fourCardsWrapper.classList.remove('four-cards-wrapper'); + } + } + + if (margintop) { + const blockParent = block.closest('.section'); + blockParent.style.marginTop = `${margintop}px`; + } + + const ul = document.createElement('ul'); + [...block.children].forEach((row) => { + const li = document.createElement('li'); + li.innerHTML = row.innerHTML; + + ul.append(li); + }); + + block.textContent = ''; + block.append(ul); + + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); + + // decorate icons only if the component is being called from www-websites + const isInLandingPages = window.location.href.includes('www-landing-pages') || window.location.href.includes('bitdefender.com/pages'); + if (!options && !isInLandingPages) { + const { decorateIcons } = await import('../../scripts/lib-franklin.js'); + decorateIcons(block.closest('.section')); + } + + if (isInLandingPages) { + const { decorateIcons } = await import('../../scripts/utils/utils.js'); + decorateIcons(block.closest('.section')); + } +} diff --git a/solutions/blocks/fragment-metadata/fragment-metadata.css b/_src/blocks/fragment-metadata/fragment-metadata.css similarity index 100% rename from solutions/blocks/fragment-metadata/fragment-metadata.css rename to _src/blocks/fragment-metadata/fragment-metadata.css diff --git a/solutions/blocks/fragment-metadata/fragment-metadata.js b/_src/blocks/fragment-metadata/fragment-metadata.js similarity index 64% rename from solutions/blocks/fragment-metadata/fragment-metadata.js rename to _src/blocks/fragment-metadata/fragment-metadata.js index 9f6e09365..d727c8d01 100644 --- a/solutions/blocks/fragment-metadata/fragment-metadata.js +++ b/_src/blocks/fragment-metadata/fragment-metadata.js @@ -1,5 +1,5 @@ import { readBlockConfig } from '../../scripts/lib-franklin.js'; -import { openUrlForOs } from '../../scripts/scripts.js'; +import { openUrlForOs } from '../../scripts/utils/utils.js'; export default function decorate(block) { const { @@ -11,7 +11,13 @@ export default function decorate(block) { } = readBlockConfig(block); if (template) { - document.body.classList.add(template); + // make sure that the added class is a string + // not a variable caught between '{' and '}' + const variableRegex = /^\{([\s\S]*)\}$/; + const variableMatch = template.match(variableRegex); + const classTemplate = variableMatch ? variableMatch[1] : template; + + document.body.classList.add(classTemplate); } if (urlMacos || urlWindows || urlAndroid || urlIos) { diff --git a/_src/blocks/header-aem/header-aem.css b/_src/blocks/header-aem/header-aem.css new file mode 100644 index 000000000..825d7e3c9 --- /dev/null +++ b/_src/blocks/header-aem/header-aem.css @@ -0,0 +1,50 @@ +.header-aem-wrapper { + .header-aem { + display: flex; + align-items: center; + height: 60px; + + img { + height: 26px; + width: auto; + } + } +} + +.header-aem-container { + background-color: #fff; + border-bottom: 1px solid #EDEDED; +} + +.header-aem-wrapper.we-container { + max-width: 100%; + padding-left: 20px; + padding-right: 20px; + margin-top: 15px; + margin-left: auto; + margin-right: auto; +} + +@media (min-width: 992px) { + .header-aem-wrapper.we-container { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } +} + +@media (min-width: 1200px) { + .header-aem-wrapper.we-container { + max-width: 1210px; + padding-left: 50px; + padding-right: 50px; + } +} + +@media (min-width: 1599px) { + .header-aem-wrapper.we-container { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } +} diff --git a/_src/blocks/header-aem/header-aem.js b/_src/blocks/header-aem/header-aem.js new file mode 100644 index 000000000..bbe10d78d --- /dev/null +++ b/_src/blocks/header-aem/header-aem.js @@ -0,0 +1,49 @@ +async function runWhitePageHeaderLogic(block, link) { + block.classList.add('white', 'py-3', 'default-content-wrapper'); + + if (link) { + // create a link and inside it put the logo + const logoLink = document.createElement('a'); + logoLink.href = link; + logoLink.classList.add('logo-link'); + const image = block.querySelector('picture'); + logoLink.appendChild(image); + block.appendChild(logoLink); + } + + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); +} + +/** + * applies header factory based on header variation + * @param {String} headerMetadata The header variation: landingpage' or none + * @param {Element} header The header element + */ +function applyHeaderFactorySetup(headerMetadata, header, link) { + switch (headerMetadata) { + case 'white': + runWhitePageHeaderLogic(header, link); + break; + default: + break; + } +} +export default async function decorate(block, options) { + const { + header, link, + } = block.closest('.section').dataset; + + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + const blockParent = block.closest('.header-aem-wrapper'); + blockParent.classList.add('we-container'); + } + + block.parentNode.classList.add(header || 'default'); + + applyHeaderFactorySetup(header, block, link); +} diff --git a/_src/blocks/header/header.css b/_src/blocks/header/header.css new file mode 100644 index 000000000..504a337d7 --- /dev/null +++ b/_src/blocks/header/header.css @@ -0,0 +1,1247 @@ +/* stylelint-disable no-descending-specificity */ + +/* header and nav layout */ +header.header-wrapper { + position: sticky; + top: 0; + transition: height 0.3s ease-in-out; + background-color: var(--white-color); + z-index: 100; +} + +header.header-wrapper nav { + display: none; +} + + +:root { + --dark-header-icon-color: #000; +} + +header.header-wrapper p { + margin: 0; +} + +header.header-wrapper > p { + margin-top: 0; + padding: 15px; + text-align: center; + font-size: var(--body-font-size-s); + color: var(--horizontal-separator-color); + text-decoration: none; + cursor: pointer; + width: 175px; + height: 50px; +} + + + + + + +header.header-wrapper .nav-wrapper { + display: none; +} + +header.header-wrapper .nav-brand, +header.header-wrapper .nav-sections { + display: inline-flex; + align-items: flex-start; + width: 49.5%; +} + +header.header-wrapper .nav-brand { + flex-wrap: nowrap; + justify-content: flex-start; +} + +header.header-wrapper .nav-sections { + flex-wrap: nowrap; + justify-content: flex-end; +} + +header.header-wrapper .nav-brand p, +header.header-wrapper .nav-sections p { + display: inline-block; +} + +header.header-wrapper .bottom-links div, .bottom-links p{ + display: inline-block; +} + +header.header-wrapper .login-modal > p { + position: relative; + width: 100%; + display: block; + text-align: center; + margin-top: 45px; +} + +@keyframes animate-bottom-border { + 0% { + transform: scaleX(0); + transform-origin: left; + } + + 100% { + transform: scaleX(1); + transform-origin: left; + } +} + +header.header-wrapper .home-button-border { + position: absolute; + margin-top: 12px; + width: 70px; + height: 3px; + background-color: var(--color-highlight-blue); +} + +header.header-wrapper .nav-divider { + display: flex; + flex-wrap: nowrap; + justify-content: flex-end; + min-width: 2px; + width: 2px; + background-color: var(--color-dark-gray); + height: 20px; + margin-right: 15px; + margin-top: 7.5px; +} + +header.header-wrapper .login-modal { + display: none; + flex-direction: column; + align-items: flex-start; + justify-content: flex-start; + position: absolute; + right: min(15px, calc(100vw - 880px)); + width: 375px; + height: 275px; + top: 80px; + background-color: var(--background-color); + border-radius: 5px; + opacity: 0; + transition: all 0.3s ease-in-out; + box-shadow: 0 10px 10px #0003; + z-index: 0; + transform: translateY(20px); +} + +header.header-wrapper .login-modal.show { + opacity: 1; + top: 60px; + z-index: 5; + transform: translateY(0); +} + + +header.header-wrapper .login-modal h2 { + position: relative; + white-space: nowrap; + color: var(--text-color); + font-size: var(--body-font-size-s); + width: 100%; + margin-left: 25px; + top: 15px; + text-align: left; +} + +header.header-wrapper .divider { + position: absolute; + margin-top: 45px; + width: 100%; + height: 1px; + background-color: var(--color-dark-gray); +} + +.login-modal a { + text-decoration: none; + color: var(--color-highlight-blue) !important; + width: 330px; + height: 55px; + border-radius: 9px; + border: 2px solid var(--color-highlight-blue) !important; + background-color: transparent !important; + margin: -70px; + padding: 5px; + display: inline-block; + font-size: var(--body-font-size-xs); + font-weight: 500; +} + +header.header-wrapper a.button:any-link { + padding: 0; +} + +header.header-wrapper .login-modal a.button:any-link { + height: 50px; + padding-right: 15px; +} + +header.header-wrapper a.button::after { + margin-left: 0; +} + +header.header-wrapper .login-modal a.button::after { + position: relative; + margin-left: 220px; +} + +header.header-wrapper .login-modal a.button:any-link span { + margin-left: 25%; + position: absolute; + font-weight: 500; +} + +header.header-wrapper .login-modal.show p.button-container:nth-child(3) span { + margin-left: 13%; +} + +header.header-wrapper .login-modal.show p.button-container:nth-child(3) a.button::after { + margin-left: 280px; +} + +header.header-wrapper .login-modal.show p.button-container:nth-child(4) span { + margin-left: 33%; +} + +header.header-wrapper .login-modal.show p.button-container:nth-child(4) a.button::after { + margin-left: 200px; +} + +header.header-wrapper .logo-container { + height: 100%; + display: flex; + justify-content: start; + align-items: center; + max-width: var(--section-desktop-max-width); + margin: 0 auto; + padding: 0 var(--body-padding); +} + +header.header-wrapper.expanded .logo-container { + height: var(--nav-height); + position: absolute; + top: 0; + left: 0; +} + +header.header-wrapper .logo-container > p { + display: none; +} + +header.header-wrapper .login-buttons a p { + text-align: center; + font-size: var(--body-font-size-xs); + font-weight: var(--font-weight-bold); + margin-top: 5px; + transition: all 0.3s ease-in-out; + height: 100%; +} + +header.header-wrapper .icon { + position: absolute; + margin: 0; + z-index: 1000; + top: 15px; + width: 103px; + height: 30px; + filter: none; + left: 20px; + color: var(--dark-background-color); +} + +header.header-wrapper .bottom-links p > a { + text-decoration: none; + font-size: var(--body-font-size-xxs) !important; + font-weight: 500 !important; +} + +header.header-wrapper .login-modal a:hover { + background-color: var(--color-highlight-blue) !important; + color: var(--background-color) !important; +} + +header.header-wrapper a.button span.button-text { + display: flex; + font-size: var(--body-font-size-xs); + font-weight: 400; +} + +header.header-wrapper a.button:hover span.button-text { + transform: none; +} + +header.header-wrapper .options-wrapper.show a { + display: block; + margin-left: 40px; + color: var(--text-color); + font-size: var(--body-font-size-xs); + margin-top: 10px; + text-decoration: none; + animation: slide-in 0.2s 0.075s forwards; + background-color: transparent !important; + border: transparent !important; +} + +header.header-wrapper .bottom-links p:hover > a { + color: var(--color-highlight-blue) !important; +} + +header.header-wrapper > p a:hover{ + color: var(--background-color); +} + +header.header-wrapper .options-wrapper.show > a:first-child { + margin-top: 40px; +} + +header.header-wrapper .login-modal.show.button-container a:hover{ + background-color: var(--color-highlight-blue); + color: var(--background-color); +} + +header.header-wrapper .triangle { + position: absolute; + width: 0; + height: 0; + top: -13px; + left: 320px; + border-left: 15px solid transparent; + border-right: 15px solid transparent; + border-bottom: 20px solid white; +} + +header.header-wrapper .mega-menu-websites div h2 { + position: relative; + font-size: var(--body-font-size-s); + font-weight: 600; + margin-left: 25px; +} + +header.header-wrapper .mega-menu-websites > div:first-child { + display: grid; + grid-template-rows: auto auto; + grid-template-columns: 1fr 1fr 1fr; + align-items: start; + border-bottom: 2px solid #f5f6f7; +} + +header.header-wrapper .mega-menu-websites > div:first-child h2 { + grid-column: span 3; +} + +header.header-wrapper .mega-menu-websites > div:first-child p { + width: 250px; + margin-top: 5px; + border-radius: 5px; + padding: 10px; + height: 85px; +} + + +header.header-wrapper .mega-menu-websites > div:first-child p:hover { + background-color: var(--highlight-light-blue); +} + +header.header-wrapper .mega-menu-websites > div:first-child > p:first-child { + grid-column: 1; +} + +header.header-wrapper .mega-menu-websites > div:first-child p a > span::after { + content: ''; + width: 24px; + height: 24px; + /* stylelint-disable-next-line property-no-vendor-prefix */ + -webkit-mask:url('/_src/icons/arrow-right.svg'); + mask: url('/_src/icons/arrow-right.svg'); + background-color: var(--button-link-color); + display: inline-block; + transition: all .2s cubic-bezier(.4,0,.2,1); + opacity: 0; +} + +header.header-wrapper .mega-menu-websites > div:first-child p a:hover span::after { + opacity: 1; + background-color: var(--color-highlight-blue); +} + +header.header-wrapper .mega-menu-websites > div:first-child p a::after { + display: none; +} + +header.header-wrapper .options-wrapper.show div { + font-weight: var(--font-weight-bold); + font-size: var(--body-font-size-s); + margin: 25px 13px 25px 20px; + position: relative; +} + +header.header-wrapper .options-wrapper.show div::before { + border-color: black; + border-style: solid; + border-width: 0 2px 2px 0; + content: ""; + width: 0.5rem; + height: 0.5rem; + display: inline-block; + position: absolute; + right: 10px; + top: 50%; + transform: translateY(-50%) rotate(-45deg); +} + +@media (max-width: 992px) { + header.header-wrapper .nav-wrapper { + display: none; + } + + header.header-wrapper p { + margin: 0; + } + + header.header-wrapper > p{ + display: none; + } + +} + +header.header-wrapper .icon.icon-arrow-right { + position: absolute; + width: 10px; + height: 10px; + margin-left: 1px; + z-index: 5; +} + +header.header-wrapper .bottom-links div:nth-child(2) { + margin-left: 120px; +} + +header.header-wrapper .menu-bar { + display: block; + width: 100%; + height: 3px; + background-color: var(--text-color); + transition: transform 0.3s ease, opacity 0.3s ease; + will-change: transform, opacity; +} + +header.header-wrapper .menu-wrapper { + position: absolute; + top: 17px; + right: 20px; + width: 25px; + height: 25px; + cursor: pointer; + display: flex; + flex-direction: column; + justify-content: space-around; + z-index: 100; +} + +header.header-wrapper .menu-wrapper.change .menu-bar:first-child { + transform: rotate(-45deg) translate(-5px, 5px); +} + +header.header-wrapper .menu-wrapper.change .menu-bar:nth-child(2) { + opacity: 0; +} + +header.header-wrapper .menu-wrapper.change .menu-bar:last-child { + transform: rotate(45deg) translate(-6px,-7px); +} + +header.header-wrapper.expanded { + height: 100vh; + width: 100vw; + z-index: 2; +} + +header.header-wrapper .options-wrapper { + position: relative; + top: var(--nav-height); + width: 100vw; + height: 0; + display: none; +} + +header.header-wrapper .options-wrapper.show{ + width: 100vw; + height: 100vh; + box-shadow: 0 10px 10px #0003; + z-index: 3; + border-top: 1px solid #cecccc; + display: block; +} + +header.header-wrapper .sub-menu { + display: none; +} + +header.header-wrapper .sub-menu.show { + display: block; +} + +header.header-wrapper .options-wrapper.show .sub-menu-title { + font-size: var(--body-font-size-xs); + font-weight: var(--font-weight-bold); + margin-left: 20px; + padding-left: 20px; + position: relative; +} + +header.header-wrapper .options-wrapper.show .sub-menu-title::before { + border-color: black; + border-style: solid; + border-width: 0 2px 2px 0; + content: ""; + width: 0.5rem; + height: 0.5rem; + display: inline-block; + position: absolute; + left: 0; + top: 50%; + transform: translate(0, -50%) rotate(135deg); +} + +@keyframes slide-in { + from { + transform: translateX(100%); + } + + to { + transform: translateX(0); + } +} + +header.header-wrapper #icons-sprite-bitdefender-logo path { + fill: currentcolor +} + +#header-ferrari { + border-bottom: 2px solid #3C3C3C; + height: 40px; + box-shadow: 0 32px 73px #000; + background-color: black; +} + +#header-ferrari div div { + margin-top: -10px; +} + +#header-ferrari ul { + padding: 0; + margin: 0; + width: 50%; + float: left; +} + +#header-ferrari ul:nth-of-type(2) { + text-align: right; +} + +#header-ferrari ul:nth-of-type(3) { + width: 100%; + margin-top: -5px; +} + +#header-ferrari ul li { + color: white; + font-size: 12px; + list-style-type: none; + display: inline-block; + padding: 0 10px; + font-weight: 600; +} + +#header-ferrari ul:nth-of-type(2) li { + border-left: 1px solid #616161; +} + +#header-ferrari ul:nth-of-type(3) li { + padding: 0 25px 0 0; +} + +#header-ferrari ul:nth-of-type(1) li:nth-of-type(1) { + padding-left: 0; +} + +#header-ferrari ul li a { + color: #DEDEDE; + font-size: 12px; + padding-bottom: 10px; + position: relative; + font-weight: 600; +} + +#header-ferrari ul li a::before { + content: ""; + position: absolute; + bottom: -2px; + height: 4px; + background: #006EFF; + transition: all 0.3s ease; + transition-property: transform; + width: 100%; + transform: scaleX(0); + will-change: transform; + transform-origin: right; +} + +#header-ferrari ul li a:hover { + text-decoration: none; +} + +#header-ferrari ul li a:hover::before { + transform: scaleX(1); + transform-origin: left; +} + +#header-ferrari ul:nth-of-type(3) li a { + color: #FFF; + font-size: 16px; + font-weight: 500; +} + +#header-ferrari ul:nth-of-type(3) li a span.icon-logo-white { + display: inline-block; + background: url("/_src/images/sigla_bd_white.svg") 0 0 no-repeat; + width: 165px; + height: 25px; +} + +#header-ferrari ul:nth-of-type(3) :nth-of-type(3) a { + font-weight: bold; +} + +header.quiz { + background: black; + + .icon { + width: 155px; + } +} + +@media(min-width: 767px) { /* tablet */ + header.header-wrapper .logo-container .icon { + width: 180px; + } + +} + +@media(min-width: 992px) { + header.header-wrapper::after { + position: absolute; + top: 64px; + left: 0; + right: 0; + width: 100%; + height: 2px; + background-color: #3c3c3c; + margin: 0 auto; + } + + header.header-wrapper .icon { + color: var(--text-color); + position: static; + } + + header.header-wrapper.black-background .icon { + color: var(--text-dark-color); + } + + header.header-wrapper .menu-wrapper { + display: none; + } + + header.header-wrapper .nav-wrapper { + width: 100%; + background-color: var(--text-color); + z-index: 100; + display: block; + margin: 0 auto; + } + + header.header-wrapper nav { + display: block; + max-width: var(--section-desktop-max-width); + height: 100%; + margin: 0 auto; + padding: 6px var(--section-desktop-padding) 10px; + position: relative; + } + + header.header-wrapper nav p { + line-height: 1.4; + font-size: var(--body-font-size-xxs); + font-weight: var(--font-weight-bold); + } + + header.header-wrapper .nav-sections { + display: inline-flex; + flex-wrap: wrap; + gap: 0; + } + + + header.header-wrapper .nav-brand a, + header.header-wrapper .nav-sections a { + color: var(--horizontal-separator-color); + text-decoration: none; + text-transform: uppercase; + font-size: var(--body-font-size-xxs); + font-weight: var(--font-weight-bold); + margin-right: 0; + letter-spacing: 0.96px; + cursor: pointer; + line-height: 1.4; + display: inline-block; + position: relative; + } + + header.header-wrapper .nav-sections a { + margin: 0 15.5px; + } + + header.header-wrapper .logo a { + display: block; + } + + header.header-wrapper .nav-brand p a { + margin: 0 12px; + } + + header.header-wrapper .mega-menu-websites div h2 > a { + transition: all 0.2s ease-in-out; + border-radius: 3px; + text-decoration: none; + padding: 7px 10px; + color: var(--link-color); + font-size: var(--body-font-size-xs); + font-weight: var(--font-weight-bold); + } + + header.header-wrapper .mega-menu-websites div p a{ + position: relative; + font-size: var(--body-font-size-xs); + font-weight: 400; + color: var(--text-color); + } + + header.header-wrapper .nav-sections a:first-child{ + margin-right: 16px; + } + + header.header-wrapper .nav-brand p:first-child a{ + margin-left: 0; + } + + header.header-wrapper .nav-sections p a::before, + header.header-wrapper .nav-brand p a::before { + content: ""; + position: absolute; + top: 25px; + height: 3px; + background: var(--color-highlight-blue); + transition: all .3s ease; + width: 100%; + transform: scaleX(0); + transform-origin: left; + left: 0; + } + + header.header-wrapper .nav-sections p a:hover::before, + header.header-wrapper .nav-brand p a.active::before, + header.header-wrapper .nav-brand p a:hover::before, + header.header-wrapper .nav-sections p.clicked a::before { + transform: scaleX(1); + transform-origin: left; + } + + /* Other existing styles */ + header.header-wrapper .mega-menu-websites div h2 > a:hover { + background-color: var(--highlight-light-blue); + } + + header.header-wrapper .nav-sections p:last-child:hover::after { + width: 50px; + } + + header.header-wrapper .nav-sections p, + header.header-wrapper .nav-brand p { + position: relative; + } + + header.header-wrapper .nav-sections p::before, + header.header-wrapper .nav-brand p:not(:first-child)::before { + content: ""; + position: absolute; + top: 0; + left: 0; + height: 16px; + width: 2px; + background-color: #616161; + } + + header.header-wrapper .logo-container { + padding: 20px var(--section-desktop-padding); + margin: 21px auto 0; + gap: 10px; + } + + header.header-wrapper .logo-container > p { + display: block; + font-weight: var(--font-weight-bold); + line-height: 1.63; + font-size: 15px; + } + + header.header-wrapper .home-solutions-link-hover { + color: #FFF; + } + + header.header-wrapper .home-solutions-link-default { + display: block; + color: var(--text-color); + cursor: pointer; + padding: 0 27px 31px; + position: relative; + margin-top: 35px; + } + + header.header-wrapper.black-background .home-solutions-link-default { + color: #dedede; + } + + header.header-wrapper .home-solutions-link-default::before { + content: ""; + position: absolute; + bottom: 3px; + height: 4px; + background: #006eff; + transition: all .3s ease; + width: 100%; + transform: scaleX(0); + transform-origin: left; + left: 0; + } + + header.header-wrapper .home-solutions-link-hover::before { + transform: scaleX(1); + transform-origin: left; + } + + header.header-wrapper .mega-menu-websites { + flex-direction: column; + position: absolute; + left: 80px; + top: 123px; + max-width: 920px; + width: 100%; + background-color: var(--background-color); + z-index: 3; + transition: opacity 0.3s ease-in-out, visibility 0.3s ease-in-out; + border-bottom-left-radius: 8px; + border-bottom-right-radius: 8px; + box-shadow: 0 10px 10px #0003; + visibility: hidden; + display: none; + opacity: 0; + } + + header.header-wrapper .mega-menu-websites-show { + opacity: 1; + visibility: visible; + display: flex; + } + + header.header-wrapper .mega-menu-websites div h2 { + position: relative; + font-size: var(--body-font-size-xs); + font-weight: var(--font-weight-boldest); + line-height: 18px; + padding: 7px 10px; + margin: 10px 25px 0 15px; + } + + header.header-wrapper .other-options > div:nth-child(5) { + grid-area: 2 / 3 / 3 / 4; + } + + header.header-wrapper .other-options > div:nth-child(4) { + grid-area: 2 / 2 / 3 / 3; + } + + header.header-wrapper .other-options > div:nth-child(3) { + grid-area: 1 / 3 / 2 / 4; + } + + header.header-wrapper .other-options > div:nth-child(2) { + grid-area: 1 / 2 / 2 / 3; + } + + header.header-wrapper .other-options > div:nth-child(1) { + grid-area: 1 / 1 / 3 / 2; + } + + header.header-wrapper .other-options > div > p { + position: relative; + top: 0; + margin-left: 20px; + font-size: var(--body-font-size-xs); + font-weight: var(--font-weight-regular); + line-height: 18px; + } + + header.header-wrapper .other-options > div > h2 { + margin-top: 0; + } + + header.header-wrapper .other-options > div > p a.button { + font-size: var(--body-font-size-xs); + font-weight: var(--font-weight-regular); + line-height: 18px; + text-decoration: none; + padding: 1px 10px; + background-color: transparent; + border-radius: 4px; + border: none; + } + + header.header-wrapper .other-options > div > p a.button:hover { + background-color: var(--highlight-light-blue); + transition: none; + transform: none; + } + + header.header-wrapper .mega-menu-websites > div:first-child p a::after { + display: none; + } + + header.header-wrapper .other-options > div > p a:hover::after { + background-color: var(--color-highlight-blue); + } + + header.header-wrapper .other-options > div > p a.button > span { + font-size: var(--body-font-size-xs); + font-weight: var(--font-weight-regular); + line-height: 18px; + position: relative; + color: var(--text-color); + } + + header.header-wrapper .mega-menu-websites > div:first-child p a > span:first-child { + font-size: var(--body-font-size-xs); + font-weight: var(--font-weight-boldest); + line-height: 18px; + align-items: center; + } + + header.header-wrapper .mega-menu-websites .button-container:hover a.button::after { + transform: none; + opacity: 1; + } + + header.header-wrapper .mega-menu-websites > div:first-child { + display: grid; + grid-template-rows: auto auto; + grid-template-columns: 1fr 1fr 1fr; + align-items: start; + border-bottom: 2px solid #f5f6f7; + padding-bottom: 14px; + } + + header.header-wrapper.mega-menu-websites > div:first-child > p > a > div { + margin-top: 5px; + line-height: 18px; + font-size: 13px; + font-weight: 400; + color: var(--color-dark-gray); + white-space: break-spaces; + text-align: left; + } + + header.header-wrapper .mega-menu-websites > div:first-child h2 { + grid-column: span 3; + } + + header.header-wrapper .mega-menu-websites div p { + margin-left: 15px; + } + + header.header-wrapper.bottom-links div p { + height: fit-content; + margin-left: 20px; + } + + header.header-wrapper .mega-menu-websites > div:first-child p { + width: 250px; + margin-top: 0; + border-radius: 5px; + padding: 0; + height: auto; + } + + header.header-wrapper .mega-menu-websites > div:first-child p:hover { + background-color: var(--highlight-light-blue); + } + + header.header-wrapper .mega-menu-websites > div:first-child > p:first-child { + grid-column: 1; + } + + header.header-wrapper .mega-menu-websites > div:first-child p a > span::after { + content: ''; + width: 24px; + height: 24px; + /* stylelint-disable-next-line property-no-vendor-prefix */ + -webkit-mask:url('/_src/icons/arrow-right.svg'); + mask: url('/_src/icons/arrow-right.svg'); + background-color: var(--button-link-color); + display: inline-block; + transition: all .2s cubic-bezier(.4,0,.2,1); + opacity: 0; + } + + header.header-wrapper .mega-menu-websites > div:first-child p a:hover > span::after { + opacity: 1; + background-color: var(--color-highlight-blue); + } + + + header.header-wrapper .mega-menu-websites > div:first-child p a { + padding: 7px 10px; + display: block; + color: var(--text-color) !important; + text-decoration: none; + font-size: var(--body-font-size-s); + background-color: transparent; + border: none; + } + + header.header-wrapper .mega-menu-websites > div:first-child p:hover a { + color: var(--color-highlight-blue) !important; + } + + header.header-wrapper .other-options { + display: grid; + grid-template-columns: repeat(3, 1fr); + grid-template-rows: repeat(2, 1fr); + grid-gap: 0; + padding-top: 14px; + } + + header.header-wrapper #new, + header.header-wrapper #evolved { + position: relative; + font-size: var(--body-font-size-xxs); + font-weight: 600; + color: var(--background-color); + background-color: var(--color-highlight-blue); + padding: 2px; + border-radius: 3px; + margin-left: 5px; + } + + header.header-wrapper .bottom-links { + background-color: rgb(158 164 177 / 10%); + padding: 8px 11px; + margin-top: 20px; + } + + header.quiz { + .icon { + width: 200px; + height: 64px; + } + } +} + +@media (min-width: 1200px) { + header.header-wrapper .mega-menu-websites { + left: 80px; + transform: translateX(0); + } +} + +@media (min-width: 1400px) { + header.header-wrapper .mega-menu-websites { + left: 210px; + transform: translateX(0); + } +} + +@media (min-width: 1600px) { + header.header-wrapper .mega-menu-websites { + left: 240px; + transform: translateX(0); + } +} + +@media (min-width: 1600px) { + header.header-wrapper nav { + max-width: var(--section-large-desktop-max-width); + padding-left: var(--section-large-desktop-padding); + padding-right: var(--section-large-desktop-padding); + } + + header.header-wrapper .nav-brand p a { + margin: 0 19px; + } + + header.header-wrapper .logo-container { + max-width: var(--section-large-desktop-max-width); + padding-left: var(--section-large-desktop-padding); + padding-right: var(--section-large-desktop-padding); + } + + header.header-wrapper .logo-container > p { + font-size: 16px; + } + + header.header-wrapper .home-solutions-link-default { + padding-left: 20px; + } +} + +/* import header spurs lp */ +@media screen and (max-width: 989px) { + #header-ferrari.header-spurs { + background-color: white; + border-bottom: 0 none; + height: 40px; + position: static; + } + + #header-ferrari.header-spurs::before { + content: ''; + background: url('/_src/images/black_company_logo.svg') no-repeat 0 0 transparent; + width: 100px; + height: 20px; + display: block; + background-size: 100%; + margin: 10px; + position: relative; + top: 7px; + } + + #header-ferrari.header-spurs .lp-header { + padding: 0!important; + } + + #header-ferrari.header-spurs .lp-header::before { + content: ''; + background: url('/_src/icons/burger_menu.JPG') no-repeat 0 0 transparent; + width: 29px; + height: 29px; + display: block; + background-size: 100%; + position: absolute; + right: 7px; + top: -26px; + cursor: pointer; + } + + #header-ferrari.header-spurs .lp-header > div { + position: absolute; + z-index: 5; + background-color: white; + width: 100%; + visibility: hidden; + } + + #header-ferrari.header-spurs .lp-header.active > div { + visibility: visible; + } + + #header-ferrari.header-spurs .lp-header > div ul li { + border-bottom: 1px solid #0003; + padding-left: 15px; + } + + .btn-white .button-container a, .btn-white.button-container a:hover { + font-size: 14px; + line-height: 17px; + padding: 10px 1em; + } + + #header-ferrari.header-spurs .lp-header > div ul li, #header-ferrari.header-spurs .lp-header > div ul li a { + width: 100%; + display: block; + padding-bottom: 0; + color: black; + font-size: 15px; + font-family: 'IBM Plex Sans', sans-serif; + text-transform: uppercase; + } + + #header-ferrari.header-spurs .lp-header > div ul li a::before { + display: none; + } + + #header-ferrari.header-spurs ul:last-of-type li:first-of-type { + display: none; + } + + + #header-ferrari { + box-shadow: none; + position: static; + height: auto; + } + + #header-ferrari div div { + margin-top: 0; + flex-direction: column; + display: flex; + } + + #header-ferrari ul { + width: 100%; + float: none; + } + + #header-ferrari ul:nth-of-type(1) { + order: 2; + } + + #header-ferrari ul:nth-of-type(2) { + text-align: left; + order: 3; + } + + #header-ferrari ul li { + padding: 0 10px 0 0; + font-size: 12px; + } + + #flipdown .flip-clock-wrapper ul li { + line-height: 48px; + } + + #header-ferrari ul:nth-of-type(2) li { + border-left: 0 none; + } + + #header-ferrari ul:nth-of-type(3) { + margin-top: 0; + padding-bottom: 0; + order: 1; + } + + #header-ferrari ul:nth-of-type(3) li a span.icon-logo-white { + width: 100px; + height: 17px; + background-size: 100%; + } + + #header-ferrari ul:nth-of-type(3) li { + padding: 0 3px 0 0; + } + + #header-ferrari ul:nth-of-type(3) li a { + font-size: 12px; + } +} diff --git a/solutions/blocks/header/header.js b/_src/blocks/header/header.js similarity index 69% rename from solutions/blocks/header/header.js rename to _src/blocks/header/header.js index 3ec8f51e3..5ba46588d 100644 --- a/solutions/blocks/header/header.js +++ b/_src/blocks/header/header.js @@ -2,8 +2,9 @@ import { getMetadata, decorateIcons, decorateButtons, decorateTags, } from '../../scripts/lib-franklin.js'; -import { decorateBlockWithRegionId, decorateLinkWithLinkTrackingId } from '../../scripts/scripts.js'; -import { adobeMcAppendVisitorId } from '../../scripts/utils.js'; +import { + adobeMcAppendVisitorId, getDomain, decorateBlockWithRegionId, decorateLinkWithLinkTrackingId, +} from '../../scripts/utils/utils.js'; function createLoginModal() { const loginModal = document.querySelector('nav > div:nth-child(4)'); @@ -34,7 +35,7 @@ function handleLoginClick() { } function appendUlToP() { - const divs = document.querySelectorAll('.mega-menu > div'); + const divs = document.querySelectorAll('.mega-menu-websites > div'); divs.forEach((div) => { const uls = div.querySelectorAll('ul'); @@ -60,7 +61,7 @@ function wrapDivsInMegaMenu() { const divs = Array.from(nav.children).filter((node) => node.tagName.toLowerCase() === 'div'); const navSectionsIndex = divs.findIndex((div) => div.classList.contains('nav-sections')); const megaMenuDiv = document.createElement('div'); - megaMenuDiv.className = 'mega-menu'; + megaMenuDiv.className = 'mega-menu-websites'; decorateBlockWithRegionId(megaMenuDiv, 'Main Menu|Home Solutions'); const otherOptionsDiv = document.createElement('div'); @@ -96,7 +97,7 @@ function wrapDivsInMegaMenu() { otherOptionsDiv.appendChild(bottomLinks.firstElementChild); } - const loginModal = document.querySelector('.mega-menu > div:first-child'); + const loginModal = document.querySelector('.mega-menu-websites > div:first-child'); nav.appendChild(loginModal); } @@ -174,20 +175,20 @@ function renderDesktopHeader(block, nav) { const bottomLinks = document.querySelector('.bottom-links'); bottomLinks.removeChild(bottomLinks.lastElementChild); - const megaMenu = document.querySelector('.mega-menu'); + const megaMenu = document.querySelector('.mega-menu-websites'); let isOverHomeSolutions = false; let isOverMegaMenu = false; const showMegaMenu = () => { megaMenu.style.display = 'flex'; setTimeout(() => { - megaMenu.classList.add('mega-menu-show'); + megaMenu.classList.add('mega-menu-websites-show'); }, 10); }; const hideMegaMenu = () => { if (!isOverHomeSolutions && !isOverMegaMenu) { - megaMenu.classList.remove('mega-menu-show'); + megaMenu.classList.remove('mega-menu-websites-show'); homeSolutions.classList.remove('home-solutions-link-hover'); } }; @@ -244,7 +245,7 @@ function handleMenuClick() { }); // Select the first child of mega-menu and all div children of other-options - const megaMenuFirstChild = document.querySelector('.mega-menu').firstElementChild; + const megaMenuFirstChild = document.querySelector('.mega-menu-websites').firstElementChild; const otherOptionsChildren = Array.from(document.querySelector('.other-options').children); const navDivs = [megaMenuFirstChild].concat(otherOptionsChildren); @@ -363,12 +364,8 @@ function renderMobileHeader(nav) { headerBlock.appendChild(optionsWrapper); } -export default async function decorate(block) { +async function runDefaultHeaderLogic(block) { const hero = document.querySelector('.hero'); - const isErrorPage = window.isErrorPage || false; - - // Check if the page isn't an error page and if the hero doesn't exist - if (!hero && !isErrorPage) return; if (hero && hero.classList.contains('black-background')) { const header = document.querySelector('header'); @@ -385,6 +382,108 @@ export default async function decorate(block) { if (resp.ok) { const html = await resp.text(); + if (html.includes('aem-banner')) { + const websiteDomain = getDomain(); + let aemFetchDomain; + + if (websiteDomain === 'en-us') { + aemFetchDomain = 'en'; + } else if (websiteDomain.includes('-global')) { + const [singleDomain] = websiteDomain.split('-'); + aemFetchDomain = singleDomain; + } else { + aemFetchDomain = websiteDomain.split('-').join('_'); + } + + const aemHeaderHostname = window.location.hostname.includes('.hlx.') + || window.location.hostname.includes('localhost') + ? 'https://stage.bitdefender.com' + : ''; + + const aemHeaderFetch = await fetch(`${aemHeaderHostname}/content/experience-fragments/bitdefender/language_master/${aemFetchDomain}/header-navigation/mega-menu/master/jcr:content/root.html`); + if (!aemHeaderFetch.ok) { + return; + } + const aemHeaderHtml = await aemHeaderFetch.text(); + + const nav = document.createElement('div'); + const shadowRoot = nav.attachShadow({ mode: 'open' }); + + const contentDiv = document.createElement('div'); + contentDiv.style.display = 'none'; + + contentDiv.innerHTML = aemHeaderHtml; + const loadedLinks = []; + contentDiv.querySelectorAll('link').forEach((linkElement) => { + // update the links so that they work on all Franklin domains + linkElement.href = `${aemHeaderHostname}${linkElement.getAttribute('href')}`; + + // add a promise for each link element in the code + // so that we can wait on all the CSS before displaying the component + loadedLinks.push(new Promise((resolve, reject) => { + linkElement.onload = () => { + resolve(); + }; + + linkElement.onerror = () => { + reject(); + }; + })); + }); + + // a list of all the components to be received from aem components + const aemComponents = ['languageBanner', 'megaMenu']; + + // add logic so that every time an AEM function is fully loaded + // it is directly run using the shadow dom as parameter + aemComponents.forEach((aemComponentName) => { + window.addEventListener(aemComponentName, () => { + window[aemComponentName](shadowRoot); + }); + }); + + // TODO: please remove this if statement when the mega menu + // for these domains gets created in AEM + const regex = /\/(zh-hk|zh-tw)\//i; + const matches = window.location.href.match(regex); + if (matches) { + const newScriptFile = document.createElement('script'); + newScriptFile.src = '/_src/scripts/vendor/mega-menu/mega-menu.js'; + newScriptFile.defer = true; + shadowRoot.appendChild(newScriptFile); + } else { + // TODO: please keep the below code and move + // it outside the if + + // select all the scripts from contet div and + const scripts = contentDiv.querySelectorAll('script'); + scripts.forEach((script) => { + const newScript = document.createElement('script'); + newScript.src = `${aemHeaderHostname}${script.getAttribute('src')}`; + newScript.defer = true; + contentDiv.appendChild(newScript); + }); + } + + shadowRoot.appendChild(contentDiv); + const body = document.querySelector('body'); + body.style.maxWidth = 'initial'; + + const header = document.querySelector('header'); + if (header) { + header.remove(); + } + + document.querySelector('body').prepend(nav); + + await Promise.allSettled(loadedLinks); + contentDiv.style.display = 'block'; + document.querySelector('body > div:first-child').classList.add('header-with-language-banner'); + + adobeMcAppendVisitorId(shadowRoot); + return; + } + const nav = document.createElement('nav'); nav.id = 'nav'; nav.innerHTML = html; @@ -446,6 +545,64 @@ export default async function decorate(block) { } } }); +} + +async function runLandingPageHeaderLogic(block) { + // fetch nav content + const navPath = getMetadata('nav') || '/nav'; + const resp = await fetch(`${navPath}.plain.html`); + const html = await resp.text(); + + block.classList.add('lp-header', 'py-3', 'default-content-wrapper'); + const headerWrapper = block.closest('header'); + + headerWrapper.id = 'header-ferrari'; + headerWrapper.classList.add('header-spurs', 'dark'); + block.innerHTML = html; + + const lpHeader = block.closest('.lp-header'); + lpHeader.addEventListener('click', () => { + lpHeader.classList.toggle('active', !lpHeader.classList.contains('active')); + }); +} + +async function runQuizPageHeaderLogic(block) { + // fetch nav content + const navPath = getMetadata('nav') || '/nav'; + const resp = await fetch(`${navPath}.plain.html`); + const html = await resp.text(); + + block.classList.add('quiz', 'py-3', 'default-content-wrapper'); + const headerWrapper = block.closest('header'); + + headerWrapper.classList.add('dark'); + block.innerHTML = html; + + decorateIcons(block); +} + +/** + * applies header factory based on header variation + * @param {String} headerMetadata The header variation: landingpage' or none + * @param {Element} header The header element + */ +function applyHeaderFactorySetup(headerMetadata, header) { + switch (headerMetadata) { + case 'landingpage': + runLandingPageHeaderLogic(header); + break; + case 'quiz': + runQuizPageHeaderLogic(header); + break; + default: + runDefaultHeaderLogic(header); + break; + } +} + +export default async function decorate(block) { + const headerMetadata = getMetadata('header-type'); + block.parentNode.classList.add(headerMetadata || 'default'); - adobeMcAppendVisitorId('header'); + applyHeaderFactorySetup(headerMetadata, block); } diff --git a/_src/blocks/hero-aem/hero-aem.css b/_src/blocks/hero-aem/hero-aem.css new file mode 100644 index 000000000..069f45473 --- /dev/null +++ b/_src/blocks/hero-aem/hero-aem.css @@ -0,0 +1,514 @@ +/* stylelint-disable */ +.hero-aem-container.hero-vsb { + overflow: unset !important; +} + +.hero-aem-container .hero-aem p:first-of-type:has(a) { + margin: 0; + font-size: 16px; +} +.hero-aem-container .hero-aem >p:first-of-type { + margin: 0; + margin-bottom: 20px; +} + + +.hero-aem-container .hero-aem p:first-of-type a { + margin: 0; + margin-bottom: 20px; +} +.hero-aem-container .hero-aem h1 { + color: #006DFF; + font-size: 38px; + font-weight: normal; + margin-top: 10px; + line-height: 1.1; + margin-bottom: 20px; +} +.hero-aem-container .hero-aem h2 { + margin-top: 0; + font-size: 24px; + font-weight: normal; + line-height: 1.1; +} +.hero-aem-container .hero-aem .hero-aem__mobile-image img { + border-top-left-radius: 20px; + border-top-right-radius: 20px; + width: 100%; + height: fit-content; + position: relative; + top: 6px; +} +.hero-aem-container .hero-aem .hero-aem__desktop-image { + display: none; +} +.hero-aem-container .hero-aem .hero-aem__card-text { + padding: 27px; + font-size: 20px; + background-color: #F7F7F7; + border-bottom-left-radius: 20px; + border-bottom-right-radius: 20px; +} + +.hero-aem-container .hero-aem .hero-aem__card-text picture img { + width: auto; + max-height: 60px; +} + +.hero-aem-container .hero-aem .hero-aem__card-text p:has(picture) { + text-align: center; +} + +.hero-aem-container .hero-aem .hero-aem__breadcrumb { + border-spacing: 0; + font-size: 12px; + margin-bottom: 5px; + align-self: flex-start; +} + +.hero-aem-container .hero-aem .hero-aem__breadcrumb a { + color: #202020; + text-decoration: none; +} + +.hero-aem-container .hero-aem .hero-aem__breadcrumb a:hover { + text-decoration: underline; +} + +.hero-aem-container .hero-aem p.button-container { + text-align: center; +} +.hero-aem-container .hero-aem p.button-container .button.primary { + width: 100%; +} +.hero-aem-container .hero-aem .prod-oldprice { + font-size: 16px; + text-decoration: line-through; +} +.hero-aem-container .hero-aem .prod-save { + color: #1C7928; + font-weight: bold; + font-size: 16px; + margin-left: 8px; +} +.hero-aem-container .hero-aem .prod-newprice { + font-size: 40px; + font-weight: bold; +} +.hero-aem-container .hero-aem .newprice-container { + line-height: 1; +} +.hero-aem-container .hero-aem .newprice-container sup { + position: relative; + top: -7px; +} +.hero-aem-container .aem-two-cards { + margin-top: 20px; +} +.hero-aem-container .aem-two-cards h2 { + font-size: 36px; + font-weight: bold; + line-height: 1.1; +} +.hero-aem-container .aem-two-cards_card { + border-radius: 20px; + background-color: #F7F7F7; + padding: 1.5rem; + display: flex; + flex-direction: column; + width: 100%; +} +.hero-aem-container .aem-two-cards_card .button-container { + margin-top: auto; +} +.hero-aem-container .aem-two-cards .aem-two-cards_card h2 { + color: #006DFF; + font-size: 24px; + font-weight: normal; + margin: 0; +} +.hero-aem-container .aem-two-cards .justify-space-between { + justify-content: space-between; +} + +.h-100 { + height: 100% !important; +} + +.hero-aem-container.we-container { + max-width: 100%; + padding-left: 20px; + padding-right: 20px; + margin-top: 15px; + margin-left: auto; + margin-right: auto; +} + +.hero-aem-container .button.primary { + font-size: 16px; + font-style: normal; + font-weight: 500; + -webkit-font-smoothing: antialiased; + display: inline-flex; + align-items: center; + box-sizing: border-box; + text-decoration: none; + padding: 10px 26px 8px 28px; + text-align: center; + cursor: pointer; + color: #fff; + background-color: #eb0000; + border: 2px solid #eb0000; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + border-radius: 8px; + height: fit-content; +} + +.hero-aem-container .button.free-download { + color: #005ed9; + font-weight: bold; + background-color: transparent; + border: none; + margin: 0; + padding: 0; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + text-decoration: none; +} + +.hero-aem-container .button.free-download:hover { + color: #0A53C5; + transform: translateX(10px); +} + +.hero-aem-container .button.free-download::after { + content: '\2192'; + width: 24px; + height: 24px; + display: inline-block; + transition: all .2s cubic-bezier(.4,0,.2,1); + transform: translateX(0); + margin-left: 2px; +} + +.hero-aem-container .button.free-download:hover::after { + transform: translateX(5px); +} + +/* this would ideally be the sales tax included text */ +.hero-aem__card-text p:last-child { + font-size: 14px; +} + +.hero-aem__card-text p:last-child a { + color: inherit; + margin-left: 8px; + font-weight: normal; +} + +.hero-aem-container .hero-aem p em a { + font-size: 16px; + font-style: normal; + font-weight: 500; + -webkit-font-smoothing: antialiased; + display: inline-flex; + align-items: center; + box-sizing: border-box; + text-decoration: none; + padding: 10px 26px 8px 28px; + text-align: center; + cursor: pointer; + color: #006DFF; + background-color: transparent; + border: 2px solid #006DFF; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + border-radius: 8px; + height: fit-content; + transition: all .2s cubic-bezier(.4,0,.2,1); +} + +.hero-aem-container .hero-aem p em a:hover { + color: white; + background-color: #006DFF; +} + +.hero-aem-container .hero-aem p em a:active { + background-color: #0D499B; +} + +.hero-aem-container .hero-aem p strong em a { + color: black; + text-decoration: underline; +} + +.hero-aem__pill { + font-size: 14px; + font-weight: 500; + line-height: 1.1; + color: #fff; + background-color: #006DFF; + border-radius: 20px; + padding: 5px 13px; + display: inline-block; + margin-right: 10px; + margin-top: 0px; +} + +.hero-aem__underPriceText { + font-size: 14px; +} + +.hero-aem-container .aem-two-cards p a { + font-size: 16px; + font-style: normal; + font-weight: 500; + -webkit-font-smoothing: antialiased; + display: inline-flex; + align-items: center; + box-sizing: border-box; + text-decoration: none; + padding: 10px 26px 8px 28px; + text-align: center; + cursor: pointer; + color: #fff; + background-color: #eb0000; + border: 2px solid #eb0000; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + border-radius: 8px; + height: fit-content; +} + +.hero-aem-container .aem-two-cards p:has(a) { + margin-top: auto; +} + +.hero-aem-container .aem-two-cards h2 { + font-size: 36px; + font-weight: bold; +} +.hero-aem-container .aem-two-cards .aem-two-cards_card h2 { + color: #006DFF; + font-size: 24px; + font-weight: normal; + margin: 0; +} +.hero-aem-container .row { + --bs-gutter-x: 1.5rem; + --bs-gutter-y: 1.5rem; + + display: flex; + flex-wrap: wrap; + margin-top: calc(-1 * var(--bs-gutter-y)); + margin-right: calc(-.5 * var(--bs-gutter-x)); + margin-left: calc(-.5 * var(--bs-gutter-x)); +} +.hero-aem-container .row>* { + display: flex; + flex-shrink: 0; + width: 100%; + max-width: 100%; + padding-right: calc(var(--bs-gutter-x) * .5); + padding-left: calc(var(--bs-gutter-x) * .5); + margin-top: var(--bs-gutter-y); + box-sizing: border-box; +} + + +.hero-aem-container .col-12 { + flex: 0 0 auto; + width: 100%; +} + + +@media (max-width: 767px) { + .hero-aem-container.hero-vsb { + padding-bottom: 0; + } + + .hero-aem-container.hero-vsb .hero-aem { + padding: 0 15px; + } + + .hero-aem-container.hero-vsb .hero-aem__card__desktop { + max-height: unset!important; + } + + .hero-aem-container.hero-vsb .hero-aem .hero-aem__card-text { + padding: 0; + background-color: transparent; + border-radius: 20px; + } + + .hero-aem-container.hero-vsb .hero-aem p.button-container { + text-align: left; + } + + .hero-aem-container.hero-vsb .hero-aem p.button-container .button.primary { + margin: 0; + max-width: 290px; + } + + .hero-aem-container.hero-vsb .hero-aem p.button-container .button.primary span { + text-align: center; + display: block; + width: 100%; + } + + .hero-aem-container.hero-vsb .hero-aem h1 { + color: #006DFF; + font-size: 29px; + } +} + +@media (min-width: 768px) { + .hero-aem-container .hero-aem { + display: flex; + flex-wrap: wrap; + } + .hero-aem-container .hero-aem .hero-aem__mobile-image { + display: none; + } + .hero-aem-container .hero-aem .hero-aem__desktop-image { + display: block; + height: 100%; + position: relative; + } + + .hero-aem-container .hero-aem .hero-aem__desktop-image::after { + content: ''; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + background: linear-gradient(to left, rgba(247, 247, 247, 0), #F7F7F7); + } + + .hero-aem-container .hero-aem .hero-aem__desktop-image img { + height: 100%; + max-width: 800px; + width: 100%; + object-fit: cover; + border-top-right-radius: 20px; + border-bottom-right-radius: 20px; + } + .hero-aem-container .hero-aem .hero-aem__card-text { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + background-color: initial; + padding: 0; + } + + .hero-aem-container .hero-aem .hero-aem__card-text p:has(picture) { + text-align: left; + } + + .hero-aem-container .hero-aem .hero-aem__card__desktop { + background-color: #F7F7F7; + border-bottom-left-radius: 20px; + border-top-left-radius: 20px; + } + + .hero-aem-container .hero-aem .hero-aem__card__desktop--center { + display: flex; + align-items: center; + } + .hero-aem-container .hero-aem .hero-aem__card__desktop > div { + padding: 24px 0px 24px 56px; + } + .hero-aem-container .hero-aem p.button-container { + text-align: left; + display: inline-block; + } + .hero-aem-container .hero-aem p.button-container .button.primary { + width: auto; + } + + .hero-aem-container .col-md-6 { + flex: 0 0 auto; + width: 50%; + } + + .hero-aem-container .col-md-4 { + flex: 0 0 auto; + width: 33.33%; + } + + .hero-aem-container .col-md-3 { + flex: 0 0 auto; + width: 24%; + } + + .hero-aem-container .aem-two-cards h2 + p { + font-size: 18px; + } + + .hero-aem-container .hero-aem p:has(a) { + display: inline-block; + } + + .hero-aem-container .hero-aem p:has(em) { + margin-left: 10px; + } +} + +@media (max-width: 992px) { + .hero-aem-container.hero-vsb .hero-aem h1 { + font-size: 32px; + } +} + +@media (min-width: 992px) { + .hero-aem-container.we-container { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } + .hero-aem-container .col-lg-6 { + flex: 0 0 auto; + width: 49%; + } + .hero-aem-container .col-lg-5 { + flex: 0 0 auto; + width: 41.66%; + } + .hero-aem-container .col-lg-3 { + flex: 1 0 auto; + width: 24%; + } + .hero-aem-container .col-lg-2 { + flex: 0 0 auto; + width: 16.66%; + } +} + +@media (min-width: 1200px) { + .hero-aem-container .col-lg-6 { + flex: 0 0 auto; + width: 49%; + } + + .hero-aem-container .col-lg-3 { + flex: 0 0 auto; + width: 24%; + } +} + +@media (min-width: 1200px) { + .hero-aem-container.we-container { + max-width: 1350px; + padding-left: 20px; + padding-right: 20px; + } + + .hero-aem-container .hero-aem .hero-aem__desktop-image img { + max-height: 600px; + } +} diff --git a/_src/blocks/hero-aem/hero-aem.js b/_src/blocks/hero-aem/hero-aem.js new file mode 100644 index 000000000..e4df40492 --- /dev/null +++ b/_src/blocks/hero-aem/hero-aem.js @@ -0,0 +1,205 @@ +/* eslint-disable prefer-const */ +/* eslint-disable no-undef */ +/* eslint-disable max-len */ +import { openUrlForOs } from '../../scripts/utils/utils.js'; + +let dataLayerProducts = []; +async function createPricesElement(storeOBJ, conditionText, saveText, prodName, prodUsers, prodYears, buylink, send2datalayer) { + const storeProduct = await storeOBJ.getProducts([new ProductInfo(prodName, 'consumer')]); + const storeOption = storeProduct[prodName].getOption(prodUsers, prodYears); + const price = storeOption.getPrice(); + const discountedPrice = storeOption.getDiscountedPrice(); + const discount = storeOption.getDiscount('valueWithCurrency'); + const buyLink = await storeOption.getStoreUrl(); + + let product = { + ID: storeOption.getAvangateId(), + name: storeOption.getName(), + devices: storeOption.getDevices(), + subscription: storeOption.getSubscription('months'), + version: storeOption.getSubscription('months') === 1 ? 'monthly' : 'yearly', + basePrice: storeOption.getPrice('value'), + discountValue: storeOption.getDiscount('value'), + discountRate: storeOption.getDiscount('percentage'), + currency: storeOption.getCurrency(), + priceWithTax: storeOption.getDiscountedPrice('value') || storeOption.getPrice('value'), + }; + dataLayerProducts.push(product); + + const priceElement = document.createElement('div'); + priceElement.classList.add('hero-aem__prices'); + priceElement.innerHTML = ` + ${!send2datalayer ? '

Yearly - individual

' : ''} +
+
+ ${price} + ${saveText} ${discount} +
+
+ ${discountedPrice} + ${conditionText || ''} +
+
+

Protection for 5 PCs, Macs, tablets, or smartphones.
Windows® | macOS® | Android™ | iOS®

`; + if (buylink) { + buylink.href = buyLink; + } + return priceElement; +} + +function createCardElementContainer(elements, mobileImage) { + const cardElementContainer = document.createElement('div'); + cardElementContainer.classList.add('hero-aem__card'); + + const cardElementText = document.createElement('div'); + cardElementText.classList.add('hero-aem__card-text'); + + elements.forEach((sibling) => { + if (mobileImage && sibling.contains(mobileImage)) { + cardElementContainer.appendChild(sibling); + } else { + cardElementText.appendChild(sibling); + } + }); + + cardElementContainer.appendChild(cardElementText); + + return cardElementContainer; +} + +// Function to dispatch 'shadowDomLoaded' event +function dispatchShadowDomLoadedEvent() { + const event = new CustomEvent('shadowDomLoaded', { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); + window.dispatchEvent(event); +} + +export default function decorate(block, options) { + const { + product, conditionText, saveText, MacOS, Windows, Android, IOS, + alignContent, height, type, send2datalayer, + } = block.closest('.section').dataset; + + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + let blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + if (type) blockParent.classList.add(type); + } + + let [richText, mainDesktopImage, richTextCard, columnsCard] = block.children; + + // Configuration for new elements + richText.classList.add('hero-aem__card__desktop', 'col-md-6'); + if (alignContent === 'center') { + richText.classList.add('hero-aem__card__desktop--center'); + } + + if (height) { + // eslint-disable-next-line array-callback-return + Array.from(block.children).map((child) => { + child.style.maxHeight = `${height}px`; + }); + } + mainDesktopImage.classList.add('col-md-6'); + mainDesktopImage.children[0].classList.add('h-100'); + + let mobileImage = block.querySelector('.hero-aem__card__desktop div > p > picture'); + if (mobileImage) { + mobileImage.classList.add('hero-aem__mobile-image'); + } else { + mobileImage = ''; + } + + // Get all the siblings after h1 + const cardElements = Array.from(block.querySelectorAll('h1 ~ *')); + // Put the siblings in a new div and append it to the block + const cardElementContainer = createCardElementContainer(cardElements, mobileImage); + + // Append the container after h1 + block.querySelector('h1').after(cardElementContainer); + + const desktopImage = block.querySelector('.hero-aem > div > div > picture'); + desktopImage.classList.add('hero-aem__desktop-image'); + + if (product && options?.store) { + const [prodName, prodUsers, prodYears] = product.split('/'); + + const buyLink = block.querySelector('a[href*="buylink"]'); + createPricesElement(options.store, conditionText, saveText, prodName, prodUsers, prodYears, buyLink, send2datalayer) + .then((pricesBox) => { + // If buyLink exists, apply styles and insert pricesBox + if (buyLink) { + buyLink.classList.add('button', 'primary'); + buyLink.parentNode.parentNode.insertBefore(pricesBox, buyLink.parentNode); + dispatchShadowDomLoadedEvent(); + return; + } + + // If buyLink does not exist, apply styles to simpleLink + const simpleLink = block.querySelector('.hero-aem__card-text a'); + if (simpleLink) { + simpleLink.classList.add('button', 'primary'); + simpleLink.parentNode.parentNode.insertBefore(pricesBox, simpleLink.parentNode); + } + + dispatchShadowDomLoadedEvent(); + }); + } else { + // If there is no product, just add the button class and dispatch the event + const simpleLink = block.querySelector('.hero-aem__card-text a'); + if (simpleLink) { + simpleLink.classList.add('button', 'primary'); + } + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); + } + + let breadcrumbTable = block.querySelector('table'); + + if (breadcrumbTable && breadcrumbTable.textContent.includes('breadcrumb')) { + breadcrumbTable.classList.add('hero-aem__breadcrumb'); + // delete the first row + breadcrumbTable.deleteRow(0); + } + + let freeDownloadButton = block.querySelector('a[href*="#free-download"]'); + if (freeDownloadButton) { + freeDownloadButton.classList.add('button', 'free-download'); + openUrlForOs(MacOS, Windows, Android, IOS, freeDownloadButton); + } + + if (columnsCard) { + const columnsCardChildren = Array.from(columnsCard.children); + const cardElement = document.createElement('div'); + cardElement.classList.add('aem-two-cards'); + // Determine the appropriate column width class based on the number of cards + const columnWidthMdClass = columnsCardChildren.length === 2 ? 'col-md-6' : 'col-md-4'; + const columnWidthLgClass = columnsCardChildren.length === 2 ? 'col-lg-3' : 'col-lg-3'; + + const columnCardsHtml = columnsCardChildren.map((col) => ` +
+
+ ${col.innerHTML} +
+
`).join(''); + + cardElement.innerHTML = ` +
+
+ ${richTextCard.innerHTML} +
+ ${columnCardsHtml} +
+ `; + + block.appendChild(cardElement); + richTextCard.innerHTML = ''; + columnsCardChildren.forEach((col) => col.remove()); + } +} diff --git a/solutions/blocks/hero/hero.css b/_src/blocks/hero/hero.css similarity index 57% rename from solutions/blocks/hero/hero.css rename to _src/blocks/hero/hero.css index 37ee4e0c4..4f1c835c1 100644 --- a/solutions/blocks/hero/hero.css +++ b/_src/blocks/hero/hero.css @@ -1,3 +1,5 @@ +/* stylelint-disable no-descending-specificity */ + /* block specific CSS goes here */ :root { /* hero font size */ @@ -21,17 +23,35 @@ --breadcrumbs-font-size-s: 12px; } +main .hero { + background-color: white; + position: relative; + padding: 1em 0 3em; + min-height: 300px; +} /* breadcrumbs */ - main .hero .hero-content .breadcrumb { font-weight: var(--font-weight-bold); color: #dedede; - min-height: 82px; + min-height: unset; padding: 12px 0; margin-bottom: 12px; } +main .hero .hero-content .signature { + font-size: 24px; + color: #006dff; + font-weight: bold; + margin-top: 8px; +} + +@media (min-width: 480px) { + main .hero .hero-content .signature { + margin-bottom: 12px; + } +} + main .hero .hero-content .breadcrumb a { font-size: var(--breadcrumbs-font-size-s); font-weight: var(--font-weight-bold); @@ -73,7 +93,6 @@ main .hero.black-background .hero-content .breadcrumb a:hover { } /* hero */ - main .hero-container > div { max-width: unset; } @@ -83,6 +102,29 @@ main .hero-container { margin: 0 auto; } +main .hero-container.blue-title .hero-content > div { + width: 100%; +} + +main .hero-container.blue-title .hero-content h1 { + --tw-text-opacity: 1; + + color: rgb(0 110 255 / var(--tw-text-opacity)); +} + +main .hero-container.migration .hero-content h2 { + font-size: 22px; + font-weight: 500; + line-height: 1.25; + margin-top: 1em; + margin-bottom: 9px; +} + +main .hero-container.migration .hero-content p em { + font-size: 1.125rem; + font-style: normal; +} + main .hero .hero-content > div { width: 100%; } @@ -91,16 +133,41 @@ main .hero-container .hero-wrapper { padding: 0; } -main .hero { - position: relative; - padding: 0; - min-height: 300px; +main .hero.new2024design::after { + display: none; } main .hero.black-background { background-color: var(--dark-background-color); } +main .hero.new2024design * { + font-weight: normal; + font-family: "IBM Plex Sans", sans-serif; + color: white; +} + +main .hero.new2024design .hero-picture:last-of-type { + display: none; +} + +main .hero.new2024design strong { + font-weight: 600; +} + +main .hero-container.breadcrumb-hidden .breadcrumb a { + color: transparent; +} + +main .hero-container.breadcrumb-hidden .breadcrumb a::after { + color: transparent; +} + +main .hero.black-background::after { + content: none; + background-color: transparent; +} + main .hero.comparison { height: 600px; } @@ -121,6 +188,41 @@ main .hero .hero-content { position: relative; } +main .hero.new2024design { + max-width: 1200px; + margin: auto; +} + +main .hero.new2024design .hero-content:last-of-type { + padding: 0 2em; +} + +main .hero.new2024design .hero-picture { + padding: 0; + min-height: 0; +} + +main .hero.new2024design .hero-picture img { + padding: 0; + border-radius: 10px; + object-fit: contain; +} + +main .hero.new2024design h1 { + font-size: var(--hero-font-size-l); + margin: 0; +} + +main .hero.new2024design p { + font-size: 16px; +} + +main .hero.new2024design .hero-content.hero-content img { + padding: 0; + border-radius: 10px; + object-fit: contain; +} + main .hero .hero-content .right-col { display: flex; justify-content: center; @@ -128,6 +230,9 @@ main .hero .hero-content .right-col { } main .hero.black-background .hero-content { + padding: 17px var(--body-padding) 56px; + display: flex; + flex-direction: column; background: linear-gradient(90deg, #000 0%, #000 15%, #fff0 100%); } @@ -139,7 +244,7 @@ main .hero.comparison .hero-content { } main .hero h1 { - font-size: var(--hero-h1-font-size); + font-size: 2.125rem; margin: 0 0 25px; } @@ -151,6 +256,11 @@ main .hero h2 { letter-spacing: .003em; } +main .hero.black-background h1 { + font-size: var(--hero-h1-font-size); + margin: 0 0 25px; +} + main .hero h2, main .hero h4 { padding: 0; @@ -181,11 +291,14 @@ main .hero p { main .hero h1 + p { margin: 8px 0 0; color: #616161; - font-size: var(--hero-font-size-xxs); - font-weight: var(--font-weight-bold); + font-size: var(--hero-font-size-xxxs); line-height: 1.5; } +main .hero h1 + p strong { + font-weight: var(--font-weight-bold); +} + main .hero.comparison p { font-size: 18px; font-weight: 400; @@ -211,7 +324,11 @@ main .hero p.button-container { gap: 2px; } -main .hero p.button-container.discount-bubble-container{ +main .hero p.button-container:last-of-type { + margin: 0 0 10px; +} + +main .hero p.button-container.discount-bubble-container { padding-top: 0; } @@ -223,7 +340,8 @@ main .hero img { main .hero .hero-picture picture img { position: absolute; - display: none; + + /* display: none; */ padding-left: 200px; } @@ -231,12 +349,12 @@ main .hero a.button { margin: 8px 13px 0 0; } -main .hero a.button.modal { +main .hero a.button.modal, main .hero a.button.central { padding: 0 28px 0 0; min-width: unset; } -@media (min-width: 1400px){ +@media (min-width: 1400px) { main .hero a.button { min-width: 360px; justify-content: center; @@ -252,9 +370,8 @@ main .hero a.button span.button-text { font-weight: var(--font-weight-bold); } - main .hero .discount-bubble { - background: #2cb43d; + background: #16A34A; border-radius: 50%; width: 72px; height: 72px; @@ -264,7 +381,6 @@ main .hero .discount-bubble { align-items: center; text-align: center; gap: 2px; - bottom: -5px; right: 0; position: relative; } @@ -275,7 +391,7 @@ main .hero .discount-bubble .discount-bubble-0 { font-weight: var(--font-weight-boldest); line-height: .8; text-decoration: none; - padding-top: 12px; + padding-top: 5px; } main .hero .discount-bubble .discount-bubble-1 { @@ -305,7 +421,7 @@ main .hero .hero-content ul { } main .hero .hero-content ul li { - font-size: var(--hero-font-size-xxxs); + font-size: var(--hero-font-size-xxs); font-weight: var(--font-weight-regular); letter-spacing: 0.096px; line-height: 1.5; @@ -317,14 +433,14 @@ main .hero .hero-content ul li { } main .hero .hero-content ul li:first-child { - margin: 9px 0 0; + margin: 5px 0; } main .hero ul li::before { content: ""; position: absolute; left: 0; - top: 3px; + top: 4px; width: 15px; height: 15px; background-color: var(--background-checkmark); @@ -336,7 +452,7 @@ main .hero ul li::after { content: ""; position: absolute; left: 5px; - top: 5px; + top: 6px; width: 3px; height: 7px; border-bottom: 2px solid var( --white-color); @@ -377,11 +493,87 @@ main .hero .hero-awards li::after { content: none; } +main .hero.pb-0 .hero-content { + padding-bottom: 0; +} + +main .v2 .hero h1 { + font-weight: var(--font-weight-regular); + font-family: var(--body-font-family); +} + +main .v2 .hero h1 + p { + font-size: var(--body-font-size-s); +} + +main .v2 .hero .hero-content > div:first-of-type { + width: 100%; +} + +main .v2 .hero .hero-content > div:last-of-type img { + height: auto; + width: 360px; + position: absolute; + bottom: 0; +} + +main .v2 .hero .hero-content > div table tr { + display: flex; +} + +main .v2 .hero .hero-content > div table tr td:first-of-type { + margin-right: 2em; + width: 280px; +} + +main .v2 .hero .hero-content > div table tr td:last-of-type { + width: 465px; +} + +/* stylelint-disable-next-line selector-class-pattern */ +main .smaller_icon .hero .hero-content > div table tr td:last-of-type { + width: fit-content; +} + +main .v2 .hero .hero-content > div table tr td img { + width: 100%; + height: auto; +} + +/* stylelint-disable-next-line selector-class-pattern */ +main .smaller_icon .hero .hero-content > div table tr td:first-of-type { + width: 70px; +} + +@media(max-width: 989px) { + main .hero.new2024design { + background-color: #006FFF; + min-height: auto; + padding: 2em 0; + } +} + +@media(max-width: 991px) { /* tablet */ + main .hero.new2024design .breadcrumb { + display: none; + } +} + @media(min-width: 767px) { /* tablet */ :root { --hero-h1-font-size: 42px; } + main .hero.new2024design h1 { + font-size: var(--hero-font-size-xl); + margin: 0; + } + + main .hero.new2024design * { + color: white; + background-color: transparent; + } + main .hero h2 { font-size: 20px; } @@ -394,9 +586,21 @@ main .hero .hero-awards li::after { margin: 0 9px; } + main .hero-container.blue-title .hero-content > div { + width: 630px; + } } @media (min-width: 990px) { /* desktop */ + main .hero.new2024design .hero-content:last-of-type { + min-height: 360px; + padding: 2em; + } + + main .hero.new2024design .hero-picture { + display: block; + height: 430px; + } main .hero .hero-content > div.left-col { width: 50%; @@ -413,19 +617,22 @@ main .hero .hero-awards li::after { } main .hero h1 { - font-size: 50px; + font-size: 2.5rem; + font-weight: 700; + font-family: "IBM Plex Sans", sans-serif; } main .hero .hero-picture { position: absolute; top: 0; - bottom: 0; + bottom: auto; left: 0; right: 0; + height: 100%; } main .hero p { - font-size: 14px; + font-size: var(--hero-font-size-xxs); margin: 0; } @@ -437,10 +644,19 @@ main .hero .hero-awards li::after { main .hero .hero-content { max-width: var(--section-desktop-max-width); min-height: unset; - padding: 112px var(--section-desktop-padding) 54px var(--section-desktop-padding); + padding: 1em var(--section-desktop-padding) 1em var(--section-desktop-padding); + display: flex; + flex-direction: row; + } + + main .hero.black-background .hero-content { + max-width: var(--section-desktop-max-width); + padding-left: var(--section-desktop-padding); + padding-right: var(--section-desktop-padding); padding-top: 115px; display: flex; flex-direction: row; + min-height: unset; } main .hero a.button.primary { @@ -479,22 +695,57 @@ main .hero .hero-awards li::after { width: auto; } + /* stylelint-disable-next-line selector-class-pattern */ + main .smaller_icon .hero .hero-content > div:last-of-type img { + width: 40%!important; + } + + /* stylelint-disable-next-line selector-class-pattern */ + main .new_v2 .hero .hero-content > div:last-of-type img { + width: 60%!important; + right: 0; + } + + main .v2 .hero .hero-content > div:last-of-type img { + width: 360px; + right: -11em !important; + bottom: -3em; + } } -@media (min-width: 1600px) { /* large desktop */ +@media (max-width: 1399px) { + main .hero .hero-content ul li { + font-size: var(--body-font-size-xs); + } + main .v2 .hero h1 { + font-size: var(--heading-font-size-xxl1); + } +} +@media (min-width: 1600px) { /* large desktop */ main .hero .hero-content .breadcrumb { padding: 9px 0; margin-bottom: 15px; } - main .hero h2 { - font-size: 24px; + main .hero h1 { + font-size: 2.5rem; + font-weight: 700; + font-family: "IBM Plex Sans", sans-serif; } - main .hero h1 { - font-size: 56px; + main .v2 .hero h1 { + font-size: var(--heading-font-size-xxl2); + } + + main .hero h2 { + color: #000; + font-size: 24px; + font-weight: 500; + line-height: 1.25; + margin-bottom: 9px; + margin-top: 10px; } main .hero .discount-bubble { @@ -511,9 +762,62 @@ main .hero .hero-awards li::after { } main .hero .hero-content { - min-height: 725px; + min-height: 640px; max-width: var(--section-large-desktop-max-width); padding-left: var(--section-large-desktop-padding); padding-right: var(--section-large-desktop-padding); } + + main .hero.black-background .hero-content { + max-width: var(--section-large-desktop-max-width); + padding-left: var(--section-large-desktop-padding); + padding-right: var(--section-large-desktop-padding); + } +} + +@media (max-width: 990px) { + main .v2 .hero h1 { + font-size: var(--heading-font-size-xl1); + } + + main .hero .hero-content > div table tr td:last-of-type { + width: 510px; + } + + main .hero .hero-content > div table tr td:first-of-type { + display: none; + } + + main .v2 .hero .hero-picture picture img { + padding-left: 0; + } + + main .v2 .hero .hero-content > div:last-of-type img { + width: 265px; + right: 0; + } +} + +@media (max-width: 768px) { + main .hero .hero-picture, main .v2 .hero .hero-content > div:last-of-type img { + display: none; + } + + main .v2 .hero .hero-content > div table tr td:last-of-type { + width: 100%; + } + + main .v2 .hero h1 { + font-size: var(--heading-font-size-l2); + } + + main .v2 .hero h1 + p { + font-size: var(--body-font-size-xs); + } +} + +@media (max-width: 450px) { + main .hero h1 { + font-size: var(--heading-font-size-m); + } } diff --git a/_src/blocks/hero/hero.js b/_src/blocks/hero/hero.js new file mode 100644 index 000000000..b82e302cc --- /dev/null +++ b/_src/blocks/hero/hero.js @@ -0,0 +1,134 @@ +/* eslint-disable max-len */ +// Description: Hero block +import { + createTag, + createNanoBlock, + renderNanoBlocks, +} from '../../scripts/utils/utils.js'; + +/** + * Builds hero block and prepends to main in a new section. + * @param {Element} element The container element + */ +function buildHeroBlock(element) { + const h1 = element.querySelector('h1'); + const picture = element.querySelector('picture'); + const pictureParent = picture ? picture.parentNode : false; + // eslint-disable-next-line no-bitwise + if (h1 && picture && (h1.compareDocumentPosition(picture) & Node.DOCUMENT_POSITION_PRECEDING)) { + const section = document.querySelector('div.hero'); + const subSection = document.querySelector('div.hero div'); + subSection.classList.add('hero-content'); + + const isHomePage = window.location.pathname.split('/').filter((item) => item).length === 1; + + if (!isHomePage) { + const breadcrumb = createTag('div', { class: 'breadcrumb' }); + document.querySelector('div.hero div div:first-child').prepend(breadcrumb); + } + + const pictureEl = document.createElement('div'); + pictureEl.classList.add('hero-picture'); + pictureEl.append(picture); + section.prepend(pictureEl); + + pictureParent.remove(); + } +} + +createNanoBlock('discount', (code, label = '{label}') => { + // code = "av/3/1" + const [product, unit, year] = code.split('/'); + + const root = document.createElement('div'); + root.classList.add('discount-bubble'); + root.classList.add('await-loader'); + + // Add the required attributes to the root element + + root.setAttribute('data-store-context', ''); + root.setAttribute('data-store-id', product); + root.setAttribute('data-store-option', `${unit}-${year}`); + root.setAttribute('data-store-department', 'consumer'); + root.setAttribute('data-store-event', 'main-product-loaded'); + root.setAttribute('data-store-hide', 'no-price=discounted;type=visibility'); + root.innerHTML = ` + --% + ${label} + `; + + return root; +}); + +async function renderBubble(block) { + await renderNanoBlocks(block); + const bubble = block?.querySelector('.discount-bubble'); + if (bubble) { + const { label } = block.closest('.section').dataset; + if (label) { + bubble.innerHTML = bubble.innerHTML.replace('{label}', label); + } + + let sibling = bubble.previousElementSibling; + + while (sibling) { + if (sibling.matches('.button-container')) { + sibling.append(bubble); + break; + } + sibling = sibling.previousElementSibling; + } + } +} + +/** + * decorates hero block + * @param {Element} block The hero block element + */ +export default function decorate(block) { + const { + // this defines wether the modals automatically refresh or not in the hero banner + stopAutomaticModalRefresh, + signature, + percentProduct, + } = block.closest('.section').dataset; + + buildHeroBlock(block); + renderBubble(block); + // Eager load images to improve LCP + [...block.querySelectorAll('img')].forEach((el) => el.setAttribute('loading', 'eager')); + + // get div class hero-content + const elementHeroContent = block.querySelector('.hero div.hero-content div'); + if (elementHeroContent !== null) { + // Select
    elements that contain a tag + const ulsWithPicture = Array.from(document.querySelectorAll('ul')).filter((ul) => ul.querySelector('picture')); + + // Apply a CSS class to each selected
      element + ulsWithPicture.forEach((ul) => ul.classList.add('hero-awards')); + + // add signature to the top of the banner + if (signature) { + const signatureElement = createTag('div', { class: 'signature' }); + signatureElement.textContent = signature; + document.querySelector('div.hero div div:first-child').prepend(signatureElement); + } + + // set the modal buttons in the hero banner to not refresh the modal on click + if (stopAutomaticModalRefresh === 'true') { + block.querySelectorAll('a.modal.button').forEach((modalButton) => { + modalButton.setAttribute('data-stop-automatic-modal-refresh', true); + }); + } + } + + // make discount dynamic + if (percentProduct) { + const [alias, variant] = percentProduct.split(','); + block.setAttribute('data-store-context', ''); + block.setAttribute('data-store-text-variable', ''); + block.setAttribute('data-store-id', alias); + block.setAttribute('data-store-department', 'consumer'); + block.setAttribute('data-store-option', variant); + } +} diff --git a/solutions/blocks/image-columns/image-columns.css b/_src/blocks/image-columns/image-columns.css similarity index 85% rename from solutions/blocks/image-columns/image-columns.css rename to _src/blocks/image-columns/image-columns.css index 4ac2bc5cc..f0f074fc0 100644 --- a/solutions/blocks/image-columns/image-columns.css +++ b/_src/blocks/image-columns/image-columns.css @@ -1,3 +1,5 @@ +/* stylelint-disable no-descending-specificity */ +/* stylelint-disable selector-class-pattern */ .image-columns-container ul { padding-left: 0; } @@ -35,6 +37,10 @@ justify-items: center; } +.image-columns.text_smaller > div > .image-columns-txt-col { + flex: 0 1 45%; +} + .image-columns > div > .image-columns-txt-col { flex: 0 1 45%; } @@ -89,6 +95,10 @@ margin-top: 0; } +.image-columns.trusted > div > .image-columns-txt-col { + flex: 0 1 25%; +} + @media (min-width: 992px) { .image-columns > div > .image-columns-txt-col h3 { margin-bottom: 26px; @@ -131,3 +141,9 @@ order: unset; } } + +@media (min-width: 1600px) { /* large desktop */ + .image-columns-wrapper { + max-width: var(--section-large-desktop-max-width); + } +} diff --git a/solutions/blocks/image-columns/image-columns.js b/_src/blocks/image-columns/image-columns.js similarity index 100% rename from solutions/blocks/image-columns/image-columns.js rename to _src/blocks/image-columns/image-columns.js diff --git a/_src/blocks/marquee/marquee.css b/_src/blocks/marquee/marquee.css new file mode 100644 index 000000000..01ed88103 --- /dev/null +++ b/_src/blocks/marquee/marquee.css @@ -0,0 +1,69 @@ +/* stylelint-disable custom-property-pattern */ +.marquee-container.section { + padding: 0; + position: relative; + overflow: unset; + max-width: 100%; +} + +.marquee-container .marquee.block { + height: 150px; + display: flex; + flex-direction: column; + width: 100%; +} + +.marquee-container .title { + font: normal normal 600 12px/15px "IBM Plex Sans", sans-serif; + letter-spacing: 0; +} + +.marquee-container .marquee-content { + display: flex; + animation: scrolling 10s linear infinite; + + --translateX: 100%; + + height: 100%; +} + +.marquee-container .marquee-item { + flex: 0 0 85px; + margin: 0 20px; +} + +.marquee-container .marquee-item img { + display: block; + width: 100%; + object-fit: contain; +} + +.marquee-container .outer-wrapper { + width: 100%; + height: 100%; + overflow: hidden; +} + +@keyframes scrolling { + from { transform: translateX(0); } + to { transform: translateX(calc(var(--translateX) * -1)); } +} + +@media (min-width: 990px) { + .marquee-container .marquee.block { + height: 120px; + } + + .marquee-container .title { + font: normal normal 600 18px/23px "IBM Plex Sans", sans-serif; + position: absolute; + top: -45px; + z-index: 1; + } +} + +@media (min-width: 1600px) { + .marquee-container .title { + margin-left: -25px + } +} diff --git a/_src/blocks/marquee/marquee.js b/_src/blocks/marquee/marquee.js new file mode 100644 index 000000000..ce8f1b073 --- /dev/null +++ b/_src/blocks/marquee/marquee.js @@ -0,0 +1,82 @@ +import { debounce, getDatasetFromSection, isView } from '../../scripts/utils/utils.js'; + +export default async function decorate(block) { + const defaultBackgroundColor = '#004299'; + const SLIDE_SIZE_ENUM = { + MOBILE: 85 + 20 * 2, + TABLET_UP: 85 + 20 * 2, + }; + + const SPEED_ANIMATION = 0.6; + + const [title, ...initialSlideList] = [...block.children]; + + function getCurrentViewportSlideSize() { + return isView('mobile') ? SLIDE_SIZE_ENUM.MOBILE : SLIDE_SIZE_ENUM.TABLET_UP; + } + function calculateSlideListBasedOnScreenWidth() { + const result = { + duplicatedSlides: null, + slidesToShift: null, + }; + + const currentViewportSlideSize = getCurrentViewportSlideSize(); + const clientWidth = window.innerWidth; + const spaceToFillMore = clientWidth - initialSlideList.length * currentViewportSlideSize; // ok + if (spaceToFillMore < 0) { + result.duplicatedSlides = initialSlideList.concat(initialSlideList); + result.slidesToShift = initialSlideList.length; + + return result; + } + // fill space + const fullWidthSlidesToFill = parseInt(spaceToFillMore / currentViewportSlideSize, 10); + const hasPartialSlideToFill = clientWidth % currentViewportSlideSize !== 0; + + result.duplicatedSlides = Array(fullWidthSlidesToFill) + .fill(initialSlideList).flatMap((slide) => slide); + + if (!hasPartialSlideToFill) { + result.duplicatedSlides = result.duplicatedSlides.concat(result.duplicatedSlides); + result.slidesToShift = result.duplicatedSlides.length; + + return result; + } + + // need to apply the patch here + result.duplicatedSlides = result.duplicatedSlides.concat(initialSlideList); + result.slidesToShift = result.duplicatedSlides.length; + result.duplicatedSlides = result.duplicatedSlides.concat(result.duplicatedSlides); + + return result; + } + + function updateTranslation(slidesToShift) { + const content = block.querySelector('.marquee-content'); + content.style.animationDuration = `${slidesToShift / SPEED_ANIMATION}s`; + content.style.setProperty('--translateX', `${getCurrentViewportSlideSize() * slidesToShift}px`); + } + + function render() { + const blockDataset = getDatasetFromSection(block); + const { background_color: backgroundColor } = blockDataset; + block.style.background = backgroundColor || defaultBackgroundColor; + + const { duplicatedSlides, slidesToShift } = calculateSlideListBasedOnScreenWidth(); + + block.innerHTML = ` +
      ${title.textContent}
      +
      +
      + ${duplicatedSlides.map((slide) => `
      ${slide.querySelector('picture').outerHTML}
      `).join('')} +
      +
      + `; + + updateTranslation(slidesToShift); + } + + render(); + + window.addEventListener('resize', debounce(render, 250)); +} diff --git a/_src/blocks/money-back/money-back.css b/_src/blocks/money-back/money-back.css new file mode 100644 index 000000000..9ac08a531 --- /dev/null +++ b/_src/blocks/money-back/money-back.css @@ -0,0 +1,289 @@ +.money-back-wrapper { + text-align: center; +} + +@media (min-width: 992px) { /* desktop */ + .money-back-wrapper { + max-width: var(--section-desktop-max-width); + padding: 0 var(--section-desktop-padding); + margin: 0 auto; + } +} + +@media (min-width: 1600px) { /* large desktop */ + .money-back-wrapper { + max-width: var(--section-large-desktop-max-width); + padding: 0 var(--section-large-desktop-padding); + } +} + +.money-back.block { + background-color: #EDF9FF; + border-radius: 20px; +} + +.creator-money-back .money-back.block { + background-color: transparent; +} + +.money-back.block.background-white { + background-color: white; +} + +.money-back-container h3 { + font: normal normal bold 32px/37px var(--body-font-family); + text-align: center; + margin-bottom: 56px; +} + +.money-back-container.we-container { + max-width: 100%; + padding-left: 20px; + padding-right: 20px; + margin-top: 15px; + margin-left: auto; + margin-right: auto; +} + +.money-back-container .icon svg { + width: auto; + height: 32px; + padding-right: 2px; +} + +.creator-money-back.money-back-container .icon svg { + width: auto; + height: 60px; + padding-right: 2px; +} + +.money-back > ul { + list-style: none; + margin: 0; + padding: 0; + display: inline-block; + } + +.creator-money-back .money-back > ul { + display: flex; + } + +.money-back > ul > li { + display: inline-block; + padding: 8px; + margin: 0 37px; + text-align: center; + width: 268px; + vertical-align: top; + font: normal normal normal 14px/16px var(--body-font-family); + } + + .creator-money-back .money-back > ul > li { + background: #F5F5F7; + border-radius: 20px; + padding: 60px 68px; + flex: 1; + width: auto; + text-align: left; + margin: 0 30px; + vertical-align: top; + font: normal normal normal 20px/23px Arial, sans-serif; + } + + .money-back > ul > li h6 { + font: normal normal bold 18px/16px var(--body-font-family); + } + + .money-back > ul > li p { + font: normal normal normal 14px/16px var(--body-font-family); + } + + .creator-money-back .money-back > ul > li h4 { + font: normal normal bold 32px/38px "IBM Plex Sans", sans-serif; + } + + .creator-money-back .money-back > ul > li p { + font: normal normal normal 20px/26px Arial, sans-serif; + } + + .money-back > ul > li p:first-of-type { + margin-bottom: 0; + } + + .creator-money-back .money-back > ul > li p:first-of-type { + margin: 0; + } + + .money-back > ul > li a { + font: normal normal normal 14px/16px var(--body-font-family); + margin-bottom: 0; + margin-top: 20px; + text-decoration: none; + color: #006EFF; + display: block; + } + + .money-back > ul > li strong { + display: inline-block; + font: normal normal bold 18px/16px var(--body-font-family); + padding-bottom: 11px; + } + + .money-back .default-content-wrapper { + text-align: center; + } + + .money-back > ul > li p.button-container { + margin-top: 0; + } + + .money-back a.button { + font: normal normal normal 14px/16px var(--body-font-family); + margin-top: 20px; + padding: 0; + background: transparent; + border: none; + color: #006EFF; + } + + .money-back a.button:hover { + text-decoration: underline; + color: #006EFF; + background: transparent; + } + + .money-back a.button span.button-text { + transition: none; + } + + .money-back a.button:hover span.button-text { + transform: none; + } + + .money-back a.button::after { + content: ''; + width: 0; + height: 0; + margin: 0; + transition: none; + } + + .creator-money-back .money-back > ul > li a { + min-width: 230px; + height: 48px; + padding: 10px 10px 10px 25px; + background: #E72325 0% 0% no-repeat padding-box; + border-radius: 40px; + justify-content: center; + font: normal normal 500 18px / 24px Roboto, sans-serif; + color: white; + } + + .creator-money-back .money-back > ul > li a:hover { + color: white; + background-color: var(--button-background-color); + text-decoration: none; + } + + .creator-money-back .money-back a.button span.button-text { + transition: transform .2s cubic-bezier(.4,0,.2,1); + } + + .creator-money-back .money-back > ul > li a.button:hover span.button-text { + transform: translate(-10px, 0); + } + + .creator-money-back .money-back > ul > li a:active { + color: white; + background-color: var(--button-background-color); + border: 0; + } + + .creator-money-back .money-back a.button::after { + content: ''; + width: 24px; + height: 24px; + margin-left: -10px; + transition: all .2s cubic-bezier(.4,0,.2,1); + } + + .money-back .icon { + height: 32px; + margin-bottom: 9px; + fill: #006EFF; + display: flex; + } + + .creator-money-back .money-back .icon { + height: 60px; + margin-bottom: 23px; + fill: #006DFF; + display: flex; + } + + .money-back img { + height: 55px; + margin-bottom: 9px; + fill: #006EFF; + } + + .creator-money-back .money-back img { + height: 60px; + fill: #006df7; + display: flex; + } + +@media (max-width: 991px) { /* mobile/tablet */ + .money-back-wrapper { + padding: var(--body-padding); + } + + .money-back > ul { + grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); + grid-gap: 14px; + flex-direction: column; + } + + .money-back > ul > li { + margin: 0; + } + + .money-back-container.we-container { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } +} + +@media (max-width: 1259px) { + .creator-money-back .money-back > ul > li { + margin-bottom: 40px; + } +} + +@media (min-width: 1200px) { + .money-back-container.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + } +} + +@media (min-width: 1600px) { + .money-back-container.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + } +} + +@media (max-width: 991px) { + .creator-money-back .money-back > ul > li { + margin: 0; + padding: 24px; + } + + .creator-money-back .money-back > ul > li p.button-container { + text-align: center; + } +} \ No newline at end of file diff --git a/_src/blocks/money-back/money-back.js b/_src/blocks/money-back/money-back.js new file mode 100644 index 000000000..e4fbe7ba9 --- /dev/null +++ b/_src/blocks/money-back/money-back.js @@ -0,0 +1,23 @@ +export default function decorate(block, options) { + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + const blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + } + const ul = document.createElement('ul'); + [...block.children].forEach((row) => { + const li = document.createElement('li'); + li.innerHTML = row.innerHTML; + + ul.append(li); + }); + + block.textContent = ''; + block.append(ul); + + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); +} diff --git a/_src/blocks/new-prod-boxes/new-prod-boxes.css b/_src/blocks/new-prod-boxes/new-prod-boxes.css new file mode 100644 index 000000000..5e8c00979 --- /dev/null +++ b/_src/blocks/new-prod-boxes/new-prod-boxes.css @@ -0,0 +1,772 @@ +/* stylelint-disable */ +.new-prod-boxes-container.remove-first > div.default-content-wrapper:first-of-type { + display: none; +} + +.creators .new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box { + border: 1px solid #ECECEC; +} + +.creators .new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .undeBuyLink { + text-align: center; + font-weight: bold; +} + +.new-prod-boxes-container { + padding-bottom: 0; + font-family: 'Arial', sans-serif; + margin: clamp(10px, 25px, 15px) 0; +} + +.new-prod-boxes-container div.default-content-wrapper:last-of-type { + padding: 0; +} + +.new-prod-boxes-container div.default-content-wrapper:last-of-type * { + font: normal normal normal 12px/14px Arial; + color: black; +} + +.new-prod-boxes-container div.default-content-wrapper:last-of-type a { + text-decoration: underline; +} + +.new-prod-boxes-container.we-container { + max-width: 100%; + padding-left: 20px; + padding-right: 20px; + margin-top: 15px; + margin-left: auto; + margin-right: auto; +} + +.new-prod-boxes-container .default-content-wrapper p:has(> a) { + text-align: center; + font-size: 16px; +} + +.new-prod-boxes-container .default-content-wrapper p:has(> a) a { + text-align: center; + font-size: 16px; + color: #005ed9; + text-decoration: none; +} + +.new-prod-boxes-container .default-content-wrapper p:has(> a) a:hover { + color: #00439c; + text-decoration: underline; +} + +.new-prod-boxes-container .default-content-wrapper h2 { + text-align: center; + font-size: 32px; + line-height: 37px; + max-width: 550px; + margin: auto; + margin-bottom: 20px; +} + +.new-prod-boxes-container .new-prod-boxes { + margin: 0 auto; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box { + flex: 1; + max-width: 410px; + margin: 8px; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box { + position: relative; + height: 100%; + background-color: #F6F6F6; + border-radius: 20px; + padding: 25px; + margin: 0 auto; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .greenTag2 { + height: 30px; + max-width: 350px; + width: 86%; + font-family: Arial, sans-serif; + color: white; + text-align: center; + background-color: #1C7928; + border-top-left-radius: 10px; + border-top-right-radius: 10px; + padding-top: 7px; + position: absolute; + top: -39px; + left: 7%; + box-sizing: content-box; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box h4 { + font-weight: bold; + font-size: 22px; + line-height: 26px; + font-family: Arial, sans-serif; + margin-top: 0; + margin-bottom: 4px; + width: 80% +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box h4 a { + transition: all 0.5s ease; + color: #000; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box h4 a:hover { + text-decoration: none; + transition: all 0.5s ease; + color: #005ed9; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .blueTagsWrapper { + display: flex; + gap: 5px; + flex-wrap: wrap; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .blueTag { + font-size: var(--body-font-size-xs); + font-family: Arial, sans-serif; + color: white; + text-align: center; + background-color: #026DFF; + display: inline-block; + border-radius: 20px; + padding: 6px 16px; + margin-bottom: 10px; + display: flex; + gap: 5px; + height: fit-content; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .blueTag .icon { + width: fit-content; + height: auto; + display: flex; + align-items: center; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .blueTag div { + display: flex; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .blueTag img { + height: 14px; + margin-right: 5px; + margin-top: -5px; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .subtitle { + font-size: clamp(10px, 14px, 14px); + font-family: Arial, sans-serif; + margin-bottom: 0; + line-height: 1.25; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .subtitle.fixed_height { + min-height: 80px; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box hr { + border: 1px solid #D1D1D1; + margin: 10px 0; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box hr:first-of-type { + margin-bottom: 0; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box hr:last-of-type { + margin-bottom: 10px; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .save_price_box { + display: flex; + justify-content: left; + align-items: center; + margin-bottom: 8px; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .save_price_box .prod-oldprice { + font-size: var(--heading-font-size-xs); + line-height: var(--heading-font-size-xs); + text-decoration: line-through; + margin-right: 10px; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .save_price_box .prod-percent { + font-size: 13px; + line-height: 15px; + color: white; + background-color: #68BA68; + border-radius: 11px; + padding: 4px 10px; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .prices_box { + display: flex; + justify-content: left; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .prices_box .prod-newprice { + font-size: var(--heading-font-size-xl); + line-height: var(--heading-font-size-xl); +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .prices_box sup { + margin: 15px 0 0 5px; + font-size: var(--heading-font-size-s); + line-height: var(--heading-font-size-s); +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .billed { + font-size: 12px; + font-family: Arial, sans-serif; + line-height: 13px; + margin: 7px 0 20px; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .buy-btn a.red-buy-button { + width: 100%; + text-transform: none; + font-size: 14px; + line-height: 14px; + font-weight: 500 !important; + padding: 10px 1% !important; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .undeBuyLink { + font-size: 12px; + font-family: Arial, sans-serif; + line-height: 13px; + margin: 10px 0; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .benefitsLists { + font-family: Arial, sans-serif; + color: transparent; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .benefitsLists p { + margin: 0; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .benefitsLists u { + font-size: var(--body-font-size-xs); + text-decoration: none; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .benefitsLists ul { + margin: 0; + margin-bottom: -5px; + padding: 0; + color: black; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .benefitsLists ul li { + padding-left: 0; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .benefitsLists ul li:first-of-type { + font-size: 16px; + line-height: 18px; + text-decoration: none; + list-style-type: none; + font-weight: bold; + font-family: Arial, sans-serif; + margin-bottom: 0.5rem; +} + +.new-prod-boxes-container { + .new-prod-boxes { + .prod_box { + .inner_prod_box { + .benefitsLists { + ul { + &.checkmark-list { + background-color: #E7E7E7; + padding: 13px 48px 16px 10px; + filter: grayscale(1); + border-radius: 8px; + margin-bottom: 8px; + li { + &:first-of-type { + display: flex; + align-items: center; + font-size: 14px; + + .checkmark { + appearance: none; + -webkit-appearance: none; + display: grid; + width: 18px; + height: 18px; + padding: 0; + border: 1px solid #FFFFFF; + border-radius: 1px; + margin-right: 16px; + transition: cubic-bezier(0.075, 0.82, 0.165, 1); + + &::after { + content: ""; + width: 18px; + height: 18px; + clip-path: polygon(17% 54%, 28% 43%, 38% 54%, 70% 22%, 81% 33%, 38% 75%, 17% 54%); + transform: scale(0); + background-color: white; + } + &:checked { + background: #016DFF 0% 0% no-repeat padding-box; + -webkit-box-shadow: 0px 0px 5px 0px rgba(1,109,255,1); + -moz-box-shadow: 0px 0px 5px 0px rgba(1,109,255,1); + box-shadow: 0px 0px 5px 0px rgba(1,109,255,1); + } + &:checked::after { + transform: scale(1); + } + } + } + } + + &.checked { + filter: grayscale(0); + background-color: #EAF5EC; + } + } + } + } + + .add-on-product { + transition: all 0.4s; + } + } + } + } +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .benefitsLists ul li:first-of-type.has_arrow::before { + content: ""; + margin: 0 5px 20px 0; + background: url("https://bitdefender.com/pages/icons/arrow-left-blue.png") no-repeat center transparent; + width: 20px; + height: 20px; + background-size: 15px 12px; + float: left; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .benefitsLists ul li:first-of-type.has_arrow_right .arrow-right { + background: url("https://bitdefender.com/icons/arrow-right-solid.svg") no-repeat center transparent; + width: 20px; + height: 20px; + background-size: 15px 12px; + position: relative; + top: 4px; + display: inline-flex; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .benefitsLists ul li:not(:first-of-type) { + font-size: 14px; + line-height: 17px; + margin-bottom: 8px; + list-style-type: none; + background: url("https://bitdefender.com/icons/circle-check-sharp-solid.svg") top 2px left no-repeat transparent; + padding-left: 22px; + background-size: 13px; + position: relative; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .benefitsLists ul li:not(:first-of-type) .white-pill-content { + position: absolute; + background-color: white; + padding: 10px; + border-radius: 10px; + margin-bottom: 28px; + left: 0; + bottom: 0; + z-index: 1; + font-size: 12px; + box-shadow: 4px 4px 7px -8px #000; + display: none; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .benefitsLists ul li:not(:first-of-type) .white-pill-content::before { + content: ""; + position: absolute; + left: 17px; + bottom: -20px; + border-width: 10px; + border-style: solid; + border-color: white transparent transparent; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .benefitsLists ul li:not(:first-of-type):hover .white-pill-content{ + display: block; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .benefitsLists ul li:not(:first-of-type) u { + font-size: 14px; + font-weight: bold; + color: white; + border-radius: 20px; + padding: 2px 21px 2px 7px; + background: url("https://bitdefender.com/pages/images/icons/individual.svg") center right 6px no-repeat #026DFF; + background-size: auto 12px; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box .inner_prod_box .benefitsLists ul:nth-of-type(2) { + min-height: 5em; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box.hasGreenTag { + margin-top: 45px; +} + +.new-prod-boxes-container .new-prod-boxes .prod_box.hasGreenTag .inner_prod_box { + box-shadow: 0 3px 7px 0 #C1C1C1; +} + +.new-prod-boxes-container .prod-oldprice { + font-size: 16px; + text-decoration: line-through; +} + +.new-prod-boxes-container .prod-save { + color: #1C7928; + font-weight: bold; +} + +.new-prod-boxes-container .prod-newprice { + font-size: 40px; + font-weight: bold; +} +.new-prod-boxes-container .prod-newprice .per-m { + font-size: 20px; + top: -12px; +} +.new-prod-boxes-container .newprice-container { + line-height: 1; +} + +.new-prod-boxes-container .newprice-container sup { + position: relative; + top: -20px; +} + +.new-prod-boxes-container .button.primary { + font-size: 16px; + font-style: normal; + font-weight: 500; + -webkit-font-smoothing: antialiased; + display: block; + align-items: center; + box-sizing: border-box; + text-decoration: none; + padding: 10px 26px 8px 28px; + text-align: center; + cursor: pointer; + color: #fff; + background-color: #eb0000; + border: 2px solid #eb0000; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + border-radius: 8px; + height: fit-content; +} + +.new-prod-boxes-container .new-prod-boxes.smallerbuttons .button.primary { + display: inline-block; + min-width: 144px; +} + +.new-prod-boxes-container .new-prod-boxes.smallerbuttons .button.secondary { + display: inline-block; + min-width: 144px; +} + +.new-prod-boxes-container .button.primary.no-arrow::after { + content: none; +} + +.new-prod-boxes-container .button.secondary.no-arrow::after { + content: none; +} + +.new-prod-boxes-container .button.primary:hover { + color: white; + background-color: #B10304; + border-color: #B10304; +} + +.new-prod-boxes-container .button.primary:active { + background-color: #920A0A; + border-color: #920A0A; +} + +.new-prod-boxes-container p em a { + font-size: 16px !important; + font-style: normal !important; + font-weight: 500 !important; + -webkit-font-smoothing: antialiased !important; + display: block !important; + align-items: center !important; + box-sizing: border-box !important; + text-decoration: none !important; + padding: 10px 26px 8px 28px !important; + text-align: center !important; + cursor: pointer !important; + color: #006EFF !important; + background-color: transparent !important; + border: 2px solid #006EFF !important; + white-space: nowrap !important; + overflow: hidden !important; + text-overflow: ellipsis !important; + border-radius: 8px !important; + height: fit-content !important; +} + +.new-prod-boxes-container .new-prod-boxes.smallerbuttons p em a { + display: inline-block; + min-width: 144px; +} + +.new-prod-boxes-container p em a:hover { + color: white !important; + background-color: #006DFF !important; +} + +.new-prod-boxes-container p em a:active { + background-color: #0D499B !important; +} + +.new-prod-boxes-container .icon { + width: 12px; + height: 14px; + margin: 0 0 0 0; +} + +.new-prod-boxes-container .icon svg { + width: 12px; + height: 14px; + margin-left: -1px; + fill: #fff; +} + +.new-prod-boxes-container .blue-pill { + background-color: #026DFF; + padding: 2.5px 6.7px; + border-radius: 20px; + color: white; + font-style: normal; + font-size: 11px; + letter-spacing: 0px; + font-weight: bold; + display: inline-flex; + justify-content: center; +} + +.new-prod-boxes-container .blue-pill .icon { + position: relative; + top: 1.5px; + display: flex; + align-items: center; + justify-content: center; + flex-wrap: wrap; +} + +.new-prod-boxes-container .blue-pill svg { + width: 9px; + height: 9px; +} + +.switchBox { + text-align: center; + padding-bottom: 35px; +} + +.switchBox .switch { + position: relative; + display: inline-flex; + align-items: center; + width: 302px; + height: 44px; + background-color: #016DFF; + border-radius: 22px; +} + +.switchBox .switch input { + display: none; +} + +.switchBox .slider { + position: absolute; + content: ""; + height: 40px; + width: 150px; + left: 2px; + bottom: 2px; + background-color: white; + border-radius: 20px; + transition: all 0.4s; +} + +.switchBox .switch input:checked + .slider { + transform: translateX(149px); +} + +.switchBox .label { + font-family: Arial, Helvetica, sans-serif; + width: 50%; + text-align: center; + font-weight: bold; + line-height: 34px; + font-size: 16px; + color: white; + transition: color 0.4s; + cursor: pointer; +} + +.switchBox .label.right { + z-index: 10; + color: black; +} + +.switchBox .label.left { + z-index: 10; +} + +.switchBox .switch input:checked ~ .label.right { + transition: color 0.4s; + color: white !important; +} + +.switchBox .switch input ~ .label .icon { + position: relative; + margin-right: 10px; + top: 2px; +} + +.switchBox .switch input ~ .label .icon svg { + width: 14px; + height: 16px; +} + +.switchBox .switch input ~ .label.right .icon svg { + fill: #026DFF; +} + +.switchBox .switch input:checked ~ .label.right .icon svg { + fill: white; +} + +.switchBox .switch input:checked ~ .label.left { + transition: color 0.4s; + color: black; +} + +.switchBox .switch input:checked ~ .label.left .icon svg { + fill: #026DFF; +} + +.prod-box.individual-box { + transition: all 0.4s; +} + +.prod_box.family-box { + display: none; + transition: all 0.4s; +} + +.hero-aem__prices { + margin-top: 20px; +} + +.plan-switcher { + display: flex; + flex-wrap: wrap; + gap: 4px; + align-items: center; + font-weight: bold; + margin-bottom: 24px; + margin-top: 16px; +} + +.plan-switcher input[type=radio] { + position: relative; + display: none; + opacity: 0; + width: auto; +} + +.plan-switcher .radio-label { + margin-right: 8px; + cursor: pointer; +} + +.plan-switcher .radio-label::before { + content: ""; + background: #f4f4f4; + color: #006DFF; + border-radius: 100%; + border: 2px solid #006DFF; + display: inline-block; + width: 1.2rem; + height: 1.2rem; + position: relative; + margin-right: 9px; + vertical-align: top; + cursor: pointer; + text-align: center; + transition: all 250ms ease; +} + +.plan-switcher input[type=radio]:checked+.radio-label:before { + background-color: #3197EE; + box-shadow: inset 0 0 0 4px #f4f4f4; +} + +.plan-switcher input[type=radio]:focus+.radio-label:before { + outline: none; + border-color: #3197EE; +} + +@media (min-width: 768px) { + .creators .new-prod-boxes-container .new-prod-boxes { + padding-bottom: 10px; + } + + .new-prod-boxes-container .new-prod-boxes { + flex-direction: row; + padding-bottom: 60px; + align-items: initial; + margin-top: 37px; + } + + .new-prod-boxes-container .new-prod-boxes .prod_box.hasGreenTag { + margin: 8px; + } +} + +@media (min-width: 992px) { + .new-prod-boxes-container.we-container { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } +} + +@media (min-width: 1200px) { + .new-prod-boxes-container.we-container { + padding-left: 20px; + padding-right: 20px; + } +} \ No newline at end of file diff --git a/_src/blocks/new-prod-boxes/new-prod-boxes.js b/_src/blocks/new-prod-boxes/new-prod-boxes.js new file mode 100644 index 000000000..6ab642245 --- /dev/null +++ b/_src/blocks/new-prod-boxes/new-prod-boxes.js @@ -0,0 +1,427 @@ +/* eslint-disable prefer-const */ +/* eslint-disable no-undef */ +/* eslint-disable max-len */ +import { + matchHeights, formatPrice, + checkIfConsumerPage, +} from '../../scripts/utils/utils.js'; +import { Store, ProductInfo } from '../../scripts/libs/store/index.js'; + +function setDiscountedPriceAttribute(type, hideDecimals, prodName) { + let priceAttribute = 'discounted||full'; + + if (type === 'monthly') { + priceAttribute = hideDecimals === 'true' ? 'discounted-monthly-no-decimal||full-monthly' : 'discounted-monthly||full-monthly'; + if (prodName.endsWith('m')) { + priceAttribute = hideDecimals === 'true' ? 'discounted-no-decimal||full' : 'discounted||full'; + } + } + + return priceAttribute; +} + +async function updateProductPrice(prodName, saveText, buyLinkSelector = null, billed = null, type = null, hideDecimals = null, perPrice = '') { + let priceElement = document.createElement('div'); + let newPrice = document.createElement('span'); + + let priceAttribute = setDiscountedPriceAttribute(type, hideDecimals, prodName); + newPrice.setAttribute('data-store-price', priceAttribute); + + let oldPrice = 'data-store-price="full"'; + let billedPrice = 'data-store-price="discounted||full"'; + if (hideDecimals === 'true') { + oldPrice = 'data-store-price="full-no-decimal"'; + billedPrice = 'data-store-price="discounted-no-decimal||full-no-decimal"'; + } + + priceElement.innerHTML = ` +
      +
      + + ${saveText} +
      +
      + ${newPrice.outerHTML} ${perPrice && `${perPrice.textContent.replace('0', '')}`} +
      + ${billed ? `
      ${billed.innerHTML.replace('0', ``)}
      ` : ''} + ${buyLinkSelector.innerText} +
      `; + return priceElement; +} + +function createPlanSwitcher(radioButtons, cardNumber, prodsNames, prodsUsers, prodsYears, variant = 'default') { + const planSwitcher = document.createElement('div'); + planSwitcher.classList.add('plan-switcher'); + planSwitcher.classList.toggle('addon', variant === 'addon'); + + let radioArray = ['yearly', 'monthly', '3-rd-button']; + if (variant === 'addon') { + radioArray = ['add-on-yearly', 'add-on-monthly']; + } + + Array.from(radioButtons.children).forEach((radio, idx) => { + let radioText = radio.textContent; + let plan = radioArray[idx]; + let productName = prodsNames[idx]; + let prodUser = prodsUsers[idx]; + let prodYear = prodsYears[idx]; + let checked = idx === 0 ? 'checked' : ''; + let defaultCheck = radio.textContent.match(/\[checked\]/g); + if (defaultCheck) { + radioText = radioText.replace('[checked]', ''); + checked = 'checked'; + } + + if (productName) { + planSwitcher.innerHTML += ` + +
      + `; + } + }); + + return planSwitcher; +} + +function createFeatureList(featuresSet) { + return Array.from(featuresSet).map((table) => { + const trList = Array.from(table.querySelectorAll('tr')); + const liString = trList.map((tr) => { + const tdList = Array.from(tr.querySelectorAll('td')); + let firstTdContent = tdList.length > 0 && tdList[0].textContent.trim() !== '' ? `${tdList[0].innerHTML}` : ''; + const secondTdContent = tdList.length > 1 && tdList[1].textContent.trim() !== '' ? `${tdList[1].innerHTML}` : ''; + let liClass = ''; + + if (firstTdContent === '') { + liClass += 'd-none'; + } + + if (firstTdContent.indexOf('?pill') !== -1) { + let pillText = firstTdContent.match(/\?pill (\w+)/); + let iconElement = firstTdContent.match(/(.*?)<\/span>/); + if (pillText) { + let icon = tdList[0].querySelector('span'); + const pillElement = document.createElement('span'); + pillElement.classList.add('blue-pill'); + pillElement.innerHTML = `${pillText[1]}${iconElement ? iconElement[0] : ''}`; + firstTdContent = firstTdContent.replace(pillText[0], `${pillElement.outerHTML}`); + if (icon) { + let count = 0; + firstTdContent = firstTdContent.replace(new RegExp(icon.outerHTML, 'g'), (match) => { + count += 1; + return (count === 2) ? '' : match; + }); + } + } + } + + if (firstTdContent.indexOf('<pill') !== -1 || firstTdContent.indexOf('<') !== -1) { + liClass += ' has_arrow'; + firstTdContent = firstTdContent.replace('<-', ''); + } + + if (firstTdContent.indexOf('->') !== -1 || firstTdContent.indexOf('>') !== -1) { + liClass += ' has_arrow_right'; + firstTdContent = firstTdContent.replace('->', ''); + } + + if (firstTdContent.indexOf('[checkmark]') !== -1) { + firstTdContent = firstTdContent.replace('[checkmark]', ''); + } + + if (firstTdContent.indexOf('[add-on]') !== -1) { + firstTdContent = firstTdContent.replace('[add-on]', ''); + } + + if (firstTdContent.indexOf('<<add-on-newprice>>') !== -1) { + firstTdContent = firstTdContent.replace('<<add-on-newprice>>', ''); + } + if (firstTdContent.indexOf('<<add-on-oldprice>>') !== -1) { + firstTdContent = firstTdContent.replace('<<add-on-oldprice>>', ''); + } + + if (firstTdContent.indexOf('<<add-on-percent-save>>') !== -1) { + firstTdContent = firstTdContent.replace('<<add-on-percent-save>>', ''); + } + + if (firstTdContent.indexOf('[[') !== -1) { + firstTdContent = firstTdContent.replace('[[', '('); + } + + if (firstTdContent.indexOf(']]') !== -1) { + firstTdContent = firstTdContent.replace(']]', ')'); + } + + const liContent = `
    • ${firstTdContent}${secondTdContent}
    • `; + return liContent; + }).join(' '); + + return `
        ${liString}
      `; + }); +} + +// Function to check if content contains [add-on] text +function checkAddOn(featuresSet) { + let addOn = false; + // eslint-disable-next-line array-callback-return + Array.from(featuresSet).map((table) => { + const trList = Array.from(table.querySelectorAll('tr')); + // eslint-disable-next-line array-callback-return + trList.map((tr) => { + const tdList = Array.from(tr.querySelectorAll('td')); + let firstTdContent = tdList.length > 0 && tdList[0].textContent.trim() !== '' ? `${tdList[0].innerHTML}` : ''; + if (firstTdContent.indexOf('[add-on]') !== -1) { + addOn = true; + } + }); + }); + + return addOn; +} + +export default async function decorate(block) { + const { + // eslint-disable-next-line no-unused-vars + products, familyProducts, monthlyProducts, pid, mainProduct, + addOnProducts, addOnMonthlyProducts, type, hideDecimals, thirdRadioButtonProducts, saveText, addonProductName, + } = block.closest('.section').dataset; + + const blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + + let defaultContentWrapperElements = block.closest('.section').querySelector('.default-content-wrapper')?.children; + let individualSwitchText; + let familySwitchText; + if (defaultContentWrapperElements) { + [...defaultContentWrapperElements].forEach((element) => { + if (element.innerHTML.includes('<slider-1 ')) { + element.innerHTML = element.innerHTML.replace('<slider-1 ', ''); + individualSwitchText = element.innerHTML; + element.remove(); + } + if (element.innerHTML.includes('<slider-2 ')) { + element.innerHTML = element.innerHTML.replace('<slider-2 ', ''); + familySwitchText = element.innerHTML; + element.remove(); + } + }); + } + + let switchBox = document.createElement('div'); + if (individualSwitchText && familySwitchText) { + switchBox.classList.add('switchBox'); + switchBox.innerHTML = ` + + `; + + // Get the checkbox inside the switchBox + let switchCheckbox = switchBox.querySelector('#switchCheckbox'); + // Add an event listener to the checkbox + switchCheckbox.addEventListener('change', () => { + if (switchCheckbox.checked) { + let familyBoxes = block.querySelectorAll('.family-box'); + familyBoxes.forEach((box) => { + box.style.display = 'block'; + }); + + let individualBoxes = block.querySelectorAll('.individual-box'); + individualBoxes.forEach((box) => { + box.style.display = 'none'; + }); + } else { + let familyBoxes = block.querySelectorAll('.family-box'); + familyBoxes.forEach((box) => { + box.style.display = 'none'; + }); + + let individualBoxes = block.querySelectorAll('.individual-box'); + individualBoxes.forEach((box) => { + box.style.display = 'block'; + }); + } + }); + } + + const productsAsList = products && products.replaceAll(' ', '').split(','); + const familyProductsAsList = familyProducts && familyProducts.replaceAll(' ', '').split(','); + const combinedProducts = productsAsList.concat(familyProductsAsList); + const monthlyPricesAsList = monthlyProducts && monthlyProducts.replaceAll(' ', '').split(','); + const thirdRadioButtonProductsAsList = thirdRadioButtonProducts && thirdRadioButtonProducts.replaceAll(' ', '').split(','); + const addOnProductsAsList = addOnProducts && addOnProducts.replaceAll(' ', '').split(','); + const addOnProductsInitial = addOnProductsAsList && addOnProductsAsList.slice(0, productsAsList.length); + const addOnMonthlyProductsAsList = addOnMonthlyProducts && addOnMonthlyProducts.replaceAll(' ', '').split(','); + + if (combinedProducts.length) { + [...block.children].map(async (prod, key) => { + const mainTable = prod.querySelector('tbody'); + const [greenTag, title, blueTag, subtitle, radioButtons, perPrice, billed, buyLink, undeBuyLink, benefitsLists, billed2, buyLink2] = [...mainTable.querySelectorAll(':scope > tr')]; + const [prodName, prodUsers, prodYears] = combinedProducts[key].split('/'); + const [prodMonthlyName, prodMonthlyUsers, prodMonthlyYears] = monthlyPricesAsList ? monthlyPricesAsList[key].split('/') : []; + const [prodThirdRadioButtonName, prodThirdRadioButtonUsers, prodThirdRadioButtonYears] = thirdRadioButtonProductsAsList ? thirdRadioButtonProductsAsList[key].split('/') : []; + const [addOnProdName, addOnProdUsers, addOnProdYears] = addOnProductsAsList ? addOnProductsAsList[key].split('/') : []; + const [addOnProdMonthlyName, addOnProdMonthlyUsers, addOnProdMonthlyYears] = addOnMonthlyProductsAsList ? addOnMonthlyProductsAsList[key].split('/') : []; + const featuresSet = benefitsLists.querySelectorAll('table'); + const featureList = createFeatureList(featuresSet); + let addOn = checkAddOn(featuresSet); + + let buyLinkSelector = prod.querySelector('a[href*="#buylink"]'); + if (buyLinkSelector) { + buyLinkSelector.classList.add('button', 'primary'); + } else { + buyLinkSelector = buyLink.querySelector('a'); + } + + let planSwitcher = document.createElement('div'); + if (radioButtons && monthlyProducts) { + let prodsNames = [prodName, prodMonthlyName, prodThirdRadioButtonName]; + let prodsUsers = [prodUsers, prodMonthlyUsers, prodThirdRadioButtonUsers]; + let prodsYears = [prodYears, prodMonthlyYears, prodThirdRadioButtonYears]; + planSwitcher = createPlanSwitcher(radioButtons, key, prodsNames, prodsUsers, prodsYears); + } + let planSwitcher2 = document.createElement('div'); + if (addOn && addOnProducts && addOnMonthlyProducts) { + let prodsNames = [addOnProdName, addOnProdMonthlyName]; + let prodsUsers = [addOnProdUsers, addOnProdMonthlyUsers]; + let prodsYears = [addOnProdYears, addOnProdMonthlyYears]; + planSwitcher2 = createPlanSwitcher(radioButtons, key, prodsNames, prodsUsers, prodsYears, 'addon'); + } + + let newBlueTag = document.createElement('div'); + if (blueTag) { + let blueTagChildren = blueTag.children; + blueTagChildren = Array.from(blueTagChildren); + blueTagChildren.forEach((child) => { + // create a different blueTag element + newBlueTag.innerHTML += `
      ${child.innerHTML}
      `; + }); + } + + let secondButton = buyLink?.querySelectorAll('a')[1]; + if (secondButton) { + secondButton.classList.add('button', 'secondary', 'no-arrow'); + } + + // set the store event on the component + let storeEvent = 'main-product-loaded'; + if (checkIfConsumerPage()) { + storeEvent = 'product-loaded'; + } + + const prodBox = document.createElement('div'); + prodBox.innerHTML = ` +
      prodEntry.includes(prodName)) ? `data-store-event="${storeEvent}"` : ''}> +
      + ${greenTag.innerText.trim() ? `
      ${greenTag.innerText.trim()}
      ` : ''} + ${title.innerText.trim() ? `

      ${title.innerHTML}

      ` : ''} + +
      ${newBlueTag.innerText.trim() ? `${newBlueTag.innerHTML.trim()}` : ''}
      + ${subtitle.innerText.trim() ? `

      ${subtitle.innerText.trim()}

      ` : ''} +
      + ${radioButtons ? planSwitcher.outerHTML : ''} +
      + ${secondButton ? secondButton.outerHTML : ''} + ${undeBuyLink.innerText.trim() ? `` : ''} +
      + ${benefitsLists.innerText.trim() ? `
      ${featureList}
      ` : ''} + +
      +
      `; + block.children[key].outerHTML = prodBox.innerHTML; + let priceBox = await updateProductPrice(prodName, saveText, buyLink.querySelector('a'), billed, type, hideDecimals, perPrice); + block.children[key].querySelector('.hero-aem__prices').appendChild(priceBox); + + let addOnPriceBox; + if (addOn && addOnProducts) { + addOnPriceBox = await updateProductPrice(addOnProdName, saveText, buyLink2.querySelector('a'), billed2, type, hideDecimals, perPrice); + block.children[key].querySelector('.hero-aem__prices__addon').appendChild(addOnPriceBox); + } + + let checkmark = block.children[key].querySelector('.checkmark'); + if (checkmark) { + let checkmarkList = checkmark.closest('ul'); + checkmarkList.classList.add('checkmark-list'); + + let li = checkmark.closest('li'); + li.removeChild(checkmark); + + let checkBox = document.createElement('input'); + checkBox.setAttribute('type', 'checkbox'); + checkBox.classList.add('checkmark'); + + // rewrite the list element so flexbox can work + let newLi = document.createElement('li'); + newLi.innerHTML = ` + ${checkBox.outerHTML} +
      ${li.innerHTML}
      `; + li.replaceWith(newLi); + + block.children[key].querySelector('.add-on-product').setAttribute('data-store-context', ''); + block.children[key].querySelector('.add-on-product').setAttribute('data-store-id', addOnProdName); + block.children[key].querySelector('.add-on-product').setAttribute('data-store-option', `${addOnProdUsers}-${addOnProdYears}`); + block.children[key].querySelector('.add-on-product').setAttribute('data-store-department', 'consumer'); + if (addOnProductsInitial && addOnProductsInitial.some((prodEntry) => prodEntry.includes(addOnProdName))) { + block.children[key].querySelector('.add-on-product').setAttribute('data-store-event', storeEvent); + } + + let productObject = await Store.getProducts([new ProductInfo(prodName), new ProductInfo(addOnProdName)]); + let product = productObject[prodName]; + let addOnProduct = productObject[addOnProdName]; + let addOnCost = addOnProduct.getOption(addOnProdUsers, addOnProdYears).getDiscountedPrice('value') - product.getOption(prodUsers, prodYears).getDiscountedPrice('value'); + addOnCost = formatPrice(addOnCost, product.getCurrency()); + + let addOnNewPrice = newLi.querySelector('.add-on-newprice'); + addOnNewPrice.textContent = addOnCost; + let addOnOldPrice = newLi.querySelector('.add-on-oldprice'); + addOnOldPrice.textContent = formatPrice(addOnProduct.getOption(addOnProdUsers, addOnProdYears).getPrice('value'), addOnProduct.getCurrency()); + let addOnPercentSave = newLi.querySelector('.add-on-percent-save'); + addOnPercentSave.textContent = `${addOnPriceBox.querySelector('.prod-save').textContent} ${addOnProduct.getOption(addOnProdUsers, addOnProdYears).getDiscount('percentageWithProcent')}`; + + let checkBoxSelector = newLi.querySelector('.checkmark'); + checkBoxSelector.addEventListener('change', () => { + if (checkBoxSelector.checked) { + checkmarkList.classList.add('checked'); + block.children[key].querySelector('.add-on-product').style.display = 'block'; + } else { + checkmarkList.classList.remove('checked'); + block.children[key].querySelector('.add-on-product').style.display = 'none'; + } + }); + } + }); + } + + if (individualSwitchText && familySwitchText) { + block.parentNode.insertBefore(switchBox, block); + } + + window.hj = window.hj || function initHotjar(...args) { + (hj.q = hj.q || []).push(...args); + }; + hj('event', 'new-prod-boxes'); + + // decorate icons if the component is being called from www-websites + const isInLandingPages = window.location.href.includes('www-landing-pages') || window.location.href.includes('bitdefender.com/pages'); + if (!isInLandingPages) { + const { decorateIcons } = await import('../../scripts/lib-franklin.js'); + decorateIcons(block.closest('.section')); + } + + matchHeights(block, '.subtitle'); + matchHeights(block, 'h2'); + matchHeights(block, 'h4'); + matchHeights(block, '.plan-switcher'); + matchHeights(block, '.blueTagsWrapper'); +} diff --git a/_src/blocks/news-bar/news-bar.css b/_src/blocks/news-bar/news-bar.css new file mode 100644 index 000000000..6e9216116 --- /dev/null +++ b/_src/blocks/news-bar/news-bar.css @@ -0,0 +1,72 @@ +.news-bar { + text-align: center; + justify-content: center; + background-color: #006EFF; + color: white; + display: flex; + line-height: 1.2; + padding: 8px 0; + align-items: center; + + a { + color: white; + transition: all 1s ease; + text-decoration: underline; + } + + transition: all 1s ease; +} + +.news-bar-container.solutions { + .news-bar { + font-size: 16px; + line-height: 21px; + } + + a { + display: block; + font-size: 14px; + font-style: normal; + font-weight: 500; + -webkit-font-smoothing: antialiased; + align-items: center; + box-sizing: border-box; + text-decoration: none; + padding: 7px 29px; + text-align: center; + cursor: pointer; + color: #fff; + background-color: #eb0000; + border: 2px solid #eb0000; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + border-radius: 8px; + height: fit-content; + width: fit-content; + margin: 10px auto 0; + transition: all 0.1s ease; + } + + a:hover { + background-color: #D80000; + border: 2px solid #D80000; + } +} + +@media screen and (min-width: 991px) { + .news-bar { + height: 44px; + } + + .news-bar-container.solutions { + .news-bar { + height: 61px; + + a { + display: inline-flex; + margin: 0 0 0 29px; + } + } + } +} \ No newline at end of file diff --git a/_src/blocks/news-bar/news-bar.js b/_src/blocks/news-bar/news-bar.js new file mode 100644 index 000000000..150c7db14 --- /dev/null +++ b/_src/blocks/news-bar/news-bar.js @@ -0,0 +1,37 @@ +export default function decorate(block, options) { + const { + solutions, hideDate, + } = block.closest('.section').dataset; + + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + } + + if (solutions) { + block.closest('.section').classList.add('solutions'); + } + + const blockParent = block.closest('.section'); + setTimeout(() => { + const elementLink = block.querySelector('a'); + block.style.backgroundColor = '#E4F2FF'; + block.style.color = '#006EFF'; + if (elementLink && !blockParent.classList.contains('solutions')) elementLink.style.color = '#006EFF'; + }, 2000); + + if (hideDate) { + const currentDate = new Date(); + const hiddenDate = new Date(hideDate); + if (hiddenDate < currentDate) { + block.style.display = 'none'; + } + } + + setTimeout(() => { + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, + }); + }, 700); +} diff --git a/_src/blocks/particle-background/particle-background.css b/_src/blocks/particle-background/particle-background.css new file mode 100644 index 000000000..c83edcfc4 --- /dev/null +++ b/_src/blocks/particle-background/particle-background.css @@ -0,0 +1,71 @@ + +.particle-background { + position: relative; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + min-height: 400px; + border-radius: 25px; + color: white; + text-align: center; + overflow: hidden; + max-width: 1332px; + z-index: 1; + margin: 48px 0; +} + +.we-container { + margin: 0 auto; + padding: 0 20px; + max-width: 1290px; + position: relative; +} + +.particle-background #ts-particles { + position: absolute; + top: 0; + left: 0; + bottom: 0; + right: 0; + padding: 0; + margin: 0; +} + +.particle-background h2 { + font-size: clamp(1.5rem, 5vw, 2.5rem); + margin: 0 auto; + line-height: 42px; + max-width: 500px; +} + +.particle-background p { + font-size: 18px; +} + +.particle-background div { + z-index: 1; + padding: 24px; +} + +@media (max-width: 768px) { + .particle-background h2 { + line-height: 30px; + } +} + +@media (min-width: 991px) { /* mobile/tablet */ + .particle-background-container.we-container { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } +} + +@media (min-width: 1200px) { + .particle-background-container.we-container { + max-width: 1290px; + padding-left: 20px; + padding-right: 20px; + } +} diff --git a/_src/blocks/particle-background/particle-background.js b/_src/blocks/particle-background/particle-background.js new file mode 100644 index 000000000..d6e7873bd --- /dev/null +++ b/_src/blocks/particle-background/particle-background.js @@ -0,0 +1,145 @@ +/* eslint-disable prefer-const */ +/* eslint-disable camelcase */ +// import * as all from '../../scripts/vendor/tsparticles/tsparticles.bundle.min.js'; +// eslint-disable-next-line no-unused-vars +// import { +// loadScript, +// } from '../../scripts/lib-franklin.js'; + +// eslint-disable-next-line no-unused-vars +function debounce(func, wait) { + let timeout; + return function executedFunction(...args) { + const later = () => { + clearTimeout(timeout); + func(...args); + }; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + }; +} + +function isView(viewport) { + const element = document.querySelectorAll(`[data-${viewport}-detector]`)[0]; + return !!(element && getComputedStyle(element).display !== 'none'); +} + +let tsParticles; +let loadAll; + +async function init(block, aemOptions) { + // eslint-disable-next-line import/no-unresolved + tsParticles = (await import('https://cdn.jsdelivr.net/npm/@tsparticles/engine@3.1.0/+esm')).tsParticles; + // eslint-disable-next-line import/no-unresolved + loadAll = (await import('https://cdn.jsdelivr.net/npm/@tsparticles/all@3.1.0/+esm')).loadAll; + const particleIdSelector = 'ts-particles'; + + const particleDiv = document.createElement('div'); + particleDiv.setAttribute('id', particleIdSelector); + + if (aemOptions) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + const blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + } else { + block.parentElement.classList.add('we-container'); + } + + const particleBackground = block.parentElement.querySelector('.particle-background'); + particleBackground.prepend(particleDiv); + + async function loadParticles(options) { + await loadAll(tsParticles); + + await tsParticles.load({ id: particleIdSelector, options }); + // await loadScript('../../../_src/scripts/vendor/tsparticles/tsparticles.bundle.min.js'); + // await window.tsParticles.load({ id: particleIdSelector, options }); + // let script = document.createElement('script'); + // script.src = 'https://cdn.jsdelivr.net/npm/tsparticles@3.3.0/tsparticles.bundle.min.js'; + // script.src = 'https://dlp-fixes--www-websites--bitdefender.hlx.page/_src/scripts/vendor/tsparticles/tsparticles.bundle.min.js'; + // script.src = '../../../_src/scripts/vendor/tsparticles/tsparticles.bundle.min.js'; + // block.appendChild(script); + // script.onload = () => { + // console.log('tsParticles loaded'); + // // console.log('tsParticles', tsParticles); + // (async () => { + // // await loadFull(tsParticles); + // await window.tsParticles.load({ id: particleIdSelector, options }); + // })(); + // }; + } + const options = { + particles: { + number: { + value: 20, + }, + color: { + value: '#ffffff', + }, + links: { + enable: true, + distance: 200, + }, + shape: { + type: 'circle', + }, + opacity: { + value: 0.6, + }, + size: { + value: { + min: 2, + max: 4, + }, + }, + move: { + enable: true, + speed: 0.5, + }, + }, + background: { + color: '#016DFF', + }, + poisson: { + enable: true, + }, + fullScreen: { enable: false }, + }; + + await loadParticles(options); +} + +// eslint-disable-next-line no-unused-vars +async function checkForMobile() { + const isMobileView = isView('mobile'); + if (isMobileView && (!tsParticles && !loadAll)) { + return; + } + + if (isMobileView && tsParticles) { + const particles = tsParticles.domItem(0); + particles.pause(); + return; + } + + if (!isMobileView && (!tsParticles && !loadAll)) { + await init(); + return; + } + + const particles = tsParticles.domItem(0); + particles.play(); +} + +export default async function decorate(block, options) { + await init(block, options); + + // uncomment this line if you want the bubbles to stop moving on mobile + // window.addEventListener('resize', debounce(checkForMobile, 250)); + + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); +} diff --git a/_src/blocks/percentage-vsb/percentage-vsb.css b/_src/blocks/percentage-vsb/percentage-vsb.css new file mode 100644 index 000000000..efabe30bc --- /dev/null +++ b/_src/blocks/percentage-vsb/percentage-vsb.css @@ -0,0 +1,109 @@ +/* stylelint-disable no-descending-specificity */ +.percentage-vsb-container { + display: flex; + justify-content: center; + font-family: 'IBM Plex Sans', sans-serif; +} + +.percentage-vsb-container.we-container{ + max-width: 100%; + padding-left: 20px; + padding-right: 20px; + margin-top: 15px; + margin-left: auto; + margin-right: auto; +} + +.percentage-vsb-container a{ + font-size: 16px; + font-style: normal; + font-weight: 500; + -webkit-font-smoothing: antialiased; + display: inline-flex; + align-items: center; + box-sizing: border-box; + text-decoration: none; + padding: 10px 26px 8px 28px; + text-align: center; + cursor: pointer; + color: #fff; + background-color: #eb0000; + border: 2px solid #eb0000; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + border-radius: 8px; + height: fit-content; +} + +.percentage-vsb-container a:hover { + background-color: #d80000; + border: 2px solid #d80000; + cursor: pointer; +} + +.percentage-vsb-wrapper { + max-width: 630px; + display: flex; + flex-direction: column; + align-items: center; + +} + +.percentage-vsb-wrapper .columns-container{ + display:flex; + flex-direction: column; + gap:0; +} + +.percentage-vsb-wrapper .columns-container .col{ + width: 100%; + padding: 5px; +} + +.percentage-vsb-wrapper .title-class h2{ + font-size: 38px; + line-height: 40px; + margin-top: 1em; +} + +.percentage-vsb-wrapper .subtitle-class{ + font-size:18px; +} + +.percentage-vsb-wrapper .columns-container h4{ + font-size: 38px; + color: #F00F0F; + margin-top: 0; + margin-bottom: 9px; +} + +.percentage-vsb-wrapper .button-container{ + display: flex; + justify-content: center; + margin-top: 1em; +} + +@media (min-width: 768px) { + .percentage-vsb-wrapper .columns-container{ + display:flex; + flex-direction: row; + margin-top:35px; + margin-bottom: 42px; + gap:20px; + } + +.percentage-vsb-wrapper .columns-container .col{ + width: 33.33%; +} + +.percentage-vsb-wrapper .title-class h2{ + font-size:48px; + line-height: 55px; +} + +.percentage-vsb-wrapper .columns-container h4{ + font-size: 48px; + line-height: 55px; +} +} diff --git a/_src/blocks/percentage-vsb/percentage-vsb.js b/_src/blocks/percentage-vsb/percentage-vsb.js new file mode 100644 index 000000000..bb1fb553a --- /dev/null +++ b/_src/blocks/percentage-vsb/percentage-vsb.js @@ -0,0 +1,49 @@ +export default function decorate(block, options) { + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + const blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + } + const [ + title, + subtitle, + button, + colTitle1, + colText1, + colTitle2, + colText2, + colTitle3, + colText3, + ] = block.children; + + title.classList.add('title-class'); + subtitle.classList.add('subtitle-class'); + const columnsContainer = document.createElement('div'); + columnsContainer.classList.add('columns-container'); + + const column1 = document.createElement('div'); + column1.appendChild(colTitle1); + column1.appendChild(colText1); + columnsContainer.appendChild(column1); + column1.classList.add('col'); + + const column2 = document.createElement('div'); + column2.appendChild(colTitle2); + column2.appendChild(colText2); + columnsContainer.appendChild(column2); + column2.classList.add('col'); + + const column3 = document.createElement('div'); + column3.appendChild(colTitle3); + column3.appendChild(colText3); + columnsContainer.appendChild(column3); + column3.classList.add('col'); + block.appendChild(columnsContainer); + button.classList.add('button-container'); + block.appendChild(button); + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); +} diff --git a/_src/blocks/platform-link/platform-link.js b/_src/blocks/platform-link/platform-link.js new file mode 100644 index 000000000..5fb3c1a96 --- /dev/null +++ b/_src/blocks/platform-link/platform-link.js @@ -0,0 +1,15 @@ +import { getDatasetFromSection, openUrlForOs } from '../../scripts/utils/utils.js'; + +export default function decorate(block) { + block.classList.add('default-content-wrapper'); + const blockDataset = getDatasetFromSection(block); + + const { + linkandroid, linkios, linkmacos, linkwindows, + } = blockDataset; + + const freeDownloadButton = block.querySelector('a'); + if (freeDownloadButton) { + openUrlForOs(linkmacos, linkwindows, linkandroid, linkios, freeDownloadButton); + } +} diff --git a/solutions/blocks/product-comparison-table/product-comparison-table.css b/_src/blocks/product-comparison-table/product-comparison-table.css similarity index 65% rename from solutions/blocks/product-comparison-table/product-comparison-table.css rename to _src/blocks/product-comparison-table/product-comparison-table.css index 95caa7052..8963998f6 100644 --- a/solutions/blocks/product-comparison-table/product-comparison-table.css +++ b/_src/blocks/product-comparison-table/product-comparison-table.css @@ -17,6 +17,37 @@ padding-right: 0; } +.section.product-comparison-table-container .default-content-wrapper { + margin-bottom: 2em; +} + +.current-price-container p { + font-size: var(--body-font-size-m); + font-weight: var(--font-weight-boldest); +} + +div[role="cell"] p { + margin: 0; +} + +.product-comparison-price p:last-of-type { + color: #7e7e7e; + font-size: var(--body-font-size-xs); + font-weight: var(--font-weight-regular); + line-height: var(--body-font-size-xs); + border-bottom: 1px dashed #dedede; + margin-bottom: 4px !important; + padding-bottom: 1.5em; +} + +.product-comparison-header div[role="columnheader"] p { + margin: 0; +} + +.section.product-comparison-table-container .default-content-wrapper p { + font-size: var(--body-font-size-m); +} + .column-fixed-width { width: 10.5rem; } @@ -54,6 +85,8 @@ .product-comparison-header div[role="columnheader"]:not(:first-child) { border: 1px solid var(--first-table-cell-color); flex: 1; + display: flex; + flex-direction: column; } .product-comparison-header div[role="columnheader"]:not(:first-child).active { @@ -83,36 +116,25 @@ .product-comparison-price { padding-top: 0.9375rem; margin: 0.9375rem 0.625rem 0; - border-top: 1px solid var(--horizontal-separator-color); -} - -.current-price-container p{ - font-size: var(--body-font-size-m); - font-weight: var(--font-weight-boldest); -} - -div[role="cell"] p { - margin: 0; -} - -.product-comparison-price p:last-of-type { - color: var(--product-comparison-text-color); -} - -.product-comparison-header div[role="columnheader"] p { - margin: 0; + border-top: 1px solid var(--horizontal-separator-color); } div[role="cell"] .button-container , .product-comparison-header div[role="columnheader"] .button-container{ margin-bottom: 0.3125rem; } +.section.product-comparison-table-container.migration p { + color: #7e7e7e; + font-size: 12px; +} + .product-comparison-header div[role="columnheader"] p:first-of-type { font-weight: var(--font-weight-bold); padding: 0; - color: var(--product-comparison-text-color); + color: #3c3c3c; text-align: center; - font-size: var(--body-font-size-xs); + font-size: var(--body-font-size-s); + flex-grow: 1; } .product-comparison-header div[role="cell"] p:first-of-type { @@ -139,6 +161,15 @@ div[role="cell"] p.button-container a, .product-comparison-header div[role="colu background-color: unset; } +.product-comparison-header div[role="columnheader"] p.button-container a:hover { + background-color: var(--button-primary-background-color); + color: white; +} + +.product-comparison-header div[role="columnheader"] p.button-container a:hover::after { + background-color: white!important; +} + .product-comparison-header div[role="columnheader"].active p.button-container a, .product-comparison-header div[role="columnheader"] p.button-container.red a { background-color: var(--button-background-color); @@ -165,12 +196,12 @@ div[role="cell"] p:last-of-type.product-comparison-header-subtitle, } .product-comparison-header div[role="columnheader"] h3 { - margin: 3rem 0.625rem 0.25rem; + margin: 2em 1em 5px; font-size: var(--heading-font-size-s); - min-height: 4rem; + font-weight: var(--font-weight-regular); } -.product-comparison-header div[role="columnheader"] .old-price-container p{ +.product-comparison-header div[role="columnheader"] .old-price-container p { font-size: var(--body-font-size-xxs); line-height: 1.2; color: var(--product-comparison-text-color); @@ -247,8 +278,10 @@ div[role="row"].expandable-row div[role="cell"] p:first-of-type { background-color: var(--first-table-cell-color); padding: 0.875rem 1.75rem 1.0625rem 2.125rem; width: 100%; - font-weight: var(--font-weight-bold); text-align: center; + font-size: var(--body-font-size-s); + font-weight: var(--font-weight-regular); + letter-spacing: .006em; } .product-comparison-table div[role='cell']:not(:first-child) { @@ -277,6 +310,31 @@ div[role="row"].expandable-row div[role="cell"] p:first-of-type { border-right: 1px solid var(--background-color-light-sky-blue); } +@media (max-width: 580px) { + .product-comparison-table.with-fixed-width { + width: 100%; + } + + .product-comparison-price .current-price-container, .product-comparison-header div[role="columnheader"] h3 { + font-size: var(--body-font-size-xs); + } + + .product-comparison-header div[role="columnheader"] h3 { + margin: 10px 0 0; + } + + .product-comparison-header div[role="columnheader"] p { + min-height: 3rem; + } + + .product-comparison-header div[role="columnheader"] p.button-container.red a { + font-size: var(--body-font-size-xxs); + padding: 5px 0; + text-align: center; + width: 100%; + } +} + @media (min-width: 580px) { .product-comparison-table-wrapper { margin: 0 auto; @@ -329,12 +387,13 @@ div[role="row"].expandable-row div[role="cell"] p:first-of-type { .product-comparison-header div[role="columnheader"] h3 { font-size: var(--heading-font-size-m); + min-height: unset !important; } .product-comparison-header-subtitle { - padding: 0 4rem; + padding: 0 1em; } - + .product-comparison-table div[role='cell'] { display: table-cell; @@ -343,6 +402,7 @@ div[role="row"].expandable-row div[role="cell"] p:first-of-type { .product-comparison-table div[role='cell']:first-child { width: 25%; text-align: left; + border-top-left-radius: 8px; } div[role="row"].expandable-row div[role="cell"] p:first-of-type { @@ -353,14 +413,14 @@ div[role="row"].expandable-row div[role="cell"] p:first-of-type { .product-comparison-table div[role='cell'] > div { display: flex; justify-content: center; - + } .collapsed.hidden-rows-wrapper { max-height: 0; transition: max-height .5s ease-in-out; overflow: hidden; - + } .expanded.hidden-rows-wrapper { @@ -467,4 +527,169 @@ div[role="row"].expandable-row div[role="cell"] p:first-of-type { .display-price-below .product-comparison-price { border: none; +} + +.product-comparison-table.two-products { + width: 100%; +} + +.section.product-comparison-table-container .old-price-box span { + color: #7e7e7e; + font-size: var(--body-font-size-m); + font-weight: var(--font-weight-regular); + line-height: 1.2; +} + +.section.product-comparison-table-container .new-price-box { + font-size: var(--heading-font-size-l); + font-weight: var(--font-weight-boldest); +} + +@media (width <= 1202px) { + .product-comparison-table div[role='columnheader']:nth-child(1) > h2 { + font-size: var(--heading-font-size-l); + } + + .section.product-comparison-table-container.migration .old-price-box span { + font-size: 13px; + flex-direction: column; + display: flex !important; + } + + .section.product-comparison-table-container.migration .old-price-box span:first-of-type { + text-align: left; + } + + .section.product-comparison-table-container.migration h3 { + font-size: 21px !important; + margin-top: 1em !important; + } + + .section.product-comparison-table-container.migration .new-price-box .total-text { + font-size: 16px; + } + } + + .section.product-comparison-table-container.migration .product-comparison-price { + border: 0 none!important; +} + +.section.product-comparison-table-container.migration h3 { + font-family: roboto, sans-serif; + font-size: 24px !important; + color: black !important; + font-weight: 500; + line-height: 1.25; +} + +.section.product-comparison-table-container.migration .old-price-box { + display: flex; + justify-content: space-between; + align-items: center; + border-bottom: 1px dashed #dedede; + padding-bottom: 10px; +} + +.section.product-comparison-table-container.migration .old-price-box .savings { + display: block; + background: rgb(44 180 61 / 20%); + border-radius: 8px; + padding: 1px 9px 5px; + text-align: right; + color: #2cb43d; + font-size: 14px; + font-weight: 500; + line-height: 1.5; +} + +.section.product-comparison-table-container.migration .new-price-box { + display: flex; + justify-content: space-between; + align-items: center; + margin: 10px auto 0; + font-size: 24px; + font-weight: 700; + line-height: .9; + color: black; +} + +.section.product-comparison-table-container.migration .new-price-box .total-text { + color: #3c3c3c; + display: inline-block; + font-size: 18px; + line-height: 1.25; + margin-right: auto; + padding: 0; + font-weight: normal; +} + +.section.product-comparison-table-container.migration p.button-container { + margin-bottom: 2em; +} + +.section.product-comparison-table-container.migration .product-comparison-price > p:last-of-type{ + text-align: right; + color: #3c3c3c; + display: block; + font-size: 10px; + font-weight: 400; + line-height: 2; + margin-bottom: 0; +} + +@media (max-width: 992px) { + .section.product-comparison-table-container .old-price-box span { + font-size: var(--body-font-size-xxs); + } +} + +@media (max-width: 768px) { + .product-comparison-header div[role="columnheader"] h3 { + font-size: var(--heading-font-size-xs); + margin: 1em 1em 5px; + } + + .product-comparison-header div[role="columnheader"] p:first-of-type { + font-size: var(--body-font-size-xs); + } + + .section.product-comparison-table-container .new-price-box { + font-size: var(--heading-font-size-s); + } + + .product-comparison-table div[role='cell']:first-child { + font-size: var(--body-font-size-xs); + } +} + +@media (max-width: 500px) { + .product-comparison-header div[role="columnheader"]:not(:first-child) { + width: 33%; + } + + .product-comparison-header div[role="columnheader"] h3 { + font-size: var(--heading-font-size-xxs); + margin: 1em 0 5px; + } + + .product-comparison-price p:last-of-type { + font-size: var(--body-font-size-xxs); + } + + .product-comparison-header div[role="columnheader"] p { + min-height: unset; + } + + div[role="cell"] p.button-container a, .product-comparison-header div[role="columnheader"] p.button-container a { + padding: 4px 26px 6px 18px; + font-size: var(--body-font-size-xs); + } + + .product-comparison-table div[role='cell']:not(:first-child) { + padding: 1em; + } + + .section.product-comparison-table-container .default-content-wrapper p { + font-size: var(--body-font-size-s); + } } \ No newline at end of file diff --git a/solutions/blocks/product-comparison-table/product-comparison-table.js b/_src/blocks/product-comparison-table/product-comparison-table.js similarity index 82% rename from solutions/blocks/product-comparison-table/product-comparison-table.js rename to _src/blocks/product-comparison-table/product-comparison-table.js index 42c9e0a23..b7e334f36 100644 --- a/solutions/blocks/product-comparison-table/product-comparison-table.js +++ b/_src/blocks/product-comparison-table/product-comparison-table.js @@ -1,10 +1,15 @@ -import { createNanoBlock, renderNanoBlocks, fetchProduct } from '../../scripts/utils.js'; +import { createNanoBlock, renderNanoBlocks, matchHeights } from '../../scripts/utils/utils.js'; -const fetchedProducts = []; +createNanoBlock('priceComparison', (code, variant, label, block, productIndex, columnEl) => { + columnEl.setAttribute('data-store-id', code); + columnEl.setAttribute('data-store-option', variant); + columnEl.setAttribute('data-store-department', 'consumer'); + columnEl.setAttribute('data-store-event', 'product-comparison'); + columnEl.setAttribute('data-store-context', ''); -createNanoBlock('price-comparison', (code, variant, label) => { const priceRoot = document.createElement('div'); priceRoot.classList.add('product-comparison-price'); + const oldPriceText = block.closest('.section').dataset.old_price_text ?? 'Old Price'; const oldPriceElement = document.createElement('p'); priceRoot.appendChild(oldPriceElement); oldPriceElement.innerText = '-'; @@ -16,19 +21,23 @@ createNanoBlock('price-comparison', (code, variant, label) => { const priceAppliedOnTime = document.createElement('p'); priceRoot.appendChild(priceAppliedOnTime); - fetchProduct(code, variant) - .then((product) => { - fetchedProducts.push({ code, variant, product }); - // eslint-disable-next-line camelcase - const { price, discount: { discounted_price: discounted }, currency_iso: currency } = product; - oldPriceElement.innerHTML = `Old Price ${price} ${currency}`; - priceElement.innerHTML = `${discounted} ${currency}`; - priceAppliedOnTime.innerHTML = label; - }) - .catch((err) => { - // eslint-disable-next-line no-console - console.error(err); - }); + oldPriceElement.innerHTML = ` +
      + ${oldPriceText} + Savings +
      `; + priceElement.innerHTML = ` +
      + +
      `; + priceAppliedOnTime.innerHTML = label; + + // update buy link + const buyLink = columnEl.querySelector('.button-container a'); + if (buyLink.href.includes('/buy/') || buyLink.href.includes('#buylink')) { + buyLink.href = '#'; + buyLink.setAttribute('data-store-buy-link', ''); + } return priceRoot; }); @@ -151,7 +160,7 @@ function extractTextFromStrongTagToParent(element) { }); } - if (element.tagName === 'STRONG') { + if (element.tagName === 'STRONG' && element.parentElement) { element.parentElement.innerHTML = element.textContent; } } @@ -159,10 +168,8 @@ function extractTextFromStrongTagToParent(element) { function buildTableHeader(block) { const header = block.querySelector('div > div'); header.classList.add('product-comparison-header'); - [...header.children].forEach((headerColumn) => { const buttonSection = headerColumn.querySelector('p.button-container'); - if (buttonSection) { const paragraphBefore = buttonSection.previousElementSibling; paragraphBefore?.classList.add('per-year-statement'); @@ -266,5 +273,14 @@ export default function decorate(block) { } extractTextFromStrongTagToParent(block); - renderNanoBlocks(block); + const headerList = [...block.children[0].children].slice(1); + const lastRowWithPrice = block.querySelector('.product-comparison-last-row-with-prices'); + [...headerList, lastRowWithPrice].forEach((item, idx) => { + if (item) { + renderNanoBlocks(item, undefined, idx, block); + } + }); + + matchHeights(block, 'h3'); + matchHeights(block, '.old-price-container'); } diff --git a/_src/blocks/products-sideview/products-sideview.css b/_src/blocks/products-sideview/products-sideview.css new file mode 100644 index 000000000..a0dc6f67a --- /dev/null +++ b/_src/blocks/products-sideview/products-sideview.css @@ -0,0 +1,321 @@ +:root { + --tab-header-color-blue: #005ed9; + --tab-description-color-light-grey: #3c3c3c; + --tab-emphasis-color: #2cb43d; +} + +.products-sideview .features-wrapper { + background: #eff6ff; + padding: 30px; + border-radius: 0 0 20px 20px; +} + +.products-sideview .features-wrapper > p, +.products-sideview .pricing-wrapper > p { + font-size: 18px; + line-height: 1.5; + letter-spacing: .006em; + font-weight: var(--font-weight-regular); +} + +.products-sideview .pricing-wrapper { + background: #f6f6f6; + border-radius: 20px 20px 0 0; + padding: 30px; +} + +.products-sideview .pricing-wrapper > p:last-child { + text-align: center; +} + +.products-sideview p.button-container > a { + width: 100%; + justify-content: center; +} + +.products-sideview .price { + font-size: 32px; + font-weight: bold; + margin: 20px 0; +} + +.products-sideview .tag-blue { + background: var(--tab-header-color-blue); + color: white; + padding: 0 10px; + border-radius: 10px; + margin-left: 5px; + font-size: 14px; + line-height: 1; + font-weight: bolder; +} + +.products-sideview-radio { + display: flex; + align-items: center; + margin-left: -2px; + margin-top: 20px; + margin-bottom: 20px; +} + +.products-sideview-radio input { + width: 25px; + height: 25px; + margin: 0; +} + +.products-sideview-radio label { + margin-left: 5px; +} + +.products-sideview-radio input:nth-last-child(2) { + margin-left: 20px; +} + +.products-sideview-selector { + position: relative; +} + +.products-sideview-selector select { /* Remove default styling */ + appearance: none; + width: 100%; + border: 1px solid #ccc; + background-color: white; + padding: 10px; + font-size: 18px; + font-weight: bold; + border-radius: 5px; +} + +.products-sideview-selector::after { + content: ''; + background: url("/_src/icons/tabs_arrow.svg") no-repeat; + position: absolute; + top: 50%; + right: 10px; + transform: rotate(180deg) translateY(50%); + pointer-events: none; /* Prevent the arrow from blocking clicks */ + width: 15px; + height: 15px; +} + +.products-sideview li { + padding: 0; + margin: 0 0 10px; +} + + +.products-sideview .benefits-list > li { + position: relative; + padding-left: 25px; + margin: 0 0 5px; +} + +.products-sideview .benefits-list > li::before { + content: url("/_src/icons/checkmark-green-circle.svg"); + position: absolute; + left: 0; + top: 4px; + width: 18px; + height: 18px; +} + +.products-sideview-wrapper { + padding: 0 var(--body-padding); +} + +.products-sideview { + /* box-shadow: 0 3px 8px 0 var(--dark-shadow); */ + + /* border-radius: 8px; */ + + /* padding: 40px 15px 20px; */ +} + +.products-sideview > div { + display: flex; + flex-direction: column; + align-items: stretch; +} + +.products-sideview img { + width: 100%; +} + +.products-sideview > div > div { + position: relative; + order: 1; +} + +.products-sideview > div > div:last-child::after { + display: none; +} + +.products-sideview > div > .features-img-col { + order: 0; +} + +.products-sideview > div > .features-img-col img { + display: block; +} + +.products-sideview p.features-tabs-hidden { + display: none; +} + +.products-sideview ul { + padding: 0; +} + +.products-sideview .features-tabs li > a { + color: var(--tab-header-color-blue); + font-size: var(--body-font-size-xs); + font-weight: var(--font-weight-bold); + position: relative; + display: inline-block; + letter-spacing: .004em; + cursor: pointer; + text-decoration: none; + padding-left: 25px; +} + +.products-sideview .features-tabs li > a::after { + content: ""; + position: absolute; + left: 0; + top: 0; + display: inline-block; + width: 14px; + height: 8px; + margin: 9px 3px; + background: url("/_src/icons/tabs_arrow.svg") no-repeat; + background-size: 100%; + transform: rotate(180deg); + transition: all .3s linear; +} + +.products-sideview .features-tabs li > a.is-open::after { + transform: rotate(0) +} + +.products-sideview .features-tabs .features-tabs-content { + opacity: 0; + height: 0; + overflow: hidden; + margin-left: 25px; + transition: all 0.3s ease-in-out; +} + +.products-sideview .features-tabs .features-tabs-content.expanded { + opacity: 1; + height: auto; + transition: all 0.3s ease-in-out; + display: block; +} + +.products-sideview .features-tabs .features-tabs-content > p { + font-size: var(--body-font-size-xxs); + font-weight: var(--font-weight-regular); + line-height: 1.6; +} + +@media (min-width: 480px) { + .products-sideview .features-tabs li > a { + font-size: 15px; + } +} + +@media (min-width: 768px) { + .products-sideview .features-wrapper { + border-radius: 0 20px 20px 0; + width: 50%; + } + + .products-sideview .pricing-wrapper { + border-radius: 20px 0 0 20px; /* desktop */ + width: 50% + } + + .products-sideview .pricing-wrapper h4 { + font-size: 26px; + line-height: 32.5px; + font-weight: 700; + } + + .products-sideview .features-wrapper h2 { + font-size: 38px; + line-height: 45.6px; + font-weight: 700; + } + + .features-tabs { + display: flex; + flex-wrap: wrap; + column-gap: 30px; + } + + .features-tabs > li { + position: relative; + } + + .products-sideview > div { + flex-flow: wrap; + } + + .products-sideview > div > div { + padding: 0 20px 20px; + } + + .products-sideview-wrapper { + max-width: var(--section-desktop-max-width); + padding: 0 var(--section-desktop-padding); + margin: 0 auto; + } + + .products-sideview > div > div:nth-child(2)::after { + display:none; + } +} + +@media (min-width: 993px) { + .products-sideview.features-3-cols > div > div { + width: calc(33.33% - 30px); + margin: 0 15px; + } + + .products-sideview.features-3-cols > div > div:nth-child(2)::after { + display:block; + } + + .products-sideview.features-2-cols > div > div:nth-child(2)::after { + display:none; + } +} + +@media (min-width: 1200px) { + .products-sideview .pricing-wrapper { + width: 33.33%; + } + + .products-sideview .features-wrapper { + width: 66.66%; + min-height: fit-content; + } + + .products-sideview .features-tabs > li { + width: calc(50% - 30px); + flex-shrink: 0; + margin-bottom: 25px; + } + + .products-sideview .features-tabs .features-tabs-content > p { + font-size: var(--body-font-size-xs); + } +} + +@media (min-width: 1600px) { /* large desktop */ + .products-sideview-wrapper { + max-width: var(--section-large-desktop-max-width); + padding: 0 var(--section-large-desktop-padding); + } +} diff --git a/_src/blocks/products-sideview/products-sideview.js b/_src/blocks/products-sideview/products-sideview.js new file mode 100644 index 000000000..e78fe0cae --- /dev/null +++ b/_src/blocks/products-sideview/products-sideview.js @@ -0,0 +1,267 @@ +import { + createNanoBlock, + getDatasetFromSection, + renderNanoBlocks, +} from '../../scripts/utils/utils.js'; + +const state = { + firstProduct: null, + secondProduct: null, + currentProduct: null, + mode: 'm', // "m" or "y", + membersIndex: 0, + blockDataset: null, +}; + +const MEMBERS_MAP = new Map(); + +function expandItem(content) { + content.style.height = `${content.scrollHeight}px`; + const transitionEndCallback = () => { + content.removeEventListener('transitionend', transitionEndCallback); + content.style.height = 'auto'; + }; + content.addEventListener('transitionend', transitionEndCallback); + content.classList.add('expanded'); +} + +function collapseItem(content) { + content.style.height = `${content.scrollHeight}px`; + requestAnimationFrame(() => { + content.classList.remove('expanded'); + content.style.height = 0; + }); +} + +function eventListener(ul) { + return (event) => { + let target = null; + + // find ancestor a tag + if (event.target.tagName !== 'A') { + target = event.target.closest('a'); + } else { + target = event.target; + } + + // if the clicked node is not open then open it + if (!target.classList.contains('is-open')) { + target.classList.add('is-open'); + + // if the clicked node has children then toggle the expanded class + if (target.parentNode.children.length > 1) { + target.parentNode.querySelectorAll('.features-tabs-content').forEach((content) => { + expandItem(content); + }); + } + + // hid the other tabs + ul.querySelectorAll('li').forEach((collapsedLi) => { + if (collapsedLi !== target.parentNode) { + collapsedLi.children[0].classList.remove('is-open'); + collapsedLi.querySelectorAll('.features-tabs-content').forEach((content) => { + collapseItem(content); + }); + } + }); + } else { + target.classList.remove('is-open'); + // if the clicked node has children then toggle the expanded class + if (target.parentNode.children.length > 1) { + target.parentNode.querySelectorAll('.features-tabs-content').forEach((content) => { + collapseItem(content); + }); + } + } + }; +} + +function extractFeatures(col) { + const ul = document.createElement('ul'); + ul.classList.add('features-tabs'); + + // select all h4 tags as feature titles + col.querySelectorAll('h4').forEach((h4) => { + const li = document.createElement('li'); + ul.appendChild(li); + + const a = document.createElement('a'); + a.setAttribute('href', '#'); + + // register click event on a tag + + a.addEventListener('click', (event) => { + event.preventDefault(); + eventListener(ul)(event); + }); + + h4.childNodes.forEach((node) => { + if (node.nodeType === Node.TEXT_NODE) { + a.appendChild(document.createTextNode(node.textContent)); + } else { + a.appendChild(node); + } + }); + + a.classList.add('features-tabs-title'); + + li.appendChild(a); + + // all descendants of a that have class tag + a.querySelectorAll('.tag').forEach((tag) => { + li.appendChild(tag); + }); + + const content = document.createElement('div'); + content.classList.add('features-tabs-content'); + li.appendChild(content); + + // every oaragraph until next h4 + let nextElement = h4.nextElementSibling; + while (nextElement && nextElement.tagName !== 'H4') { + content.appendChild(nextElement); + nextElement = h4.nextElementSibling; + } + + ul.appendChild(li); + + h4.remove(); + }); + + return ul; +} + +function updateBuyLink(block) { + const buyLink = block.querySelector('.button-container > .button'); + if (buyLink) { + buyLink.href = '#'; + buyLink.setAttribute('data-store-buy-link', ''); + } +} + +function renderPrice(block, _firstProduct, secondProduct) { + const variant = '5-1'; + const el = document.createElement('DIV'); + el.classList.add('price'); + el.classList.add('await-loader'); + block.setAttribute('data-store-context', ''); + block.setAttribute('data-store-id', secondProduct); + block.setAttribute('data-store-option', variant); + block.setAttribute('data-store-department', 'consumer'); + block.setAttribute('data-store-event', 'main-product-loaded'); + el.setAttribute('data-store-price', 'discounted||full'); + updateBuyLink(block); + return el; +} + +function renderRadioGroup(block) { + const metadata = block.parentElement.parentElement.dataset; + const [firstProduct, secondProduct] = metadata.price.split(','); + const el = document.createElement('DIV'); + el.classList.add('products-sideview-radio'); + el.innerHTML = ` + + + + + + `; + return el; +} + +function getBlueTags(block) { + let blueTags = block.querySelectorAll('.tag-blue'); + if (!blueTags.length) { + const benefitsList = block.querySelector('ul'); + benefitsList?.classList.add('benefits-list'); + const benefitsListElements = benefitsList?.querySelectorAll('li'); + benefitsListElements?.forEach((element) => { + const blueTag = document.createElement('span'); + blueTag.classList.add('tag-blue'); + element.insertAdjacentElement('beforeend', blueTag); + }); + blueTags = block.querySelectorAll('.tag-blue'); + } + return blueTags; +} + +function updateBenefits(block, selectEl, metadata) { + const blueTags = getBlueTags(block); + const selectedOption = [...selectEl.options].find((option) => option.hasAttribute('selected')); + const neededIndex = [...selectEl.options].indexOf(selectedOption); + const updatedBenefits = JSON.parse(metadata[neededIndex]); + let counter = 0; + blueTags.forEach((tag) => { + // eslint-disable-next-line no-plusplus + tag.textContent = `x${updatedBenefits[counter++]}`; + }); +} + +function renderSelector(block, ...options) { + const selectorOptions = options + .filter((option) => option && !Number.isNaN(Number(option))) + .map((opt) => Number(opt)); + const defaultSelection = Number(state.blockDataset.defaultselection) || selectorOptions[1]; + const el = document.createElement('div'); + el.classList.add('products-sideview-selector'); + + el.innerHTML = ` + + `; + + const selectEl = el.querySelector('select'); + const metadata = block.parentElement.parentElement.dataset; + selectEl.value = defaultSelection; + + selectEl.addEventListener('change', (e) => { + [...selectEl.options].forEach((option) => option.removeAttribute('selected')); + [...selectEl.options].find((option) => option.value === e.target.value)?.setAttribute('selected', ''); + updateBenefits(block, selectEl, metadata.benefits.split(',,')); + }); + + updateBenefits(block, selectEl, metadata.benefits.split(',,')); + + return el; +} + +createNanoBlock('price', renderPrice); +createNanoBlock('monthlyYearly', renderRadioGroup); +createNanoBlock('selectMembers', renderSelector); + +function initMembersMap() { + const selectMembers = state.blockDataset.selectmembers.trim().split(','); + selectMembers.forEach((member, index) => MEMBERS_MAP.set(index, Number(member))); +} + +export default function decorate(block) { + const blockDataset = getDatasetFromSection(block); + state.blockDataset = blockDataset; + + initMembersMap(); + + block.firstElementChild.classList.add('d-flex'); + block.firstElementChild.firstElementChild.classList.add('pricing-wrapper'); + block.firstElementChild.lastElementChild.classList.add('features-wrapper'); + + renderNanoBlocks(block.firstElementChild, block); + + const cols = [...block.firstElementChild.children]; + block.classList.add(`features-${cols.length}-cols`); + + const col = block.children[0].children[1]; + col.appendChild(extractFeatures(col)); +} diff --git a/solutions/blocks/products/products.css b/_src/blocks/products/products.css similarity index 85% rename from solutions/blocks/products/products.css rename to _src/blocks/products/products.css index edb933227..de624544d 100644 --- a/solutions/blocks/products/products.css +++ b/_src/blocks/products/products.css @@ -37,6 +37,67 @@ flex-grow: 0; } +.v2 .product-card .price { + flex: 1; + justify-content: center; + align-items: flex-end; + display: flex; +} + +.product-card .price:last-of-type { + font-weight: var(--font-weight-bold); + margin-bottom: 0; +} + +.v2 .product-card .price:last-of-type { + flex: 0; +} + +.product-card .price em { + color: black; + font-size: var(--body-font-size-xxs); + display: block; + font-style: normal; + line-height: 1.4em; + font-weight: bold; +} + +.v2 .product-card .price:last-of-type em { + color: #7e7e7e; + font-size: var(--body-font-size-xxxs); + font-weight: var(--font-weight-bold); + line-height: 2.4; +} + +.product-card p { + font-size: var(--body-font-size-s); + color: #3c3c3c; + margin: 0; +} + +.product-card p:nth-of-type(2) { + font-size: var(--body-font-size-xs); +} + +.product-card .price ~ p { + font-size:var(--body-font-size-xxs); + color: #7e7e7e; +} + +.v2 .product-card p:last-of-type { + line-height: 16px; +} + +.product-card hr { + margin: 17px 0; + border-bottom: 1px solid #e5e7eb; + width: 100%; +} + +.v2 .product-card hr { + margin: 12px 0; +} + .product-card .button-container { flex-grow: 0; display: flex; @@ -45,6 +106,10 @@ margin: 25px 0 5px; } +.v2 .product-card .button-container { + margin: 15px 0; +} + .products.compact .product-card, .products.plans .product-card { text-align: center; } @@ -57,27 +122,12 @@ padding-top: var(--highlight-spacing); } -.product-card p { - font-size: var(--body-font-size-s); - color: #3c3c3c; - margin: 0; -} - -.product-card p:nth-of-type(2) { - font-size: var(--body-font-size-xs); -} - .product-card p a { - text-decoration: underline; + text-decoration: none; color: inherit; color: var(--link-color); } -.product-card .price ~ p { - font-size:var(--body-font-size-xxs); - color: #666; -} - .products.plans .product-card p { font-size: var(--body-font-size-xxs); } @@ -121,7 +171,7 @@ } .products.compact .product-card h3, .products.plans .product-card h3 { - font-size: var(--body-font-size-s); + font-size: var(--body-font-size-m); margin: 0; flex: 0; } @@ -166,12 +216,12 @@ } .product-card .featured { - color: white; - background-color: #218728; - border-radius: 15px; - font-size: var(--body-font-size-xxs); - padding: 5px 15px; - font-weight: bold; + color: #2cb43d; + background-color: rgb(44 180 61 / 20%); + border-radius: 8px; + font-size: var(--body-font-size-xs); + font-weight: var(--font-weight-bold); + padding: 2px 8px; display: inline-block; align-self: self-start; margin-bottom: 10px; @@ -179,7 +229,7 @@ :is(.products.compact, .products.plans) .product-card .featured { align-self: center; - margin: 10px 0 15px; + margin: 7px 0; } .products:not(.compact) .product-card img { @@ -195,6 +245,7 @@ margin: 60px 0 25px; top: auto; right: auto; + display: none; } .products.compact .product-card .featured ~ p img { @@ -221,7 +272,7 @@ } .product-card .ul-header-text { - margin: 1.5rem 0; + margin: 1.5rem 0; text-align: left; } @@ -282,14 +333,9 @@ text-decoration: underline; } -.product-card .price:last-of-type { - font-weight: 700; - margin-bottom: 15px; -} - .products.plans .product-card .price .old-price { font-weight: normal; - font-size: var(--body-font-size-l); + font-size: var(--body-font-size-xl); color: #666; } @@ -299,19 +345,9 @@ .products.compact .product-card .price strong, .products.plans .product-card .price strong { font-size: var(--heading-font-size-l); -} - -.product-card .price em { - font-size: var(--body-font-size-xxs); - display: block; - font-style: normal; - line-height: 1.4em; -} - -.product-card hr { - margin: 10px; - border-bottom: 1px solid #e5e7eb; - width: 100%; + font-weight: var(--font-weight-bolder); + display: flex; + justify-content: center; } .two-columns .columns .product-card hr { @@ -352,7 +388,7 @@ .product-card a.button::after { top: calc(50% - 10px); } - + } .product-card .button-text { @@ -363,7 +399,7 @@ .product-card ul.variant-selector { list-style: none; padding: 0; - margin: 4px 0 10px; + margin: 15px 0; } .product-card ul.variant-selector > li { @@ -465,11 +501,10 @@ height: 250px; top: -42px; right: -60px; - border: 20px white solid; + border: 20px white solid; } } - @media (min-width: 1600px) { /* large desktop */ .products-wrapper { max-width: var(--section-large-desktop-max-width); @@ -478,17 +513,20 @@ .product-card .highlight { width: 100%; + height: 40px; position: absolute; top: 0; left: 0; - background-color: #218728; + background-color: #2cb43d; border-top-left-radius: 8px; border-top-right-radius: 8px; - padding: 4px 0 8px; - font-size: 18px; - font-weight: 700; + font-weight: var(--font-weight-bolder); color: #fff; letter-spacing: .96px; + display: flex; + justify-content: center; + align-items: center; + font-size: 12px; } .product-card .discount { @@ -537,7 +575,7 @@ } .products.compare .product-card .featured { - font-size: var(--body-font-size-s); + font-size: var(--body-font-size-s); margin: 0 auto 32px; } @@ -684,4 +722,54 @@ font-size: 20px; } +} + +@media (min-width: 310px) and (max-width: 768px) { + .product-card { + width: 310px; + margin: 1em auto; + } +} + +@media (max-width: 500px) { + .products.compact .product-card, .products.plans .product-card { + width: 100%!important; + max-width: unset!important; + } +} + +@media (max-width: 768px) { + .products.plans { + flex-direction: column; + } + + .products.plans .product-card .price .old-price.no-old-price { + display: none; + } + + .product-card .featured.no-save-price { + display: none; + } + + .products.plans .product-card { + margin: 0 auto; + max-width: unset; + width: 310px; + } +} + +@media (max-width: 992px) { + .products.compact, .products.plans { + --max-columns: 2; + + display: flex; + flex-wrap: wrap; + text-align: center; + justify-content: center; + } + + .products.compact .product-card, .products.plans .product-card { + max-width: unset; + width: 310px; + } } \ No newline at end of file diff --git a/_src/blocks/products/products.js b/_src/blocks/products/products.js new file mode 100644 index 000000000..56e6361b9 --- /dev/null +++ b/_src/blocks/products/products.js @@ -0,0 +1,423 @@ +import { + createNanoBlock, + renderNanoBlocks, + createTag, + matchHeights, + checkIfConsumerPage, +} from '../../scripts/utils/utils.js'; + +// all avaiable text variables +const TEXT_VARIABLES_MAPPING = [ + { + variable: 'percent', + storeVariable: '{DISCOUNT_PERCENTAGE}', + }, +]; + +/** + * Nanoblock representing the plan selectors. + * If only one plan is declared, the plan selector will not be visible. + * @param plans The list of plans to display [ labelToDisplay, productCode, variantId, ... ] + * @param defaultSelection The default selection. + * @returns Root node of the nanoblock + */ +function renderPlanSelector(plans, defaultSelection) { + // TODO: Remove unecessary div + const root = document.createElement('div'); + const ul = document.createElement('ul'); + ul.classList.add('variant-selector'); + root.appendChild(ul); + + if (plans.length === 3) { + ul.style.display = 'none'; + } + + for (let idx = 0; idx < plans.length - 2; idx += 3) { + const label = plans[idx]; + const liStoreParameters = {}; + + if (Number(defaultSelection)) { + liStoreParameters['data-store-click-set-devices'] = label; + } else { + const productCode = plans[idx + 1]; + liStoreParameters['data-store-click-set-product'] = ''; + liStoreParameters['data-store-product-id'] = productCode; + liStoreParameters['data-store-department'] = 'consumer'; + liStoreParameters['data-product-type'] = productCode.slice(-1) === 'm' ? 'monthly' : 'yearly'; + } + + const li = createTag( + 'li', + liStoreParameters, + `${label}`, + ); + + // set the + if (defaultSelection === label) { + li.classList.add('active'); + } + + li.addEventListener('click', () => { + root.querySelectorAll('.active').forEach((option) => option.classList.remove('active')); + li.classList.add('active'); + }); + + ul.appendChild(li); + } + + return root; +} + +/** + * Nanoblock representing the old product price + * @param text The text located before the price + * @param monthly Show the monthly price if equal to 'monthly' + * @returns Root node of the nanoblock + */ +function renderOldPrice(text = '', monthly = '') { + // TODO: simplify CSS + const oldPrice = document.createElement('del'); + if (monthly.toLowerCase() === 'monthly') { + oldPrice.setAttribute('data-store-price', 'full-monthly'); + } else { + oldPrice.setAttribute('data-store-price', 'full'); + } + + const root = createTag( + 'div', + { + 'data-store-hide': 'no-price=discounted;type=visibility', + class: 'price await-loader', + }, + `${text} ${oldPrice.outerHTML}`, + ); + + // insert text to mark monthly price + if (monthly.toLowerCase() === 'monthly') { + root.querySelector('.old-price').insertAdjacentHTML('beforeend', '/mo'); + } + + return root; +} + +/** + * Nanoblock representing the new product price + * @param text The text located before the price + * @param monthly Show the monthly price if equal to 'monthly' + * @returns Root node of the nanoblock + */ +function renderPrice(text = '', monthly = '', monthTranslation = 'mo') { + // TODO simplify CSS + const newPrice = document.createElement('strong'); + if (monthly.toLowerCase() === 'monthly') { + newPrice.setAttribute('data-store-price', 'discounted-monthly||full-monthly'); + } else { + newPrice.setAttribute('data-store-price', 'discounted||full'); + } + + const root = createTag( + 'div', + { + class: 'price await-loader', + }, + `${text} ${newPrice.outerHTML}`, + ); + + // insert text to mark monthly price + if (monthly.toLowerCase() === 'monthly') { + root.querySelector('.new-price').insertAdjacentHTML('beforeend', `/${monthTranslation}`); + } + + return root; +} + +/** + * Renders the green section on top of the product card highlighting the potential savings + * @param text Text to display + * @param percent Show the saving in percentage if equals to `percent` + * @returns Root node of the nanoblock + */ +function renderHighlightSavings(text = 'Save', percent = '') { + const highlighSaving = document.createElement('span'); + highlighSaving.setAttribute('data-store-text-variable', ''); + highlighSaving.textContent = `${text} ${ + percent.toLowerCase() === 'percent' ? '{DISCOUNT_PERCENTAGE}' : '{DISCOUNT_VALUE}' + }`; + + const root = createTag( + 'div', + { + 'data-store-hide': 'no-price=discounted;type=visibility', + class: 'highlight', + style: 'display=none', + }, + `${highlighSaving.outerHTML}`, + ); + + return root; +} + +/** + * Nanoblock representing a text to highlight in the product card + * @param text Text to display + * @returns Root node of the nanoblock + */ +function renderHighlight(text) { + return createTag( + 'div', + { + class: 'highlight', + style: 'visibility:hidden', + }, + `${text}`, + ); +} + +/** + * + * @param {string} text Text of the featured nanoblock + * @return {string} Text with variables replaced + */ +const replaceVariablesInText = (text) => { + let replacedText = text; + + // replace the percent variable with correct percentage of the produc + TEXT_VARIABLES_MAPPING.forEach((textVariableMapping) => { + replacedText = replacedText.replaceAll( + textVariableMapping.variable, + textVariableMapping.storeVariable, + ); + }); + + return replacedText; +}; + +/** + * + * @param {string} text + * @return {boolean} wether the text contains variables or not + */ +const checkIfTextContainsVariables = (text) => TEXT_VARIABLES_MAPPING.some( + (textVariableMapping) => text.includes(textVariableMapping.variable), +); + +/** + * Nanoblock representing a text to Featured + * @param text Text of the featured nanoblock + * @returns Root node of the nanoblock + */ +function renderFeatured(text) { + const root = document.createElement('div'); + root.classList.add('featured'); + root.textContent = text; + + if (checkIfTextContainsVariables(text)) { + root.classList.add('await-loader'); + root.textContent = replaceVariablesInText(root.textContent); + } + + return root; +} + +/** + * Nanoblock representing a text to Featured and the corresponding savings + * @param text Text of the featured nanoblock + * @param percent Show the saving in percentage if equals to `percent` + * @returns Root node of the nanoblock + */ +function renderFeaturedSavings(text = 'Save', percent = '') { + const featuredSaving = document.createElement('span'); + featuredSaving.setAttribute('data-store-text-variable', ''); + featuredSaving.textContent = `${text} ${ + percent.toLowerCase() === 'percent' ? '{DISCOUNT_PERCENTAGE}' : '{DISCOUNT_VALUE}' + }`; + + const root = createTag( + 'div', + { + 'data-store-hide': 'no-price=discounted;type=visibility', + class: 'featured', + }, + `${featuredSaving.outerHTML}`, + ); + root.classList.add('await-loader'); + + return root; +} + +/** + * Nanoblock representing the lowest product price + * @returns root node of the nanoblock + */ +function renderLowestPrice(...params) { + const fileteredParams = params.filter((paramValue) => paramValue && (typeof paramValue !== 'object')).slice(-2); + const text = fileteredParams.length > 1 ? fileteredParams[1] : fileteredParams[0]; + const monthly = fileteredParams.length > 1 ? fileteredParams[0] : ''; + + const root = document.createElement('p'); + const textArea = document.createElement('span'); + root.classList.add('await-loader'); + textArea.setAttribute('data-store-text-variable', ''); + textArea.textContent = text.replace('0', monthly.toLowerCase() === 'monthly' ? '{SMALLEST_PRICE_PER_MONTH}' : '{SMALLEST_PRICE}'); + root.appendChild(textArea); + return root; +} + +/** + * Nanoblock representing the price conditions below the Price + * @param text Conditions + * @returns Root node of the nanoblock + */ +function renderPriceCondition(text) { + return createTag( + 'div', + { + class: 'price', + }, + `${text}`, + ); +} + +// declare nanoblocks +createNanoBlock('plans', renderPlanSelector); +createNanoBlock('price', renderPrice); +createNanoBlock('oldPrice', renderOldPrice); +createNanoBlock('priceCondition', renderPriceCondition); +createNanoBlock('featured', renderFeatured); +createNanoBlock('featuredSavings', renderFeaturedSavings); +createNanoBlock('highlightSavings', renderHighlightSavings); +createNanoBlock('highlight', renderHighlight); +createNanoBlock('lowestPrice', renderLowestPrice); + +/** + * Main decorate function + */ +export default function decorate(block) { + const metadata = block.closest('.section').dataset; + const plans = []; + + Object.entries(metadata).forEach(([key, value]) => { + if (key.includes('plans')) { + const allImportantData = value.match(/[^,{}[\]]+/gu).map((importantData) => importantData.trim()); + + plans.push({ + productCode: allImportantData[1], + defaultVariant: `${Number(allImportantData.slice(-1)[0]) + ? allImportantData.slice(-1)[0] : allImportantData[2].match(/[0-9-]+/g)[0] + }${allImportantData[2].match(/[0-9-]+/g)[1]}`, + }); + } + }); + + block.parentElement.parentElement.setAttribute('data-store-context', ''); + [...block.children].forEach((row, idxParent) => { + [...(row.children)].forEach((col, idxCol) => { + const plansIndex = idxParent * row.children.length + idxCol; + + // set the store event on the component + let storeEvent = 'main-product-loaded'; + if (checkIfConsumerPage()) { + storeEvent = 'product-loaded'; + } + + col.classList.add('product-card'); + col.setAttribute('data-store-context', ''); + if (plans[plansIndex]) { + col.setAttribute('data-store-id', plans[plansIndex].productCode); + col.setAttribute('data-store-option', plans[plansIndex].defaultVariant); + } + col.setAttribute('data-store-department', 'consumer'); + col.setAttribute('data-store-event', storeEvent); + col.querySelector('.button-container a')?.setAttribute('data-store-buy-link', ''); + + block.appendChild(col); + renderNanoBlocks(col, undefined, idxParent); + }); + row.remove(); + }); + + // render nanoblocks in section's content default wrapper + const defaultContent = block.parentNode.parentNode.querySelector('.default-content-wrapper'); + if (defaultContent) { + renderNanoBlocks(defaultContent); + } + + // style the product card if the author has added a featured card inside + [...block.querySelectorAll('.product-card .featured')].forEach((featured) => { + featured.closest('.product-card').classList.add('featured'); + }); + + // add class to avoid using :has selector + block.querySelectorAll('.product-card li').forEach((li) => { + if (li.querySelector('del')) { + li.classList.add('with-del'); + } else { + li.classList.remove('with-del'); + } + }); + + block.querySelectorAll('.product-card ul').forEach((ul) => { + if (ul.previousElementSibling?.tagName === 'P') { + ul.previousElementSibling.classList.add('ul-header-text'); + } + }); + + block.querySelectorAll('.product-card ul li u').forEach((li) => { + li.parentNode.classList.add('icon-important'); + }); + + const paragraphs = block.querySelectorAll('.product-card.featured p'); + + // Iterate through each paragraph + paragraphs.forEach((paragraph) => { + // Check if the paragraph only contains span elements + const containsOnlySpans = Array.from(paragraph.childNodes).every((node) => node.nodeName === 'SPAN'); + + // If the paragraph only contains span elements, add a class + if (containsOnlySpans) { + paragraph.classList.add('os-availability'); + + if (paragraph.nextElementSibling.nodeName === 'P') { + paragraph.nextElementSibling.classList.add('os-availability-text'); + } + } + }); + + // Height matching logic + const cards = block.querySelectorAll('.product-card'); + const featuredCard = block.querySelector('.product-card.featured'); + cards.forEach((card) => { + const priceElements = card.querySelectorAll('.price.nanoblock'); + if (priceElements.length >= 2) { + const secondToLastPrice = priceElements[priceElements.length - 2]; + const previousElement = secondToLastPrice.previousElementSibling; + if (previousElement && previousElement.tagName.toLowerCase() === 'p') { + previousElement.classList.add('first-year-price-text'); + } else { + const newP = document.createElement('p'); + newP.classList.add('first-year-price-text'); + secondToLastPrice.before(newP); + } + } + if (!card.classList.contains('featured')) { + // If there is no featured card, do nothing + if (!featuredCard) { + return; + } + let space = card.querySelector('h3'); + space = space.nextElementSibling; + const emptyDiv = document.createElement('div'); + space.insertAdjacentElement('afterend', emptyDiv); + emptyDiv.classList.add('featured', 'nanoblock'); + emptyDiv.style.visibility = 'hidden'; + } + }); + matchHeights(block, '.first-year-price-text'); + matchHeights(block, '.price.nanoblock:not(:last-of-type)'); + matchHeights(block, 'h3:nth-of-type(2)'); + matchHeights(block, 'p:nth-of-type(2)'); + matchHeights(block, 'p:nth-of-type(3)'); + matchHeights(block, 'h4'); + matchHeights(block, 'ul:not(.variant-selector)'); + matchHeights(block, '.featured.nanoblock'); +} diff --git a/_src/blocks/questions-answers/questions-answers.css b/_src/blocks/questions-answers/questions-answers.css new file mode 100644 index 000000000..ff528f049 --- /dev/null +++ b/_src/blocks/questions-answers/questions-answers.css @@ -0,0 +1,187 @@ +.questions-answers-wrapper { + padding: var(--body-padding); +} + +@media (min-width: 992px) { /* desktop */ + .questions-answers-wrapper { + max-width: var(--section-desktop-max-width); + padding: 0 var(--section-desktop-padding); + margin: 0 auto; + } +} + +.qa-creators.questions-answers-container h3 { + text-align: center; + font: bold 60px/69px "IBM Plex Sans", sans-serif; + margin-bottom: 32px; +} + +.questions-answers-container h4 { + text-align: center; + font: normal normal bold 32px/28px var(--body-font-family); + margin-bottom: 32px; +} + +.qa-creators.questions-answers-container h4 { + text-align: center; + font: bold 24px/26px "IBM Plex Sans", sans-serif; + margin-bottom: 32px; +} + +.questions-answers-container .default-content-wrapper p { + font: italic normal normal 14px/16px var(--body-font-family); +} + +.questions-answers .questions-answers-item { + margin: 16px 0; + padding: 16px 16px 16px 40px; + background-color: #F4F8FF; + border-radius: 10px; + border-color: rgb(229 231 235); + border-width: 0; + display: flex; + flex-direction: column; + cursor: pointer; +} + +.questions-answers .questions-answers-item.expanded { + box-shadow: 0 3px 8px 0 rgb(0 0 0 / 10%); +} + +.questions-answers-item .question { + position: relative; + font: normal normal bold 18px/21px var(--body-font-family); + color: #000; + display: flex; + justify-content: space-between; + align-items: center; + padding-right: 25px; +} + +.qa-creators .questions-answers-item .question h4 { + position: relative; + font: normal normal bold 18px/21px var(--body-font-family); + color: #000; + display: flex; + justify-content: space-between; + align-items: center; + padding: 0; + margin: 0; + text-align: left; +} + +.questions-answers-item .question::before { + position: absolute; + font: normal normal normal 24px/11px var(--body-font-family); + content: url("/_src/icons/plus-sharp-regular.svg"); + width: 14px; + height: 16px; + display: block; + left: -24px; + bottom:0; + top:3px; + margin-right: 10px; + filter: invert(25%) sepia(100%) saturate(10000%) hue-rotate(200deg) brightness(100%) contrast(100%); +} + +.questions-answers-item.expanded .question { + color: #006EFF; +} + +.questions-answers-item.expanded .question::before { + font: normal normal normal 24px/11px var(--body-font-family); + top: 3px; + content: url("/_src/icons/minus-sharp-regular.svg"); + width: 14px; + height: 16px; + display: inline-block; + filter: invert(25%) sepia(100%) saturate(10000%) hue-rotate(200deg) brightness(100%) contrast(100%); +} + +.questions-answers-item .answer { + opacity: 0; + height: 0; + overflow: hidden; + transition: all 0.3s ease-in-out; +} + +.questions-answers-item .answer p { + font: normal normal normal 14px/16px var(--body-font-family); +} + +.questions-answers-item .answer p a { + color: #006EFF; +} + +.qa-creators.questions-answers-container .default-content-wrapper p { + font: bold 24px / 26px "IBM Plex Sans", sans-serif; + margin-bottom: 32px; + text-align: center; +} + +.questions-answers-item.expanded .answer { + opacity: 1; + height: auto; + transition: all 0.3s ease-in-out; +} + +.questions-answers-item.questions-answers-item-open .answer { + display: block; +} + +.questions-answers-container.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + margin: 0 auto; +} + +@media (max-width: 991px) { + .questions-answers-container h4 { + font: normal normal bold 29px / 28px var(--body-font-family); + margin: 0; + } + + .qa-creators.questions-answers-container h3 { + font-size: var(--heading-font-size-l); + line-height: 1.2; + font-family: "IBM Plex Sans", sans-serif; + font-weight: 300; + } + + .qa-creators.questions-answers-container h4 { + margin-bottom: 0; + font-weight: 300; + font-family: "IBM Plex Sans", sans-serif; + } +} + +@media (min-width: 992px) { /* desktop */ + .questions-answers-container.we-container { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } + + .default-content-wrapper { + max-width: var(--section-desktop-max-width); + padding: 23px var(--section-desktop-padding); + border-radius: 0; + } +} + +@media (min-width: 1200px) { + .questions-answers-container.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + } +} + +@media (min-width: 1600px) { + .questions-answers-container.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + } +} diff --git a/_src/blocks/questions-answers/questions-answers.js b/_src/blocks/questions-answers/questions-answers.js new file mode 100644 index 000000000..b930ed02a --- /dev/null +++ b/_src/blocks/questions-answers/questions-answers.js @@ -0,0 +1,71 @@ +function expandItem(item) { + const [, content] = item.children; + content.style.height = `${content.scrollHeight}px`; + const transitionEndCallback = () => { + content.removeEventListener('transitionend', transitionEndCallback); + content.style.height = 'auto'; + }; + content.addEventListener('transitionend', transitionEndCallback); + item.classList.add('expanded'); +} + +function collapseItem(item) { + const [, content] = item.children; + content.style.height = `${content.scrollHeight}px`; + requestAnimationFrame(() => { + item.classList.remove('expanded'); + content.style.height = 0; + }); +} + +function handleAccordionItemClick(item, items) { + if (!item.classList.contains('expanded')) { + items.filter((i) => i.classList.contains('expanded')).forEach((i) => collapseItem(i)); + expandItem(item); + } else { + collapseItem(item); + } +} + +export default function decorate(block, options) { + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + const blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + } + const items = Array.from(block.querySelectorAll(':scope > div')); + items.forEach((item) => { + item.classList.add('questions-answers-item'); + const [header, content] = item.children; + header.classList.add('question'); + + if (content) { + content.classList.add('answer'); + // check if .accordion-item-content has a

      + const p = content.querySelector('p'); + // if it doesn't, add a

      and move the content inside + if (!p) { + const newP = document.createElement('p'); + newP.innerHTML = content.innerHTML; + content.innerHTML = ''; + content.appendChild(newP); + } + } + + if ([...block.classList].includes('action-only-on-header')) { + header.addEventListener('click', handleAccordionItemClick.bind(null, header.parentElement, items)); + } else { + item.addEventListener('click', handleAccordionItemClick.bind(null, item, items)); + } + }); + + if (block.classList.contains('first-open')) { + items[0].classList.add('expanded'); + } + + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); +} diff --git a/_src/blocks/quiz-hero/quiz-hero.css b/_src/blocks/quiz-hero/quiz-hero.css new file mode 100644 index 000000000..acb18cbd4 --- /dev/null +++ b/_src/blocks/quiz-hero/quiz-hero.css @@ -0,0 +1,118 @@ +.quiz-hero-container.section { + padding: 0; +} + +.quiz-hero-container .quiz-hero-wrapper .block { + display: flex; + flex-direction: column; +} + +.quiz-hero-container h1 { + font: normal normal normal 32px/40px "IBM Plex Sans", sans-serif; +} + +.quiz-hero-container h2, +.quiz-hero-container h3, +.quiz-hero-container h4 { + font: normal normal normal 20px/23px Arial, sans-serif; +} + +.quiz-hero-container p, +.quiz-hero-container div { + font: normal normal normal 14px/18px Arial, sans-serif; +} + +.quiz-hero-container .rte-wrapper { + position: relative; + z-index: 4; + background-color: #006EFF; +} + +.quiz-hero-container .img-container { + width: 100%; + min-height: 250px; + height: 60vw; + position: relative; +} + +.quiz-hero-container .default-content-wrapper { + padding-top: 20px !important; + z-index: 4; + background-color: #006EFF; + color: white; +} + +.quiz-hero-container a.button:any-link { + border: solid white 2px !important; + background-color: white; + color: #006EFF; + margin-top: 15px; +} + +@media (min-width: 768px) { + .quiz-hero-container .img-container { + height: 470px; + } +} + +@media (min-width: 992px) { + .quiz-hero-container.section { + margin-top: 40px; + } + + .quiz-hero-container h1 { + font: normal normal normal 60px/66px "IBM Plex Sans", sans-serif; + } + + .quiz-hero-container h2, + .quiz-hero-container h3, + .quiz-hero-container h4 { + font: normal normal normal 32px/37px Arial, sans-serif; + } + + .quiz-hero-container p, + .quiz-hero-container div { + font: normal normal normal 18px/25px Arial, sans-serif; + } + + .quiz-hero-container { + height: 670px; + } + + .quiz-hero-container .quiz-hero-wrapper { + height: 100%; + } + + .quiz-hero-container .quiz-hero-wrapper .block { + height: 100%; + display: flex; + flex-direction: row; + } + + .quiz-hero-container .rte-wrapper { + width: 100%; + } + + .quiz-hero-container .img-container { + width: 100%; + height: 100%; + } + + .quiz-hero-container .default-content-wrapper { + padding-top: 0 !important; + order: unset; + position: absolute; + left: 0; + right: 0; + height: 100%; + display: flex; + align-items: center; + background-color: unset; + } + + .quiz-hero-container .default-content-wrapper > div { + width: 50%; + padding-right: 30px; + } +} + diff --git a/_src/blocks/quiz-hero/quiz-hero.js b/_src/blocks/quiz-hero/quiz-hero.js new file mode 100644 index 000000000..b1a6a50ae --- /dev/null +++ b/_src/blocks/quiz-hero/quiz-hero.js @@ -0,0 +1,15 @@ +import { adobeMcAppendVisitorId } from '../../scripts/utils/utils.js'; + +export default async function decorate(block) { + const [rte, pictureEl] = [...block.children[0].children]; + + block.innerHTML = ` +

      +
      ${pictureEl.querySelector('picture').innerHTML}
      +
      + ${rte.outerHTML} +
      + `; + + adobeMcAppendVisitorId('header'); +} diff --git a/_src/blocks/quiz-result/quiz-result.css b/_src/blocks/quiz-result/quiz-result.css new file mode 100644 index 000000000..d6c45a82e --- /dev/null +++ b/_src/blocks/quiz-result/quiz-result.css @@ -0,0 +1,81 @@ +.quiz-result-container { + h3 { + font: normal normal bold 24px/27px Arial, sans-serif; + } + + h2 { + font: normal normal bold 32px/35px rial, sans-serif; + color: #006EFF; + } + + p, div { + font: normal normal normal 16px/18px rial, sans-serif; + } + + .results-wrapper { + position: relative; + box-shadow: 0 4px 13px 4px #0000003b; + border-radius: 20px; + padding: 10px 20px; + display: flex; + flex-direction: column; + align-items: center; + text-align: center; + } + + .social-wrapper { + display: flex; + align-items: center; + font: normal normal bold 16px/18px rial, sans-serif; + color: #006EFF; + margin: 30px 0; + + a { + margin-left: 20px; + } + + .icon { + width: 20px; + height: 20px; + margin: 0; + } + } +} + +@media screen { + .quiz-result-container { + .results-wrapper { + background: url('/_src/images/quiz-results-bg.jpg') no-repeat; + } + } +} + +@media (min-width: 992px) { + .quiz-result-container { + .block > :first-child { + display: flex; + justify-content: center; + } + + h3 { + font: normal normal bold 24px/27px rial, sans-serif; + } + + h2 { + font: normal normal bold 42px/42px rial, sans-serif; + } + + p, div { + font: normal normal normal 18px/21px rial, sans-serif; + } + + .results-wrapper { + min-height: 600px; + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; + padding: 0 15%; + } + } +} diff --git a/_src/blocks/quiz-result/quiz-result.js b/_src/blocks/quiz-result/quiz-result.js new file mode 100644 index 000000000..df69fff77 --- /dev/null +++ b/_src/blocks/quiz-result/quiz-result.js @@ -0,0 +1,33 @@ +import { getDatasetFromSection } from '../../scripts/utils/utils.js'; + +export default async function decorate(block) { + const dataset = getDatasetFromSection(block); + + const { socialTitlePost } = dataset; + + block.classList.add('default-content-wrapper'); + block.children[0].children[0].classList.add('results-wrapper'); + block.children[0].children[0].lastElementChild.classList.add('social-wrapper'); + + const resultPageUrl = window.location.href; + + const socialWrapperEl = block.querySelector('.social-wrapper'); + [...socialWrapperEl.querySelectorAll('a')].forEach((anchor) => { + anchor.target = '_blank'; + anchor.rel = 'noopener noreferrer'; + + if (anchor.href.includes('twitter')) { + const twitterBaseUrl = 'https://twitter.com/intent/post?'; + const twitterText = `text=${encodeURIComponent(socialTitlePost)}`; + const twitterUrl = `&url=${encodeURIComponent(resultPageUrl)}`; + const fullTwitterUrl = twitterBaseUrl + twitterText + twitterUrl; + anchor.href = fullTwitterUrl; + } + if (anchor.href.includes('facebook')) { + const facebookBaseUrl = 'https://www.facebook.com/sharer/sharer.php?'; + const facebookUrl = `u=${encodeURIComponent(resultPageUrl)}`; + const fullFacebookUrl = facebookBaseUrl + facebookUrl; + anchor.href = fullFacebookUrl; + } + }); +} diff --git a/_src/blocks/quiz-stepper/quiz-stepper.css b/_src/blocks/quiz-stepper/quiz-stepper.css new file mode 100644 index 000000000..48b6731b1 --- /dev/null +++ b/_src/blocks/quiz-stepper/quiz-stepper.css @@ -0,0 +1,196 @@ +.quiz-stepper-container { + .block { + overflow: hidden; + padding-bottom: 200px; + } + + .slide-wrapper { + display: flex; + width: 100%; + transition: transform .250s ease-in-out; + padding: 5px 0; + } + + .form-wrapper { + width: 100%; + flex-shrink: 0; + margin-right: 60px; + } + + .step { + box-shadow: 0 3px 6px #00000029; + border-radius: 16px; + padding: 25px 30px calc(235px / 2 + 30px); + position: relative; + width: 100%; + flex-shrink: 0; + + fieldset { + legend { + text-align: left; + font: normal normal bold 18px/22px Arial, sans-serif; + color: #000; + margin-bottom: 20px; + } + + .error-message { + visibility: hidden; + color: red; + font-weight: 500; + } + + &.invalid { + .error-message { + visibility: visible; + } + } + } + + .img-container { + height: 235px; + border-radius: 30px; + overflow: hidden; + position: absolute; + bottom: calc(-235px / 2); + left: 25px; + right: 25px; + } + } + + .step-header { + display: flex; + align-items: center; + margin-bottom: 20px; + } + + .step-index { + padding: 3px 10px; + background: #E4F2FF 0% 0% no-repeat padding-box; + border-radius: 20px; + } + + .step-previous { + font: normal normal normal 12px/14px Arial, sans-serif; + color: #7E7E7E; + margin-left: auto; + position: relative; + display: flex; + align-items: center; + cursor: pointer; + + &::before { + content: ''; + display: block; + width: 20px; + height: 20px; + background: url('/_src/icons/arrow-right.svg') no-repeat; + opacity: 0.5; + transform: rotate(-180deg); + } + } + + .step-radio-wrapper { + display: flex; + align-items: flex-start; + margin-bottom: 13px; + cursor: pointer; + + input[type="radio"] { + display: block; + margin: 0; + padding: 0; + background-color: #fff; + font: inherit; + width: 16px; + height: 16px; + flex-shrink: 0; + } + + label { + font: normal normal normal 16px/18px Arial, sans-serif; + margin-left: 10px; + cursor: pointer; + } + + &.selected { + label { + font-weight: 600; + } + } + } + + .button-container.submit { + display: flex; + justify-content: center; + margin-top: 50px; + + .button { + background-color: #006EFF; + color: white; + border-radius: 5px; + padding: 16px; + width: 100%; + justify-content: center; + + &::after { + background-color: white; + } + } + } +} + +@media (min-width: 768px) { + .quiz-stepper-container { + .step { + height: 630px; + + .img-container { + height: 400px; + bottom: calc(-400px / 2); + } + } + } +} + +@media (min-width: 992px) { + .quiz-stepper-container { + .block { + padding-bottom: 0; + } + + .step { + height: unset; + width: calc(100% - 250px); + padding: 40px 40% 40px 40px; + + .img-container { + width: 500px; + height: 385px; + bottom: unset; + left: unset; + top: calc(50% - 385px / 2); + right: -250px; + } + + fieldset { + legend { + font: normal normal bold 22px/27px Arial, sans-serif; + margin-bottom: 30px; + } + + label { + font: normal normal normal 18px/21px Arial, sans-serif; + } + } + } + + .button-container.submit { + justify-content: flex-start; + margin-top: 30px; + + .button { + width: 60%; + } + } + } +} diff --git a/_src/blocks/quiz-stepper/quiz-stepper.js b/_src/blocks/quiz-stepper/quiz-stepper.js new file mode 100644 index 000000000..14d9a9718 --- /dev/null +++ b/_src/blocks/quiz-stepper/quiz-stepper.js @@ -0,0 +1,146 @@ +import { getDatasetFromSection } from '../../scripts/utils/utils.js'; + +export default async function decorate(block) { + const dataset = getDatasetFromSection(block); + + const { + questionLabel, nextButtonLabel, previousButtonLabel, seeResultsLabel, selectErrorLabel, + } = dataset; + + const state = { + score: 0, + currentStep: 0, + }; + + block.classList.add('default-content-wrapper'); + block.closest('.section').id = 'quiz-form'; + + const steps = [...block.children]; + + function renderStep(step, index) { + const stepTitle = step.children[0].children[0].textContent; + const stepOptions = [...step.children[0].children[1].children]; + const stepImage = step.children[1].children[0]; + const isFirstStep = index === 0; + const isLastStep = index === steps.length - 1; + + const fieldId = `question-${index}`; + + return ` +
      +
      +
      +
      ${questionLabel} ${index + 1}/${steps.length}:
      + ${!isFirstStep ? `${previousButtonLabel}` : ''} +
      + + +
      + ${stepTitle} + + + ${stepOptions.map((option, idx) => { + const value = option.querySelector('u') ? 1 : 0; + const forLabel = `${fieldId}-${idx}`; + + return ` +
      + + +
      + `; + }).join('')} +
      ${selectErrorLabel}
      +
      + +

      + ${!isLastStep ? nextButtonLabel : seeResultsLabel} +

      + +
      + ${stepImage.outerHTML} +
      +
      +
      + `; + } + + function moveToNextStep() { + state.currentStep += 1; + const slideWrapper = block.querySelector('.slide-wrapper'); + const offset = 60; + + const transformValue = `translateX(calc(-100% * ${state.currentStep} - (${offset}px * ${state.currentStep})))`; + slideWrapper.style.transform = transformValue; + } + + function moveToPreviousStep() { + state.currentStep -= 1; + const slideWrapper = block.querySelector('.slide-wrapper'); + const offset = 60; + + const transformValue = `translateX(calc(-100% * ${state.currentStep} - (${offset}px * ${state.currentStep})))`; + slideWrapper.style.transform = transformValue; + } + + function renderResults() { + block.style.transform = null; + + // get score + /* eslint-disable-next-line */ + const score = [...block.querySelectorAll('input[type="radio"]:checked')].map((inputEl) => inputEl.value).reduce((sc, value) => sc += Number(value), 0); + + const legendScore = Object.keys(dataset) + .filter((item) => item.includes('result_')) + .map((item) => ({ + template: item.split('result_')[1].split('_').join('-'), + interval: [...dataset[item].split('-')], + })); + + /* eslint-disable max-len */ + const foundLegend = legendScore.find(({ interval: [min, max] }) => Number(min) <= score && score <= Number(max)); + + const { origin, pathname } = window.location; + // redirect + window.location.replace(`${origin}${pathname}${foundLegend.template}`); + } + + function validateForm(e) { + e.preventDefault(); + + const formEl = e.target.closest('form'); + const selectedOption = formEl.querySelector('input[type="radio"]:checked'); + const isLastStep = state.currentStep === steps.length - 1; + + if (!selectedOption) { + formEl.querySelector('fieldset').classList.add('invalid'); + return; + } + + if (!isLastStep) { + moveToNextStep(); + return; + } + + renderResults(); + } + + block.innerHTML = ` +
      ${steps.map((step, index) => renderStep(step, index)).join('')}
      + `; + + block.querySelectorAll('form').forEach((form) => { + const radios = form.querySelectorAll('input[type="radio"]'); + + radios.forEach((radio) => { + radio.addEventListener('change', (event) => { + if (event.target.checked) { + form.querySelector('fieldset').classList.remove('invalid'); + } + }); + }); + + form.querySelectorAll('.button-container.submit').forEach((buttonEl) => buttonEl.addEventListener('click', validateForm)); + form.querySelectorAll('.step-previous').forEach((previousEl) => previousEl.addEventListener('click', moveToPreviousStep)); + }); +} diff --git a/solutions/blocks/quote-carousel/quote-carousel.css b/_src/blocks/quote-carousel/quote-carousel.css similarity index 91% rename from solutions/blocks/quote-carousel/quote-carousel.css rename to _src/blocks/quote-carousel/quote-carousel.css index 48f1c39c5..7a51c8b53 100644 --- a/solutions/blocks/quote-carousel/quote-carousel.css +++ b/_src/blocks/quote-carousel/quote-carousel.css @@ -5,7 +5,8 @@ main .quote-carousel { main .quote-carousel .slides-container { border-radius: 8px; - max-width: 630px; + max-width: auto; + width: 100%; margin-bottom: 30px; box-shadow: 0 3px 8px 0 rgb(0 0 0 / 10%); background: var(--background-color); @@ -30,11 +31,12 @@ main .quote-carousel .slides-container { @media (min-width: 992px) { main .quote-carousel { - max-width: 90%; + max-width: 100%; margin: 55px 0 0; } main .quote-carousel .slides-container { + max-width: 590px; margin-bottom: 80px; } } @@ -59,7 +61,7 @@ main .quote-carousel .slides-container { flex-shrink: 0; width: 100%; transition: all 0.3s ease-in-out; - padding: 30px 30px 40px 25px; + padding: 2em 2em 1em; gap: 8px; } @@ -68,6 +70,10 @@ main .quote-carousel .slides-container { gap: 8px; padding-left: 30px; } + + main .quote-carousel .slides-container { + max-width: 630px; + } } .slide .icon { @@ -134,6 +140,10 @@ main .quote-carousel .slides-container { padding-top: 16px; } +.slides-container .slide p:last-of-type { + padding-top: 5px; +} + @media (min-width: 768px) { .slides-container .slide p { line-height: 1.25; @@ -162,7 +172,7 @@ main .quote-carousel .slides-container { align-self: flex-start; display: flex; list-style: none; - gap: 16px; + gap: 8px; } .slides-container .slides-dots li { @@ -202,3 +212,9 @@ main .quote-carousel .slides-container { .slides-container .slides-dots li:hover button { background: #006eff; } + +@media (max-width: 992px) { + main .quote-carousel { + margin-top: 0; + } +} \ No newline at end of file diff --git a/solutions/blocks/quote-carousel/quote-carousel.js b/_src/blocks/quote-carousel/quote-carousel.js similarity index 98% rename from solutions/blocks/quote-carousel/quote-carousel.js rename to _src/blocks/quote-carousel/quote-carousel.js index 350afa44d..e6c758b96 100644 --- a/solutions/blocks/quote-carousel/quote-carousel.js +++ b/_src/blocks/quote-carousel/quote-carousel.js @@ -1,4 +1,4 @@ -import { createTag } from '../../scripts/utils.js'; +import { createTag } from '../../scripts/utils/utils.js'; import { decorateIcons } from '../../scripts/lib-franklin.js'; const SLIDE_PREFIX = 'carousel-slide-'; diff --git a/solutions/blocks/quote/quote.css b/_src/blocks/quote/quote.css similarity index 100% rename from solutions/blocks/quote/quote.css rename to _src/blocks/quote/quote.css diff --git a/solutions/blocks/quote/quote.js b/_src/blocks/quote/quote.js similarity index 96% rename from solutions/blocks/quote/quote.js rename to _src/blocks/quote/quote.js index beba25c50..fd176c411 100644 --- a/solutions/blocks/quote/quote.js +++ b/_src/blocks/quote/quote.js @@ -1,4 +1,4 @@ -import { createTag } from '../../scripts/utils.js'; +import { createTag } from '../../scripts/utils/utils.js'; import { decorateIcons } from '../../scripts/lib-franklin.js'; function createQuote(item) { diff --git a/_src/blocks/round-card/round-card.css b/_src/blocks/round-card/round-card.css new file mode 100644 index 000000000..a5806dfb9 --- /dev/null +++ b/_src/blocks/round-card/round-card.css @@ -0,0 +1,87 @@ +main .section.round-card-container.mt-n60 { + padding-top: 0; + margin-top: -60px; +} + +.round-card-container .inner-wrapper { + display: flex; + background-color: #fff; + border-radius: 8px; + box-shadow: 0 3px 6px 0 rgb(0 0 0 / 8%); + position: relative; + overflow: hidden; + z-index: 2; + width: 100%; + margin: 10px 0; + padding: 40px 23px 2pc; +} + +/* first paragraph */ +.round-card-container .inner-wrapper > div:nth-child(2) > p:nth-child(3) { + margin-top: 40px; +} + +.round-card-container .inner-wrapper > div:last-child { + border-radius: 50%; + position: absolute; + right: -35px; + top: -60px; + width: 225px; + height: 225px; + overflow: hidden; +} + +.round-card-container img { + width: 100%; + height: 100%; + object-fit: cover; + transition: transform .3s ease-in-out,-webkit-transform .3s ease-in-out; + transform: scale(1); +} + +.round-card-container .inner-wrapper > a:first-child { + position: absolute; + top: 0; + left: 0; + z-index: 2; + width: 100%; + height: 100%; + text-indent: -999999px; +} + +.round-card-container .inner-wrapper > div:nth-child(2) > * { + max-width: 150px; +} + +@media(min-width: 767px) { + /* tablet */ + .round-card-container .inner-wrapper > div:nth-child(2) { + max-width: calc(100% - 280px); + } + + .round-card-container .inner-wrapper > div:nth-child(2) > * { + max-width: unset; + } + + .round-card-container .inner-wrapper p { + font-size: 18px; + } + + .round-card-container .inner-wrapper > div:last-child { + width: 285px; + height: 285px; + } + + .round-card-container .inner-wrapper > a:first-child:hover ~ div p.button-container > a::after { + transform: translateX(5px); + opacity: 1; + } + + .round-card-container .inner-wrapper > a:first-child:hover ~ div p.button-container > a span.button-text { + transform: translate(-10px, 0); + } + + .round-card-container .inner-wrapper > a:first-child:hover ~ div img { + transform: scale(1.1); + } +} diff --git a/_src/blocks/round-card/round-card.js b/_src/blocks/round-card/round-card.js new file mode 100644 index 000000000..3a4b35a2e --- /dev/null +++ b/_src/blocks/round-card/round-card.js @@ -0,0 +1,15 @@ +export default function decorate(block) { + const innerWrapper = block.children[0]; + innerWrapper.classList = 'inner-wrapper'; + + const originalAnchorEl = innerWrapper.children[0].lastElementChild.firstElementChild; + const newAnchorEl = originalAnchorEl.cloneNode(); + newAnchorEl.classList = ''; + innerWrapper.prepend(newAnchorEl); + + const defaultWrapper = document.createElement('div'); + defaultWrapper.classList = 'default-content-wrapper'; + + defaultWrapper.append(innerWrapper); + block.prepend(defaultWrapper); +} diff --git a/_src/blocks/spurs-hero/spurs-hero.css b/_src/blocks/spurs-hero/spurs-hero.css new file mode 100644 index 000000000..a0ab1b792 --- /dev/null +++ b/_src/blocks/spurs-hero/spurs-hero.css @@ -0,0 +1,181 @@ +.spurs-hero-container.section { + padding: 0; +} + +.spurs-hero-container .spurs-hero-wrapper .block { + display: flex; + flex-direction: column; +} + +.spurs-hero-container h1 { + font-size: 24px; + font-weight: 600; + line-height: 1.25; +} + +.spurs-hero-container.hero-ferrari h1 { + font-size: 29px; + line-height: 1.2; + font-weight: normal; +} + +.spurs-hero-container.hero-ferrari h2 { + font-size: 18px; + font-weight: normal; +} + +.spurs-hero-container p, +.spurs-hero-container div { + font-size: 16px; + font-weight: 500; + line-height: 1.6; +} + +.spurs-hero-container .rte-wrapper { + position: relative; + z-index: 4; + background-color: #006EFF; +} + +.spurs-hero-container .img-container { + display: none; + width: 100%; + height: 200px; + position: relative; +} + +.hero-ferrari .img-container { + display: block; + width: 100%; + height: 48vw; +} + +.spurs-hero-container .default-content-wrapper { + padding-top: 20px !important; + z-index: 4; + background-color: #006EFF; + color: white; +} + +.spurs-hero-container a.button:any-link { + border: solid white 2px !important; + background-color: white; + color: #006EFF; + margin-top: 15px; +} + +.spurs-hero-container .default-content-wrapper p.button-container a { + border: solid white 2px !important; + background-color: transparent; + color: white; + margin-top: 15px; +} + +.spurs-hero-container .default-content-wrapper p:not(.button-container):nth-last-child(2) { + position: relative; + margin-top: 80px; +} + +.spurs-hero-container .default-content-wrapper p:not(.button-container) img { + width: 90px; + position: absolute; + top: -45px; + left: 5px; +} + +.spurs-hero-container .default-content-wrapper p:not(.button-container) a { + background: white; + padding: 10px 16px 10px 100px; + font-size: 14px; + color: #006DFF; + font-weight: 600; + text-transform: none; + display: inline-block; + text-align: center; + border-radius: 8px; + transition: background-color 0.2s; + width: auto; + border-style: none; + cursor: pointer; +} + +@media (min-width: 992px) { + .spurs-hero-container h1 { + font-size: 40px; + font-weight: 300; + line-height: 1; + } + + .spurs-hero-container.hero-ferrari h1 { + font-size: 48px; + font-weight: 300; + line-height: 57px; + } + + .spurs-hero-container.hero-ferrari h2 { + font-size: 32px; + font-weight: 300; + } + + .spurs-hero-container p, + .spurs-hero-container div { + /* font: normal normal normal 18px/25px Arial; */ + font-size: 28px; + font-weight: 300; + line-height: 1.3; + } + + .spurs-hero-container { + height: 600px; + } + + .spurs-hero-container .spurs-hero-wrapper { + height: 100%; + } + + .spurs-hero-container .spurs-hero-wrapper .block { + height: 100%; + display: flex; + flex-direction: row; + } + + .spurs-hero-container .rte-wrapper { + width: 100%; + } + + .spurs-hero-container .default-content-wrapper { + padding-top: 0 !important; + order: unset; + position: absolute; + left: 0; + right: 0; + height: 100%; + display: flex; + align-items: center; + background-color: unset; + } + + .spurs-hero-container .default-content-wrapper > div { + width: 50%; + padding-top: 65px; + } + + .spurs-hero-container .img-container { + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + background-color: #006EFF; + } + + .spurs-hero-container.hero-ferrari .img-container { + align-items: normal; + justify-content: left; + } + + .spurs-hero-container .img-container picture { + width: 90%; + } +} + diff --git a/_src/blocks/spurs-hero/spurs-hero.js b/_src/blocks/spurs-hero/spurs-hero.js new file mode 100644 index 000000000..cbbde9eee --- /dev/null +++ b/_src/blocks/spurs-hero/spurs-hero.js @@ -0,0 +1,24 @@ +import { adobeMcAppendVisitorId } from '../../scripts/utils/utils.js'; + +export default async function decorate(block) { + const [rte, pictureEl] = [...block.children[0].children]; + + if (window.location.href.indexOf('scuderiaferrari') !== -1) { + block.closest('.section').classList.add('hero-ferrari'); + } + + block.innerHTML = ` +
      +
      ${pictureEl.querySelector('picture').outerHTML}
      +
      + ${rte.outerHTML} +
      + `; + + block.querySelectorAll('.button-container > a').forEach((anchorEl) => { + anchorEl.target = '_blank'; + anchorEl.rel = 'noopener noreferrer'; + }); + + adobeMcAppendVisitorId('header'); +} diff --git a/solutions/blocks/sticky-navigation/sticky-navigation.css b/_src/blocks/sticky-navigation/sticky-navigation.css similarity index 84% rename from solutions/blocks/sticky-navigation/sticky-navigation.css rename to _src/blocks/sticky-navigation/sticky-navigation.css index 8260de001..5aa0abdc2 100644 --- a/solutions/blocks/sticky-navigation/sticky-navigation.css +++ b/_src/blocks/sticky-navigation/sticky-navigation.css @@ -4,6 +4,7 @@ main .section.sticky-navigation-container { padding-top: 0; + padding-bottom: 0; } .sticky-navigation { @@ -25,10 +26,10 @@ main .section.sticky-navigation-container { display: none; flex-direction: column; justify-content: center; - align-items: baseline; + align-items: center; box-shadow: 0 3px 6px 0 rgb(0 0 0 / 8%); padding: 0 var(--body-padding) var(--body-padding) var(--body-padding); - + } .sticky-navigation ul { @@ -39,6 +40,16 @@ main .section.sticky-navigation-container { list-style-type: none; } +.sticky-navigation ul li { + border-bottom: 1px solid var(--sticky-nav-border-color); + padding: 0; + margin: 0; +} + +.sticky-navigation ul li.opened { + border-bottom: 1px solid #006EFF; +} + .sticky-navigation ul li a { display: block; font-weight: var(--font-weight-bold); @@ -50,12 +61,6 @@ main .section.sticky-navigation-container { padding: 22px 0; } -.sticky-navigation ul li { - border-bottom: 1px solid var(--sticky-nav-border-color); - padding: 0; - margin: 0; -} - .sticky-navigation ul li.active::after { width: 100%; } @@ -111,13 +116,18 @@ main .section.sticky-navigation-container { .sticky-navigation .button-container { margin:0; - padding: 40px 0 20px 20px; + padding: 40px 0 20px 20px; } .sticky-navigation .button-container a { - font-size: var(--body-font-size-xxs); + font-size: var(--body-font-size-s); vertical-align: middle; - padding: 6px 15px; + padding: 6px 9px 6px 18px; + text-transform: capitalize; +} + +.sticky-navigation .button-container a .button-text{ + white-space: nowrap; } @media (min-width: 992px) { /* desktop */ @@ -142,7 +152,7 @@ main .section.sticky-navigation-container { .sticky-navigation ul li { border: none; - margin-right: 20px; + margin-right: 40px; } .sticky-navigation ul li a { @@ -157,19 +167,25 @@ main .section.sticky-navigation-container { .sticky-navigation .button-container { vertical-align: middle; - padding: 0; + padding: 0; + } +} + +@media (max-width: 1399px) { /* desktop */ + .sticky-navigation .menu-with-button { + padding: 0 var(--section-large-desktop-padding); } } @media (min-width: 1600px) { /* large desktop */ .sticky-navigation .button-container a { - font-size: var(--body-font-size-xs); - padding: 8px 15px; + font-size: var(--body-font-size-s); + font-weight: var(--font-weight-bold); + padding: 8px 8px 8px 20px; } .sticky-navigation .menu-with-button { max-width: var(--section-large-desktop-max-width); padding: 0 var(--section-large-desktop-padding); } - } \ No newline at end of file diff --git a/solutions/blocks/sticky-navigation/sticky-navigation.js b/_src/blocks/sticky-navigation/sticky-navigation.js similarity index 95% rename from solutions/blocks/sticky-navigation/sticky-navigation.js rename to _src/blocks/sticky-navigation/sticky-navigation.js index 2c8fbf64f..1b9a47428 100644 --- a/solutions/blocks/sticky-navigation/sticky-navigation.js +++ b/_src/blocks/sticky-navigation/sticky-navigation.js @@ -63,7 +63,11 @@ function renderStickyNavigation(block) { menuWithButton.appendChild(stickyNavMenu); /** close the dropdown menu after user selection */ - stickyNavMenu.addEventListener('click', () => { + stickyNavMenu.addEventListener('click', (event) => { + event.target.closest('ul').querySelectorAll('li').forEach((item) => { + item.classList.remove('opened'); + }); + event.target.closest('li').classList.toggle('opened'); mobileDropDown.classList.toggle('opened'); }); diff --git a/_src/blocks/system-requirements/system-requirements.css b/_src/blocks/system-requirements/system-requirements.css new file mode 100644 index 000000000..792e1831f --- /dev/null +++ b/_src/blocks/system-requirements/system-requirements.css @@ -0,0 +1,257 @@ +.system-requirements-container { + --dark-background-color: #000; + --black-color: #000; + --white-color: #fff; + --background-color: #fff; + --link-color: #005ed9; + --link-hover-color: #00439c; + --button-link-color: #fff; + --button-background-color: #eb0000; + --button-hover-background-color: #d80000; + --button-primary-background-color: #000; + --button-primary-hover-background-color: #000; + --button-secondary-color: #000; + --button-secondary-hover-background-color: #000; + --overlay-background-color: #eee; + --highlight-background-color: #ccc; + --text-color: #000; + --text-error-color: #f00; + --color-highlight-blue: #006dff; + --color-dark-gray: #616161; + --checkbox-label: #3c3c3c; + --highlight-light-blue: #f3f7fe; + --text-dark-color: #fff; + --horizontal-separator-color: #dedede; + --modal-background-color: rgb(0 0 0 / 50%); + --background-color-light-sky-blue: #e4f2ff; + --icon-color: #205fff; + --background-light-blue: #d9eeff; + --background-blue: #005ed9; + --dark-blue-tag: #005eff; + --light-blue-tag: #13b0a7; + --green-tag: #218728; + --dark-shadow: #0000001a; + --background-checkmark: #61AF53; + --body-font-family: "Roboto", "roboto-normal-400-fallback", helvetica, ubuntu, roboto, noto, sans-serif; + --heading-font-family: var(--body-font-family); + --fixed-font-family: var(--body-font-family); + --font-weight-thin: 300; + --font-weight-regular: 400; + --font-weight-bold: 500; + --font-weight-bolder: 600; + --font-weight-boldest: 700; + --font-weight-heavy: 900; + --body-font-size-l: 22px; + --body-font-size-m: 18px; + --body-font-size-s: 16px; + --body-font-size-xs: 14px; + --body-font-size-xxs: 12px; + --body-font-size-xxxs: 10px; + --heading-font-size-xxxl: 60px; + --heading-font-size-xxl: 48px; + --heading-font-size-xl: 40px; + --heading-font-size-l: 32px; + --heading-font-size-m: 24px; + --heading-font-size-s: 20px; + --heading-font-size-xs: 18px; + --heading-font-size-xxs: 16px; + --nav-height: 63px; + --nav-height-desktop: 40px; + --body-max-width: 1920px; + --body-padding: 20px; + --section-desktop-max-width: 1290px; + --section-desktop-padding: 20px; + --section-desktop-padding-vertical: 48px; + --section-mobile-padding-vertical: 32px; + --cta-background-light-blue: var(--background-light-blue); + + background-color: #f2f2f2; +} + +.system-requirements-wrapper { + padding: var(--body-padding); +} + +.default-content-wrapper { + width: 100%; + margin: 0 auto; + max-width: var(--body-max-width); + padding: var(--body-padding); + position: relative; +} + +.system-requirements-container h6 { + text-align: left; + font: normal normal bold 16px/18px var(--body-font-family); + margin: 0; +} + + +/* remove padding from userguide wrapper */ +.system-requirements-container :last-child { + padding-bottom: 1px; +} + +.system-requirements-container-userguides { + background-color: #f2f2f2; +} + +.system-requirements-container .default-content-wrapper p { + font: normal normal normal 12px/14px var(--body-font-family); +} + +.system-requirements-container .system-requirements-item { + padding: 8px 16px 8px 24px; + display: flex; + flex-direction: column; + cursor: pointer; +} + +.system-requirements-item .system { + position: relative; + font: normal normal bold 12px/14px var(--body-font-family); + color: #006EFF; + display: flex; + justify-content: space-between; + align-items: center; + padding-right: 25px; +} + +.system-requirements-item .system::before { + position: absolute; + font: normal normal normal 24px/11px var(--body-font-family); + content: url("/_src/icons/plus-sharp-regular.svg"); + width: 14px; + height: 16px; + display: block; + left: -24px; + bottom:0; + top:-1px; + margin-right: 10px; + filter: invert(25%) sepia(100%) saturate(10000%) hue-rotate(200deg) brightness(100%) contrast(100%); +} + +.system-requirements-item.expanded .system { + color: #006EFF; +} + +.system-requirements-item.expanded .system::before { + font: normal normal normal 24px/11px var(--body-font-family); + top: -1px; + content: url("/_src/icons/minus-sharp-regular.svg"); + width: 14px; + height: 16px; + display: inline-block; + filter: invert(25%) sepia(100%) saturate(10000%) hue-rotate(200deg) brightness(100%) contrast(100%); +} + +.system-requirements-item .requirement { + opacity: 0; + height: 0; + overflow: hidden; + transition: all 0.3s ease-in-out; +} + +.system-requirements-item .requirement > ul { + list-style: none; + margin: 0; + padding: 0; + display: grid; + grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); + grid-gap: 24px; +} + +.system-requirements-item .requirement > ul > li { + font: normal normal normal 12px/14px var(--body-font-family); + list-style: none; + display: inline-block; + padding-left: 0; +} + +.system-requirements-item .requirement > ul > li > br { + display: block; + margin-bottom: 14px; + content: " "; +} + +.system-requirements-item .requirement > ul > li > br:first-of-type { + margin: 0; +} + +.system-requirements-item.expanded .requirement { + opacity: 1; + height: auto; + transition: all 0.3s ease-in-out; +} + +.system-requirements-item.system-requirements-open .requirement { + display: block; +} + +.system-requirements-container .default-content-wrapper p a { + font: normal normal normal 12px/14px var(--body-font-family); + padding: 0 30px 0 0; + color: #006EFF; + border: 0; + display: inline-block; + position: relative; +} + +.system-requirements-container .default-content-wrapper p a::before { + content: url("/_src/icons/book-sharp-regular.svg"); + margin-right: 10px; + width: 14px; + height: 16px; + filter: invert(25%) sepia(100%) saturate(10000%) hue-rotate(200deg) brightness(100%) contrast(100%); + display: inline-block; + position: relative; + top: 3px; +} + +.system-requirements-container .default-content-wrapper p a:hover { + color: #006EFF; + text-decoration: underline; +} + +.system-requirements-container.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + margin: 0 auto; +} + +@media (min-width: 992px) { /* desktop */ + .system-requirements-wrapper { + max-width: var(--section-desktop-max-width); + padding: 0 var(--section-desktop-padding); + margin: 0 auto; + } + + .system-requirements-container.we-container { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } + + .default-content-wrapper { + max-width: var(--section-desktop-max-width); + padding: 23px var(--section-desktop-padding); + border-radius: 0; + } +} + +@media (min-width: 1200px) { + .system-requirements-container.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + } +} + +@media (min-width: 1600px) { + .system-requirements-container.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + } +} diff --git a/_src/blocks/system-requirements/system-requirements.js b/_src/blocks/system-requirements/system-requirements.js new file mode 100644 index 000000000..48b7ad480 --- /dev/null +++ b/_src/blocks/system-requirements/system-requirements.js @@ -0,0 +1,72 @@ +function expandItem(item) { + const [, content] = item.children; + content.style.height = `${content.scrollHeight}px`; + const transitionEndCallback = () => { + content.removeEventListener('transitionend', transitionEndCallback); + content.style.height = 'auto'; + }; + content.addEventListener('transitionend', transitionEndCallback); + item.classList.add('expanded'); +} + +function collapseItem(item) { + const [, content] = item.children; + content.style.height = `${content.scrollHeight}px`; + requestAnimationFrame(() => { + item.classList.remove('expanded'); + content.style.height = 0; + }); +} + +function handleAccordionItemClick(item, items) { + if (!item.classList.contains('expanded')) { + items.filter((i) => i.classList.contains('expanded')).forEach((i) => collapseItem(i)); + expandItem(item); + } else { + collapseItem(item); + } +} + +export default function decorate(block, options) { + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + // const blockParent = block.closest('.section'); + // blockParent.classList.add('we-container'); + } + + const items = Array.from(block.querySelectorAll(':scope > div')); + items.forEach((item) => { + item.classList.add('system-requirements-item'); + const [header, content] = item.children; + header.classList.add('system'); + + if (content) { + content.classList.add('requirement'); + // check if .accordion-item-content has a

      + // const p = content.querySelector('ul li p'); + // // if it doesn't, add a

      and move the content inside + // if (!p) { + // const newP = document.createElement('p'); + // newP.innerHTML = content.querySelector('ul li').innerHTML; + // content.querySelector('ul li').innerHTML = ''; + // content.querySelector('ul li').appendChild(newP); + // } + } + + if ([...block.classList].includes('action-only-on-header')) { + header.addEventListener('click', handleAccordionItemClick.bind(null, header.parentElement, items)); + } else { + item.addEventListener('click', handleAccordionItemClick.bind(null, item, items)); + } + }); + + if (block.classList.contains('first-open')) { + items[0].classList.add('expanded'); + } + + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); +} diff --git a/_src/blocks/tabs-component/tabs-component.css b/_src/blocks/tabs-component/tabs-component.css new file mode 100644 index 000000000..1363f7209 --- /dev/null +++ b/_src/blocks/tabs-component/tabs-component.css @@ -0,0 +1,248 @@ +.tabs-component-container .tabs-component { + display: flex; + flex-direction: column; + align-items: center; + margin-top: 48px; +} + +.tabs-component-container.we-container { + max-width: 100%; + padding-left: 20px; + padding-right: 20px; + margin-top: 15px; + margin-left: auto; + margin-right: auto; +} + +.tabs-component-container .icon svg { + width: 12px; + height: 14px; + padding-right: 2px; + fill: #fff; +} + +.tabs-component-container h3 { + font: normal normal bold 24px/28px Arial, sans-serif; +} + +.tabs-component-container p { + font: normal normal normal 16px/24px Arial, sans-serif; +} + +.tabs-component-container span { + font: normal normal bold 16px/18px Arial, sans-serif; +} + +.tabs-component-container .title-class div { + max-width: 630px; + text-align: center; + margin-bottom: 27px; + font: normal normal bold 32px/37px Arial, sans-serif; +} + +.tabs-component-container .subtitle-class div { + max-width: 630px; + text-align: center; + margin-bottom: 67px; + font: normal normal normal 18px/26px Arial, sans-serif; +} + +.tabs-component-container .tabs-container { + display: flex; + justify-content: center; + margin-bottom: 40px; + flex-wrap: wrap; + border-bottom: 1px solid #E4F2FF; +} + +.tabs-component-container .card-container { + display: flex; + flex-direction: column-reverse; + align-items: center; + gap: 3%; +} + +.tabs-component-container .hide { + display: none; +} + +.tabs-component-container .tabs-container button { + background-color: white; + color: black; + border: 0; + font: normal normal bold 18px/21px Arial, sans-serif; + padding: 9px; + display: flex; + gap: 10px; + align-items: center; + position: relative; + cursor: pointer; +} + +.tabs-component-container a { + color: #006dff !important; + background-color: #fff !important; + border: 0 !important; +} + +.tabs-component-container a::after { + opacity: 1; + margin-left: 0; +} + +.tabs-component-container .tabs-container button a { + background-color: white; + border: 0; + font: normal normal bold 18px/21px Arial, sans-serif; + padding: 9px; + margin-bottom: 10px; + display: flex; + gap: 10px; + align-items: center; +} + +/* stylelint-disable-next-line no-descending-specificity */ +.tabs-component-container .card-container a { + overflow: visible; + padding-left: 0 !important; +} + +.tabs-component-container .card-container a .button-text { + transform: unset; +} + +.tabs-component-container .card-container a:hover { + color: #0A53C5; +} + +.tabs-component-container .card-container a::after { + content: '\2192'; + width: 24px; + height: 24px; + display: inline-block; + transition: all .2s cubic-bezier(.4,0,.2,1); + transform: translateX(0); + margin-left: 2px; + margin-bottom:2px; + mask: none !important; +} + +.tabs-component-container .card-container a:hover::after { + transform: translateX(5px); +} + +.tabs-component-container .tabs-container button::after { + background: #006eff; + border-radius: 0; + content: ""; + height: 4px; + position: absolute; + left: 0; + bottom: 0; + width: 0; + z-index: 1; +} + +.tabs-component-container .tabs-container button.selected::after { + transition: all 1s ease; + width: 100%; +} + +.tabs-component-container .left { + width: 80%; +} + +.tabs-component-container .left img { + border-radius: 20px; + width: auto; + max-width: 100%; + height: auto; +} + +.tabs-component-container .right { + width: 80%; + display: flex; + flex-direction: column; + justify-content: center; +} + +.tabs-component-container .right p { + font-size: 16px; +} + +.tabs-component-container .tabs-container button picture img { + width: 50px; + height: auto; +} + +.tabs-component-container button strong { + display: none; +} + +.tabs-component-container .tabs-container picture { + display: flex; + align-items: center; +} + +.tabs-component-container { + align-items: normal !important; +} + +@media (min-width: 768px) { + .tabs-component-container .tabs-container { + flex-wrap: nowrap; + } + + .tabs-component-container .left { + width: 60%; + } + + .tabs-component-container .right { + width: 60%; + } +} + +@media (min-width: 992px) { + .tabs-component-container .card-container { + flex-direction: row; + width: 830px; + } + + .tabs-component-container button strong { + display: block; + } + + .tabs-component-container .tabs-container button picture img { + width: 30px; + } + + .tabs-component-container .left { + width: 50%; + } + + .tabs-component-container .right { + width: 50%; + } + + .tabs-component-container.we-container { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } +} + +@media (min-width: 1200px) { + .tabs-component-container.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + } +} + +@media (min-width: 1600px) { + .tabs-component-container.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + } +} diff --git a/_src/blocks/tabs-component/tabs-component.js b/_src/blocks/tabs-component/tabs-component.js new file mode 100644 index 000000000..b9ebc69f7 --- /dev/null +++ b/_src/blocks/tabs-component/tabs-component.js @@ -0,0 +1,83 @@ +export default function decorate(block, options) { + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + const blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + } + + const parentSelector = block.closest('.section'); + // eslint-disable-next-line no-unused-vars + const metaData = parentSelector.dataset; + const [title, subtitle, tabsTitle, ...sections] = block.children; + + title.classList.add('title-class'); + subtitle.classList.add('subtitle-class'); + // Add class 'tabs-container' to the first div + tabsTitle.classList.add('tabs-container'); + + // Get the container for the buttons + const container = block.querySelector('.tabs-container'); + + // Check if the container exists + if (container) { + const divs = container.querySelectorAll('div'); + + // Loop through each div to create buttons + divs.forEach((div, index) => { + const button = document.createElement('button'); + if (index === 0) button.classList.add('selected'); + button.innerHTML = div.innerHTML; // Use innerHTML instead of textContent + button.addEventListener('click', () => { + // Remove 'selected' class from all buttons + const buttons = block.querySelectorAll('.tabs-container button'); + buttons.forEach((btn) => btn.classList.remove('selected')); + + // Add 'selected' class to the clicked button + button.classList.add('selected'); + + // Hide all card-container elements + const cardContainers = block.querySelectorAll('.card-container'); + cardContainers.forEach((card) => card.classList.add('hide')); + + // Show the corresponding card-container element based on the index + sections[index].classList.remove('hide'); + }); + + div.parentNode.replaceChild(button, div); + }); + } else { + // eslint-disable-next-line no-console + console.error('Container not found'); + } + + // click on the next element every 5 seconds + // setInterval(() => { + // const buttons = block.querySelectorAll('.tabs-container button'); + // const selectedButton = block.querySelector('.tabs-container button.selected'); + // const buttonIndex = Array.from(buttons).indexOf(selectedButton); + // const nextIndex = (buttonIndex + 1) % buttons.length; + // buttons[nextIndex].click(); + // }, 6000); + + // Add classes to each card-container and hide all but the first one + sections.forEach((element, index) => { + element.classList.add('card-container'); + if (index === 0) { + element.classList.add('show'); + } + if (index !== 0) { + element.classList.add('hide'); + } + + // Add classes to children divs + const photoDiv = element.querySelector('div:nth-child(1)'); + const textDiv = element.querySelector('div:nth-child(2)'); + photoDiv.classList.add('left'); + textDiv.classList.add('right'); + }); + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); +} diff --git a/solutions/blocks/tabs/tabs.css b/_src/blocks/tabs/tabs.css similarity index 100% rename from solutions/blocks/tabs/tabs.css rename to _src/blocks/tabs/tabs.css diff --git a/solutions/blocks/tabs/tabs.js b/_src/blocks/tabs/tabs.js similarity index 100% rename from solutions/blocks/tabs/tabs.js rename to _src/blocks/tabs/tabs.js diff --git a/_src/blocks/teaser-logos/teaser-logos.css b/_src/blocks/teaser-logos/teaser-logos.css new file mode 100644 index 000000000..a64d8f203 --- /dev/null +++ b/_src/blocks/teaser-logos/teaser-logos.css @@ -0,0 +1,89 @@ +/* stylelint-disable custom-property-pattern */ +.teaser-logos-container.section { + padding: 0; + background: #EFF6FF; +} + +.teaser-logos-container .main-wrapper { + display: flex; + height: 160px; +} + +.teaser-logos-container .default-content-wrapper { + display: flex; + padding-top: 0 !important; + height: 200px; +} + +.teaser-logos-container .main-wrapper .col, +.teaser-logos-container .default-content-wrapper .col { + display: flex; + justify-content: center; + position: relative; + width: 50%; +} + +.teaser-logos-container .main-wrapper .col { + background: #EFF6FF; +} + +.teaser-logos-container .main-wrapper .col:first-child::before { + content: ''; + display: block; + width: 0; + height: 0; + border-left: 50px solid transparent; + border-right: 50px solid transparent; + border-bottom: 170px solid var(--backgroundColor); + transform: rotate(180deg); + position: absolute; + right: -20px; + top: 0; + z-index: 2; +} + +.teaser-logos-container .main-wrapper .col:last-child::before { + content: ''; + display: block; + width: 0; + height: 0; + border-left: 50px solid transparent; + border-right: 50px solid transparent; + border-bottom: 170px solid var(--backgroundColor); + transform: rotate(0deg); + position: absolute; + left: -37.5px; + top: 0; + z-index: 1; +} + +.teaser-logos-container .default-content-wrapper .col .img-wrapper { + padding-top: 30px; + position: relative; + z-index: 3; + width: 100%; +} + +.teaser-logos-container .default-content-wrapper .col .img-wrapper img { + object-fit: cover; + width: 100%; +} + +@media screen and (min-width: 768px) { + .teaser-logos-container .main-wrapper { + height: 400px; + } + + .teaser-logos-container .main-wrapper .col:first-child::before, + .teaser-logos-container .main-wrapper .col:last-child::before { + border-bottom-width: 400px; + } + + .teaser-logos-container .default-content-wrapper .col .img-wrapper { + width: 50%; + height: 180px; + display: flex; + align-items: center; + } +} + diff --git a/_src/blocks/teaser-logos/teaser-logos.js b/_src/blocks/teaser-logos/teaser-logos.js new file mode 100644 index 000000000..3b78433f3 --- /dev/null +++ b/_src/blocks/teaser-logos/teaser-logos.js @@ -0,0 +1,11 @@ +export default async function decorate(block) { + const boxes = [...block.children[0].children]; + + block.innerHTML = ` +

      + ${boxes.map((box) => ` +
      ${box.innerHTML}
      + `).join('')} +
      + `; +} diff --git a/_src/blocks/terms/terms.css b/_src/blocks/terms/terms.css new file mode 100644 index 000000000..a12b4c276 --- /dev/null +++ b/_src/blocks/terms/terms.css @@ -0,0 +1,145 @@ +.terms-container { + --dark-background-color: #000; + --black-color: #000; + --white-color: #fff; + --background-color: #fff; + --link-color: #005ed9; + --link-hover-color: #00439c; + --button-link-color: #fff; + --button-background-color: #eb0000; + --button-hover-background-color: #d80000; + --button-primary-background-color: #000; + --button-primary-hover-background-color: #000; + --button-secondary-color: #000; + --button-secondary-hover-background-color: #000; + --overlay-background-color: #eee; + --highlight-background-color: #ccc; + --text-color: #000; + --text-error-color: #f00; + --color-highlight-blue: #006dff; + --color-dark-gray: #616161; + --checkbox-label: #3c3c3c; + --highlight-light-blue: #f3f7fe; + --text-dark-color: #fff; + --horizontal-separator-color: #dedede; + --modal-background-color: rgb(0 0 0 / 50%); + --background-color-light-sky-blue: #e4f2ff; + --icon-color: #205fff; + --background-light-blue: #d9eeff; + --background-blue: #005ed9; + --dark-blue-tag: #005eff; + --light-blue-tag: #13b0a7; + --green-tag: #218728; + --dark-shadow: #0000001a; + --background-checkmark: #61AF53; + --body-font-family: "Roboto", "roboto-normal-400-fallback", helvetica, ubuntu, roboto, noto, sans-serif; + --heading-font-family: var(--body-font-family); + --fixed-font-family: var(--body-font-family); + --font-weight-thin: 300; + --font-weight-regular: 400; + --font-weight-bold: 500; + --font-weight-bolder: 600; + --font-weight-boldest: 700; + --font-weight-heavy: 900; + --body-font-size-l: 22px; + --body-font-size-m: 18px; + --body-font-size-s: 16px; + --body-font-size-xs: 14px; + --body-font-size-xxs: 12px; + --body-font-size-xxxs: 10px; + --heading-font-size-xxxl: 60px; + --heading-font-size-xxl: 48px; + --heading-font-size-xl: 40px; + --heading-font-size-l: 32px; + --heading-font-size-m: 24px; + --heading-font-size-s: 20px; + --heading-font-size-xs: 18px; + --heading-font-size-xxs: 16px; + --nav-height: 63px; + --nav-height-desktop: 40px; + --body-max-width: 1920px; + --body-padding: 20px; + --section-desktop-max-width: 1290px; + --section-desktop-padding: 20px; + --section-desktop-padding-vertical: 48px; + --section-mobile-padding-vertical: 32px; + --cta-background-light-blue: var(--background-light-blue); + + background-color: #f2f2f2; +} + +@media (min-width: 992px) { /* desktop */ + .terms-wrapper { + max-width: var(--section-desktop-max-width); + padding: 15px var(--section-desktop-padding) 40px var(--section-desktop-padding); + margin: 0 auto; + } +} + +.terms-container h5 { + font-size: 16px; + font-weight: bold; + margin: 0; +} + +.terms-container h6 { + font-size: 16px; + font-weight: bold; + margin: 0; +} + +.terms-container .terms div, +.terms-container .terms div p { + font-size: 12px; +} + +.terms-container .terms div p strong { + font-weight: bold; + margin-top: 15px; +} + +.terms-container.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + margin: 0 auto; +} + +.terms.border-on-top { + border-top: 1px solid #dedede; + padding-top: 20px; +} + +@media (max-width: 992px) { /* mobile/tablet */ + .terms-wrapper { + padding: var(--body-padding); + } + + .terms-container.we-container { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } + + .default-content-wrapper { + max-width: var(--section-desktop-max-width); + padding: 23px var(--section-desktop-padding); + border-radius: 0; + } +} + +@media (min-width: 1200px) { + .terms-container.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + } +} + +@media (min-width: 1600px) { + .terms-container.we-container { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + } +} diff --git a/_src/blocks/terms/terms.js b/_src/blocks/terms/terms.js new file mode 100644 index 000000000..fe60b0391 --- /dev/null +++ b/_src/blocks/terms/terms.js @@ -0,0 +1,15 @@ +export default async function decorate(block, options) { + block.closest('.section').id = 'tos'; + + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + const blockParent = block.closest('.terms-wrapper'); + blockParent.classList.add('we-container'); + } + + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); +} diff --git a/_src/blocks/testimonials-component/testimonials-component.css b/_src/blocks/testimonials-component/testimonials-component.css new file mode 100644 index 000000000..8f18b135c --- /dev/null +++ b/_src/blocks/testimonials-component/testimonials-component.css @@ -0,0 +1,172 @@ +.testimonials-component-container { + display: flex; + flex-direction: column; + align-items: center; + font: italic normal normal 14px/19px Arial, sans-serif; +} + +.testimonials-component-container h2 { + font: normal normal bold 32px/37px Arial, sans-serif; +} + +.testimonials-component-container .testimonials-component { + display: flex; + flex-direction: column; + align-items: center; + gap: 3%; +} + +.testimonials-component-container.we-container { + max-width: 100%; + padding-left: 20px; + padding-right: 20px; + margin: 15px auto; +} + +.testimonials-component-container .title-class { + text-align: center; + font: normal normal bold 32px/37px Arial, sans-serif; +} + +.testimonials-component-container .subtitle-class { + font: normal normal normal 18px/21px Arial, sans-serif; + margin-bottom: 40px; + text-align: center; + max-width: 90%; +} + +.testimonials-component-container .review-container { + display: flex; + align-items: flex-start; + flex: 1; + gap: 2%; + background: #edf9ff; + padding: 26px 23px; + border-radius: 16px; +} + +.testimonials-component-container.grey-bck .review-container { + background-color: #F6F6F6;; +} + +.testimonials-component-container hr { + margin-left: 0; + width: 24px; + margin-bottom: 8px; + border: 1px solid #00439c; +} + +.testimonials-component-container .review { + width: 90%; +} + +.testimonials-component-container .review p { + width: 90%; + margin-top: 0; +} + +.testimonials-component-container .review p:last-child { + font-style: normal; +} + +.testimonials-component-container.grey-bck .review p { + font-size: 14px; + font-style: normal; +} + +.testimonials-component-container .hide { + display: none; +} + +.testimonials-component-container .show { + display: flex; +} + +.testimonials-component-container .navigation-container { + display: flex; + justify-content: space-between; + gap: 3%; + max-width: 90%; + width: 100%; + margin-top: 20px; + align-items: center; +} + +.testimonials-component-container .buttons-container { + display: flex; + gap: 3%; +} + +.testimonials-component-container .next-button, +.testimonials-component-container .prev-button { + width: 45px; + height: 45px; + border: 0; + background-color: #edf9ff; + border-radius: 50%; + display: flex; + justify-content: center; + align-items: center; +} + +.testimonials-component-container .prev-button { + margin-right: 10px; +} + +.testimonials-component-container .next-button:hover, +.prev-button:hover { + border: 1px solid #006eff; +} + +@media (min-width: 768px) { + .testimonials-component-container .title-class { + width: 715px; + } + + .testimonials-component-container .reviews-container { + display: flex; + flex-direction: column; + } +} + +@media (min-width: 990px) { + .testimonials-component-container .reviews-container { + display: flex; + flex-direction: row; + gap: 3%; + } + + .testimonials-component-container .hide { + display: flex; + } + + .testimonials-component-container .show { + display: flex; + } + + .testimonials-component-container .buttons-container { + display: none; + } + + .testimonials-component-container .navigation-container { + justify-content: center; + } + + .testimonials-component-container.we-container { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } +} + +@media (min-width: 1200px) { + .testimonials-component-container .testimonials-component { + max-width: 1294px; + } + + .testimonials-component-container.we-container { + max-width: 1290px; + padding-left: 20px; + padding-right: 20px; + } +} \ No newline at end of file diff --git a/_src/blocks/testimonials-component/testimonials-component.js b/_src/blocks/testimonials-component/testimonials-component.js new file mode 100644 index 000000000..beaabf0b5 --- /dev/null +++ b/_src/blocks/testimonials-component/testimonials-component.js @@ -0,0 +1,110 @@ +export default function decorate(block, options) { + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + const blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + } + + const parentSelector = block.closest('.section'); + // eslint-disable-next-line no-unused-vars + const metaData = parentSelector.dataset; + const [title, subtitle, source, ...reviews] = block.children; + + title.classList.add('title-class'); + subtitle.classList.add('subtitle-class'); + source.classList.add('source-class'); + + // Create a new div for reviews + const reviewsContainer = document.createElement('div'); + reviewsContainer.classList.add('reviews-container'); + + // Iterate over each review element + reviews.forEach((review, index) => { + review.classList.add('review'); + + // Create SVG element + const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); + svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg'); + svg.setAttribute('viewBox', '0 0 448 512'); + svg.setAttribute('width', '32px'); // Set width to 32 pixels + svg.setAttribute('height', '32px'); // Set height to 32 pixels + svg.style.fill = '#006EFF'; // Set the SVG color to blue + svg.innerHTML = ''; + + // Create a container for the SVG and review content + const reviewContainer = document.createElement('div'); + reviewContainer.classList.add('review-container'); + if (index === 0) { + reviewContainer.classList.add('show'); + } else { + reviewContainer.classList.add('hide'); + } + + // Append SVG and review to the review container + reviewContainer.appendChild(svg); + reviewContainer.appendChild(review); + + // Append review container to the reviews container + reviewsContainer.appendChild(reviewContainer); + }); + + // Append the reviews container to the block + block.appendChild(reviewsContainer); + + // Create navigation buttons for the slider + const prevButton = document.createElement('button'); + // Set SVG icon for previous button with color #006EFF + prevButton.innerHTML = ''; + prevButton.classList.add('prev-button'); + prevButton.addEventListener('click', () => { + // eslint-disable-next-line no-use-before-define + navigateSlider(-1); + }); + + const nextButton = document.createElement('button'); + // Set SVG icon for next button with color #006EFF + nextButton.innerHTML = ` + +`; + nextButton.classList.add('next-button'); + nextButton.addEventListener('click', () => { + // eslint-disable-next-line no-use-before-define + navigateSlider(1); + }); + + // Create navigation container + const navigationContainer = document.createElement('div'); + navigationContainer.classList.add('navigation-container'); + block.appendChild(navigationContainer); + navigationContainer.appendChild(source); + // create buttons container + const buttonsContainer = document.createElement('div'); + buttonsContainer.classList.add('buttons-container'); + navigationContainer.appendChild(buttonsContainer); + // Append navigation buttons to the block + buttonsContainer.appendChild(prevButton); + buttonsContainer.appendChild(nextButton); + + // Slider navigation function + let currentIndex = 0; + const reviewsCount = reviews.length; + + function navigateSlider(direction) { + const currentReview = block.querySelector('.show'); + const nextIndex = (currentIndex + direction + reviewsCount) % reviewsCount; + const nextReview = reviewsContainer.children[nextIndex]; + + currentReview.classList.remove('show'); + currentReview.classList.add('hide'); + + nextReview.classList.remove('hide'); + nextReview.classList.add('show'); + + currentIndex = nextIndex; + } + window.dispatchEvent(new CustomEvent('shadowDomLoaded'), { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); +} diff --git a/_src/blocks/thank-you/thank-you.css b/_src/blocks/thank-you/thank-you.css new file mode 100644 index 000000000..e5fa9623e --- /dev/null +++ b/_src/blocks/thank-you/thank-you.css @@ -0,0 +1,244 @@ +.thank-you-container { + .thank-you { + display: flex; + flex-direction: column; + flex: 0 1 50%; + font-family: Arial, Roboto, sans-serif; + + @media (min-width: 768px) { + & { + flex-direction: row; + } + } + + img { + max-width: 100%; + width: auto; + height: auto; + } + + .content-right { + padding-left: 20px; + display: flex; + align-items: end; + justify-content: center; + flex: 1 0 auto; + + + img { + max-width: 520px; + box-shadow: 0 35px 40px 0 #0000000F; + } + } + + .content-left { + max-width: 630px; + + >p:first-of-type { + color: #3782F9; + font-size: 18px; + line-height: clamp(15px, 5vw, 44px); + } + + h1 { + font-size: clamp(24px, 5vw, 53px); + font-weight: 400; + line-height: clamp(30px, 5vw, 77px); + + strong { + color: #006EFF; + font-weight: normal; + } + } + + .qr-content { + display: flex; + font-size: clamp(16px, 5vw, 20px); + align-items: center; + + img { + max-width: 170px; + height: auto; + box-shadow: 0 35px 40px 0 #0000000F; + } + } + } + + /* Importing from styles.css to be able to import in aem */ + p a { + font-family: var(--body-font-family); + font-size: var(--body-font-size-s); + font-style: normal; + font-weight: var(--font-weight-bold); + -webkit-font-smoothing: antialiased; + display: inline-flex; + align-items: center; + box-sizing: border-box; + text-decoration: none; + padding: 10px 26px 8px 28px; + text-align: center; + cursor: pointer; + color: var(--button-link-color); + background-color: var(--button-background-color); + border: 2px solid var(--button-background-color); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + border-radius: 8px; + height: fit-content; + } + + p a::after { + content: ''; + width: 24px; + height: 24px; + /* stylelint-disable-next-line property-no-vendor-prefix */ + -webkit-mask:url('https::/bitdefender.com/_src/icons/arrow-right.svg'); + mask: url('https::/bitdefender.com/_src/icons/arrow-right.svg'); + background-color: var(--button-link-color); + display: inline-block; + transition: all .2s cubic-bezier(.4,0,.2,1); + transform: translateX(0); + opacity: 0; + margin-left: -10px; + } + + p a:hover, p a:focus { + background-color: var(--button-hover-background-color); + border: 2px solid var(--button-hover-background-color); + cursor: pointer; + } + + p a:hover::after { + transform: translateX(5px); + opacity: 1; + } + } + + &.we-container { + max-width: 100%; + padding-left: 20px; + padding-right: 20px; + margin-top: 15px; + margin-left: auto; + margin-right: auto; + + + @media (min-width: 990px) { + & { + max-width: 1300px; + padding-left: 50px; + padding-right: 50px; + } + } + + @media (min-width: 1200px) { + & { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + } + } + + @media (min-width: 1600px) { + & { + max-width: 1332px; + padding-left: 20px; + padding-right: 20px; + } + } + } + + @media (min-width: 990px) { + margin-top: 120px; + margin-bottom: 120px; + } + + +} + +/* stylelint-disable-next-line no-duplicate-selectors */ +.thank-you-container { + /* colors */ + --dark-background-color: #000; + --black-color: #000; + --white-color: #fff; + --background-color: #fff; + --link-color: #005ed9; + --link-hover-color: #00439c; + --button-link-color: #fff; + --button-background-color: #eb0000; + --button-hover-background-color: #d80000; + --button-primary-background-color: #000; + --button-primary-hover-background-color: #000; + --button-secondary-color: #000; + --button-secondary-hover-background-color: #000; + --overlay-background-color: #eee; + --highlight-background-color: #ccc; + --text-color: #000; + --text-error-color: #f00; + --color-highlight-blue: #006dff; + --color-dark-gray: #616161; + --checkbox-label: #3c3c3c; + --highlight-light-blue: #f3f7fe; + --text-dark-color: #fff; + --horizontal-separator-color: #dedede; + --modal-background-color: rgb(0 0 0 / 50%); + --background-color-light-sky-blue: #e4f2ff; + --icon-color: #205fff; + --background-light-blue: #d9eeff; + --background-blue: #005ed9; + --dark-blue-tag: #005eff; + --light-blue-tag: #13b0a7; + --green-tag: #218728; + --dark-shadow: #0000001a; + --background-checkmark: #61AF53; + + /* fonts */ + --body-font-family: "Roboto", "roboto-normal-400-fallback", helvetica, ubuntu, roboto, noto, sans-serif; + --heading-font-family: var(--body-font-family); + --fixed-font-family: var(--body-font-family); + + /* font weights */ + --font-weight-thin: 300; + --font-weight-regular: 400; + --font-weight-bold: 500; + --font-weight-bolder: 600; + --font-weight-boldest: 700; + --font-weight-heavy: 900; + + /* body sizes */ + --body-font-size-l: 22px; + --body-font-size-m: 18px; + --body-font-size-s: 16px; + --body-font-size-xs: 14px; + --body-font-size-xxs: 12px; + --body-font-size-xxxs: 10px; + + /* heading sizes */ + --heading-font-size-xxxl: 60px; + --heading-font-size-xxl: 48px; + --heading-font-size-xl: 40px; + --heading-font-size-l: 32px; + --heading-font-size-m: 24px; + --heading-font-size-s: 20px; + --heading-font-size-xs: 18px; + --heading-font-size-xxs: 16px; + + /* nav height */ + --nav-height: 63px; + --nav-height-desktop: 40px; + + /* body width */ + --body-max-width: 1920px; + --body-padding: 20px; + --section-desktop-max-width: 1300px; + --section-desktop-padding: 20px; + --section-large-desktop-max-width: 1332px; + --section-large-desktop-padding: 50px; + --section-desktop-padding-vertical: 48px; + --section-mobile-padding-vertical: 32px; + + /* cta styles */ + --cta-background-light-blue: var(--background-light-blue) +} \ No newline at end of file diff --git a/_src/blocks/thank-you/thank-you.js b/_src/blocks/thank-you/thank-you.js new file mode 100644 index 000000000..fcb4a11f4 --- /dev/null +++ b/_src/blocks/thank-you/thank-you.js @@ -0,0 +1,43 @@ +// Function to dispatch 'shadowDomLoaded' event +function dispatchShadowDomLoadedEvent() { + const event = new CustomEvent('shadowDomLoaded', { + bubbles: true, + composed: true, // This allows the event to cross the shadow DOM boundary + }); + window.dispatchEvent(event); +} + +export default function decorate(block, options) { + if (options) { + // eslint-disable-next-line no-param-reassign + block = block.querySelector('.block'); + const blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + } else { + // eslint-disable-next-line no-param-reassign + const blockParent = block.closest('.section'); + blockParent.classList.add('we-container'); + } + + const [richTextPicture, richTextQR] = block.children; + const [richTextPictureText, richTextPicturePicture] = richTextPicture.children; + const [richTextQRText, richTextQRPicture] = richTextQR.children; + const html = ` +
      + ${richTextPictureText.innerHTML} +
      + ${richTextQRText.innerHTML} +
      + ${richTextQRPicture.innerHTML} +
      +
      +
      +
      + ${richTextPicturePicture.innerHTML} +
      + `; + + block.innerHTML = html; + + dispatchShadowDomLoadedEvent(); +} diff --git a/_src/blocks/trusted-hero/trusted-hero.css b/_src/blocks/trusted-hero/trusted-hero.css new file mode 100644 index 000000000..429f7098a --- /dev/null +++ b/_src/blocks/trusted-hero/trusted-hero.css @@ -0,0 +1,166 @@ +.trusted-hero-container.section { + padding: 0; + background: #EFF6FF; + color: black; +} + +.trusted-hero-container .trusted-hero-wrapper .block { + display: flex; + flex-direction: column; +} + +.trusted-hero-container h1, +.trusted-hero-container h2 { + font: normal normal normal 28px/32px var(--font-ibm); +} + +.trusted-hero-container h1 { + font-weight: 500; +} + +.trusted-hero-container .video-wrapper { + height: 200px; + position: relative; +} + +.trusted-hero-container .video-wrapper iframe { + width: 100%; + height: 100%; + object-fit: cover; + position: absolute; + left: 0; +} + +.trusted-hero-container .default-content-wrapper { + position: relative; + padding-top: 20px !important; + z-index: 4; + order: -1; + padding-bottom: 140px; +} + +.trusted-hero-container p.button-container:nth-last-child(1) { + position: absolute; + bottom: 0; + left: 1em; + right: 1em; +} + +.trusted-hero-container p.button-container:nth-last-child(2) { + position: absolute; + bottom: 60px; + left: 1em; + right: 1em; +} + +.trusted-hero-container p.button-container a { + background-color: transparent !important; + border: solid black 1px !important; + color: black; + width: 100%; + justify-content: center; + font-weight: 500 !important; +} + +.trusted-hero-container p.button-container:nth-last-child(2) a { + width: 100%; + justify-content: center; + font-weight: 400; + border: 1px solid var(--blue); +} + +.trusted-hero-container p.button-container a:hover { + background-color: var(--blue) !important; + border: 1px solid var(--blue) !important; + color: white; +} + +@media (min-width: 768px) { + /* .trusted-hero-container a.button:any-link:not(.modal, .primary) { */ + + /* width: unset; */ + + /* justify-content: unset; */ + + /* display: inline-flex; */ + + /* margin-right: 15px; */ + + /* } */ + .trusted-hero-container h1, + .trusted-hero-container h2 { + font: normal normal 500 29px / 33px var(--font-ibm); + } + + .trusted-hero-container h2 { + margin: 50px 0 0; + color: black; + } +} + +@media (min-width: 992px) { + .trusted-hero-container { + background: #EFF6FF; + color: black; + height: 670px; + } + + .trusted-hero-container h1 { + font: normal normal 500 47px / 48px var(--font-ibm); + } + + .trusted-hero-container .trusted-hero-wrapper { + height: 100%; + } + + .trusted-hero-container .trusted-hero-wrapper .block { + height: 100%; + display: flex; + flex-direction: row; + } + + .trusted-hero-container .rte-wrapper { + width: 100%; + } + + .trusted-hero-container .video-wrapper { + width: 100%; + height: 100%; + } + + .trusted-hero-container .default-content-wrapper { + padding-top: 0 !important; + order: unset; + position: absolute; + left: 0; + right: 0; + height: 100%; + display: flex; + align-items: center; + gap: 30px; + padding-bottom: unset; + } + + .trusted-hero-container .default-content-wrapper > .rte-wrapper { + width: 555px; + padding-right: 4em; + } + + .trusted-hero-container .default-content-wrapper > .video-wrapper { + width: 60%; + height: 385px; + } + + .trusted-hero-container .default-content-wrapper p.button-container { + position: unset; + display: inline-block; + } + + .trusted-hero-container a.button:any-link:not(.modal, .primary) { + width: unset; + justify-content: unset; + display: inline-flex; + margin-right: 15px; + } +} + diff --git a/_src/blocks/trusted-hero/trusted-hero.js b/_src/blocks/trusted-hero/trusted-hero.js new file mode 100644 index 000000000..18231b6ee --- /dev/null +++ b/_src/blocks/trusted-hero/trusted-hero.js @@ -0,0 +1,34 @@ +export default async function decorate(block) { + const [rte, videoUrl] = [...block.children]; + + const autoplay = false; + const url = new URL(videoUrl.textContent.trim()); + const usp = new URLSearchParams(url.search); + const suffix = autoplay ? '&muted=1&autoplay=1' : ''; + let vid = usp.get('v') ? encodeURIComponent(usp.get('v')) : ''; + const embed = url.pathname; + + if (url.origin.includes('youtu.be')) { + [, vid] = url.pathname.split('/'); + } + + block.innerHTML = ` +
      +
      ${rte.innerHTML}
      +
      + +
      +
      + `; + + block.querySelectorAll('.button-container > a').forEach((anchorEl) => { + anchorEl.target = '_blank'; + anchorEl.rel = 'noopener noreferrer'; + }); +} diff --git a/_src/blocks/trusted-main-carousel/trusted-main-carousel.css b/_src/blocks/trusted-main-carousel/trusted-main-carousel.css new file mode 100644 index 000000000..bb190d046 --- /dev/null +++ b/_src/blocks/trusted-main-carousel/trusted-main-carousel.css @@ -0,0 +1,183 @@ +.trusted-main-carousel-container { + background: white; +} + +.trusted-main-carousel-container .navigation-wrapper { + display: flex; + scrollbar-width: none; + overflow: auto; +} + +.trusted-main-carousel-container .navigation-wrapper::-webkit-scrollbar { + display: none; /* For Chrome, Safari, Opera */ +} + +.trusted-main-carousel-container .navigation-wrapper .first-nav { + display: flex; + cursor: pointer; + border-radius: 8px; + background: #EFF6FF; +} + +.trusted-main-carousel-container .navigation-wrapper .second-nav { + display: none; +} + +.trusted-main-carousel-container .navigation-wrapper .nav-item { + color: black; + font-weight: 500; + font-size: 9px; + flex-shrink: 0; + padding: 15px; +} + +.trusted-main-carousel-container .default-content-wrapper { + overflow: hidden; +} + +.trusted-main-carousel-container .navigation-wrapper .nav-item.active { + background: #006EFF; + border-radius: 8px; + color: white; + transition: all .25s linear; + position: relative; + z-index: 1; +} + +.trusted-main-carousel-container .content-wrapper { + color: black; + display: flex; + transform: translateX(0); + transition: transform 0.25s ease-out; +} + +.trusted-main-carousel-container .block.scrolling .content-wrapper { + overflow: unset; +} + +.trusted-main-carousel-container .content-wrapper .slide { + width: 100%; + flex-shrink: 0; + box-sizing: border-box; + margin-right: 50px; +} + +.trusted-main-carousel-container .content-wrapper .slide u { + display: none; +} + +.trusted-main-carousel-container .content-wrapper .slide > * { + position: relative; +} + +.trusted-main-carousel-container .content-wrapper .slide >:first-child p.button-container { + display: flex; + justify-content: center; +} + +.trusted-main-carousel-container .content-wrapper .slide >:last-child { + width: calc(100% + 2em); + margin-left: -1em; + height: 200px; + top: -15px; + z-index: -1; +} + +.trusted-main-carousel-container .content-wrapper .slide >:last-child img { + object-fit: cover; + width: 100%; + height: 100%; +} + +.trusted-main-carousel-container .content-wrapper .slide >:first-child p.button-container a.button:any-link { + background-color: white; + color: black; + font-weight: normal; + border: 1px solid black; + width: 250px; + justify-content: center; +} + +.trusted-main-carousel-container .content-wrapper .slide >:first-child img { + width: 160px; +} + +@media (min-width: 768px) { + .trusted-main-carousel-container .navigation-wrapper .nav-item { + font-size: 100%; + } + + .trusted-main-carousel-container .navigation-wrapper .second-nav { + display: flex; + margin-left: auto; + } + + .trusted-main-carousel-container .left-arrow, + .trusted-main-carousel-container .right-arrow { + color: black; + } + + .trusted-main-carousel-container .left-arrow svg { + transform: rotate(180deg); + } + + .trusted-main-carousel-container .arrow { + width: 100px; + } + + .trusted-main-carousel-container .arrow svg { + width: 100%; + height: 50px; + } + + .trusted-main-carousel-container .arrow svg path { + fill: black; + } + + .trusted-main-carousel-container .left-arrow { + margin-left: auto; + } + + .trusted-main-carousel-container .content-wrapper .slide >:first-child p.button-container { + position: unset; + } + + .trusted-main-carousel-container .content-wrapper .slide >:last-child { + height: 400px; + } +} + +@media (min-width: 992px) { + .trusted-main-carousel-container .content-wrapper .slide { + display: flex; + gap: 50px; + margin-top: 30px; + } + + .trusted-main-carousel-container .navigation-wrapper .nav-item { + padding: 15px 30px; + } + + .trusted-main-carousel-container .content-wrapper .slide >:last-child { + width: calc(60% - 50px); + margin-left: unset; + height: auto; + } + + .trusted-main-carousel-container .content-wrapper .slide >:first-child p.button-container { + justify-content: unset; + } + + .trusted-main-carousel-container .content-wrapper .slide >:first-child > *:not(h2) { + margin: 40px 0; + } + + .trusted-main-carousel-container .content-wrapper .slide >:last-child img { + object-fit: contain; + } + + .trusted-main-carousel-container .content-wrapper .slide > div { + width: calc(40% - 50px); + flex-shrink: 0; + } +} diff --git a/_src/blocks/trusted-main-carousel/trusted-main-carousel.js b/_src/blocks/trusted-main-carousel/trusted-main-carousel.js new file mode 100644 index 000000000..c5138b1b4 --- /dev/null +++ b/_src/blocks/trusted-main-carousel/trusted-main-carousel.js @@ -0,0 +1,167 @@ +import { debounce, isView } from '../../scripts/utils/utils.js'; + +export default async function decorate(block) { + const slides = [...block.children]; + const AUTOMATIC_SLIDING = { + enabled: true, + viewport: 'desktop', + slideDelay: 3 * 1000, + }; + + const state = { + currentStep: 0, + carouselIsFocused: false, + currentInterval: null, + }; + + const navItemsNames = slides.map((slideEl) => slideEl.children[0].firstElementChild.textContent); + + block.classList.add('default-content-wrapper'); + block.innerHTML = ` + + +
      + ${slides.map((slide, index) => ` +
      + ${slide.innerHTML} +
      + `).join('')} +
      + `; + + const contentWrapper = block.querySelector('.content-wrapper'); + + const navItems = block.querySelectorAll('.nav-item'); + const slideItems = block.querySelectorAll('.slide'); + const leftArrow = block.querySelector('.left-arrow'); + const rightArrow = block.querySelector('.right-arrow'); + function selectNavItem(itemPosition) { + navItems.forEach((item) => item.classList.remove('active')); + navItems[itemPosition].classList.add('active'); + } + + function selectSlideItem(itemPosition) { + slideItems.forEach((item) => item.classList.remove('active')); + slideItems[itemPosition].classList.add('active'); + } + + function slideToSection(itemPosition) { + block.classList.add('scrolling'); + + const transformValue = -100 * (itemPosition); + const offset = 50 * itemPosition; + contentWrapper.style.transform = `translateX(calc(${transformValue}% - ${offset}px ))`; + setTimeout(() => { + block.classList.remove('scrolling'); + }, 200); + } + + function selectStep(itemPosition) { + state.currentStep = itemPosition; + selectNavItem(itemPosition); + selectSlideItem(itemPosition); + slideToSection(itemPosition); + } + + function endAutomaticSliding(interval) { + clearInterval(interval || state.currentInterval); + } + + function beginAutomaticSliding() { + if (!AUTOMATIC_SLIDING.enabled) return; + + endAutomaticSliding(); + + if (state.carouselIsFocused || !isView(AUTOMATIC_SLIDING.viewport)) { + return; + } + + const interval = setInterval(() => { + const isLastStep = state.currentStep === navItems.length - 1; + const nextStepToSelect = isLastStep ? 0 : (state.currentStep + 1); + selectStep(nextStepToSelect); + + if (!isView(AUTOMATIC_SLIDING.viewport) || state.carouselIsFocused) { + endAutomaticSliding(interval); + } + }, AUTOMATIC_SLIDING.slideDelay); + + state.currentInterval = interval; + } + + function addEventListeners() { + block.addEventListener('mouseenter', () => { + state.carouselIsFocused = true; + endAutomaticSliding(); + }); + + block.addEventListener('mouseleave', () => { + state.carouselIsFocused = false; + beginAutomaticSliding(); + }); + + navItems.forEach((navEl, itemPosition) => { + navEl.addEventListener('click', () => { + selectStep(itemPosition); + }); + }); + + leftArrow.addEventListener('click', (e) => { + e.preventDefault(); + + const isFirstStep = state.currentStep === 0; + if (isFirstStep) { + return; + } + + selectStep(state.currentStep - 1); + }); + + rightArrow.addEventListener('click', (e) => { + e.preventDefault(); + + const isLastStep = state.currentStep === navItems.length - 1; + if (isLastStep) { + return; + } + + selectStep(state.currentStep + 1); + }); + } + + addEventListeners(); + + beginAutomaticSliding(); + window.addEventListener('resize', debounce(beginAutomaticSliding, 250)); +} diff --git a/_src/blocks/trusted-teaser-impact/trusted-teaser-impact.css b/_src/blocks/trusted-teaser-impact/trusted-teaser-impact.css new file mode 100644 index 000000000..5a6c0876c --- /dev/null +++ b/_src/blocks/trusted-teaser-impact/trusted-teaser-impact.css @@ -0,0 +1,112 @@ +.trusted-teaser-impact-container { + background: white; + padding-top: 0 !important; +} + +.trusted-teaser-impact-container .carousel-header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 30px; +} + +.trusted-teaser-impact .carousel-header .title { + color: black; + width: 100%; + display: flex; + flex-direction: column; + align-items: center; +} + +.trusted-teaser-impact .carousel-header .title >:first-child { + margin: 0; +} + +.trusted-teaser-impact .box-wrapper { + display: flex; + flex-wrap: wrap; + gap: 20px; +} + +.trusted-teaser-impact .box-wrapper .box-item { + width: calc(50% - 10px); + flex-shrink: 0; + color: black; + position: relative; + padding-right: 10px; +} + +.trusted-teaser-impact .box-wrapper .box-item::after { + content: ''; + display: block; + width: 1px; + height: 80%; + position: absolute; + top: 10%; + right: -3px; + background: #006EFF; + opacity: 0.25; + visibility: hidden; +} + +.trusted-teaser-impact .box-wrapper .box-item:nth-child(1)::after, +.trusted-teaser-impact .box-wrapper .box-item:nth-child(3)::after { + visibility: visible; +} + +.trusted-teaser-impact .box-wrapper .box-item .icon { + width: 35px; + height: 35px; + margin: 0; +} + +.trusted-teaser-impact .box-wrapper .box-item .icon .cls-1 { + fill: #006EFF; +} + +.trusted-teaser-impact .box-wrapper .box-item .title { + font-size: 35px; + font-weight: bold; +} + +@media (min-width: 768px) { + .trusted-teaser-impact .box-wrapper .box-item .icon { + width: 50px; + height: 50px; + } + + .trusted-teaser-impact .box-wrapper .box-item:nth-child(2), + .trusted-teaser-impact .box-wrapper .box-item:nth-child(4) { + padding-left: 20px; + } + +} + +@media (min-width: 992px) { + .trusted-teaser-impact .box-wrapper .box-item { + width: calc(25% - 15px); + } + + .trusted-teaser-impact .box-wrapper .box-item .title { + font-size: 50px; + color: #35383C; + } + + .trusted-teaser-impact .box-wrapper .box-item .subtitle { + margin-top: 0; + } + + .trusted-teaser-impact .box-wrapper .box-item .icon { + width: 70px; + height: 70px; + } + + .trusted-teaser-impact .box-wrapper .box-item:nth-child(3) { + padding-left: 20px; + } + + .trusted-teaser-impact .box-wrapper .box-item:nth-child(2)::after { + visibility: visible; + } +} + diff --git a/_src/blocks/trusted-teaser-impact/trusted-teaser-impact.js b/_src/blocks/trusted-teaser-impact/trusted-teaser-impact.js new file mode 100644 index 000000000..24ecf121c --- /dev/null +++ b/_src/blocks/trusted-teaser-impact/trusted-teaser-impact.js @@ -0,0 +1,38 @@ +import { decorateIcons } from '../../scripts/lib-franklin.js'; +import { debounce } from '../../scripts/utils/utils.js'; + +export default async function decorate(block) { + const [titleEl, ...boxes] = [...block.children]; + + function render() { + block.classList.add('default-content-wrapper'); + + block.innerHTML = ` + + +
      + ${boxes.map((box) => ` +
      + ${box.children[0].children[0].innerHTML} + +
      + ${box.children[0].children[1].textContent} +
      + +

      + ${box.children[0].children[2].innerHTML} +

      +
      + `).join('')} +
      + `; + + decorateIcons(block); + } + + render(); + + window.addEventListener('resize', debounce(render, 250)); +} diff --git a/_src/blocks/video/video.css b/_src/blocks/video/video.css new file mode 100644 index 000000000..bcac2bf4d --- /dev/null +++ b/_src/blocks/video/video.css @@ -0,0 +1,87 @@ +.video { + width: unset; + text-align: center; + margin-top: 32px; + margin-bottom: 32px; +} + +.video.lazy-loading { + /* reserve an approximate space to avoid extensive layout shifts */ + aspect-ratio: 16/9; +} + +.video > div { + display: flex; + justify-content: center; + border-radius: 13px; + overflow: hidden; +} + +.video.left { + margin-right: auto; +} + +.video.center { + margin-left: auto; + margin-right: auto; +} + +.video.right { + margin-left: auto; +} + +.video video { + max-width: 100%; +} + +.video video[data-loading] { + /* reserve an approximate space to avoid extensive layout shifts */ + width: 100%; + aspect-ratio: 16/9; +} + +.video .video-placeholder { + width: 100%; + aspect-ratio: 16/9; + position: relative; +} + +.video .video-placeholder > * { + display: flex; + align-items: center; + justify-content: center; + position: absolute; + inset: 0; +} + +.video .video-placeholder picture img { + width: 100%; + height: 100%; + object-fit: cover; +} + +.video .video-placeholder-play button { + box-sizing: border-box; + position: relative; + display: block; + transform: scale(3); + width: 22px; + height: 22px; + border: 2px solid; + border-radius: 20px; + padding: 0; +} + +.video .video-placeholder-play button::before { + content: ""; + display: block; + box-sizing: border-box; + position: absolute; + width: 0; + height: 10px; + border-top: 5px solid transparent; + border-bottom: 5px solid transparent; + border-left: 6px solid; + top: 4px; + left: 7px; +} \ No newline at end of file diff --git a/_src/blocks/video/video.js b/_src/blocks/video/video.js new file mode 100644 index 000000000..482179405 --- /dev/null +++ b/_src/blocks/video/video.js @@ -0,0 +1,108 @@ +/* + * Video Block + * Show a video referenced by a link + * https://www.hlx.live/developer/block-collection/video + */ +function embedYoutube(url, autoplay) { + const usp = new URLSearchParams(url.search); + const suffix = autoplay ? '&muted=1&autoplay=1' : ''; + let vid = usp.get('v') ? encodeURIComponent(usp.get('v')) : ''; + const embed = url.pathname; + if (url.origin.includes('youtu.be')) { + [, vid] = url.pathname.split('/'); + } + return `
      + +
      `; +} + +function embedVimeo(url, autoplay) { + const [, video] = url.pathname.split('/'); + const suffix = autoplay ? '?muted=1&autoplay=1' : ''; + return `
      + +
      `; +} + +function getVideoElement(source, autoplay) { + const video = document.createElement('video'); + video.setAttribute('controls', ''); + video.dataset.loading = 'true'; + video.addEventListener('loadedmetadata', () => delete video.dataset.loading); + if (autoplay) video.setAttribute('autoplay', ''); + + const sourceEl = document.createElement('source'); + sourceEl.setAttribute('src', source); + sourceEl.setAttribute('type', `video/${source.split('.').pop()}`); + video.append(sourceEl); + + return video; +} + +const loadVideoEmbed = (block, link, autoplay) => { + if (block.dataset.embedIsLoaded) { + return; + } + const url = new URL(link); + + const isYoutube = link.includes('youtube') || link.includes('youtu.be'); + const isVimeo = link.includes('vimeo'); + const isMp4 = link.includes('.mp4'); + + if (isYoutube) { + block.innerHTML = embedYoutube(url, autoplay); + } else if (isVimeo) { + block.innerHTML = embedVimeo(url, autoplay); + } else if (isMp4) { + block.textContent = ''; + block.append(getVideoElement(link, autoplay)); + } + + block.dataset.embedIsLoaded = true; +}; + +const DESKTOP_ALIGN_ENUM = { + left: 'left', + right: 'right', + center: 'center', +}; + +function positionVideoContainer(block, desktopAlign) { + block.classList.add(DESKTOP_ALIGN_ENUM[desktopAlign] || DESKTOP_ALIGN_ENUM.LEFT); +} + +export default async function decorate(block) { + block.classList.add('default-content-wrapper'); + block.closest('.section').style.padding = '0'; + const { desktopAlign } = block.closest('.section').dataset; // left / middle / right + const placeholder = block.querySelector('picture'); + const link = block.querySelector('a').href; + block.textContent = ''; + + positionVideoContainer(block, desktopAlign); + + if (placeholder) { + const wrapper = document.createElement('div'); + wrapper.className = 'video-placeholder'; + wrapper.innerHTML = '
      '; + wrapper.prepend(placeholder); + wrapper.addEventListener('click', () => { + loadVideoEmbed(block, link, true); + }); + block.append(wrapper); + } else { + block.classList.add('lazy-loading'); + const observer = new IntersectionObserver((entries) => { + if (entries.some((e) => e.isIntersecting)) { + observer.disconnect(); + loadVideoEmbed(block, link, false); + block.classList.remove('lazy-loading'); + } + }); + observer.observe(block); + } +} diff --git a/_src/fonts/ibm-plex-sans-300.woff2 b/_src/fonts/ibm-plex-sans-300.woff2 new file mode 100644 index 000000000..5eb6300c8 Binary files /dev/null and b/_src/fonts/ibm-plex-sans-300.woff2 differ diff --git a/_src/fonts/ibm-plex-sans-400.woff2 b/_src/fonts/ibm-plex-sans-400.woff2 new file mode 100644 index 000000000..8e1333308 Binary files /dev/null and b/_src/fonts/ibm-plex-sans-400.woff2 differ diff --git a/_src/fonts/ibm-plex-sans-500.woff2 b/_src/fonts/ibm-plex-sans-500.woff2 new file mode 100644 index 000000000..1b3f5c649 Binary files /dev/null and b/_src/fonts/ibm-plex-sans-500.woff2 differ diff --git a/solutions/fonts/roboto-300.woff2 b/_src/fonts/roboto-300.woff2 similarity index 100% rename from solutions/fonts/roboto-300.woff2 rename to _src/fonts/roboto-300.woff2 diff --git a/solutions/fonts/roboto-400.woff2 b/_src/fonts/roboto-400.woff2 similarity index 100% rename from solutions/fonts/roboto-400.woff2 rename to _src/fonts/roboto-400.woff2 diff --git a/solutions/fonts/roboto-500.woff2 b/_src/fonts/roboto-500.woff2 similarity index 100% rename from solutions/fonts/roboto-500.woff2 rename to _src/fonts/roboto-500.woff2 diff --git a/_src/icons/arow_down.png b/_src/icons/arow_down.png new file mode 100644 index 000000000..194b19a3b Binary files /dev/null and b/_src/icons/arow_down.png differ diff --git a/solutions/icons/arrow-right.svg b/_src/icons/arrow-right.svg similarity index 100% rename from solutions/icons/arrow-right.svg rename to _src/icons/arrow-right.svg diff --git a/_src/icons/b-logo-red.svg b/_src/icons/b-logo-red.svg new file mode 100644 index 000000000..14d05cb41 --- /dev/null +++ b/_src/icons/b-logo-red.svg @@ -0,0 +1 @@ + diff --git a/_src/icons/bd-round-thumb.svg b/_src/icons/bd-round-thumb.svg new file mode 100644 index 000000000..102b37c76 --- /dev/null +++ b/_src/icons/bd-round-thumb.svg @@ -0,0 +1,17 @@ + + + + + + + + + diff --git a/solutions/icons/blue-circle.svg b/_src/icons/blue-circle.svg similarity index 100% rename from solutions/icons/blue-circle.svg rename to _src/icons/blue-circle.svg diff --git a/_src/icons/book-sharp-regular.svg b/_src/icons/book-sharp-regular.svg new file mode 100644 index 000000000..2c2316457 --- /dev/null +++ b/_src/icons/book-sharp-regular.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/_src/icons/burger_menu.JPG b/_src/icons/burger_menu.JPG new file mode 100644 index 000000000..3743e7ef1 Binary files /dev/null and b/_src/icons/burger_menu.JPG differ diff --git a/_src/icons/checkmark-green-circle.svg b/_src/icons/checkmark-green-circle.svg new file mode 100644 index 000000000..de0d9ec77 --- /dev/null +++ b/_src/icons/checkmark-green-circle.svg @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/solutions/icons/checkmark_solid-circle.svg b/_src/icons/checkmark-light-green-circle.svg similarity index 100% rename from solutions/icons/checkmark_solid-circle.svg rename to _src/icons/checkmark-light-green-circle.svg diff --git a/solutions/icons/checkmark-solid-circle-white.svg b/_src/icons/checkmark-solid-circle-white.svg similarity index 100% rename from solutions/icons/checkmark-solid-circle-white.svg rename to _src/icons/checkmark-solid-circle-white.svg diff --git a/_src/icons/checkmark-x-circle.svg b/_src/icons/checkmark-x-circle.svg new file mode 100644 index 000000000..ed5ad8c7d --- /dev/null +++ b/_src/icons/checkmark-x-circle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/_src/icons/checkmark_solid-circle.svg b/_src/icons/checkmark_solid-circle.svg new file mode 100644 index 000000000..151ed5733 --- /dev/null +++ b/_src/icons/checkmark_solid-circle.svg @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/_src/icons/close_x.JPG b/_src/icons/close_x.JPG new file mode 100644 index 000000000..f5067718a Binary files /dev/null and b/_src/icons/close_x.JPG differ diff --git a/solutions/icons/dark-blue-quote.svg b/_src/icons/dark-blue-quote.svg similarity index 100% rename from solutions/icons/dark-blue-quote.svg rename to _src/icons/dark-blue-quote.svg diff --git a/_src/icons/facebook.svg b/_src/icons/facebook.svg new file mode 100644 index 000000000..ff4c4a0e7 --- /dev/null +++ b/_src/icons/facebook.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/_src/icons/linkedin.svg b/_src/icons/linkedin.svg new file mode 100644 index 000000000..c731c259f --- /dev/null +++ b/_src/icons/linkedin.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/_src/icons/minus-sharp-regular.svg b/_src/icons/minus-sharp-regular.svg new file mode 100644 index 000000000..81c865a81 --- /dev/null +++ b/_src/icons/minus-sharp-regular.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/_src/icons/particle-band.svg b/_src/icons/particle-band.svg new file mode 100644 index 000000000..589d18298 --- /dev/null +++ b/_src/icons/particle-band.svg @@ -0,0 +1 @@ + diff --git a/_src/icons/plus-sharp-regular.svg b/_src/icons/plus-sharp-regular.svg new file mode 100644 index 000000000..395763b64 --- /dev/null +++ b/_src/icons/plus-sharp-regular.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/_src/icons/quot.png b/_src/icons/quot.png new file mode 100644 index 000000000..c5d74ede4 Binary files /dev/null and b/_src/icons/quot.png differ diff --git a/_src/icons/quote-left.svg b/_src/icons/quote-left.svg new file mode 100644 index 000000000..a98b2aa46 --- /dev/null +++ b/_src/icons/quote-left.svg @@ -0,0 +1 @@ + diff --git a/solutions/icons/search.svg b/_src/icons/search.svg similarity index 100% rename from solutions/icons/search.svg rename to _src/icons/search.svg diff --git a/solutions/icons/tabs_arrow.svg b/_src/icons/tabs_arrow.svg similarity index 100% rename from solutions/icons/tabs_arrow.svg rename to _src/icons/tabs_arrow.svg diff --git a/_src/icons/twitter.svg b/_src/icons/twitter.svg new file mode 100644 index 000000000..91888f30f --- /dev/null +++ b/_src/icons/twitter.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/_src/icons/user-guide-white.svg b/_src/icons/user-guide-white.svg new file mode 100644 index 000000000..947acceb9 --- /dev/null +++ b/_src/icons/user-guide-white.svg @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/solutions/icons/user-guide.svg b/_src/icons/user-guide.svg similarity index 100% rename from solutions/icons/user-guide.svg rename to _src/icons/user-guide.svg diff --git a/_src/icons/youtube.svg b/_src/icons/youtube.svg new file mode 100644 index 000000000..731648bb4 --- /dev/null +++ b/_src/icons/youtube.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/_src/images/appstore.webp b/_src/images/appstore.webp new file mode 100644 index 000000000..029cf0a47 Binary files /dev/null and b/_src/images/appstore.webp differ diff --git a/solutions/images/b-red-mask.png b/_src/images/b-red-mask.png similarity index 100% rename from solutions/images/b-red-mask.png rename to _src/images/b-red-mask.png diff --git a/_src/images/black_company_logo.svg b/_src/images/black_company_logo.svg new file mode 100644 index 000000000..485f5412a --- /dev/null +++ b/_src/images/black_company_logo.svg @@ -0,0 +1,3 @@ + + + diff --git a/_src/images/playstore.webp b/_src/images/playstore.webp new file mode 100644 index 000000000..dbe58b8b4 Binary files /dev/null and b/_src/images/playstore.webp differ diff --git a/_src/images/quiz-results-bg.jpg b/_src/images/quiz-results-bg.jpg new file mode 100644 index 000000000..50f80d497 Binary files /dev/null and b/_src/images/quiz-results-bg.jpg differ diff --git a/_src/images/sigla_bd_white.svg b/_src/images/sigla_bd_white.svg new file mode 100644 index 000000000..23ab4e9f2 --- /dev/null +++ b/_src/images/sigla_bd_white.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/_src/plugins/experimentation/CODE_OF_CONDUCT.md b/_src/plugins/experimentation/CODE_OF_CONDUCT.md new file mode 100644 index 000000000..e69de29bb diff --git a/solutions/plugins/experimentation/LICENSE.md b/_src/plugins/experimentation/LICENSE.md similarity index 100% rename from solutions/plugins/experimentation/LICENSE.md rename to _src/plugins/experimentation/LICENSE.md diff --git a/solutions/plugins/experimentation/README.md b/_src/plugins/experimentation/README.md similarity index 100% rename from solutions/plugins/experimentation/README.md rename to _src/plugins/experimentation/README.md diff --git a/solutions/plugins/experimentation/package-lock.json b/_src/plugins/experimentation/package-lock.json similarity index 100% rename from solutions/plugins/experimentation/package-lock.json rename to _src/plugins/experimentation/package-lock.json diff --git a/solutions/plugins/experimentation/package.json b/_src/plugins/experimentation/package.json similarity index 100% rename from solutions/plugins/experimentation/package.json rename to _src/plugins/experimentation/package.json diff --git a/solutions/plugins/experimentation/src/index.js b/_src/plugins/experimentation/src/index.js similarity index 100% rename from solutions/plugins/experimentation/src/index.js rename to _src/plugins/experimentation/src/index.js diff --git a/solutions/plugins/experimentation/src/preview.css b/_src/plugins/experimentation/src/preview.css similarity index 100% rename from solutions/plugins/experimentation/src/preview.css rename to _src/plugins/experimentation/src/preview.css diff --git a/solutions/plugins/experimentation/src/preview.js b/_src/plugins/experimentation/src/preview.js similarity index 100% rename from solutions/plugins/experimentation/src/preview.js rename to _src/plugins/experimentation/src/preview.js diff --git a/solutions/plugins/experimentation/src/ued.js b/_src/plugins/experimentation/src/ued.js similarity index 100% rename from solutions/plugins/experimentation/src/ued.js rename to _src/plugins/experimentation/src/ued.js diff --git a/solutions/plugins/rum-conversion/.eslintignore b/_src/plugins/rum-conversion/.eslintignore similarity index 100% rename from solutions/plugins/rum-conversion/.eslintignore rename to _src/plugins/rum-conversion/.eslintignore diff --git a/solutions/plugins/experimentation/.eslintrc.js b/_src/plugins/rum-conversion/.eslintrc.js similarity index 100% rename from solutions/plugins/experimentation/.eslintrc.js rename to _src/plugins/rum-conversion/.eslintrc.js diff --git a/solutions/plugins/rum-conversion/.gitignore b/_src/plugins/rum-conversion/.gitignore similarity index 100% rename from solutions/plugins/rum-conversion/.gitignore rename to _src/plugins/rum-conversion/.gitignore diff --git a/solutions/plugins/rum-conversion/.npmignore b/_src/plugins/rum-conversion/.npmignore similarity index 100% rename from solutions/plugins/rum-conversion/.npmignore rename to _src/plugins/rum-conversion/.npmignore diff --git a/solutions/plugins/experimentation/.stylelintrc.json b/_src/plugins/rum-conversion/.stylelintrc.json similarity index 100% rename from solutions/plugins/experimentation/.stylelintrc.json rename to _src/plugins/rum-conversion/.stylelintrc.json diff --git a/solutions/plugins/rum-conversion/LICENSE b/_src/plugins/rum-conversion/LICENSE similarity index 100% rename from solutions/plugins/rum-conversion/LICENSE rename to _src/plugins/rum-conversion/LICENSE diff --git a/solutions/plugins/rum-conversion/README.md b/_src/plugins/rum-conversion/README.md similarity index 100% rename from solutions/plugins/rum-conversion/README.md rename to _src/plugins/rum-conversion/README.md diff --git a/solutions/plugins/rum-conversion/package-lock.json b/_src/plugins/rum-conversion/package-lock.json similarity index 100% rename from solutions/plugins/rum-conversion/package-lock.json rename to _src/plugins/rum-conversion/package-lock.json diff --git a/solutions/plugins/rum-conversion/package.json b/_src/plugins/rum-conversion/package.json similarity index 100% rename from solutions/plugins/rum-conversion/package.json rename to _src/plugins/rum-conversion/package.json diff --git a/solutions/plugins/rum-conversion/src/index.js b/_src/plugins/rum-conversion/src/index.js similarity index 100% rename from solutions/plugins/rum-conversion/src/index.js rename to _src/plugins/rum-conversion/src/index.js diff --git a/solutions/scripts/breadcrumbs.js b/_src/scripts/breadcrumbs.js similarity index 80% rename from solutions/scripts/breadcrumbs.js rename to _src/scripts/breadcrumbs.js index 0a701a416..716e3effb 100644 --- a/solutions/scripts/breadcrumbs.js +++ b/_src/scripts/breadcrumbs.js @@ -2,17 +2,16 @@ import { createTag, fetchIndex, fixExcelFilterZeroes, -} from './utils.js'; - -// eslint-disable-next-line import/no-cycle -import { decorateBlockWithRegionId } from './scripts.js'; + getDomain, + decorateBlockWithRegionId, +} from './utils/utils.js'; function prependSlash(path) { return path.startsWith('/') ? path : `/${path}`; } function getName(pageIndex, path, part, current) { - const pg = pageIndex.find((page) => page.path === path); + const pg = pageIndex.find((page) => page.path.replace(/^\/[^/]+/, '') === path.replace(/^\/[^/]+/, '')); if (pg && pg.breadcrumbtitle && pg.breadcrumbtitle !== '0') { return pg.breadcrumbtitle; } @@ -40,7 +39,8 @@ async function createBreadcrumbs(container) { const { pathname } = window.location; const pathSeparator = '/'; // split pathname into parts add / at the end and remove empty parts - const pathSplit = pathname.split('/').reduce((acc, curr, index, array) => { + const domain = getDomain(); + const pathSplit = pathname.split('/').filter((item) => item !== domain).reduce((acc, curr, index, array) => { if (index < array.length - 1) { acc.push(`${curr}/`); } else if (curr !== '') { @@ -57,19 +57,19 @@ async function createBreadcrumbs(container) { const breadcrumbs = [ { name: 'Home', - url_path: '/', + url_path: `/${domain}/`, }, ...pathSplit.slice(1, -1).map((part, index) => { const url = urlForIndex(index); return { - name: getName(pageIndex, url, part, false), - url_path: url, + name: getName(pageIndex, `/${domain}${url}`, part, false, domain), + url_path: `/${domain}${url}`, }; }), { // get the breadcrumb title from the metadata; if the metadata does not contain it, // the last part of the path is used as the breadcrumb title - name: getName(pageIndex, pathname, pathSplit[pathSplit.length - 1], true), + name: getName(pageIndex, pathname, pathSplit[pathSplit.length - 1], true, domain), }, ]; diff --git a/_src/scripts/delayed.js b/_src/scripts/delayed.js new file mode 100644 index 000000000..2b6e6dc09 --- /dev/null +++ b/_src/scripts/delayed.js @@ -0,0 +1,24 @@ +// eslint-disable-next-line import/no-cycle +import { + sampleRUM, + getMetadata, +} from './lib-franklin.js'; + +import { loadBreadcrumbs } from './breadcrumbs.js'; +import { openUrlForOs } from './utils/utils.js'; + +// Core Web Vitals RUM collection +sampleRUM('cwv'); + +// Load breadcrumbs +loadBreadcrumbs(); + +// Get the open URL for the user's OS +const urlMacos = getMetadata('open-url-macos'); +const urlWindows = getMetadata('open-url-windows'); +const urlAndroid = getMetadata('open-url-android'); +const urlIos = getMetadata('open-url-ios'); + +if (urlMacos || urlWindows || urlAndroid || urlIos) { + openUrlForOs(urlMacos, urlWindows, urlAndroid, urlIos); +} diff --git a/_src/scripts/lib-franklin-api.js b/_src/scripts/lib-franklin-api.js new file mode 100644 index 000000000..7cfa9d3f0 --- /dev/null +++ b/_src/scripts/lib-franklin-api.js @@ -0,0 +1,264 @@ +/** + * @param {HTMLDivElement} shadoRoot + * @param {string} origin - prepends the origin to the relative links + */ +const updateLinkSources = (shadoRoot, origin) => { + shadoRoot + .querySelectorAll('source') + .forEach(source => source.srcset = new URL(source.getAttribute("srcset"), origin).href); + + shadoRoot + .querySelectorAll('img') + .forEach(image => image.src = new URL(image.getAttribute("src"), origin).href); +}; + +let ICONS_CACHE = {}; +async function decorateIcons(element) { + // Prepare the inline sprite + let svgSprite = element.getElementById('franklin-svg-sprite'); + if (!svgSprite) { + const div = document.createElement('div'); + div.innerHTML = ''; + svgSprite = div.firstElementChild; + element.append(div.firstElementChild); + } + // Download all new icons + const icons = [...element.querySelectorAll('span.icon')]; + await Promise.all(icons.map(async (span) => { + const iconName = Array.from(span.classList).find((c) => c.startsWith('icon-')).substring(5); + if (!ICONS_CACHE[iconName]) { + ICONS_CACHE[iconName] = true; + try { + let dynamicIconsSharepointPath = 'https://www.bitdefender.com/common/icons/'; + if (window.location.hostname.includes('bitdefender.co.uk')) { + dynamicIconsSharepointPath = 'https://www.bitdefender.co.uk/content/dam/franklin/'; + } + if (window.location.hostname.includes('bitdefender.fr')) { + dynamicIconsSharepointPath = 'https://www.bitdefender.fr/content/dam/franklin/'; + } + // check for localhost + if (window.location.hostname === 'localhost') { + dynamicIconsSharepointPath = 'https://www.bitdefender.com/common/icons/'; + } + const response = await fetch(`${dynamicIconsSharepointPath}${iconName}.svg`); + if (!response.ok) { + ICONS_CACHE[iconName] = false; + return; + } + // Styled icons don't play nice with the sprite approach because of shadow dom isolation + const svg = await response.text(); + if (svg.match(/(