Gutenberg Big Slider

Posted on: October 7th, 2024
By: Tadeo Martinez

Block.json

{
	"$schema": "https://schemas.wp.org/trunk/block.json",
	"apiVersion": 3,
	"name": "create-block/content-big-slider",
	"version": "0.1.0",
	"title": "Content Big Slider",
	"category": "widgets",
	"icon": "smiley",
	"description": "Example block scaffolded with Create Block tool.",
	"example": {},
	"supports": {
		"html": false
	},
	"attributes": {
		"section_style": {
			"type": "string",
			"default": "position-relative"
		},
		"section_class": {
			"type": "string",
			"default": "padding:0px 0px;"
		},
		"section_id": {
			"type": "string",
			"default": ""
		},
		"section_image": {
		  "type": "string",
		  "default": null
		},
	"section_image_class": {
	  "type": "string"
	},
	"section_image_style": {
	  "type": "string"
	},
		"section_block": {
		  "type": "string",
		  "default":""
		},
		"carousel_class": {
			"type": "string",
			"default": "carousel-slider owl-carousel owl-theme"
		},
		"carousel_style": {
			"type": "string",
			"default": ""
		},
		"carousel_data_aos": {
			"type": "string",
			"default": ""
		},
		"carousel_data_aos_delay": {
			"type": "string",
			"default": ""
		},
		"carousel_data_aos_offset": {
			"type": "string",
			"default": ""
		},
		"gallery_images": {
			"type": "array",
			"default": []
		},
		"gallery_images_class": {
			"type": "string",
			"default": "w-100"
		},
		"gallery_images_style": {
			"type": "string",
			"default": "object-fit:cover;height:550px;"
		}
	},
	"textdomain": "content-big-slider",
	"editorScript": "file:./index.js",
	"editorStyle": "file:./index.css",
	"style": "file:./style-index.css",
	"viewScript": "file:./view.js"
}

Edit.js

/**
 * Retrieves the translation of text.
 *
 * @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-i18n/
 */
import { __ } from '@wordpress/i18n';

/**
 * React hook that is used to mark the block wrapper element.
 * It provides all the necessary props like the class name.
 *
 * @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-block-editor/#useblockprops
 */
import { InspectorControls, useBlockProps, InnerBlocks, MediaUpload, MediaUploadCheck } from '@wordpress/block-editor';
import { Button, PanelBody, __experimentalInputControl as InputControl,TextControl, } from '@wordpress/components';
import { useState, useEffect } from '@wordpress/element';

/**
 * Lets webpack process CSS, SASS or SCSS files referenced in JavaScript files.
 * Those files can contain any CSS code that gets applied to the editor.
 *
 * @see https://www.npmjs.com/package/@wordpress/scripts#using-css
 */
import './editor.scss';

/**
 * The edit function describes the structure of your block in the context of the
 * editor. This represents what the editor will render when the block is used.
 *
 * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-edit-save/#edit
 *
 * @return {Element} Element to render.
 */
