Skip to content

Commit 4ddc470

Browse files
authored
Merge pull request #15 from rtCamp/develop
Merge `develop` into `main`
2 parents 86b6aca + 9ad5b9a commit 4ddc470

2 files changed

Lines changed: 75 additions & 22 deletions

File tree

blueprint.json

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"$schema": "https://playground.wordpress.net/blueprint-schema.json",
3+
"preferredVersions": {
4+
"php": "8.2",
5+
"wp": "latest"
6+
},
7+
"landingPage": "/",
8+
"steps": [
9+
{
10+
"step": "installPlugin",
11+
"pluginData": {
12+
"resource": "url",
13+
"url": "https://github.com/rtCamp/core-carousel/releases/latest/download/core-carousel.zip"
14+
}
15+
},
16+
{
17+
"step": "login",
18+
"username": "admin",
19+
"password": "password"
20+
},
21+
{
22+
"step": "runPHP",
23+
"code": "<?php require_once 'wordpress/wp-load.php';\n\n$post_content = '<!-- wp:heading -->\\n<h2 class=\"wp-block-heading\">Core Carousel: A Composable System</h2>\\n<!-- /wp:heading -->\\n\\n<!-- wp:paragraph -->\\n<p>This demo showcases the <strong>Core Carousel</strong> system. Notice how the navigation controls and dots are separate blocks, allowing for total layout freedom.</p>\\n<!-- /wp:paragraph -->\\n\\n<!-- wp:core-carousel/carousel {\"loop\":true,\"autoplay\":true,\"autoplayDelay\":4000,\"slideGap\":20} -->\\n<div class=\"wp-block-core-carousel-carousel\">\\n <!-- wp:core-carousel/carousel-viewport -->\\n <div class=\"wp-block-core-carousel-carousel-viewport\">\\n <!-- wp:core-carousel/carousel-slide -->\\n <div class=\"wp-block-core-carousel-carousel-slide\">\\n <!-- wp:cover {\"url\":\"https://s.w.org/images/core/5.9/architecture.jpg\",\"dimRatio\":50,\"minHeight\":400,\"minHeightUnit\":\"px\",\"isDark\":true} -->\\n <div class=\"wp-block-cover is-light\" style=\"min-height:400px\"><img class=\"wp-block-cover__image-background\" src=\"https://s.w.org/images/core/5.9/architecture.jpg\" data-object-fit=\"cover\"/><div class=\"wp-block-cover__inner-container\"><!-- wp:heading {\"textAlign\":\"center\",\"level\":3} --><h3 class=\"wp-block-heading has-text-align-center\">Slide One</h3><!-- /wp:heading --></div></div>\\n <!-- /wp:cover -->\\n </div>\\n <!-- /wp:core-carousel/carousel-slide -->\\n\\n <!-- wp:core-carousel/carousel-slide -->\\n <div class=\"wp-block-core-carousel-carousel-slide\">\\n <!-- wp:cover {\"url\":\"https://s.w.org/images/core/5.9/puebla.jpg\",\"dimRatio\":50,\"minHeight\":400,\"minHeightUnit\":\"px\",\"isDark\":true} -->\\n <div class=\"wp-block-cover is-light\" style=\"min-height:400px\"><img class=\"wp-block-cover__image-background\" src=\"https://s.w.org/images/core/5.9/puebla.jpg\" data-object-fit=\"cover\"/><div class=\"wp-block-cover__inner-container\"><!-- wp:heading {\"textAlign\":\"center\",\"level\":3} --><h3 class=\"wp-block-heading has-text-align-center\">Slide Two</h3><!-- /wp:heading --></div></div>\\n <!-- /wp:cover -->\\n </div>\\n <!-- /wp:core-carousel/carousel-slide -->\\n\\n <!-- wp:core-carousel/carousel-slide -->\\n <div class=\"wp-block-core-carousel-carousel-slide\">\\n <!-- wp:cover {\"url\":\"https://s.w.org/images/core/5.9/victoria.jpg\",\"dimRatio\":50,\"minHeight\":400,\"minHeightUnit\":\"px\",\"isDark\":true} -->\\n <div class=\"wp-block-cover is-light\" style=\"min-height:400px\"><img class=\"wp-block-cover__image-background\" src=\"https://s.w.org/images/core/5.9/victoria.jpg\" data-object-fit=\"cover\"/><div class=\"wp-block-cover__inner-container\"><!-- wp:heading {\"textAlign\":\"center\",\"level\":3} --><h3 class=\"wp-block-heading has-text-align-center\">Slide Three</h3><!-- /wp:heading --></div></div>\\n <!-- /wp:cover -->\\n </div>\\n <!-- /wp:core-carousel/carousel-slide -->\\n </div>\\n <!-- /wp:core-carousel/carousel-viewport -->\\n\\n <!-- wp:spacer {\"height\":\"20px\"} -->\\n <div style=\"height:20px\" aria-hidden=\"true\" class=\"wp-block-spacer\"></div>\\n <!-- /wp:spacer -->\\n\n <!-- wp:group {\"layout\":{\"type\":\"flex\",\"flexWrap\":\"nowrap\",\"justifyContent\":\"space-between\"}} -->\\n <div class=\"wp-block-group\">\\n <!-- wp:core-carousel/carousel-dots /-->\\n <!-- wp:core-carousel/carousel-controls /-->\\n </div>\\n <!-- /wp:group -->\\n</div>\\n<!-- /wp:core-carousel/carousel -->';\n\n$post_id = wp_insert_post( array(\n 'post_title' => 'Core Carousel Interactive Demo',\n 'post_content' => $post_content,\n 'post_status' => 'publish',\n 'post_type' => 'page',\n) );\n\nupdate_option( 'show_on_front', 'page' );\nupdate_option( 'page_on_front', $post_id );"
24+
}
25+
]
26+
}

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)