From 260685cc35ac440b7be43c51a8a8410e441937f7 Mon Sep 17 00:00:00 2001 From: Tomasz Dziezyk Date: Fri, 7 Jun 2024 13:56:09 +0200 Subject: [PATCH 1/5] Update fonts and primary color --- blocks/hero/hero.css | 9 +++++++ styles/styles.css | 58 +++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 64 insertions(+), 3 deletions(-) diff --git a/blocks/hero/hero.css b/blocks/hero/hero.css index 1a377ac..a8599f3 100644 --- a/blocks/hero/hero.css +++ b/blocks/hero/hero.css @@ -32,3 +32,12 @@ main .hero-container { width: 100%; height: 100%; } + +.hero h1, +.hero h2, +.hero h3, +.hero h4, +.hero h5, +.hero h6 { + color: white; +} diff --git a/styles/styles.css b/styles/styles.css index ff5fa54..03b1a85 100644 --- a/styles/styles.css +++ b/styles/styles.css @@ -12,8 +12,8 @@ :root { /* colors */ - --link-color: #035fe6; - --link-hover-color: #136ff6; + --link-color: #80ba27; + --link-hover-color: #80ba27; --background-color: white; --light-color: #eee; --dark-color: #ccc; @@ -21,7 +21,7 @@ /* fonts */ --body-font-family: roboto, roboto-fallback; - --heading-font-family: var(--body-font-family); + --heading-font-family: font-family: calibre, helvetica, tahoma, arial, sans-serif; --fixed-font-family: 'Roboto Mono', menlo, consolas, 'Liberation Mono', monospace; /* body sizes */ @@ -224,3 +224,55 @@ main .section.light, main .section.highlight { background-color: var(--light-color); } + +.h1,h1 { + font-weight: 300; + font-size: 5rem; + color: #000; + letter-spacing: -.084rem; + line-height: 6rem; + margin-bottom: 3rem +} + +@media (width <= 1023.9px) { + .h1,h1 { + font-size:3rem; + line-height: 3.5rem; + margin-bottom: 1.5rem + } +} + +.h2,h2 { + font-weight: 300; + font-size: 4rem; + color: #000; + letter-spacing: -.02rem; + line-height: 4.5rem; + margin: 0; + padding: 0 +} + +@media (width <= 1023.9px) { + .h2,h2 { + font-size:3rem; + line-height: 3.5rem; + letter-spacing: -.05rem + } +} + +.h3,h3 { + font-weight: 300; + font-size: 3rem; + color: #000; + letter-spacing: -.015rem; + line-height: 4rem; + margin: 0; + padding: 0 +} + +@media (width <= 1023.9px) { + .h3,h3 { + font-size:2.6rem; + line-height: 3rem + } +} From 2244aab3901c5d5a3f17cce4e86523f947af4b85 Mon Sep 17 00:00:00 2001 From: Tomasz Dziezyk Date: Fri, 7 Jun 2024 15:32:34 +0200 Subject: [PATCH 2/5] Add accordion, embed and quote blocks --- blocks/accordion/accordion.css | 57 +++++++++++++++++ blocks/accordion/accordion.js | 33 ++++++++++ blocks/embed/embed.css | 62 ++++++++++++++++++ blocks/embed/embed.js | 113 +++++++++++++++++++++++++++++++++ blocks/quote/quote.css | 34 ++++++++++ blocks/quote/quote.js | 30 +++++++++ 6 files changed, 329 insertions(+) create mode 100644 blocks/accordion/accordion.css create mode 100644 blocks/accordion/accordion.js create mode 100644 blocks/embed/embed.css create mode 100644 blocks/embed/embed.js create mode 100644 blocks/quote/quote.css create mode 100644 blocks/quote/quote.js diff --git a/blocks/accordion/accordion.css b/blocks/accordion/accordion.css new file mode 100644 index 0000000..e9b3c2c --- /dev/null +++ b/blocks/accordion/accordion.css @@ -0,0 +1,57 @@ +.accordion details { + border: 1px solid var(--dark-color); +} + +/* stylelint-disable-next-line no-descending-specificity */ +.accordion details + details { + margin-top: 16px; +} + +.accordion details summary { + position: relative; + padding: 0 16px; + padding-right: 48px; + cursor: pointer; + list-style: none; + overflow: auto; + transition: background-color 0.2s; +} + +.accordion details[open] summary { + background-color: var(--light-color); +} + +.accordion details summary:focus, +.accordion details summary:hover { + background-color: var(--dark-color); +} + +.accordion details summary::-webkit-details-marker { + display: none; +} + +.accordion details summary::after { + content: ""; + position: absolute; + top: 50%; + right: 18px; + transform: translateY(-50%) rotate(135deg); + width: 9px; + height: 9px; + border: 2px solid; + border-width: 2px 2px 0 0; + transition: transform 0.2s; +} + +.accordion details[open] summary::after { + transform: translateY(-50%) rotate(-45deg); +} + +.accordion details .accordion-item-body { + padding: 0 16px; +} + +.accordion details[open] .accordion-item-body { + border-top: 1px solid var(--dark-color); + background-color: var(--background-color); +} \ No newline at end of file diff --git a/blocks/accordion/accordion.js b/blocks/accordion/accordion.js new file mode 100644 index 0000000..53ded06 --- /dev/null +++ b/blocks/accordion/accordion.js @@ -0,0 +1,33 @@ +/* + * Accordion Block + * Recreate an accordion + * https://www.hlx.live/developer/block-collection/accordion + */ + +function hasWrapper(el) { + return !!el.firstElementChild && window.getComputedStyle(el.firstElementChild).display === 'block'; +} + +export default function decorate(block) { + [...block.children].forEach((row) => { + // decorate accordion item label + const label = row.children[0]; + const summary = document.createElement('summary'); + summary.className = 'accordion-item-label'; + summary.append(...label.childNodes); + if (!hasWrapper(summary)) { + summary.innerHTML = `

${summary.innerHTML}

`; + } + // decorate accordion item body + const body = row.children[1]; + body.className = 'accordion-item-body'; + if (!hasWrapper(body)) { + body.innerHTML = `

${body.innerHTML}

`; + } + // decorate accordion item + const details = document.createElement('details'); + details.className = 'accordion-item'; + details.append(summary, body); + row.replaceWith(details); + }); +} diff --git a/blocks/embed/embed.css b/blocks/embed/embed.css new file mode 100644 index 0000000..28c4429 --- /dev/null +++ b/blocks/embed/embed.css @@ -0,0 +1,62 @@ +.embed { + width: unset; + text-align: center; + max-width: 800px; + margin: 32px auto; +} + +.embed > div { + display: flex; + justify-content: center; +} + +.embed.embed-twitter .twitter-tweet-rendered { + margin-left: auto; + margin-right: auto; +} + +.embed .embed-placeholder { + width: 100%; + aspect-ratio: 16 / 9; + position: relative; +} + +.embed .embed-placeholder > * { + display: flex; + align-items: center; + justify-content: center; + position: absolute; + inset: 0; +} + +.embed .embed-placeholder picture img { + width: 100%; + height: 100%; + object-fit: cover; +} + +.embed .embed-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; +} + +.embed .embed-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/blocks/embed/embed.js b/blocks/embed/embed.js new file mode 100644 index 0000000..a695ec0 --- /dev/null +++ b/blocks/embed/embed.js @@ -0,0 +1,113 @@ +/* + * Embed Block + * Show videos and social posts directly on your page + * https://www.hlx.live/developer/block-collection/embed + */ + +const loadScript = (url, callback, type) => { + const head = document.querySelector('head'); + const script = document.createElement('script'); + script.src = url; + if (type) { + script.setAttribute('type', type); + } + script.onload = callback; + head.append(script); + return script; +}; + +const getDefaultEmbed = (url) => `
+ +
`; + +const 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('/'); + } + const embedHTML = `
+ +
`; + return embedHTML; +}; + +const embedVimeo = (url, autoplay) => { + const [, video] = url.pathname.split('/'); + const suffix = autoplay ? '?muted=1&autoplay=1' : ''; + const embedHTML = `
+ +
`; + return embedHTML; +}; + +const embedTwitter = (url) => { + const embedHTML = ``; + loadScript('https://platform.twitter.com/widgets.js'); + return embedHTML; +}; + +const loadEmbed = (block, link, autoplay) => { + if (block.classList.contains('embed-is-loaded')) { + return; + } + + const EMBEDS_CONFIG = [ + { + match: ['youtube', 'youtu.be'], + embed: embedYoutube, + }, + { + match: ['vimeo'], + embed: embedVimeo, + }, + { + match: ['twitter'], + embed: embedTwitter, + }, + ]; + + const config = EMBEDS_CONFIG.find((e) => e.match.some((match) => link.includes(match))); + const url = new URL(link); + if (config) { + block.innerHTML = config.embed(url, autoplay); + block.classList = `block embed embed-${config.match[0]}`; + } else { + block.innerHTML = getDefaultEmbed(url); + block.classList = 'block embed'; + } + block.classList.add('embed-is-loaded'); +}; + +export default function decorate(block) { + const placeholder = block.querySelector('picture'); + const link = block.querySelector('a').href; + block.textContent = ''; + + if (placeholder) { + const wrapper = document.createElement('div'); + wrapper.className = 'embed-placeholder'; + wrapper.innerHTML = '
'; + wrapper.prepend(placeholder); + wrapper.addEventListener('click', () => { + loadEmbed(block, link, true); + }); + block.append(wrapper); + } else { + const observer = new IntersectionObserver((entries) => { + if (entries.some((e) => e.isIntersecting)) { + observer.disconnect(); + loadEmbed(block, link); + } + }); + observer.observe(block); + } +} diff --git a/blocks/quote/quote.css b/blocks/quote/quote.css new file mode 100644 index 0000000..1fc60e9 --- /dev/null +++ b/blocks/quote/quote.css @@ -0,0 +1,34 @@ +.quote blockquote { + margin: 0 auto; + padding: 0 32px; + max-width: 700px; +} + +.quote blockquote .quote-quotation { + font-size: 120%; +} + +.quote blockquote .quote-quotation > :first-child { + text-indent: -0.6ch; +} + +.quote blockquote .quote-quotation > :first-child::before, +.quote blockquote .quote-quotation > :last-child::after { + line-height: 0; +} + +.quote blockquote .quote-quotation > :first-child::before { + content: "“"; +} + +.quote blockquote .quote-quotation > :last-child::after { + content: "”"; +} + +.quote blockquote .quote-attribution { + text-align: right; +} + +.quote blockquote .quote-attribution > :first-child::before { + content: "—"; +} \ No newline at end of file diff --git a/blocks/quote/quote.js b/blocks/quote/quote.js new file mode 100644 index 0000000..d6c51ed --- /dev/null +++ b/blocks/quote/quote.js @@ -0,0 +1,30 @@ +function hasWrapper(el) { + return !!el.firstElementChild && window.getComputedStyle(el.firstElementChild).display === 'block'; +} + +export default async function decorate(block) { + const [quotation, attribution] = [...block.children].map((c) => c.firstElementChild); + const blockquote = document.createElement('blockquote'); + // decorate quotation + quotation.className = 'quote-quotation'; + if (!hasWrapper(quotation)) { + quotation.innerHTML = `

${quotation.innerHTML}

`; + } + blockquote.append(quotation); + // decoration attribution + if (attribution) { + attribution.className = 'quote-attribution'; + if (!hasWrapper(attribution)) { + attribution.innerHTML = `

${attribution.innerHTML}

`; + } + blockquote.append(attribution); + const ems = attribution.querySelectorAll('em'); + ems.forEach((em) => { + const cite = document.createElement('cite'); + cite.innerHTML = em.innerHTML; + em.replaceWith(cite); + }); + } + block.innerHTML = ''; + block.append(blockquote); +} From 3df62ecf6720b6c16a03195dc8a1888c61eb1763 Mon Sep 17 00:00:00 2001 From: Tomasz Dziezyk Date: Fri, 7 Jun 2024 16:01:16 +0200 Subject: [PATCH 3/5] Add table block --- blocks/table/table.css | 58 ++++++++++++++++++++++++++++++++++++++++++ blocks/table/table.js | 36 ++++++++++++++++++++++++++ 2 files changed, 94 insertions(+) create mode 100644 blocks/table/table.css create mode 100644 blocks/table/table.js diff --git a/blocks/table/table.css b/blocks/table/table.css new file mode 100644 index 0000000..7f18772 --- /dev/null +++ b/blocks/table/table.css @@ -0,0 +1,58 @@ +.table { + width: 100%; + overflow-x: auto; +} + +.table table { + width: 100%; + max-width: 100%; + border-collapse: collapse; + font-size: var(--body-font-size-xs); +} + +@media (width >= 600px) { + .table table { + font-size: var(--body-font-size-s); + } +} + +@media (width >= 900px) { + .table table { + font-size: var(--body-font-size-m); + } +} + +.table table thead tr { + border-top: 2px solid; + border-bottom: 2px solid; +} + +.table table tbody tr { + border-bottom: 1px solid; +} + +.table table th { + font-weight: 700; +} + +.table table th, +.table table td { + padding: 8px 16px; + text-align: left; +} + +/* no header variant */ +.table.no-header table tbody tr { + border-top: 1px solid; +} + +/* striped variant */ +.table.striped tbody tr:nth-child(odd) { + background-color: var(--overlay-background-color); +} + +/* bordered variant */ +.table.bordered table th, +.table.bordered table td { + border: 1px solid; +} \ No newline at end of file diff --git a/blocks/table/table.js b/blocks/table/table.js new file mode 100644 index 0000000..f545f38 --- /dev/null +++ b/blocks/table/table.js @@ -0,0 +1,36 @@ +/* + * Table Block + * Recreate a table + * https://www.hlx.live/developer/block-collection/table + */ + +function buildCell(rowIndex) { + const cell = rowIndex ? document.createElement('td') : document.createElement('th'); + if (!rowIndex) cell.setAttribute('scope', 'col'); + return cell; +} + +export default async function decorate(block) { + const table = document.createElement('table'); + const thead = document.createElement('thead'); + const tbody = document.createElement('tbody'); + + const header = !block.classList.contains('no-header'); + if (header) { + table.append(thead); + } + table.append(tbody); + + [...block.children].forEach((child, i) => { + const row = document.createElement('tr'); + if (header && i === 0) thead.append(row); + else tbody.append(row); + [...child.children].forEach((col) => { + const cell = buildCell(header ? i : i + 1); + cell.innerHTML = col.innerHTML; + row.append(cell); + }); + }); + block.innerHTML = ''; + block.append(table); +} From b66b8f6bd59ccfdf6c9631f4659d2f439b20d18e Mon Sep 17 00:00:00 2001 From: Tomasz Dziezyk Date: Mon, 10 Jun 2024 09:28:13 +0200 Subject: [PATCH 4/5] Add tabs block --- blocks/tabs/tabs.css | 46 +++++++++++++++++++++++++++++++++++++ blocks/tabs/tabs.js | 54 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+) create mode 100644 blocks/tabs/tabs.css create mode 100644 blocks/tabs/tabs.js diff --git a/blocks/tabs/tabs.css b/blocks/tabs/tabs.css new file mode 100644 index 0000000..0244877 --- /dev/null +++ b/blocks/tabs/tabs.css @@ -0,0 +1,46 @@ +.tabs .tabs-list { + display: flex; + gap: 8px; + max-width: 100%; + overflow-x: auto; +} + +.tabs .tabs-list button { + flex: 0 0 max-content; + margin: 0; + border: 1px solid var(--dark-color); + border-radius: 0; + padding: 8px 16px; + background-color: var(--light-color); + color: initial; + font-size: unset; + font-weight: bold; + line-height: unset; + text-align: initial; + text-overflow: unset; + overflow: unset; + white-space: unset; + transition: background-color 0.2s; +} + +.tabs .tabs-list button[aria-selected="true"] { + border-bottom: 1px solid var(--background-color); + background-color: var(--background-color); + cursor: initial; +} + +.tabs .tabs-list button[aria-selected="false"]:hover, +.tabs .tabs-list button[aria-selected="false"]:focus { + background-color: var(--dark-color); +} + +.tabs .tabs-panel { + margin-top: -1px; + padding: 0 16px; + border: 1px solid var(--dark-color); + overflow: auto; +} + +.tabs .tabs-panel[aria-hidden="true"] { + display: none; +} \ No newline at end of file diff --git a/blocks/tabs/tabs.js b/blocks/tabs/tabs.js new file mode 100644 index 0000000..89a2885 --- /dev/null +++ b/blocks/tabs/tabs.js @@ -0,0 +1,54 @@ +// eslint-disable-next-line import/no-unresolved +import { toClassName } from '../../scripts/aem.js'; + +function hasWrapper(el) { + return !!el.firstElementChild && window.getComputedStyle(el.firstElementChild).display === 'block'; +} + +export default async function decorate(block) { + // build tablist + const tablist = document.createElement('div'); + tablist.className = 'tabs-list'; + tablist.setAttribute('role', 'tablist'); + + // decorate tabs and tabpanels + const tabs = [...block.children].map((child) => child.firstElementChild); + tabs.forEach((tab, i) => { + const id = toClassName(tab.textContent); + + // decorate tabpanel + const tabpanel = block.children[i]; + tabpanel.className = 'tabs-panel'; + tabpanel.id = `tabpanel-${id}`; + tabpanel.setAttribute('aria-hidden', !!i); + tabpanel.setAttribute('aria-labelledby', `tab-${id}`); + tabpanel.setAttribute('role', 'tabpanel'); + if (!hasWrapper(tabpanel.lastElementChild)) { + tabpanel.lastElementChild.innerHTML = `

${tabpanel.lastElementChild.innerHTML}

`; + } + + // build tab button + const button = document.createElement('button'); + button.className = 'tabs-tab'; + button.id = `tab-${id}`; + button.innerHTML = tab.innerHTML; + button.setAttribute('aria-controls', `tabpanel-${id}`); + button.setAttribute('aria-selected', !i); + button.setAttribute('role', 'tab'); + button.setAttribute('type', 'button'); + button.addEventListener('click', () => { + block.querySelectorAll('[role=tabpanel]').forEach((panel) => { + panel.setAttribute('aria-hidden', true); + }); + tablist.querySelectorAll('button').forEach((btn) => { + btn.setAttribute('aria-selected', false); + }); + tabpanel.setAttribute('aria-hidden', false); + button.setAttribute('aria-selected', true); + }); + tablist.append(button); + tab.remove(); + }); + + block.prepend(tablist); +} From b1bd5179a5bd131956aa0e4edc34661cc00e3401 Mon Sep 17 00:00:00 2001 From: Tomasz Dziezyk Date: Mon, 10 Jun 2024 10:15:52 +0200 Subject: [PATCH 5/5] Add video block --- blocks/video/video.css | 72 +++++++++++++++++++++++ blocks/video/video.js | 129 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 201 insertions(+) create mode 100644 blocks/video/video.css create mode 100644 blocks/video/video.js diff --git a/blocks/video/video.css b/blocks/video/video.css new file mode 100644 index 0000000..19262de --- /dev/null +++ b/blocks/video/video.css @@ -0,0 +1,72 @@ +.video { + width: unset; + text-align: center; + max-width: 800px; + margin: 32px auto; +} + +.video.lazy-loading { + /* reserve an approximate space to avoid extensive layout shifts */ + aspect-ratio: 16 / 9; +} + +.video > div { + display: flex; + justify-content: center; +} + +.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/blocks/video/video.js b/blocks/video/video.js new file mode 100644 index 0000000..d68c1e0 --- /dev/null +++ b/blocks/video/video.js @@ -0,0 +1,129 @@ +/* + * Video Block + * Show a video referenced by a link + * https://www.hlx.live/developer/block-collection/video + */ + +function embedYoutube(url, replacePlaceholder, autoplay) { + const usp = new URLSearchParams(url.search); + let suffix = ''; + if (replacePlaceholder || autoplay) { + const suffixParams = { + autoplay: '1', + mute: autoplay ? '1' : '0', + controls: autoplay ? '0' : '1', + disablekb: autoplay ? '1' : '0', + loop: autoplay ? '1' : '0', + playsinline: autoplay ? '1' : '0', + }; + suffix = `&${Object.entries(suffixParams).map(([k, v]) => `${k}=${encodeURIComponent(v)}`).join('&')}`; + } + let vid = usp.get('v') ? encodeURIComponent(usp.get('v')) : ''; + const embed = url.pathname; + if (url.origin.includes('youtu.be')) { + [, vid] = url.pathname.split('/'); + } + + const temp = document.createElement('div'); + temp.innerHTML = `
+ +
`; + return temp.children.item(0); +} + +function embedVimeo(url, replacePlaceholder, autoplay) { + const [, video] = url.pathname.split('/'); + let suffix = ''; + if (replacePlaceholder || autoplay) { + const suffixParams = { + autoplay: '1', + background: autoplay ? '1' : '0', + }; + suffix = `?${Object.entries(suffixParams).map(([k, v]) => `${k}=${encodeURIComponent(v)}`).join('&')}`; + } + const temp = document.createElement('div'); + temp.innerHTML = `
+ +
`; + return temp.children.item(0); +} + +function getVideoElement(source, replacePlaceholder, autoplay) { + const video = document.createElement('video'); + video.setAttribute('controls', ''); + video.dataset.loading = 'true'; + video.addEventListener('loadedmetadata', () => delete video.dataset.loading); + if (autoplay || replacePlaceholder) { + video.setAttribute('autoplay', ''); + if (autoplay) { + video.setAttribute('loop', ''); + video.setAttribute('playsinline', ''); + video.removeAttribute('controls'); + video.addEventListener('canplay', () => { + video.muted = true; + video.play(); + }); + } + } + + 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, replacePlaceholder, 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'); + + let embedEl; + if (isYoutube) { + embedEl = embedYoutube(url, replacePlaceholder, autoplay); + } else if (isVimeo) { + embedEl = embedVimeo(url, replacePlaceholder, autoplay); + } else if (isMp4) { + embedEl = getVideoElement(link, replacePlaceholder, autoplay); + } + block.replaceChildren(embedEl); + + block.dataset.embedIsLoaded = true; +}; + +export default async function decorate(block) { + const placeholder = block.querySelector('picture'); + const link = block.querySelector('a').href; + block.textContent = ''; + + if (placeholder) { + const wrapper = document.createElement('div'); + wrapper.className = 'video-placeholder'; + wrapper.innerHTML = '
'; + wrapper.prepend(placeholder); + wrapper.addEventListener('click', () => { + loadVideoEmbed(block, link, true, false); + }); + 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.contains('autoplay')); + block.classList.remove('lazy-loading'); + } + }); + observer.observe(block); + } +}