export default function Edit({ attributes, setAttributes }) {
	const { section_style, section_class, section_id, carousel_class,carousel_style,carousel_data_aos,carousel_data_aos_delay,carousel_data_aos_offset, gallery_images, gallery_images_class,gallery_images_style } = attributes;

	const [value, setValue] = useState('');

	const onSelectBackgroundImages = ( newBackgroundImages ) => {
		// console.log( newImages );
		setAttributes( { gallery_images: newBackgroundImages } );
	};

	return (
		<>
			<InspectorControls>
				<PanelBody title={__('Section')} initialOpen={false}>
					<InputControl
						label="Section Style"
						value={section_style}
						onChange={(nextValue) => setAttributes({ section_style: nextValue })}
					/>
					<InputControl
						label="Section Class"
						value={section_class}
						onChange={(nextValue) => setAttributes({ section_class: nextValue })}
					/>
					<InputControl
						label="Section ID"
						value={section_id}
						onChange={(nextValue) => setAttributes({ section_id: nextValue })}
					/>
				</PanelBody>
				{/* <PanelBody title={__('Background Image')} initialOpen={false}>
					
				</PanelBody> */}
				<PanelBody title={__('Carousel Details')} initialOpen={false}>
				<InputControl
					label="Carousel Class"
					value={carousel_class}
					onChange={(nextValue) => setAttributes({ carousel_class: nextValue })}
				/>
				<InputControl
					label="Carousel Style"
					value={carousel_style}
					onChange={(nextValue) => setAttributes({ carousel_style: nextValue })}
				/>
				<InputControl
					label="Carousel Data AOS"
					value={carousel_data_aos}
					onChange={(nextValue) => setAttributes({ carousel_data_aos: nextValue })}
				/>
				<InputControl
					label="Carousel Data AOS Delay"
					value={carousel_data_aos_delay}
					onChange={(nextValue) => setAttributes({ carousel_data_aos_delay: nextValue })}
				/>
				<InputControl
					label="Carousel Data AOS Offset"
					value={carousel_data_aos_offset}
					onChange={(nextValue) => setAttributes({ carousel_data_aos_offset: nextValue })}
				/>
				</PanelBody>
				<PanelBody title={__('Carousel Images')} initialOpen={false}>
				<InputControl
						label="Gallery Image Class"
						value={gallery_images_class}
						onChange={(nextValue) => setAttributes({ gallery_images_class: nextValue })}
					/>
					<InputControl
						label="Gallery Image Style"
						value={gallery_images_style}
						onChange={(nextValue) => setAttributes({ gallery_images_style: nextValue })}
					/>
					<MediaUploadCheck>
						<MediaUpload
							onSelect={ onSelectBackgroundImages }
							type="image"
							multiple
							gallery
							value={ gallery_images.map(({id}) => id) }
							render={ ( { open } ) => (
								<button onClick={ open }>
									Open Media Library
								</button>
							) }
						/>
					</MediaUploadCheck>
					<Gallery
						gallery_images={gallery_images}
						gallery_columns={ 1 }
						setAttributes={setAttributes}
						/>
				</PanelBody>
				<PanelBody title={__('Code Block')} initialOpen={false}>
					<label style={{lineHeight:'2'}}>Code Block</label>
					<textarea
						id="sectionStyleTextarea"
						value={attributes.section_block}
						onChange={(event) => setAttributes({ section_block: event.target.value })}
						placeholder="Enter section block here"
						style={{width:'100%'}}
					/>
				</PanelBody>
				{/* <PanelBody title={__('Container')} initialOpen={false}>
					<InputControl
						label="Container Section Style"
						value={container_style}
						onChange={(nextValue) => setAttributes({ container_style: nextValue })}
					/>
					<InputControl
						label="Container Section Class"
						value={container_class}
						onChange={(nextValue) => setAttributes({ container_class: nextValue })}
					/>
					<InputControl
						label="Container Section ID"
						value={container_id}
						onChange={(nextValue) => setAttributes({ container_id: nextValue })}
					/>
				</PanelBody> */}
				{/* <PanelBody title={__('Row')} initialOpen={false}>
					<InputControl
						label="Row Style"
						value={row_style}
						onChange={(nextValue) => setAttributes({ row_style: nextValue })}
					/>
					<InputControl
						label="Row Class"
						value={row_class}
						onChange={(nextValue) => setAttributes({ row_class: nextValue })}
					/>
					<InputControl
						label="Row ID"
						value={row_id}
						onChange={(nextValue) => setAttributes({ row_id: nextValue })}
					/>
				</PanelBody> */}
				{/* <PanelBody title={__('Column')} initialOpen={false}>
					<InputControl
						label="Column Style"
						value={col_style}
						onChange={(nextValue) => setAttributes({ col_style: nextValue })}
					/>
					<InputControl
						label="Column Class"
						value={col_class}
						onChange={(nextValue) => setAttributes({ col_class: nextValue })}
					/>
					<InputControl
						label="Column ID"
						value={col_id}
						onChange={(nextValue) => setAttributes({ col_id: nextValue })}
					/>
					<InputControl
						label="Column Data AOS"
						value={col_data_aos}
						onChange={(nextValue) => setAttributes({ col_data_aos: nextValue })}
					/>
					<InputControl
						label="Column Data AOS Delay"
						value={col_data_aos_delay}
						onChange={(nextValue) => setAttributes({ col_data_aos_delay: nextValue })}
					/>
				</PanelBody> */}
			</InspectorControls>
			<section {...useBlockProps()}>
				{/* <img src={section_image} alt="" /> */}
				{ /* Your gallery rendering logic */ }
				{ gallery_images &&
					gallery_images.map( ( image ) => (
						
						<img
						key={ image.id }
						src={ image.url }
						alt={ image.alt }
						style={{width:'400px'}}
						/>

					) ) }
			<InnerBlocks />
			</section>
		</>
	);
}
// Define your Gallery component
const Gallery = ( { gallery_images, setAttributes } ) => {
    // Render your gallery based on the images and columns
    // You can use the images array to loop through and display the selected images

	const deleteImage = (id) => {
        setAttributes( { gallery_images: gallery_images.filter( ( image ) => image.id !== id ) } );
    }
    return (
        <div className={ `gallery columns-` }>
            { /* Your gallery rendering logic */ }
            { gallery_images &&
                gallery_images.map( ( image ) => (
                    <div>
                    <button 
                    onClick={()=>deleteImage(image.id)}
                    >X</button>
                    <img key={ image.id } src={ image.url } alt={ image.alt } />
                    </div>
                ) ) }
        </div>
    );
};

