Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
## [1.0.3](https://github.com/rtCamp/carousel-system-interactivity-api/compare/v1.0.2...v1.0.3) (2026-02-24)


### Bug Fixes

* enable loop on editor ([fe4566a](https://github.com/rtCamp/carousel-system-interactivity-api/commit/fe4566afcf72e1e663c7eb481a7957d62c2d3365))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we update these links to rtcamp/carousel-kit ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I will raise a separate PR for this.

* state corruption when clicking between slides ([637e4a5](https://github.com/rtCamp/carousel-system-interactivity-api/commit/637e4a507eb2c58576c4004d5460e8aa7295db9f))

## [1.0.2](https://github.com/rtCamp/carousel-system-interactivity-api/compare/v1.0.1...v1.0.2) (2026-02-23)


Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "carousel-kit",
"version": "1.0.2",
"version": "1.0.3",
"description": "Carousel block using Embla and WordPress Interactivity API",
"author": "rtCamp",
"private": true,
Expand Down
2 changes: 1 addition & 1 deletion src/blocks/carousel/edit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ export default function Edit( {
checked={ loop }
onChange={ ( value ) => setAttributes( { loop: value } ) }
help={ __(
'Infinite scrolling of slides (Frontend only). Disabled in editor for stability.',
'Enables infinite scrolling of slides.',
'carousel-kit',
) }
/>
Expand Down
63 changes: 30 additions & 33 deletions src/blocks/carousel/viewport/edit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,22 +93,22 @@ export default function Edit( {
return;
}

const viewportEl = emblaRef.current;
let embla: EmblaCarouselType | undefined;
let observer: MutationObserver | undefined;

const initEmbla = () => {
if ( embla ) {
embla.destroy();
}

const queryLoopContainer = emblaRef.current?.querySelector(
const queryLoopContainer = viewportEl.querySelector(
'.wp-block-post-template',
) as HTMLElement;

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const options = carouselOptions as any;

embla = EmblaCarousel( emblaRef.current!, {
embla = EmblaCarousel( viewportEl, {
loop: options?.loop ?? false,
dragFree: options?.dragFree ?? false,
containScroll: options?.containScroll || 'trimSnaps',
Expand All @@ -117,9 +117,12 @@ export default function Edit( {
direction: options?.direction || 'ltr',
slidesToScroll: options?.slidesToScroll || 1,
container: queryLoopContainer || undefined,
watchDrag: false, // Clicks in slide gaps must not trigger Embla scroll in the editor.
watchSlides: false, // Gutenberg injects block UI nodes into .embla__container; Embla's built-in MutationObserver would call reInit() on those, corrupting slide order and transforms.
watchResize: false, // Block toolbar appearing on selection can cause a layout shift that triggers an unwanted reInit.
} );

( emblaRef.current as { [EMBLA_KEY]?: typeof embla } )[ EMBLA_KEY ] = embla;
( viewportEl as { [EMBLA_KEY]?: typeof embla } )[ EMBLA_KEY ] = embla;

const onSelect = () => {
const canPrev = embla!.canScrollPrev();
Expand All @@ -140,42 +143,40 @@ export default function Edit( {

initEmbla();

if ( emblaRef.current ) {
observer = new MutationObserver( ( mutations ) => {
let shouldReInit = false;
const observer = new MutationObserver( ( mutations ) => {
let shouldReInit = false;

for ( const mutation of mutations ) {
const target = mutation.target as HTMLElement;
for ( const mutation of mutations ) {
const target = mutation.target as HTMLElement;

if ( target.classList.contains( 'wp-block-post-template' ) ) {
shouldReInit = true;
break;
}
if ( target.classList.contains( 'wp-block-post-template' ) ) {
shouldReInit = true;
break;
}

if (
mutation.addedNodes.length > 0 &&
if (
mutation.addedNodes.length > 0 &&
( target.querySelector( '.wp-block-post-template' ) ||
Array.from( mutation.addedNodes ).some(
( node ) =>
node instanceof HTMLElement &&
node.classList.contains( 'wp-block-post-template' ),
) )
) {
shouldReInit = true;
break;
}
) {
shouldReInit = true;
break;
}
}

if ( shouldReInit ) {
setTimeout( initEmbla, 10 );
}
} );
if ( shouldReInit ) {
setTimeout( initEmbla, 10 );
}
} );

observer.observe( emblaRef.current, {
childList: true,
subtree: true,
} );
}
observer.observe( viewportEl, {
childList: true,
subtree: true,
} );

return () => {
if ( embla ) {
Expand All @@ -184,11 +185,7 @@ export default function Edit( {
if ( observer ) {
observer.disconnect();
}
if ( emblaRef.current ) {
delete ( emblaRef.current as { [EMBLA_KEY]?: typeof embla } )[
EMBLA_KEY
];
}
delete ( viewportEl as { [EMBLA_KEY]?: typeof embla } )[ EMBLA_KEY ];
};
}, [ setEmblaApi, setCanScrollPrev, setCanScrollNext, carouselOptions ] );

Expand Down