Skip to content

Commit a64ddab

Browse files
authored
Merge pull request #14 from rtCamp/feat/lazy-loading-carousel
Feature: Lazy initialize carousels when (about to be) in view
2 parents 725009c + 2594d1b commit a64ddab

1 file changed

Lines changed: 49 additions & 22 deletions

File tree

src/blocks/carousel/view.ts

Lines changed: 49 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,13 @@ store( 'core-carousel/carousel', {
104104
return false;
105105
}
106106

107+
// Filter siblings to find index among valid slides
108+
const slides = Array.from( slide.parentElement.children ).filter(
109+
( child: Element ) =>
110+
child.classList?.contains( 'embla__slide' ) ||
111+
child.classList?.contains( 'wp-block-post' ),
112+
);
113+
107114
const index = slides.indexOf( slide );
108115
if ( index === -1 ) {
109116
return false;
@@ -137,9 +144,7 @@ store( 'core-carousel/carousel', {
137144
return;
138145
}
139146

140-
const viewport = element.querySelector(
141-
'.embla',
142-
);
147+
const viewport = element.querySelector( '.embla' );
143148

144149
if ( ! viewport ) {
145150
// eslint-disable-next-line no-console
@@ -196,12 +201,14 @@ store( 'core-carousel/carousel', {
196201
const plugins = [];
197202

198203
if ( context.autoplay ) {
199-
plugins.push(
200-
Autoplay( context.autoplay as AutoplayOptionsType ),
201-
);
204+
plugins.push( Autoplay( context.autoplay as AutoplayOptionsType ) );
202205
}
203206

204-
const embla = EmblaCarousel( viewport as HTMLElement, options, plugins );
207+
const embla = EmblaCarousel(
208+
viewport as HTMLElement,
209+
options,
210+
plugins,
211+
);
205212

206213
emblaInstances.set( viewport, embla );
207214
viewport[ EMBLA_KEY ] = embla;
@@ -238,26 +245,46 @@ store( 'core-carousel/carousel', {
238245
};
239246

240247
let cleanupEmbla: ( () => void ) | undefined;
241-
let observer: ResizeObserver | undefined;
248+
let resizeObserver: ResizeObserver | undefined;
249+
let intersectionObserver: IntersectionObserver | undefined;
250+
251+
const init = () => {
252+
if ( viewport.getBoundingClientRect().width > 0 ) {
253+
cleanupEmbla = startEmbla();
254+
} else {
255+
resizeObserver = new ResizeObserver( ( entries ) => {
256+
for ( const entry of entries ) {
257+
if ( entry.contentRect.width > 0 ) {
258+
cleanupEmbla = startEmbla();
259+
resizeObserver?.disconnect();
260+
resizeObserver = undefined;
261+
break;
262+
}
263+
}
264+
} );
265+
resizeObserver.observe( viewport );
266+
}
267+
};
242268

243-
if ( viewport.getBoundingClientRect().width > 0 ) {
244-
cleanupEmbla = startEmbla();
245-
} else {
246-
observer = new ResizeObserver( ( entries ) => {
247-
for ( const entry of entries ) {
248-
if ( entry.contentRect.width > 0 ) {
249-
cleanupEmbla = startEmbla();
250-
observer?.disconnect();
251-
observer = undefined;
252-
break;
269+
if ( 'IntersectionObserver' in window ) {
270+
intersectionObserver = new IntersectionObserver(
271+
( entries ) => {
272+
if ( entries[ 0 ].isIntersecting ) {
273+
init();
274+
intersectionObserver?.disconnect();
275+
intersectionObserver = undefined;
253276
}
254-
}
255-
} );
256-
observer.observe( viewport );
277+
},
278+
{ rootMargin: '200px' },
279+
);
280+
intersectionObserver.observe( viewport );
281+
} else {
282+
init();
257283
}
258284

259285
return () => {
260-
observer?.disconnect();
286+
resizeObserver?.disconnect();
287+
intersectionObserver?.disconnect();
261288
cleanupEmbla?.();
262289
};
263290
} catch ( e ) {

0 commit comments

Comments
 (0)