Save.js

/**
 * React hook that is used to mark the block wrapper element.
 * It provides all the necessary props like the class name.
 *
 * @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-block-editor/#useblockprops
 */
import { useBlockProps, InnerBlocks } from '@wordpress/block-editor';
import { RawHTML } from '@wordpress/element';

/**
 * The save function defines the way in which the different attributes should
 * be combined into the final markup, which is then serialized by the block
 * editor into `post_content`.
 *
 * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-edit-save/#save
 *
 * @return {Element} Element to render.
 */
export default function save({ attributes }) {
	const blockProps = useBlockProps.save();

	// const setOuterHTML = (htmlString) => {
	// 	const tempDiv = document.createElement('div');
	  
	// 	// Append a text node with the HTML string
	// 	tempDiv.appendChild(document.createTextNode(htmlString));
	  
	// 	// Use React.createElement to create a React element based on the outerHTML
	// 	const reactElement = React.createElement('div', { dangerouslySetInnerHTML: { __html: tempDiv.outerHTML } });
	  
	// 	return reactElement;
	//   };

	return (
		<div {...blockProps}>
		<section className={`${attributes.section_class}`} style={`${attributes.section_style}`} id={attributes.section_id}>

		<div className={`${attributes.carousel_class}`} style={`${attributes.carousel_style}`} data-aos={attributes.carousel_data_aos} data-aos-delay={attributes.carousel_data_aos_delay} data-aos-offset={attributes.carousel_data_aos_offset}>
		{ attributes.gallery_images &&
		attributes.gallery_images.map( ( image ) => (
		<a href={ image.url } data-lightbox="slider-carousel" data-title={image.alt}>
			<img
				key={ image.id }
				src={ image.url }
				alt={ image.alt }
				style={`${ attributes.gallery_images_style }`}
				className={`${attributes.gallery_images_class}`}
			/>
			</a>
		) ) }
		</div>

			<RawHTML>{attributes.section_block}</RawHTML>

			{/* <div className={`${attributes.container_class} position-relative`} style={`${attributes.container_style}z-index:1;`} id={attributes.container_id}>
				<div className={attributes.row_class} style={attributes.row_style} id={attributes.row_id}>
					<div className={attributes.col_class} style={attributes.col_style} id={attributes.col_id} data-aos={attributes.col_data_aos} data-aos-delay={attributes.col_data_aos_delay}>
					<InnerBlocks.Content />
					</div>
				</div>
			</div> */}
		</section>
		</div>
	);
}

