Skip to content
54 changes: 11 additions & 43 deletions package-lock.json

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

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"@wordpress/icons": "11.5.0",
"@wordpress/interactivity": "6.37.0",
"embla-carousel": "8.6.0",
"embla-carousel-auto-scroll": "8.6.0",
"embla-carousel-autoplay": "8.6.0",
"react": "^18.3.1",
"react-dom": "^18.3.1"
Expand Down
18 changes: 18 additions & 0 deletions src/blocks/carousel/__tests__/edit.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,12 @@ const createAttributes = (): CarouselAttributes => ( {
ariaLabel: 'Carousel',
slidesToScroll: '1',
slideGap: 0,
autoScroll: false,
autoScrollSpeed: 2,
autoScrollDirection: 'forward' as const,
autoScrollStartDelay: 1000,
autoScrollStopOnInteraction: true,
autoScrollStopOnMouseEnter: false,
} );

describe( 'Carousel Edit setup flow', () => {
Expand Down Expand Up @@ -217,4 +223,16 @@ describe( 'Carousel Edit setup flow', () => {
Object.defineProperty( globalThis, 'document', originalDocumentDescriptor );
}
} );

it( 'should have correct default autoScroll attributes', () => {
const attributes = createAttributes();
expect( attributes.autoScroll ).toBe( false );
expect( attributes.autoScrollSpeed ).toBe( 2 );
expect( attributes.autoScrollDirection ).toBe( 'forward' );
expect( attributes.autoScrollStartDelay ).toBe( 1000 );
expect( attributes.autoScrollStopOnInteraction ).toBe( true );
expect( attributes.autoScrollStopOnMouseEnter ).toBe( false );
} );


} );
31 changes: 31 additions & 0 deletions src/blocks/carousel/__tests__/view.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ const createMockContext = (
scrollProgress: 0,
slideCount: 3,
ariaLabelPattern: 'Go to slide %d',
autoScroll: false,
...overrides,
} );

Expand Down Expand Up @@ -1010,4 +1011,34 @@ describe( 'Edge Cases and Error Handling', () => {
expect( mockContext.scrollSnaps ).toHaveLength( 100 );
expect( mockContext.selectedIndex ).toBe( 50 );
} );

it( 'should handle autoScroll configuration', () => {
const mockContextWithAutoScroll = createMockContext( {
autoScroll: {
speed: 3,
direction: 'forward',
startDelay: 500,
stopOnInteraction: false,
stopOnMouseEnter: true,
stopOnFocusIn: false,
},
} );

expect( mockContextWithAutoScroll.autoScroll ).toEqual( {
speed: 3,
direction: 'forward',
startDelay: 500,
stopOnInteraction: false,
stopOnMouseEnter: true,
stopOnFocusIn: false,
} );
} );

