From 681fcbbff35138521fec0b8af7b2d99418a129d3 Mon Sep 17 00:00:00 2001 From: Sagar Tamang Date: Tue, 31 Mar 2026 17:03:34 +0545 Subject: [PATCH 01/11] feat: add lazy load images attribute and control to carousel block --- src/blocks/carousel/block.json | 4 ++++ src/blocks/carousel/edit.tsx | 10 ++++++++++ src/blocks/carousel/types.ts | 1 + 3 files changed, 15 insertions(+) diff --git a/src/blocks/carousel/block.json b/src/blocks/carousel/block.json index af51de7..ae2d09c 100644 --- a/src/blocks/carousel/block.json +++ b/src/blocks/carousel/block.json @@ -85,6 +85,10 @@ "slidesToScroll": { "type": "string", "default": "1" + }, + "lazyLoadImages": { + "type": "boolean", + "default": true } }, "editorScript": "file:./index.js", diff --git a/src/blocks/carousel/edit.tsx b/src/blocks/carousel/edit.tsx index 3b0d652..3a2543a 100644 --- a/src/blocks/carousel/edit.tsx +++ b/src/blocks/carousel/edit.tsx @@ -50,6 +50,7 @@ export default function Edit( { autoplayStopOnMouseEnter, ariaLabel, slidesToScroll = '1', + lazyLoadImages, } = attributes; const [ emblaApi, setEmblaApi ] = useState(); @@ -199,6 +200,15 @@ export default function Edit( { onChange={ ( value ) => setAttributes( { dragFree: value } ) } help={ __( 'Enables momentum scrolling.', 'carousel-kit' ) } /> + setAttributes( { lazyLoadImages: value } ) } + help={ __( + 'Load images only when they enter the viewport.', + 'carousel-kit', + ) } + /> ; From f4a492fbb882f072985f68541e757360b19ee8e4 Mon Sep 17 00:00:00 2001 From: Sagar Tamang Date: Tue, 31 Mar 2026 17:03:47 +0545 Subject: [PATCH 02/11] feat: add disable lazy load images attribute to carousel slide --- src/blocks/carousel/slide/block.json | 4 ++++ src/blocks/carousel/slide/edit.tsx | 18 +++++++++++++++++- src/blocks/carousel/types.ts | 1 + 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/blocks/carousel/slide/block.json b/src/blocks/carousel/slide/block.json index ccde54d..9bf5082 100644 --- a/src/blocks/carousel/slide/block.json +++ b/src/blocks/carousel/slide/block.json @@ -14,6 +14,10 @@ "attributes": { "verticalAlignment": { "type": "string" + }, + "disableLazyLoadImages": { + "type": "boolean", + "default": false } }, "usesContext": [ diff --git a/src/blocks/carousel/slide/edit.tsx b/src/blocks/carousel/slide/edit.tsx index ef78777..d2cd2c9 100644 --- a/src/blocks/carousel/slide/edit.tsx +++ b/src/blocks/carousel/slide/edit.tsx @@ -3,7 +3,10 @@ import { useInnerBlocksProps, BlockControls, BlockVerticalAlignmentToolbar, + InspectorControls, } from '@wordpress/block-editor'; +import { PanelBody, ToggleControl } from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; import type { CarouselSlideAttributes } from '../types'; export default function Edit( { @@ -17,7 +20,7 @@ export default function Edit( { } ) { const allowedBlocks = context[ 'carousel-kit/carousel/allowedSlideBlocks' ]; - const { verticalAlignment } = attributes; + const { verticalAlignment, disableLazyLoadImages = false } = attributes; const blockProps = useBlockProps( { className: `embla__slide${ @@ -41,6 +44,19 @@ export default function Edit( { } /> + + + setAttributes( { disableLazyLoadImages: value } ) } + help={ __( + 'Override carousel lazy loading for this slide.', + 'carousel-kit', + ) } + /> + +
); diff --git a/src/blocks/carousel/types.ts b/src/blocks/carousel/types.ts index b1081d4..4d73415 100644 --- a/src/blocks/carousel/types.ts +++ b/src/blocks/carousel/types.ts @@ -24,6 +24,7 @@ export type CarouselAttributes = { export type CarouselViewportAttributes = Record; export type CarouselSlideAttributes = { verticalAlignment?: BlockVerticalAlignmentToolbar.Value; + disableLazyLoadImages?: boolean; }; export type CarouselControlsAttributes = Record; export type CarouselDotsAttributes = Record; From a7fedc8ce65b2a82dc7f858c6d9ac3b7d307ee23 Mon Sep 17 00:00:00 2001 From: Sagar Tamang Date: Tue, 31 Mar 2026 17:03:56 +0545 Subject: [PATCH 03/11] feat: add lazy load images attribute to carousel attributes tests --- src/blocks/carousel/__tests__/types.test.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/blocks/carousel/__tests__/types.test.ts b/src/blocks/carousel/__tests__/types.test.ts index efccbb9..ee761cc 100644 --- a/src/blocks/carousel/__tests__/types.test.ts +++ b/src/blocks/carousel/__tests__/types.test.ts @@ -33,6 +33,7 @@ describe( 'CarouselAttributes Type', () => { ariaLabel: 'Image carousel', slideGap: 16, slidesToScroll: '1', + lazyLoadImages: true, }; expect( attributes ).toBeDefined(); @@ -58,6 +59,7 @@ describe( 'CarouselAttributes Type', () => { ariaLabel: '', slideGap: 0, slidesToScroll: 'auto', + lazyLoadImages: false, }; // Verify all keys exist From 2e8547fdab36f652b28fbdf71e579911a0caed6e Mon Sep 17 00:00:00 2001 From: Sagar Tamang Date: Tue, 31 Mar 2026 19:50:00 +0545 Subject: [PATCH 04/11] feat: add lazy load images context to carousel and slide blocks --- src/blocks/carousel/block.json | 5 +++-- src/blocks/carousel/slide/block.json | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/blocks/carousel/block.json b/src/blocks/carousel/block.json index ae2d09c..0a0e359 100644 --- a/src/blocks/carousel/block.json +++ b/src/blocks/carousel/block.json @@ -9,7 +9,8 @@ "description": "Carousel container using Embla and Interactivity API.", "textdomain": "carousel-kit", "providesContext": { - "carousel-kit/carousel/allowedSlideBlocks": "allowedSlideBlocks" + "carousel-kit/carousel/allowedSlideBlocks": "allowedSlideBlocks", + "carousel-kit/carousel/lazyLoadImages": "lazyLoadImages" }, "supports": { "interactivity": true, @@ -95,4 +96,4 @@ "editorStyle": "file:./index.css", "style": "file:./style-index.css", "viewScriptModule": "file:./view.js" -} \ No newline at end of file +} diff --git a/src/blocks/carousel/slide/block.json b/src/blocks/carousel/slide/block.json index 9bf5082..9eff627 100644 --- a/src/blocks/carousel/slide/block.json +++ b/src/blocks/carousel/slide/block.json @@ -21,7 +21,8 @@ } }, "usesContext": [ - "carousel-kit/carousel/allowedSlideBlocks" + "carousel-kit/carousel/allowedSlideBlocks", + "carousel-kit/carousel/lazyLoadImages" ], "editorScript": "file:./index.js" -} \ No newline at end of file +} From f9c1ee7a97783a6e2c4342fb080ce2235e9f2216 Mon Sep 17 00:00:00 2001 From: Sagar Tamang Date: Tue, 31 Mar 2026 19:52:25 +0545 Subject: [PATCH 05/11] feat: implement lazy loading for images in carousel slides --- inc/Plugin.php | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/inc/Plugin.php b/inc/Plugin.php index 25f975a..3f969d6 100644 --- a/inc/Plugin.php +++ b/inc/Plugin.php @@ -9,6 +9,8 @@ namespace Carousel_Kit; +use WP_Block; +use WP_HTML_Tag_Processor; use Carousel_Kit\Traits\Singleton; // Exit if accessed directly. @@ -39,6 +41,7 @@ protected function setup_hooks(): void { add_filter( 'block_categories_all', [ $this, 'register_block_category' ] ); add_action( 'init', [ $this, 'register_pattern_category' ] ); add_action( 'init', [ $this, 'register_block_patterns' ] ); + add_filter( 'render_block_carousel-kit/carousel-slide', [ $this, 'handle_lazy_load_images' ], 10, 3 ); } /** @@ -198,4 +201,47 @@ private function load_patterns_from_disk(): array { return $data; } + + /** + * Add loading="lazy" to images in carousel slides. + * + * @param string $block_content The block content. + * @param array $parsed_block The parsed block. + * @param WP_Block $instance The block instance. + * + * @return string Modified block content. + */ + public function handle_lazy_load_images( string $block_content, array $parsed_block, ?WP_Block $instance ): string { + // Bail early if the parent block to check lazyLoadImages setting is not set. + if ( ! isset( $instance->context["carousel-kit/carousel/lazyLoadImages"] ) ) { + return $block_content; + } + + $lazy_load = $instance->context["carousel-kit/carousel/lazyLoadImages"]; + + // If lazy loading is disabled, return as-is. + if ( ! $lazy_load ) { + return $block_content; + } + + // Check if this slide has disableLazyLoadImages set. + $slide_attrs = $parsed_block['attrs'] ?? array(); + $disable_lazy = isset( $slide_attrs['disableLazyLoadImages'] ) ? $slide_attrs['disableLazyLoadImages'] : false; + + if ( $disable_lazy ) { + return $block_content; + } + + // Use WP_HTML_Tag_Processor to add loading="lazy" to tags. + $processor = new WP_HTML_Tag_Processor( $block_content ); + + while ( $processor->next_tag( 'img' ) ) { + // Only add if loading attribute is not already set. + if ( null === $processor->get_attribute( 'loading' ) ) { + $processor->set_attribute( 'loading', 'lazy' ); + } + } + + return $processor->get_updated_html(); + } } From 58f097c6870a4d5ca56bd3f4d880e4df29ff89aa Mon Sep 17 00:00:00 2001 From: Sagar Tamang Date: Tue, 31 Mar 2026 20:12:00 +0545 Subject: [PATCH 06/11] docs: add lazyLoadImages attribute to carousel block configuration --- docs/USAGE.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/USAGE.md b/docs/USAGE.md index 8918d62..c352088 100644 --- a/docs/USAGE.md +++ b/docs/USAGE.md @@ -23,6 +23,7 @@ The parent block acts as the controller and wrapper. It handles configuration, s | `axis` | string | `'x'` | Carousel axis direction (`'x'` for horizontal, `'y'` for vertical). | | `direction` | string | `'ltr'` | Carousel item direction: `'ltr'` (left-to-right) or `'rtl'` (right-to-left). | | `slidesToScroll` | number | `1` | Number of slides to scroll per navigation action. | +| `lazyLoadImages` | boolean | `true` | Lazy load images in the slides. | --- From 7e49ef400eb33337f27e541fb552633d5f5ba262 Mon Sep 17 00:00:00 2001 From: Sagar Tamang Date: Tue, 31 Mar 2026 20:19:02 +0545 Subject: [PATCH 07/11] docs: enhance lazyLoadImages attribute description and add disableLazyLoadImages for slides --- docs/USAGE.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/docs/USAGE.md b/docs/USAGE.md index c352088..4d7db65 100644 --- a/docs/USAGE.md +++ b/docs/USAGE.md @@ -23,7 +23,18 @@ The parent block acts as the controller and wrapper. It handles configuration, s | `axis` | string | `'x'` | Carousel axis direction (`'x'` for horizontal, `'y'` for vertical). | | `direction` | string | `'ltr'` | Carousel item direction: `'ltr'` (left-to-right) or `'rtl'` (right-to-left). | | `slidesToScroll` | number | `1` | Number of slides to scroll per navigation action. | -| `lazyLoadImages` | boolean | `true` | Lazy load images in the slides. | +| `lazyLoadImages` | boolean | `true` | Enable lazy loading for slide images. Individual slides can override this setting. | + +--- + +### Child Block: `carousel-kit/carousel-slide` +The child block that serves as a container for individual slide content. Each slide can display custom blocks as defined by the parent's `allowedSlideBlocks` configuration. + +#### Attributes + +| Attribute | Type | Default | Description | +| :-------------------------- | :------ | :------------ | :------------------------------------------ | +| `disableLazyLoadImages` | boolean | `false` | Override parent's `lazyLoadImages` setting for this slide only. | --- From 9aef8ce4815c315fbfd6ea82999f9126b3dccda5 Mon Sep 17 00:00:00 2001 From: Sagar Tamang Date: Tue, 31 Mar 2026 20:35:45 +0545 Subject: [PATCH 08/11] docs: update lazyLoadImages and disableLazyLoadImages descriptions in usage guide and edit component --- docs/USAGE.md | 4 ++-- src/blocks/carousel/slide/edit.tsx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/USAGE.md b/docs/USAGE.md index 4d7db65..9b7d2f3 100644 --- a/docs/USAGE.md +++ b/docs/USAGE.md @@ -23,7 +23,7 @@ The parent block acts as the controller and wrapper. It handles configuration, s | `axis` | string | `'x'` | Carousel axis direction (`'x'` for horizontal, `'y'` for vertical). | | `direction` | string | `'ltr'` | Carousel item direction: `'ltr'` (left-to-right) or `'rtl'` (right-to-left). | | `slidesToScroll` | number | `1` | Number of slides to scroll per navigation action. | -| `lazyLoadImages` | boolean | `true` | Enable lazy loading for slide images. Individual slides can override this setting. | +| `lazyLoadImages` | boolean | `true` | Add `loading="lazy"` to images in slides. Slides can opt out via `disableLazyLoadImages`. | --- @@ -34,7 +34,7 @@ The child block that serves as a container for individual slide content. Each sl | Attribute | Type | Default | Description | | :-------------------------- | :------ | :------------ | :------------------------------------------ | -| `disableLazyLoadImages` | boolean | `false` | Override parent's `lazyLoadImages` setting for this slide only. | +| `disableLazyLoadImages` | boolean | `false` | Disable lazy loading for images in this slide (when carousel lazy loading is enabled). | --- diff --git a/src/blocks/carousel/slide/edit.tsx b/src/blocks/carousel/slide/edit.tsx index d2cd2c9..742cc84 100644 --- a/src/blocks/carousel/slide/edit.tsx +++ b/src/blocks/carousel/slide/edit.tsx @@ -51,7 +51,7 @@ export default function Edit( { checked={ disableLazyLoadImages } onChange={ ( value ) => setAttributes( { disableLazyLoadImages: value } ) } help={ __( - 'Override carousel lazy loading for this slide.', + 'Disable lazy loading for images in this slide (when carousel lazy loading is enabled).', 'carousel-kit', ) } /> From 9b274e3e73f614b44bf5c03b0ef105a861fc3d8c Mon Sep 17 00:00:00 2001 From: Sagar Tamang Date: Tue, 31 Mar 2026 20:36:19 +0545 Subject: [PATCH 09/11] fix: update handle_lazy_load_images method to require WP_Block instance --- inc/Plugin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/Plugin.php b/inc/Plugin.php index 3f969d6..de35bcb 100644 --- a/inc/Plugin.php +++ b/inc/Plugin.php @@ -211,7 +211,7 @@ private function load_patterns_from_disk(): array { * * @return string Modified block content. */ - public function handle_lazy_load_images( string $block_content, array $parsed_block, ?WP_Block $instance ): string { + public function handle_lazy_load_images( string $block_content, array $parsed_block, WP_Block $instance ): string { // Bail early if the parent block to check lazyLoadImages setting is not set. if ( ! isset( $instance->context["carousel-kit/carousel/lazyLoadImages"] ) ) { return $block_content; From 00463ad5a87ad8c0afde29deb485525c40236399 Mon Sep 17 00:00:00 2001 From: Sagar Tamang Date: Tue, 31 Mar 2026 20:44:18 +0545 Subject: [PATCH 10/11] refactor: improve handle_lazy_load_images method and fix attribute handling --- inc/Plugin.php | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/inc/Plugin.php b/inc/Plugin.php index de35bcb..4fced95 100644 --- a/inc/Plugin.php +++ b/inc/Plugin.php @@ -9,9 +9,9 @@ namespace Carousel_Kit; +use Carousel_Kit\Traits\Singleton; use WP_Block; use WP_HTML_Tag_Processor; -use Carousel_Kit\Traits\Singleton; // Exit if accessed directly. if ( ! defined( 'ABSPATH' ) ) { @@ -205,19 +205,19 @@ private function load_patterns_from_disk(): array { /** * Add loading="lazy" to images in carousel slides. * - * @param string $block_content The block content. - * @param array $parsed_block The parsed block. - * @param WP_Block $instance The block instance. + * @param string $block_content The block content. + * @param array $parsed_block The parsed block. + * @param \WP_Block $instance The block instance. * * @return string Modified block content. */ public function handle_lazy_load_images( string $block_content, array $parsed_block, WP_Block $instance ): string { // Bail early if the parent block to check lazyLoadImages setting is not set. - if ( ! isset( $instance->context["carousel-kit/carousel/lazyLoadImages"] ) ) { + if ( ! isset( $instance->context['carousel-kit/carousel/lazyLoadImages'] ) ) { return $block_content; } - $lazy_load = $instance->context["carousel-kit/carousel/lazyLoadImages"]; + $lazy_load = $instance->context['carousel-kit/carousel/lazyLoadImages']; // If lazy loading is disabled, return as-is. if ( ! $lazy_load ) { @@ -225,7 +225,7 @@ public function handle_lazy_load_images( string $block_content, array $parsed_bl } // Check if this slide has disableLazyLoadImages set. - $slide_attrs = $parsed_block['attrs'] ?? array(); + $slide_attrs = $parsed_block['attrs'] ?? []; $disable_lazy = isset( $slide_attrs['disableLazyLoadImages'] ) ? $slide_attrs['disableLazyLoadImages'] : false; if ( $disable_lazy ) { @@ -237,9 +237,11 @@ public function handle_lazy_load_images( string $block_content, array $parsed_bl while ( $processor->next_tag( 'img' ) ) { // Only add if loading attribute is not already set. - if ( null === $processor->get_attribute( 'loading' ) ) { - $processor->set_attribute( 'loading', 'lazy' ); + if ( null !== $processor->get_attribute( 'loading' ) ) { + continue; } + + $processor->set_attribute( 'loading', 'lazy' ); } return $processor->get_updated_html(); From 10bc14af716d7751ca8e18ca6e3568a568d697bc Mon Sep 17 00:00:00 2001 From: Sagar Tamang Date: Tue, 31 Mar 2026 21:41:21 +0545 Subject: [PATCH 11/11] fix: correct lazy loading attribute handling in handle_lazy_load_images method --- inc/Plugin.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/inc/Plugin.php b/inc/Plugin.php index 4fced95..7531670 100644 --- a/inc/Plugin.php +++ b/inc/Plugin.php @@ -237,11 +237,10 @@ public function handle_lazy_load_images( string $block_content, array $parsed_bl while ( $processor->next_tag( 'img' ) ) { // Only add if loading attribute is not already set. - if ( null !== $processor->get_attribute( 'loading' ) ) { - continue; + if ( null === $processor->get_attribute( 'loading' ) ) { + $processor->set_attribute( 'loading', 'lazy' ); } - $processor->set_attribute( 'loading', 'lazy' ); } return $processor->get_updated_html();