PHP file

<?php
/**
 * Plugin Name:       Content Big Slider
 * Description:       Example block scaffolded with Create Block tool.
 * Requires at least: 6.6
 * Requires PHP:      7.2
 * Version:           0.1.0
 * Author:            The WordPress Contributors
 * License:           GPL-2.0-or-later
 * License URI:       https://www.gnu.org/licenses/gpl-2.0.html
 * Text Domain:       content-big-slider
 *
 * @package CreateBlock
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

/**
 * Registers the block using the metadata loaded from the `block.json` file.
 * Behind the scenes, it registers also all assets so they can be enqueued
 * through the block editor in the corresponding context.
 *
 * @see https://developer.wordpress.org/reference/functions/register_block_type/
 */
function create_block_content_big_slider_block_init() {
	// owl carousel
	if ( ! wp_style_is( 'custom-owl.carousel.min', 'enqueued' ) ) {
		wp_enqueue_style('custom-owl.carousel.min', get_theme_file_uri('/owl-carousel/owl.carousel.min.css'));
	}
	if ( ! wp_style_is( 'custom-owl.theme.default', 'enqueued' ) ) {
		wp_enqueue_style('custom-owl.theme.default', get_theme_file_uri('/owl-carousel/owl.theme.default.min.css'));
	}
	register_block_type( __DIR__ . '/build' );
	if ( ! wp_script_is( 'owl-carousel-jquery-min-custom', 'enqueued' ) ) {
		wp_enqueue_script('owl-carousel-jquery-min-custom', get_theme_file_uri('/owl-carousel/jquery.min.js'));
	}
	if ( ! wp_script_is( 'owl-carousel-min-js', 'enqueued' ) ) {
		wp_enqueue_script('owl-carousel-min-js', get_theme_file_uri('/owl-carousel/owl.carousel.min.js'));
	}
	if ( ! wp_script_is( 'owl-carousel-custom', 'enqueued' ) ) {
		wp_enqueue_script('owl-carousel-custom', get_theme_file_uri('/owl-carousel/owl-carousels.js'));
	}
}
add_action( 'init', 'create_block_content_big_slider_block_init' );

Style.css

/**
 * The following styles get applied both on the front of your site
 * and in the editor.
 *
 * Replace them with your own styles or remove the file completely.
 */

.wp-block-create-block-content-big-slider {
    button.owl-prev,
    button.owl-next {
        position: absolute;
        top: 35%;
    }
    button.owl-prev {
        left:1%;
    }
    button.owl-next {
        right:1%;
    }
    button.owl-prev span,
    button.owl-next span {
        color:white;
    }
    
    .owl-theme .owl-dots .owl-dot span {
        width: 200px;
        height: 3px;
        border-radius: 0;
        transition:all .25s ease-in-out;
    }
    .owl-theme .owl-dots .owl-dot.active span,
    .owl-theme .owl-dots .owl-dot:hover span {
        background: white;
    }
    .owl-dots {
        position: absolute;
        bottom: 0;
        width: 100%;
    }
    .owl-prev span, .owl-next span {
        font-size: 8rem;
        line-height: 1;
    }

    @media only screen and (max-width:767px) {
        .owl-carousel img {
            height: 300px !important;
        }
        .owl-theme .owl-dots .owl-dot span {
            width: 50px;
            height: 3px;
            border-radius: 0;
            transition:all .25s ease-in-out;
        }
    }
}

Have any questions or comments? Write them below!


Leave a Reply

Your email address will not be published. Required fields are marked *