it( 'should handle autoScroll disabled', () => {
const mockContext = createMockContext( {
autoScroll: false,
} );

expect( mockContext.autoScroll ).toBe( false );
} );
} );
25 changes: 25 additions & 0 deletions src/blocks/carousel/block.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,31 @@
"slidesToScroll": {
"type": "string",
"default": "1"
},
"autoScroll": {
"type": "boolean",
"default": false
},
"autoScrollSpeed": {
"type": "number",
"default": 2
},
"autoScrollDirection": {
"type": "string",
"default": "ltr",
"enum": ["forward", "backward"]
},
"autoScrollStartDelay": {
"type": "number",
"default": 1000
},
"autoScrollStopOnInteraction": {
"type": "boolean",
"default": true
},
"autoScrollStopOnMouseEnter": {
"type": "boolean",
"default": false
}
},
"editorScript": "file:./index.js",
Expand Down
85 changes: 80 additions & 5 deletions src/blocks/carousel/edit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ export default function Edit( {
autoplayStopOnMouseEnter,
ariaLabel,
slidesToScroll = '1',
autoScroll,
autoScrollSpeed,
autoScrollDirection,
autoScrollStartDelay,
autoScrollStopOnInteraction,
autoScrollStopOnMouseEnter
} = attributes;

const [ emblaApi, setEmblaApi ] = useState<EmblaCarouselType | undefined>();
Expand Down Expand Up @@ -314,11 +320,11 @@ export default function Edit( {
<ToggleControl
label={ __( 'Loop', 'rt-carousel' ) }
checked={ loop }
disabled={ autoScrollDirection === 'backward' }
onChange={ ( value ) => setAttributes( { loop: value } ) }
help={ __(
'Enables infinite scrolling of slides.',
'rt-carousel',
) }
help={ autoScrollDirection === 'backward'
? __( 'Loop is required for backward auto scroll.', 'rt-carousel' )
: __( 'Enables infinite scrolling of slides.', 'rt-carousel' ) }
/>
<ToggleControl
label={ __( 'Free Drag', 'rt-carousel' ) }
Expand Down Expand Up @@ -421,7 +427,12 @@ export default function Edit( {
<ToggleControl
label={ __( 'Enable Autoplay', 'rt-carousel' ) }
checked={ autoplay }
onChange={ ( value ) => setAttributes( { autoplay: value } ) }
onChange={ ( value ) => {
setAttributes( {
autoplay: value,
autoScroll: value ? false : autoScroll,
} )
}}
/>
{ autoplay && (
<>
Expand Down Expand Up @@ -460,6 +471,70 @@ export default function Edit( {
</>
) }
</PanelBody>
<PanelBody
title={ __( 'Auto Scroll', 'rt-carousel' ) }
initialOpen={ false }
>
<ToggleControl
label={ __( 'Enable Auto Scroll', 'rt-carousel' ) }
checked={ autoScroll }
onChange={ ( value ) => setAttributes( {
autoScroll: value,
autoplay: value ? false : autoplay,
} ) }
/>
{ autoScroll && ( <>
<RangeControl
label={ __( 'Speed', 'rt-carousel' ) }
value={ autoScrollSpeed }
onChange={ ( value ) =>
setAttributes( { autoScrollSpeed: value ?? 2 } )
}
min={ 1 }
max={ 10 }
/>
<SelectControl
label={ __( 'Direction', 'rt-carousel' ) }
value={ autoScrollDirection }
options={ [
{ label: __( 'Forward', 'rt-carousel' ), value: 'forward' },
{ label: __( 'Backward', 'rt-carousel' ), value: 'backward' },
] }
onChange={ ( value ) =>
setAttributes( {
autoScrollDirection: value as CarouselAttributes['autoScrollDirection'],
loop: value === 'backward' ? true : loop,
} )
}
/>
<RangeControl
label={ __( 'Start Delay (ms)', 'rt-carousel' ) }
value={ autoScrollStartDelay }
onChange={ ( value ) =>
setAttributes( { autoScrollStartDelay: value ?? 1000 } )
}
min={ 0 }
max={ 10000 }
step={ 100 }
/>
<ToggleControl
label={ __( 'Stop on Interaction', 'rt-carousel' ) }
checked={ autoScrollStopOnInteraction }
onChange={ ( value ) =>
setAttributes( { autoScrollStopOnInteraction: value } )
}
help={ __( 'Stop auto scroll when user interacts with carousel.', 'rt-carousel' ) }
/>
<ToggleControl
label={ __( 'Stop on Mouse Enter', 'rt-carousel' ) }
checked={ autoScrollStopOnMouseEnter }
onChange={ ( value ) =>
setAttributes( { autoScrollStopOnMouseEnter: value } )
}
help={ __( 'Stop auto scroll when mouse hovers over carousel.', 'rt-carousel' ) }
/>
</> ) }
</PanelBody>
</InspectorControls>
<InspectorAdvancedControls>
<TextControl
Expand Down
Loading