Changes to blocks

This commit is contained in:
Jeremy Rangel
2024-12-22 15:20:12 -08:00
parent cfbb860bf9
commit f3fbe0fa32
25 changed files with 612 additions and 1035 deletions

View File

View File

@ -3,15 +3,16 @@
/* Blocks */
//include get_template_directory(). '/includes/blocks/lcp-gallery/lcp-gallery.php';
//include get_template_directory(). '/includes/blocks/lcp-gallery/lcp-gallery.php'; //include get_template_directory(). '/includes/blocks/lcp-gallery/lcp-gallery.php';
include get_template_directory() . '/includes/classes/blocks.php'; include get_template_directory() . '/includes/classes/blocks.php';
new Lcp_Blocks(); new Lcp_Blocks();
function lcp_block_theme_setup() { function lcp_block_theme_setup() {
add_theme_support( 'block-templates' ); add_theme_support( 'block-templates' );
} }
@ -26,6 +27,15 @@ function lcp_enqueue() {
add_action('wp_enqueue_scripts', 'lcp_enqueue'); add_action('wp_enqueue_scripts', 'lcp_enqueue');
function lcp_backend_enqueue() {
// Enqueue the theme's main stylesheet (style.css)
wp_enqueue_style('lcp-style', get_stylesheet_uri());
wp_enqueue_script('lcp-script', get_template_directory_uri() . '/script.js');
}
add_action('admin_enqueue_scripts', 'lcp_enqueue');
// Backend enqueue // Backend enqueue
function lcp_enqueue_svg_repeater_script($hook) { function lcp_enqueue_svg_repeater_script($hook) {
// Only enqueue on the theme settings page // Only enqueue on the theme settings page
@ -164,6 +174,11 @@ add_action('save_post', 'save_key_points_meta_box');
/* BACKEND PAGES */ /* BACKEND PAGES */
// Create backend pages // Create backend pages
@ -250,7 +265,7 @@ function lcp_custom_svgs_field() {
<?php <?php
} }
// Enqueue the JavaScript for handling the repeater functionality
@ -438,3 +453,5 @@ function add_login_form_to_footer() {
add_action( 'wp_footer', 'add_login_form_to_footer' ); add_action( 'wp_footer', 'add_login_form_to_footer' );

View File

@ -1,12 +1,76 @@
<?php /** <?php /**
* Function to generate random class and add dynamic padding styles * Function to generate random class and add dynamic padding styles
*/ */
function render_lcp_container( $attributes, $content ) { if (!function_exists('lcp_random_string')) {
function lcp_random_string($length = 8, $css_compliant = false, $include_character_types = '') {
// Define character sets
$lowercase = 'abcdefghijklmnopqrstuvwxyz';
$uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$numbers = '0123456789';
$special_chars = '!@#$%^&*()_+-=[]{}|;:,.<>?';
$all_chars = $lowercase . $uppercase . $numbers . $special_chars;
// Default to using all characters if no specific types are provided
if (empty($include_character_types)) {
$include_character_types = 'all';
}
// Build the allowed character set
$char_set = '';
if ($include_character_types === 'all') {
// Include everything
$char_set = $all_chars;
} else {
// Add specific types requested
if (strpos($include_character_types, 'lowercase') !== false) {
$char_set .= $lowercase;
}
if (strpos($include_character_types, 'uppercase') !== false) {
$char_set .= $uppercase;
}
if (strpos($include_character_types, 'numbers') !== false) {
$char_set .= $numbers;
}
if (strpos($include_character_types, 'special') !== false) {
$char_set .= $special_chars;
}
}
// Ensure that the string is valid for CSS (starts with a letter and can only include letters, digits, hyphens, or underscores)
$css_char_set = $lowercase . $uppercase . $numbers . '-_';
// Random string generation logic
$random_string = '';
$first_char = '';
// If CSS compliant, start with a letter (either lowercase or uppercase)
if ($css_compliant) {
// Ensure the first character is a letter (CSS compliant start)
$first_char = $lowercase[rand(0, strlen($lowercase) - 1)];
$random_string .= $first_char;
$length--; // Decrease length by 1 as we already added the first char
}
// Fill the rest of the string with random characters from the valid set (CSS compliant)
for ($i = 0; $i < $length; $i++) {
// Use only characters that are CSS compliant (letters, digits, hyphens, or underscores)
$random_string .= $css_char_set[rand(0, strlen($css_char_set) - 1)];
}
// Return the string
return $random_string;
}
}
function render_lcp_container( $attributes, $content ) {
// Debugging: Check the passed attributes // Debugging: Check the passed attributes
//var_dump($attributes); //var_dump($attributes);
// Generate a random class name (optional, could be customized) // Generate a random class name (optional, could be customized)
$random_class = 'lcp-container-' . wp_generate_password( 12, false, false ); $random_class = lcp_random_string(12,true);
// Get the padding and backgroundColor attributes // Get the padding and backgroundColor attributes
$padding = isset( $attributes['padding'] ) ? $attributes['padding'] : array(); $padding = isset( $attributes['padding'] ) ? $attributes['padding'] : array();

View File

@ -0,0 +1,103 @@
import React, { useState, useEffect, useRef, useCallback } from 'react';
import LightGallery from 'lightgallery/react';
import lgZoom from 'lightgallery/plugins/zoom';
import lgHash from 'lightgallery/plugins/hash';
import 'lightgallery/css/lightgallery.css';
const LcpGallery = (props) => {
const [settings, setSettings] = useState({
elementClassNames: 'lcp-gallery grid',
plugins: [],
zoom: false,
hash: false,
download: false
});
const lightGallery = useRef(null);
// onInit callback to initialize the lightGallery instance
const onInit = useCallback((detail) => {
if (detail) {
lightGallery.current = detail.instance;
}
}, []);
// Update settings based on the props
useEffect(() => {
console.log("Props received:", props);
const plugins = [];
// Convert plugin strings to actual plugin functions
if (props.plugins) {
props.plugins.forEach((plugin) => {
console.log(`Adding plugin: ${plugin}`);
if (plugin === 'lgZoom') {
plugins.push(lgZoom); // Add lgZoom function
} else if (plugin === 'lgHash') {
plugins.push(lgHash); // Add lgHash function
}
});
}
// Update settings with new plugins and options
setSettings((prevSettings) => ({
...prevSettings,
plugins, // Updated plugins
zoom: props.zoom || false, // Default zoom option
hash: props.hash || false, // Default hash option
download: props.download || false
}));
}, [props]);
// Reinitialize gallery when settings change (with careful timing)
useEffect(() => {
console.log("Settings changed:", settings);
// Check if gallery instance exists and only refresh if initialized
if (lightGallery.current) {
console.log("Refreshing gallery...");
lightGallery.current.refresh(); // Refresh the gallery instance
}
}, [settings]);
return (
<LightGallery
ref={lightGallery}
plugins={settings.plugins}
elementClassNames={settings.elementClassNames}
zoom={settings.zoom}
hash={settings.hash}
download={settings.download}
onInit={onInit} // Pass the onInit callback to initialize the gallery instance
>
{/* Gallery Items */}
<a
data-lg-size="1600-1067"
className="gallery-item"
data-src="https://images.unsplash.com/photo-1609342122563-a43ac8917a3a?ixlib=rb-1.2.1&ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&auto=format&fit=crop&w=1600&q=80"
data-sub-html="<h4>Photo by - <a href='https://unsplash.com/@tobbes_rd' >Tobias Rademacher </a></h4><p> Location - <a href='https://unsplash.com/s/photos/puezgruppe%2C-wolkenstein-in-gr%C3%B6den%2C-s%C3%BCdtirol%2C-italien'>Puezgruppe, Wolkenstein in Gröden, Südtirol, Italien</a>layers of blue.</p>"
>
<img
alt="layers of blue."
className="img-responsive"
src="https://images.unsplash.com/photo-1609342122563-a43ac8917a3a?ixlib=rb-1.2.1&ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&auto=format&fit=crop&w=240&q=80"
/>
</a>
<a
data-lg-size="1600-2400"
className="gallery-item"
data-src="https://images.unsplash.com/photo-1608481337062-4093bf3ed404?ixlib=rb-1.2.1&ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&auto=format&fit=crop&w=1600&q=80"
data-sub-html="<h4>Photo by - <a href='https://unsplash.com/@therawhunter' >Massimiliano Morosinotto </a></h4><p> Location - <a href='https://unsplash.com/s/photos/tre-cime-di-lavaredo%2C-italia'>Tre Cime di Lavaredo, Italia</a>This is the Way</p>"
>
<img
className="img-responsive"
src="https://images.unsplash.com/photo-1608481337062-4093bf3ed404?ixlib=rb-1.2.1&ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&auto=format&fit=crop&w=240&q=80"
/>
</a>
</LightGallery>
);
};
export default LcpGallery;

View File

@ -1,33 +0,0 @@
import { FC, useCallback, useEffect, useRef, useState } from 'react';
import LightGallery from 'lightgallery/react';
import lgZoom from 'lightgallery/plugins/zoom';
import lgThumbnail from 'lightgallery/plugins/thumbnail';
import { LightGallery as ILightGallery } from 'lightgallery/lightgallery';
import '../style.css';
export const App = () => {
const dynamicEl = [
{
src: '...',
responsive: '...',
thumb: '...',
subHtml: `...`,
},
{
src: '...',
responsive: '...',
subHtml: `...`,
},
// Add more placeholder images as needed
];
return (
<>
<LightGallery
dynamic={true}
dynamicEl={dynamicEl}
/>
</>
);
};

View File

@ -1,668 +0,0 @@
@font-face {
font-family: "lg";
src: url("../fonts/lg.woff2?io9a6k") format("woff2"), url("../fonts/lg.ttf?io9a6k") format("truetype"), url("../fonts/lg.woff?io9a6k") format("woff"), url("../fonts/lg.svg?io9a6k#lg") format("svg");
font-weight: normal;
font-style: normal;
font-display: block;
}
.lg-icon {
/* use !important to prevent issues with browser extensions that change fonts */
font-family: "lg" !important;
speak: never;
font-style: normal;
font-weight: normal;
font-variant: normal;
text-transform: none;
line-height: 1;
/* Better Font Rendering =========== */
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.lg-container {
font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
}
.lg-next,
.lg-prev {
background-color: rgba(0, 0, 0, 0.45);
border-radius: 2px;
color: #999;
cursor: pointer;
display: block;
font-size: 22px;
margin-top: -10px;
padding: 8px 10px 9px;
position: absolute;
top: 50%;
z-index: 1084;
outline: none;
border: none;
}
.lg-next.disabled,
.lg-prev.disabled {
opacity: 0 !important;
cursor: default;
}
.lg-next:hover:not(.disabled),
.lg-prev:hover:not(.disabled) {
color: #fff;
}
.lg-single-item .lg-next,
.lg-single-item .lg-prev {
display: none;
}
.lg-next {
right: 20px;
}
.lg-next:before {
content: "\e095";
}
.lg-prev {
left: 20px;
}
.lg-prev:after {
content: "\e094";
}
@-webkit-keyframes lg-right-end {
0% {
left: 0;
}
50% {
left: -30px;
}
100% {
left: 0;
}
}
@-moz-keyframes lg-right-end {
0% {
left: 0;
}
50% {
left: -30px;
}
100% {
left: 0;
}
}
@-ms-keyframes lg-right-end {
0% {
left: 0;
}
50% {
left: -30px;
}
100% {
left: 0;
}
}
@keyframes lg-right-end {
0% {
left: 0;
}
50% {
left: -30px;
}
100% {
left: 0;
}
}
@-webkit-keyframes lg-left-end {
0% {
left: 0;
}
50% {
left: 30px;
}
100% {
left: 0;
}
}
@-moz-keyframes lg-left-end {
0% {
left: 0;
}
50% {
left: 30px;
}
100% {
left: 0;
}
}
@-ms-keyframes lg-left-end {
0% {
left: 0;
}
50% {
left: 30px;
}
100% {
left: 0;
}
}
@keyframes lg-left-end {
0% {
left: 0;
}
50% {
left: 30px;
}
100% {
left: 0;
}
}
.lg-outer.lg-right-end .lg-object {
-webkit-animation: lg-right-end 0.3s;
-o-animation: lg-right-end 0.3s;
animation: lg-right-end 0.3s;
position: relative;
}
.lg-outer.lg-left-end .lg-object {
-webkit-animation: lg-left-end 0.3s;
-o-animation: lg-left-end 0.3s;
animation: lg-left-end 0.3s;
position: relative;
}
.lg-toolbar {
z-index: 1082;
left: 0;
position: absolute;
top: 0;
width: 100%;
}
.lg-media-overlap .lg-toolbar {
background-image: linear-gradient(0deg, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.4));
}
.lg-toolbar .lg-icon {
color: #999;
cursor: pointer;
float: right;
font-size: 24px;
height: 47px;
line-height: 27px;
padding: 10px 0;
text-align: center;
width: 50px;
text-decoration: none !important;
outline: medium none;
will-change: color;
-webkit-transition: color 0.2s linear;
-o-transition: color 0.2s linear;
transition: color 0.2s linear;
background: none;
border: none;
box-shadow: none;
}
.lg-toolbar .lg-icon.lg-icon-18 {
font-size: 18px;
}
.lg-toolbar .lg-icon:hover {
color: #fff;
}
.lg-toolbar .lg-close:after {
content: "\e070";
}
.lg-toolbar .lg-maximize {
font-size: 22px;
}
.lg-toolbar .lg-maximize:after {
content: "\e90a";
}
.lg-toolbar .lg-download:after {
content: "\e0f2";
}
.lg-sub-html {
color: #eee;
font-size: 16px;
padding: 10px 40px;
text-align: center;
z-index: 1080;
opacity: 0;
-webkit-transition: opacity 0.2s ease-out 0s;
-o-transition: opacity 0.2s ease-out 0s;
transition: opacity 0.2s ease-out 0s;
}
.lg-sub-html h4 {
margin: 0;
font-size: 13px;
font-weight: bold;
}
.lg-sub-html p {
font-size: 12px;
margin: 5px 0 0;
}
.lg-sub-html a {
color: inherit;
}
.lg-sub-html a:hover {
text-decoration: underline;
}
.lg-media-overlap .lg-sub-html {
background-image: linear-gradient(180deg, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.6));
}
.lg-item .lg-sub-html {
position: absolute;
bottom: 0;
right: 0;
left: 0;
}
.lg-error-msg {
font-size: 14px;
color: #999;
}
.lg-counter {
color: #999;
display: inline-block;
font-size: 16px;
padding-left: 20px;
padding-top: 12px;
height: 47px;
vertical-align: middle;
}
.lg-closing .lg-toolbar,
.lg-closing .lg-prev,
.lg-closing .lg-next,
.lg-closing .lg-sub-html {
opacity: 0;
-webkit-transition: -webkit-transform 0.08 cubic-bezier(0, 0, 0.25, 1) 0s, opacity 0.08 cubic-bezier(0, 0, 0.25, 1) 0s, color 0.08 linear;
-moz-transition: -moz-transform 0.08 cubic-bezier(0, 0, 0.25, 1) 0s, opacity 0.08 cubic-bezier(0, 0, 0.25, 1) 0s, color 0.08 linear;
-o-transition: -o-transform 0.08 cubic-bezier(0, 0, 0.25, 1) 0s, opacity 0.08 cubic-bezier(0, 0, 0.25, 1) 0s, color 0.08 linear;
transition: transform 0.08 cubic-bezier(0, 0, 0.25, 1) 0s, opacity 0.08 cubic-bezier(0, 0, 0.25, 1) 0s, color 0.08 linear;
}
body:not(.lg-from-hash) .lg-outer.lg-start-zoom .lg-item:not(.lg-zoomable) .lg-img-wrap,
body:not(.lg-from-hash) .lg-outer.lg-start-zoom .lg-item:not(.lg-zoomable) .lg-video-cont,
body:not(.lg-from-hash) .lg-outer.lg-start-zoom .lg-item:not(.lg-zoomable) .lg-media-cont {
opacity: 0;
-moz-transform: scale3d(0.5, 0.5, 0.5);
-o-transform: scale3d(0.5, 0.5, 0.5);
-ms-transform: scale3d(0.5, 0.5, 0.5);
-webkit-transform: scale3d(0.5, 0.5, 0.5);
transform: scale3d(0.5, 0.5, 0.5);
will-change: transform, opacity;
-webkit-transition: -webkit-transform 250ms cubic-bezier(0, 0, 0.25, 1) 0s, opacity 250ms cubic-bezier(0, 0, 0.25, 1) !important;
-moz-transition: -moz-transform 250ms cubic-bezier(0, 0, 0.25, 1) 0s, opacity 250ms cubic-bezier(0, 0, 0.25, 1) !important;
-o-transition: -o-transform 250ms cubic-bezier(0, 0, 0.25, 1) 0s, opacity 250ms cubic-bezier(0, 0, 0.25, 1) !important;
transition: transform 250ms cubic-bezier(0, 0, 0.25, 1) 0s, opacity 250ms cubic-bezier(0, 0, 0.25, 1) !important;
}
body:not(.lg-from-hash) .lg-outer.lg-start-zoom .lg-item:not(.lg-zoomable).lg-complete .lg-img-wrap,
body:not(.lg-from-hash) .lg-outer.lg-start-zoom .lg-item:not(.lg-zoomable).lg-complete .lg-video-cont,
body:not(.lg-from-hash) .lg-outer.lg-start-zoom .lg-item:not(.lg-zoomable).lg-complete .lg-media-cont {
opacity: 1;
-moz-transform: scale3d(1, 1, 1);
-o-transform: scale3d(1, 1, 1);
-ms-transform: scale3d(1, 1, 1);
-webkit-transform: scale3d(1, 1, 1);
transform: scale3d(1, 1, 1);
}
.lg-icon:focus-visible {
color: #fff;
border-radius: 3px;
outline: 1px dashed rgba(255, 255, 255, 0.6);
}
.lg-toolbar .lg-icon:focus-visible {
border-radius: 8px;
outline-offset: -5px;
}
.lg-group:after {
content: "";
display: table;
clear: both;
}
.lg-container {
display: none;
outline: none;
}
.lg-container.lg-show {
display: block;
}
.lg-on {
scroll-behavior: unset;
}
.lg-overlay-open {
overflow: hidden;
}
.lg-toolbar,
.lg-prev,
.lg-next,
.lg-pager-outer,
.lg-hide-sub-html .lg-sub-html {
opacity: 0;
will-change: transform, opacity;
-webkit-transition: -webkit-transform 0.25s cubic-bezier(0, 0, 0.25, 1) 0s, opacity 0.25s cubic-bezier(0, 0, 0.25, 1) 0s;
-moz-transition: -moz-transform 0.25s cubic-bezier(0, 0, 0.25, 1) 0s, opacity 0.25s cubic-bezier(0, 0, 0.25, 1) 0s;
-o-transition: -o-transform 0.25s cubic-bezier(0, 0, 0.25, 1) 0s, opacity 0.25s cubic-bezier(0, 0, 0.25, 1) 0s;
transition: transform 0.25s cubic-bezier(0, 0, 0.25, 1) 0s, opacity 0.25s cubic-bezier(0, 0, 0.25, 1) 0s;
}
.lg-show-in .lg-toolbar,
.lg-show-in .lg-prev,
.lg-show-in .lg-next,
.lg-show-in .lg-pager-outer {
opacity: 1;
}
.lg-show-in.lg-hide-sub-html .lg-sub-html {
opacity: 1;
}
.lg-show-in .lg-hide-items .lg-prev {
opacity: 0;
-webkit-transform: translate3d(-10px, 0, 0);
transform: translate3d(-10px, 0, 0);
}
.lg-show-in .lg-hide-items .lg-next {
opacity: 0;
-webkit-transform: translate3d(10px, 0, 0);
transform: translate3d(10px, 0, 0);
}
.lg-show-in .lg-hide-items .lg-toolbar {
opacity: 0;
-webkit-transform: translate3d(0, -10px, 0);
transform: translate3d(0, -10px, 0);
}
.lg-show-in .lg-hide-items.lg-hide-sub-html .lg-sub-html {
opacity: 0;
-webkit-transform: translate3d(0, 20px, 0);
transform: translate3d(0, 20px, 0);
}
.lg-outer {
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
z-index: 1050;
text-align: left;
opacity: 0.001;
outline: none;
will-change: auto;
overflow: hidden;
-webkit-transition: opacity 0.15s ease 0s;
-o-transition: opacity 0.15s ease 0s;
transition: opacity 0.15s ease 0s;
}
.lg-outer * {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.lg-outer.lg-zoom-from-image {
opacity: 1;
}
.lg-outer.lg-visible {
opacity: 1;
}
.lg-outer.lg-css3 .lg-item:not(.lg-start-end-progress).lg-prev-slide, .lg-outer.lg-css3 .lg-item:not(.lg-start-end-progress).lg-next-slide, .lg-outer.lg-css3 .lg-item:not(.lg-start-end-progress).lg-current {
-webkit-transition-duration: inherit !important;
transition-duration: inherit !important;
-webkit-transition-timing-function: inherit !important;
transition-timing-function: inherit !important;
}
.lg-outer.lg-css3.lg-dragging .lg-item.lg-prev-slide, .lg-outer.lg-css3.lg-dragging .lg-item.lg-next-slide, .lg-outer.lg-css3.lg-dragging .lg-item.lg-current {
-webkit-transition-duration: 0s !important;
transition-duration: 0s !important;
opacity: 1;
}
.lg-outer.lg-grab img.lg-object {
cursor: -webkit-grab;
cursor: -moz-grab;
cursor: -o-grab;
cursor: -ms-grab;
cursor: grab;
}
.lg-outer.lg-grabbing img.lg-object {
cursor: move;
cursor: -webkit-grabbing;
cursor: -moz-grabbing;
cursor: -o-grabbing;
cursor: -ms-grabbing;
cursor: grabbing;
}
.lg-outer .lg-content {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.lg-outer .lg-inner {
width: 100%;
position: absolute;
left: 0;
top: 0;
bottom: 0;
-webkit-transition: opacity 0s;
-o-transition: opacity 0s;
transition: opacity 0s;
white-space: nowrap;
}
.lg-outer .lg-item {
display: none !important;
}
.lg-outer .lg-item:not(.lg-start-end-progress) {
background: url("../images/loading.gif") no-repeat scroll center center transparent;
}
.lg-outer.lg-css3 .lg-prev-slide,
.lg-outer.lg-css3 .lg-current,
.lg-outer.lg-css3 .lg-next-slide {
display: inline-block !important;
}
.lg-outer.lg-css .lg-current {
display: inline-block !important;
}
.lg-outer .lg-item,
.lg-outer .lg-img-wrap {
display: inline-block;
text-align: center;
position: absolute;
width: 100%;
height: 100%;
}
.lg-outer .lg-item:before,
.lg-outer .lg-img-wrap:before {
content: "";
display: inline-block;
height: 100%;
vertical-align: middle;
}
.lg-outer .lg-img-wrap {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
white-space: nowrap;
font-size: 0;
}
.lg-outer .lg-item.lg-complete {
background-image: none;
}
.lg-outer .lg-item.lg-current {
z-index: 1060;
}
.lg-outer .lg-object {
display: inline-block;
vertical-align: middle;
max-width: 100%;
max-height: 100%;
width: auto;
height: auto;
position: relative;
}
.lg-outer .lg-empty-html.lg-sub-html,
.lg-outer .lg-empty-html .lg-sub-html {
display: none;
}
.lg-outer.lg-hide-download .lg-download {
opacity: 0.75;
pointer-events: none;
}
.lg-outer .lg-first-slide .lg-dummy-img {
position: absolute;
top: 50%;
left: 50%;
}
.lg-outer.lg-components-open:not(.lg-zoomed) .lg-components {
-webkit-transform: translate3d(0, 0%, 0);
transform: translate3d(0, 0%, 0);
opacity: 1;
}
.lg-outer.lg-components-open:not(.lg-zoomed) .lg-sub-html {
opacity: 1;
transition: opacity 0.2s ease-out 0.15s;
}
.lg-outer .lg-media-cont {
text-align: center;
display: inline-block;
vertical-align: middle;
position: relative;
}
.lg-outer .lg-media-cont .lg-object {
width: 100% !important;
height: 100% !important;
}
.lg-outer .lg-has-iframe .lg-media-cont {
-webkit-overflow-scrolling: touch;
overflow: auto;
}
.lg-backdrop {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 1040;
background-color: #000;
opacity: 0;
will-change: auto;
-webkit-transition: opacity 333ms ease-in 0s;
-o-transition: opacity 333ms ease-in 0s;
transition: opacity 333ms ease-in 0s;
}
.lg-backdrop.in {
opacity: 1;
}
.lg-css3.lg-no-trans .lg-prev-slide,
.lg-css3.lg-no-trans .lg-next-slide,
.lg-css3.lg-no-trans .lg-current {
-webkit-transition: none 0s ease 0s !important;
-moz-transition: none 0s ease 0s !important;
-o-transition: none 0s ease 0s !important;
transition: none 0s ease 0s !important;
}
.lg-css3.lg-use-css3 .lg-item {
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
backface-visibility: hidden;
}
.lg-css3.lg-fade .lg-item {
opacity: 0;
}
.lg-css3.lg-fade .lg-item.lg-current {
opacity: 1;
}
.lg-css3.lg-fade .lg-item.lg-prev-slide, .lg-css3.lg-fade .lg-item.lg-next-slide, .lg-css3.lg-fade .lg-item.lg-current {
-webkit-transition: opacity 0.1s ease 0s;
-moz-transition: opacity 0.1s ease 0s;
-o-transition: opacity 0.1s ease 0s;
transition: opacity 0.1s ease 0s;
}
.lg-css3.lg-use-css3 .lg-item.lg-start-progress {
-webkit-transition: -webkit-transform 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) 0s;
-moz-transition: -moz-transform 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) 0s;
-o-transition: -o-transform 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) 0s;
transition: transform 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) 0s;
}
.lg-css3.lg-use-css3 .lg-item.lg-start-end-progress {
-webkit-transition: -webkit-transform 1s cubic-bezier(0, 0, 0.25, 1) 0s;
-moz-transition: -moz-transform 1s cubic-bezier(0, 0, 0.25, 1) 0s;
-o-transition: -o-transform 1s cubic-bezier(0, 0, 0.25, 1) 0s;
transition: transform 1s cubic-bezier(0, 0, 0.25, 1) 0s;
}
.lg-css3.lg-slide.lg-use-css3 .lg-item {
opacity: 0;
}
.lg-css3.lg-slide.lg-use-css3 .lg-item.lg-prev-slide {
-webkit-transform: translate3d(-100%, 0, 0);
transform: translate3d(-100%, 0, 0);
}
.lg-css3.lg-slide.lg-use-css3 .lg-item.lg-next-slide {
-webkit-transform: translate3d(100%, 0, 0);
transform: translate3d(100%, 0, 0);
}
.lg-css3.lg-slide.lg-use-css3 .lg-item.lg-current {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
opacity: 1;
}
.lg-css3.lg-slide.lg-use-css3 .lg-item.lg-prev-slide, .lg-css3.lg-slide.lg-use-css3 .lg-item.lg-next-slide, .lg-css3.lg-slide.lg-use-css3 .lg-item.lg-current {
-webkit-transition: -webkit-transform 1s cubic-bezier(0, 0, 0.25, 1) 0s, opacity 0.1s ease 0s;
-moz-transition: -moz-transform 1s cubic-bezier(0, 0, 0.25, 1) 0s, opacity 0.1s ease 0s;
-o-transition: -o-transform 1s cubic-bezier(0, 0, 0.25, 1) 0s, opacity 0.1s ease 0s;
transition: transform 1s cubic-bezier(0, 0, 0.25, 1) 0s, opacity 0.1s ease 0s;
}
.lg-container {
display: none;
}
.lg-container.lg-show {
display: block;
}
.lg-container.lg-dragging-vertical .lg-backdrop {
-webkit-transition-duration: 0s !important;
transition-duration: 0s !important;
}
.lg-container.lg-dragging-vertical .lg-css3 .lg-item.lg-current {
-webkit-transition-duration: 0s !important;
transition-duration: 0s !important;
opacity: 1;
}
.lg-inline .lg-backdrop,
.lg-inline .lg-outer {
position: absolute;
}
.lg-inline .lg-backdrop {
z-index: 1;
}
.lg-inline .lg-outer {
z-index: 2;
}
.lg-inline .lg-maximize:after {
content: "\e909";
}
.lg-components {
-webkit-transform: translate3d(0, 100%, 0);
transform: translate3d(0, 100%, 0);
will-change: transform;
-webkit-transition: -webkit-transform 0.35s ease-out 0s;
-moz-transition: -moz-transform 0.35s ease-out 0s;
-o-transition: -o-transform 0.35s ease-out 0s;
transition: transform 0.35s ease-out 0s;
z-index: 1080;
position: absolute;
bottom: 0;
right: 0;
left: 0;
}
/*# sourceMappingURL=lightgallery.css.map */

View File

@ -87,14 +87,51 @@ if (!function_exists('lcp_random_string')) {
} }
} }
// Return a valid array of Media IDs
// Used to return custom meta fields/table fields data as an array
function validate_media_ids($input) {
// Check if the input is a serialized array (e.g., 'a:2:{i:0;s:2:"63";i:1;s:2:"64";}')
if (is_string($input) && (@unserialize($input) !== false || $input === 'b:0;')) {
// If serialized, unserialize it
$media_ids = unserialize($input);
// Ensure the unserialized data is an array
if (is_array($media_ids)) {
// Return the array of IDs (ensure they're integers)
return array_map('intval', array_filter($media_ids));
}
}
// Check if the input is a comma-separated string of IDs (e.g., "112,512,581")
if (is_string($input)) {
// Split the string into an array using commas as separators
$media_ids = array_map('intval', explode(',', $input));
// Filter out any invalid IDs (non-numeric or empty)
return array_filter(array_unique($media_ids));
}
// Check if the input is already an array (e.g., [63, 64, 112])
if (is_array($input)) {
// Ensure the array only contains integers
return array_filter(array_map('intval', $input));
}
// Return an empty array if the input format is not recognized
return [];
}
// Return an array of Media IDs // Return an array of Media IDs
function get_media_ids($attributes) { function get_media_ids($attributes) {
// Ensure 'galleryItems' exists in the attributes array // Manual Source
if (isset($attributes['galleryItems']) && $attributes['source'] == "manual") { if ($attributes['source'] == "manual" && isset($attributes['galleryItems'])) {
// Extract 'id' from each item in the 'galleryItems' array // Extract 'id' from each item in the 'galleryItems' array
$media_ids = array_map(function($item) { $media_ids = array_map(function($item) {
return $item['id']; // Return the 'id' value from each array item return $item['id']; // Return the 'id' value from each array item
}, $attributes['galleryItems']); // Use $attributes['galleryItems'] here }, $attributes['galleryItems']); // Use $attributes['galleryItems'] here
// Check if we need to include the post thumbnail // Check if we need to include the post thumbnail
if ($attributes['includePostThumbnail']) { if ($attributes['includePostThumbnail']) {
// Get the featured image (post thumbnail) ID // Get the featured image (post thumbnail) ID
@ -104,14 +141,30 @@ function get_media_ids($attributes) {
array_unshift($media_ids, $featured_media_id); array_unshift($media_ids, $featured_media_id);
} }
} }
// Return the array of media IDs
// Post Meta Source
return $media_ids; return $media_ids;
}
// Meta Field Source
elseif (isset($attributes['source']) && $attributes['source'] == "metaField") {
// Ensure 'sourceMetaField' exists in the attributes array
if (isset($attributes['sourceMetaField'])) {
// Retrieve the raw data directly from the custom field (it will be automatically unserialized by WordPress if it's a serialized string)
$raw_media_ids = get_post_meta(get_the_ID(), $attributes['sourceMetaField'], true);
// Pass the raw data to the helper function to decide how to process it
$media_ids = validate_media_ids($raw_media_ids);
// Return the processed media IDs
return $media_ids;
}
} }
// Return an empty array if 'galleryItems' doesn't exist or 'source' is not 'manual'
// Return an empty array if no gallery items or source is not handled
return []; return [];
} }
//Get the gallery items from the media IDs //Get the gallery items from the media IDs
function get_gallery_items_data($media_ids) { function get_gallery_items_data($media_ids) {
$gallery_items = array(); $gallery_items = array();
@ -390,42 +443,42 @@ function render_lcp_gallery_block($attributes) {
// Generate styles for the gallery based on the unique class // Generate styles for the gallery based on the unique class
$classes = 'lcp-gallery '; // Start with lcp-gallery class $classes = 'lcp-gallery '; // Start with lcp-gallery class
$classes .= $unique_class; $classes .= $unique_class;
// Check if 'initialLayout' is set to 'grid' and add grid column classes if applicable // Check if 'initialLayout' is set to 'grid' and add grid column classes if applicable
if (isset($attributes['initialLayout']) && $attributes['initialLayout'] === 'grid') { if (isset($attributes['initialLayout']) && $attributes['initialLayout'] === 'grid') {
// Image aspect ratios // Image aspect ratios
$classes .= ' aspect-' . esc_attr($attributes['itemsAspectRatio']); $classes .= ' aspect-' . esc_attr($attributes['itemsAspectRatio']);
// Grid classes // Grid classes
$classes .= ' grid'; $classes .= ' grid';
// Grid columns // Grid columns
if (isset($attributes['gridColumnsLarge'])) { if (isset($attributes['gridColumnsLarge'])) {
$classes .= ' large-' . esc_attr($attributes['gridColumnsLarge']) . '-columns'; $classes .= ' large-' . esc_attr($attributes['gridColumnsLarge']) . '-columns';
}
if (isset($attributes['gridColumnsMedium'])) {
$classes .= ' medium-' . esc_attr($attributes['gridColumnsMedium']) . '-columns';
}
if (isset($attributes['gridColumnsSmall'])) {
$classes .= ' small-' . esc_attr($attributes['gridColumnsSmall']) . '-columns';
}
} }
if (isset($attributes['gridColumnsMedium'])) {
$classes .= ' medium-' . esc_attr($attributes['gridColumnsMedium']) . '-columns'; // Add 'initialLayout' class if it exists and isn't 'grid'
if (isset($attributes['initialLayout']) && !empty($attributes['initialLayout']) && $attributes['initialLayout'] !== 'grid') {
$classes .= ' ' . "lcp-inline-gallery";
} }
if (isset($attributes['gridColumnsSmall'])) {
$classes .= ' small-' . esc_attr($attributes['gridColumnsSmall']) . '-columns';
}
}
// Add 'initialLayout' class if it exists and isn't 'grid'
if (isset($attributes['initialLayout']) && !empty($attributes['initialLayout']) && $attributes['initialLayout'] !== 'grid') {
$classes .= ' ' . "lcp-inline-gallery";
}
// Build the styles using the unique class (if necessary) // Build the styles using the unique class (if necessary)
$styles = build_gallery_styles($attributes, $unique_class); $styles = build_gallery_styles($attributes, $unique_class);
// Return the complete gallery HTML with the unique class and the settings as a JSON string // Return the complete gallery HTML with the unique class and the settings as a JSON string
return " return "
<div class= '{$classes}' data-lgSettings='" . esc_attr($gallery_settings_json) . "'> <div class= '{$classes}' data-lgSettings='" . esc_attr($gallery_settings_json) . "'>
{$gallery_items_html} {$gallery_items_html}
</div>"; </div>";
} }
/* Initialize Gallery Block */ /* Initialize Gallery Block */
function lcp_gallery_block_init() { function lcp_gallery_block_init() {

View File

@ -1,8 +1,8 @@
{ {
"name": "gallery", "name": "gallery",
"version": "0.1.0", "version": "0.1.0",
"description": "Example block scaffolded with Create Block tool.", "description": "A dynamic gallery block",
"author": "The WordPress Contributors", "author": "Rangel Digital",
"license": "GPL-2.0-or-later", "license": "GPL-2.0-or-later",
"main": "build/index.js", "main": "build/index.js",
"scripts": { "scripts": {

View File

@ -1,6 +1,13 @@
import { __ } from '@wordpress/i18n'; import { __ } from '@wordpress/i18n';
import { useBlockProps, InspectorControls, MediaUpload, MediaUploadCheck } from '@wordpress/block-editor'; import {
import { useState, useEffect } from 'react'; InspectorControls,
MediaUpload,
MediaUploadCheck
} from '@wordpress/block-editor';
import { useState,
useEffect,
FC
} from 'react';
import { useSelect } from '@wordpress/data'; import { useSelect } from '@wordpress/data';
import { import {
PanelBody, PanelBody,
@ -18,12 +25,48 @@ import {
import metadata from './block.json'; import metadata from './block.json';
import './editor.scss'; import './editor.scss';
import LightGallery from 'lightgallery/react'; //Import the LcpGallery component
import 'lightgallery/css/lightgallery.css'; import LcpGallery from '../components/LightGallery';
import 'lightgallery/css/lg-zoom.css';
import 'lightgallery/css/lg-thumbnail.css';
import lgThumbnail from 'lightgallery/plugins/thumbnail'; const galleryElements = [
import lgZoom from 'lightgallery/plugins/zoom'; {
src:
"https://images.unsplash.com/photo-1542103749-8ef59b94f47e?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1400&q=80",
responsive:
"https://images.unsplash.com/photo-1542103749-8ef59b94f47e?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=480&q=80 480, https://images.unsplash.com/photo-1542103749-8ef59b94f47e?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=80 800",
thumb:
"https://images.unsplash.com/photo-1542103749-8ef59b94f47e?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=240&q=80",
subHtml: (
<div className="lightGallery-captions">
<h4>
Photo by <a href="https://unsplash.com/@dann">Dan</a>
</h4>
<p>Published on November 13, 2018</p>
</div>
),
},
{
src:
"https://images.unsplash.com/photo-1473876988266-ca0860a443b8?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1400&q=80",
responsive:
"https://images.unsplash.com/photo-1473876988266-ca0860a443b8?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=480&q=80 480, https://images.unsplash.com/photo-1473876988266-ca0860a443b8?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=80 800",
thumb:
"https://images.unsplash.com/photo-1473876988266-ca0860a443b8?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=240&q=80",
subHtml: (
<div className="lightGallery-captions">
<h4>
Photo by <a href="https://unsplash.com/@kylepyt">Kyle Peyton</a>
</h4>
<p>Published on September 14, 2016</p>
</div>
),
},
]
// Aspect ratio options // Aspect ratio options
const aspectRatioOptions = [ const aspectRatioOptions = [
@ -41,9 +84,9 @@ const { apiFetch } = wp;
apiFetch({ path: '/custom/v1/get-gallery-supported-plugins-data' }) apiFetch({ path: '/custom/v1/get-gallery-supported-plugins-data' })
.then((data) => { .then((data) => {
console.log(data); // Log the entire data object console.log(data); // Log the entire data object
if (data.jetengine_active) { if (data.jetengine_active) {
console.log('Jet Engine is activated'); console.log('Jet Engine is activated');
// Other logic here // Other logic here
} }
}) })
@ -125,12 +168,7 @@ export default function Edit(props) {
// Handle Updating LightGallery settings // Handle Updating LightGallery settings
const [settings, setSettings] = useState(lgSettings); const [settings, setSettings] = useState(lgSettings);
useEffect(() => {
// Only update state if lgSettings actually change
if (JSON.stringify(settings) !== JSON.stringify(lgSettings)) {
setSettings(lgSettings);
}
}, [lgSettings]); // Runs only when lgSettings change
const [borders, setBorders] = useState(thumbnailsBorders || { const [borders, setBorders] = useState(thumbnailsBorders || {
top: { color: '#000000', style: 'solid', width: '1px' }, top: { color: '#000000', style: 'solid', width: '1px' },
@ -211,38 +249,6 @@ export default function Edit(props) {
]; ];
useEffect(() => {
// Initialize plugins array
const updatedPlugins = [];
// Loop through the plugin requirements
lgPluginRequirements.forEach(({ setting, plugin }) => {
// If the setting is enabled, add the corresponding plugin to the plugins array
if (lgSettings[setting]) {
updatedPlugins.push(plugin);
}
});
// Use function-based setAttributes to get the latest lgSettings and update plugins array
setAttributes((prevAttributes) => {
const updatedLgSettings = {
...prevAttributes.lgSettings,
plugins: updatedPlugins, // Updated plugins array
};
// Log the lgSettings after update
console.log("Updated lgSettings:", updatedLgSettings);
return {
...prevAttributes,
lgSettings: updatedLgSettings,
};
});
}, [lgSettings.zoom, lgSettings.thumbnail, lgSettings.rotate, lgSettings.autoplay, lgSettings.fullScreen, lgSettings.download, setAttributes]);
// Retrieve current post type, post ID, and check if it's a template mode using useSelect // Retrieve current post type, post ID, and check if it's a template mode using useSelect
const { isTemplate, postType, postId } = useSelect((select) => { const { isTemplate, postType, postId } = useSelect((select) => {
@ -263,25 +269,57 @@ const { isTemplate, postType, postId } = useSelect((select) => {
if (isTemplate) { if (isTemplate) {
sourceOptions = [ sourceOptions = [
{ value: 'manual', label: __('Manually Select', metadata.textdomain) }, { value: 'manual', label: __('Manually Select', metadata.textdomain) },
{ value: 'lcp_post_gallery', label: __('Post Gallery', metadata.textdomain) }, { value: 'lcpPostGallery', label: __('Post Gallery', metadata.textdomain) },
{ value: 'meta_field', label: __('Meta field of current post', metadata.textdomain) }, { value: 'metaField', label: __('Meta field of current post', metadata.textdomain) },
{ value: 'linked_table', label: __('Linked Table', metadata.textdomain) } ]; { value: 'linkedTable', label: __('Linked Table', metadata.textdomain) } ];
// Add logic to adjust block's behavior when editing a template // Add logic to adjust block's behavior when editing a template
} else { } else {
sourceOptions = [ sourceOptions = [
{ value: 'manual', label: __('Manually Select', metadata.textdomain) }, { value: 'manual', label: __('Manually Select', metadata.textdomain) },
{ value: 'lcp_post_gallery', label: __('Post Gallery', metadata.textdomain) } { value: 'lcpPostGallery', label: __('Post Gallery', metadata.textdomain) }
]; ];
// Add logic for post/page editing mode // Add logic for post/page editing mode
} }
// Now you can use sourceOptions as needed in your block rendering logic
const updateLgSetting = (key, value) => {
setAttributes({
lgSettings: {
...lgSettings,
[key]: value,
},
});
};
// Function to toggle plugins (add/remove a plugin)
const togglePlugin = (plugin, enable) => {
setAttributes({
lgSettings: {
...lgSettings,
plugins: enable
? [...lgSettings.plugins, plugin] // Add the plugin if enabled
: lgSettings.plugins.filter((p) => p !== plugin), // Remove the plugin if disabled
},
});
};
// Toggle Control for enabling 'Hash' and updating the plugin array
const handleToggleHash = (value) => {
updateLgSetting('hash', value);
togglePlugin('lgHash', value); // Add/Remove lgHash plugin based on toggle value
};
// Example control for enabling 'Zoom' and updating the plugin array
const handleToggleZoom = (value) => {
updateLgSetting('zoom', value);
togglePlugin('lgZoom', value); // Add/Remove lgZoom plugin based on toggle value
};
return ( return (
<> <>
{/* The Gallery */}
<LightGallery {...attributes.lgSettings} />
<InspectorControls> <InspectorControls>
{/* Settings and Style Tabs */} {/* Settings and Style Tabs */}
<TabPanel <TabPanel
@ -313,14 +351,14 @@ const { isTemplate, postType, postId } = useSelect((select) => {
options={sourceOptions} options={sourceOptions}
/> />
{source === 'manual' && <MultiMediaUpload onSelect={handleSelectMedia} />} {source === 'manual' && <MultiMediaUpload onSelect={handleSelectMedia} />}
{source === 'meta_field' && ( {source === 'metaField' && (
<TextControl <TextControl
label={__('Meta Field Name')} label={__('Meta Field Name')}
value={sourceMetaField} value={sourceMetaField}
onChange={(newValue) => setAttributes({ sourceMetaField: newValue })} onChange={(newValue) => setAttributes({ sourceMetaField: newValue })}
/> />
)} )}
{source === 'linked_table' && ( {source === 'linkedTable' && (
<> <>
<TextControl <TextControl
label={__('Table Name')} label={__('Table Name')}
@ -500,13 +538,14 @@ const { isTemplate, postType, postId } = useSelect((select) => {
label={__('Enable Zoom', 'lcp')} label={__('Enable Zoom', 'lcp')}
checked={lgSettings.zoom} checked={lgSettings.zoom}
onChange={(value) => { onChange={(value) => {
// Update autoplay
setAttributes({ setAttributes({
lgSettings: { lgSettings: {
...lgSettings, ...lgSettings,
zoom: value, // Update the zoom setting zoom: value, // Update the zoom setting
plugins: value plugins: value
? [...lgSettings.plugins, 'lgZoom'] // Add lgZoom plugin if enabled ? [...lgSettings.plugins, 'lgZoom'] // Add lgFullScreen plugin if enabled
: lgSettings.plugins.filter(plugin => plugin !== 'lgZoom'), // Remove lgZoom plugin if disabled : lgSettings.plugins.filter(plugin => plugin !== 'lgZoom'), // Remove lgFullScreen plugin if disabled
}, },
}); });
}} }}
@ -814,8 +853,6 @@ const { isTemplate, postType, postId } = useSelect((select) => {
</TabPanel> </TabPanel>
</InspectorControls> </InspectorControls>
</> </>
); );
} }

View File

@ -24,10 +24,10 @@ if ( ! defined( 'ABSPATH' ) ) {
* *
* @see https://developer.wordpress.org/reference/functions/register_block_type/ * @see https://developer.wordpress.org/reference/functions/register_block_type/
*/ */
function header_container_block_init() { function lcp_header_container_block_init() {
register_block_type( __DIR__ . '/build' , array( register_block_type( __DIR__ . '/build' , array(
'parent' => array( 'lcp/viewport', 'lcp/main-area' ), // Only allow this block to be inserted inside the 'lcp/viewport' block //'parent' => array( 'lcp/viewport', 'lcp/main-area' ), // Only allow this block to be inserted inside the 'lcp/viewport' block
) )
); );
} }
add_action( 'init', 'header_container_block_init' ); add_action( 'init', 'lcp_header_container_block_init' );

View File

@ -24,7 +24,7 @@ if ( ! defined( 'ABSPATH' ) ) {
* *
* @see https://developer.wordpress.org/reference/functions/register_block_type/ * @see https://developer.wordpress.org/reference/functions/register_block_type/
*/ */
function main_content_init() { function lcp_main_content_init() {
register_block_type( __DIR__ . '/build' ); register_block_type( __DIR__ . '/build' );
} }
add_action( 'init', 'main_content_init' ); add_action( 'init', 'lcp_main_content_init' );

View File

@ -37,7 +37,7 @@ export default function Edit(props) {
</InspectorControls> </InspectorControls>
{/* Main block content */} {/* Main block content */}
<div {...innerBlocksProps} style={style}> <div {...innerBlocksProps} id="lcp-main-wrap">
<InnerBlocks {...innerBlocksProps} /> <InnerBlocks {...innerBlocksProps} />

View File

@ -7,3 +7,7 @@
.wp-block-create-block-lcp-viewport { .wp-block-create-block-lcp-viewport {
border: 1px dotted #f00; border: 1px dotted #f00;
} }
#lcp-main-wrap {
margin-left:340px
}

View File

@ -23,7 +23,7 @@ export default function Save( {attributes} ) {
maxWidth: maxWidth, maxWidth: maxWidth,
}; };
return ( return (
<div {...blockProps} id="lcp-main-content" style={style}> <div {...blockProps} id="lcp-main-wrap" style={style}>
<InnerBlocks.Content /> <InnerBlocks.Content />

View File

@ -9,7 +9,10 @@
"description": "A separate content area to be nested inside the LCP viewport", "description": "A separate content area to be nested inside the LCP viewport",
"example": {}, "example": {},
"supports": { "supports": {
"html": false "color": {
"background": true,
"text": false
}
}, },
"textdomain": "lcp", "textdomain": "lcp",
"editorScript": "file:./index.js", "editorScript": "file:./index.js",

View File

@ -11,7 +11,7 @@ import { __ } from '@wordpress/i18n';
* *
* @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-block-editor/#useblockprops * @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-block-editor/#useblockprops
*/ */
import { useBlockProps, InnerBlocks} from '@wordpress/block-editor'; import { useBlockProps, InnerBlocks } from '@wordpress/block-editor';
/** /**
* Lets webpack process CSS, SASS or SCSS files referenced in JavaScript files. * Lets webpack process CSS, SASS or SCSS files referenced in JavaScript files.
@ -30,15 +30,23 @@ import './editor.scss';
* @return {Element} Element to render. * @return {Element} Element to render.
*/ */
export default function Edit() { export default function Edit() {
return (<div> // Block props
<p { ...useBlockProps() }> const blockProps = useBlockProps();
{ __( 'Lcp Sidecontent hello from the editor!', 'lcp' ) }
</p>
<InnerBlocks
// Optional: You can provide a template or allowed blocks
// template={[['core/paragraph'], ['core/image']]}
/> // Custom appender logic (you can customize this as needed)
const renderAppender = () => {
return <InnerBlocks.ButtonBlockAppender />;
};
return (
<div {...useBlockProps}>
<div id="lcp-sidecontent">
<InnerBlocks
// Optional: You can provide a template or allowed blocks
// template={[['core/paragraph'], ['core/image']]}
renderAppender={renderAppender} // Add the custom appender here
/>
</div> </div>
</div>
); );
} }

View File

@ -7,3 +7,16 @@
.wp-block-create-block-lcp-sidecontent { .wp-block-create-block-lcp-sidecontent {
border: 1px dotted #f00; border: 1px dotted #f00;
} }
#lcp-sidecontent {
position: absolute; /* or fixed depending on your JS logic */
left: 0;
background: #fff;
width: 340px; /* Fixed width of 340px */
height: 100%;
overflow: scroll;
z-index: 2;
border-right: 2px solid #eee;
outline: 0;
top: var(--my-top); /* Dynamically controlled top position via JS */
}

View File

@ -21,8 +21,17 @@ export default function Save() {
return ( return (
<div {...blockProps} id="lcp-sidecontent"> <div {...blockProps} id="lcp-sidecontent">
<div id="lcp-sidecontent-inner">
<InnerBlocks.Content /> <InnerBlocks.Content />
</div>
</div> <div id="lcp-scroll-track">
<div id="lcp-scroll-bar">
</div>
</div>
</div>
); );
} }

View File

@ -21,5 +21,5 @@
*/ */
/* eslint-disable no-console */ /* eslint-disable no-console */
console.log( 'Hello World! (from create-block-lcp-sidecontent block)' );
/* eslint-enable no-console */ /* eslint-enable no-console */

View File

@ -6,8 +6,10 @@ import './editor.scss';
export default function Edit({ attributes, setAttributes }) { export default function Edit({ attributes, setAttributes }) {
const { hasSidecontent } = attributes; const { hasSidecontent } = attributes;
// Block props // Block props with custom className management
const blockProps = useBlockProps(); const blockProps = useBlockProps({
className: hasSidecontent ? 'has-sidecontent' : '', // Custom class
});
// Custom template logic based on hasSidecontent // Custom template logic based on hasSidecontent
const template = [ const template = [
@ -31,15 +33,15 @@ export default function Edit({ attributes, setAttributes }) {
/> />
</InspectorControls> </InspectorControls>
<p> <div id="lcp-viewport-outer">
{__('Lcp Viewport hello from the editor!', 'lcp-viewport')} <div id="lcp-viewport-inner">
</p> {/* Render the InnerBlocks with conditional template */}
<InnerBlocks
{/* Render the InnerBlocks with conditional template */} template={template} // Use the template logic here
<InnerBlocks renderAppender={renderAppender} // Custom appender logic
template={template} // Use the template logic here />
renderAppender={renderAppender} // Custom appender logic </div>
/> </div>
</div> </div>
); );
} }

View File

@ -13,13 +13,13 @@ export default function Save({ attributes }) {
const { hasSidecontent } = attributes; // Retrieve the hasSidecontent attribute const { hasSidecontent } = attributes; // Retrieve the hasSidecontent attribute
const blockProps = useBlockProps.save(); const blockProps = useBlockProps.save();
// Conditionally add the .lcp-has-sidecontent class if hasSidecontent is true // Conditionally add the 'has-sidecontent' class if hasSidecontent is true
const hasSidecontentClass = hasSidecontent ? 'class="lcp-has-sidecontent"' : null; const className = hasSidecontent ? 'has-sidecontent' : '';
return ( return (
<div {...blockProps} id="lcp-viewport-outer" > <div class={className} id="lcp-viewport-outer">
<div hasSidecontentClass id="lcp-viewport-inner"> <div id="lcp-viewport-inner" class={className}>
<InnerBlocks.Content /> <InnerBlocks.Content />
</div> </div>
</div> </div>
); );

View File

@ -5,3 +5,9 @@
* Replace them with your own styles or remove the file completely. * Replace them with your own styles or remove the file completely.
*/ */
#lcp-viewport-inner {
display: block; /* Arrange the side content and main content side-by-side */
width: 100%;
position: relative; /* To ensure side content stays in place */
}

View File

@ -20,10 +20,10 @@ class Lcp_Blocks {
include $this->template_directory. '/includes/blocks/lcp-gallery/lcp-gallery.php'; include $this->template_directory. '/includes/blocks/lcp-gallery/lcp-gallery.php';
include $this->template_directory. '/includes/blocks/lcp-viewport/lcp-viewport.php'; include $this->template_directory. '/includes/blocks/lcp-viewport/lcp-viewport.php';
include $this->template_directory. '/includes/blocks/lcp-sidecontent/lcp-sidecontent.php'; include $this->template_directory. '/includes/blocks/lcp-sidecontent/lcp-sidecontent.php';
include $this->template_directory. '/includes/blocks/lcp-main-area/main-area.php'; include $this->template_directory. '/includes/blocks/lcp-main-area/lcp-main-area.php';
include $this->template_directory. '/includes/blocks/lcp-header-container/header-container.php'; include $this->template_directory. '/includes/blocks/lcp-header-container/lcp-header-container.php';
include $this->template_directory. '/includes/blocks/lcp-container/lcp-dynamic-container.php'; include $this->template_directory. '/includes/blocks/lcp-dynamic-container/lcp-dynamic-container.php';
include $this->template_directory. '/includes/blocks/lcp-key-points/key-points.php'; include $this->template_directory. '/includes/blocks/lcp-key-points/lcp-key-points.php';
include $this->template_directory. '/includes/blocks/lcp-button/lcp-button.php'; include $this->template_directory. '/includes/blocks/lcp-button/lcp-button.php';
} }

272
script.js
View File

@ -1,197 +1,109 @@
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function () {
// Get references to the DOM elements
// Select all elements with the class .lcpOpenLoginPopup
const openLoginButtons = document.querySelectorAll('.lcpOpenLoginPopup');
// Loop through all the elements with the .lcpOpenLoginPopup class
openLoginButtons.forEach(function(button) {
button.addEventListener('click', function() {
// Add the .open class to the #lcp-login-form when clicked
const loginForm = document.getElementById('lcp-login-form');
console.log("login form");
if (loginForm) {
loginForm.classList.add('open');
}
});
});
// Get references to the DOM elements once
const header = document.getElementById('lcp-header-container'); const header = document.getElementById('lcp-header-container');
const sideContent = document.getElementById('lcp-sidecontent'); const sideContent = document.getElementById('lcp-sidecontent');
const mainContent = document.getElementById('lcp-main-content');
const adminBarHeight = getAdminBarHeight(); // Get admin bar height
// Ensure elements exist before applying logic
if (!header || !sideContent || !mainContent) return;
// Update position of side content and adjust margin of main content based on header lcp-sticky class
updateSideContentPosition(header, sideContent, adminBarHeight);
adjustMainContentMargin(header, mainContent, adminBarHeight);
// Ensure the header and side content are properly positioned on page load
handleInitialPageLoad(header, sideContent, adminBarHeight);
// Debounce the scroll handler to limit the frequency of the function calls
const debouncedScroll = debounce(() => handleScroll(header, sideContent, adminBarHeight), 10); // 10ms debounce delay
// Add the scroll event listener // Ensure elements exist before proceeding
window.addEventListener('scroll', debouncedScroll); if (!header || !sideContent) return;
// Add the resize event listener // Measure the height of the header once the DOM is loaded
window.addEventListener('resize', debounce(function() {
updateSideContentPosition(header, sideContent, adminBarHeight);
adjustMainContentMargin(header, mainContent, adminBarHeight);
}, 0)); // 0ms debounce delay
// Optional: Popup auto-open after a delay (e.g., 2 seconds)
setTimeout(function() {
var popups = document.querySelectorAll('.lcp-popup');
popups.forEach(function(popup) {
// Uncomment the line below if you want the popup to auto-open
// popup.classList.add('open');
});
}, 2000); // 2 seconds delay
});
// Function to get the height of the admin bar if it's visible
function getAdminBarHeight() {
const adminBar = document.getElementById('wpadminbar');
return adminBar ? adminBar.offsetHeight : 0; // Returns 32px if admin bar is present, 0 if not
}
// Function to update the position of side content
function updateSideContentPosition(header, sideContent, adminBarHeight) {
const headerHeight = header.offsetHeight;
// If the header has the 'lcp-sticky' or 'lcp-sticky-on-scroll' class, position side content below it, considering the admin bar height
if (header.classList.contains('lcp-sticky') || header.classList.contains('lcp-sticky-on-scroll')) {
sideContent.style.top = (headerHeight + adminBarHeight) + 'px'; // Update side content position
}
}
// Function to adjust margin-top of the main content
function adjustMainContentMargin(header, mainContent, adminBarHeight) {
if (header.classList.contains('lcp-sticky')) {
const headerHeight = header.offsetHeight;
mainContent.style.marginTop = (headerHeight + adminBarHeight) + 'px'; // Set margin-top to header + admin bar height
}
}
// Debounce function to limit the frequency of function calls
function debounce(func, delay) {
let timeout;
return function (...args) {
clearTimeout(timeout);
timeout = setTimeout(() => {
func.apply(this, args);
}, delay);
};
}
// Scroll handler function to update the 'scrolled' variable and toggle the lcp-sticky class
function handleScroll(header, sideContent, adminBarHeight) {
const scrolled = window.scrollY || document.documentElement.scrollTop;
const headerHeight = header.offsetHeight; const headerHeight = header.offsetHeight;
// Add 'lcp-fixed' class to side content if scrolled beyond the header height + admin bar height // Set the height of #lcp-sidecontent to 100vh minus the header height
if (scrolled > (headerHeight + adminBarHeight)) { sideContent.style.height = `calc(100vh - ${headerHeight}px)`;
sideContent.classList.add('lcp-fixed');
} else {
sideContent.classList.remove('lcp-fixed');
}
// Check if the header has the 'lcp-sticky-on-scroll' class and toggle the lcp-sticky class // Function to handle the scroll event
if (header.classList.contains('lcp-sticky-on-scroll')) { function handleScroll() {
if (scrolled > (headerHeight + adminBarHeight)) { const scrolled = window.scrollY || document.documentElement.scrollTop;
header.classList.add('lcp-stuck'); // Slide the header down
// Check if the page has scrolled past the height of the header
if (scrolled >= headerHeight) {
// Add the 'lcp-fixed' class and set 'top' to 0
sideContent.classList.add('lcp-fixed');
sideContent.style.top = '0';
} else { } else {
header.classList.remove('lcp-stuck'); // Hide the header if scrolling back up // Remove the 'lcp-fixed' class if scrolled back above the header
sideContent.classList.remove('lcp-fixed');
sideContent.style.top = ''; // Reset the 'top' style
} }
} }
// Add the scroll event listener
window.addEventListener('scroll', handleScroll);
// Also trigger the scroll handler once on load in case the page is already scrolled
handleScroll();
});
const sidecontent = document.getElementById("lcp-sidecontent");
const innerContent = document.getElementById("lcp-sidecontent-inner");
const scrollTrack = document.getElementById("lcp-scroll-track");
const scrollBar = document.getElementById("lcp-scroll-bar");
let isDragging = false;
let startY = 0;
let startScrollTop = 0;
// Update the custom scrollbar position based on the content's scroll position
function updateCustomScrollbar() {
const contentHeight = innerContent.scrollHeight;
const visibleHeight = innerContent.clientHeight;
const scrollTrackHeight = scrollTrack.clientHeight;
// Calculate the proportion of visible content to total content
const thumbHeight = (visibleHeight / contentHeight) * scrollTrackHeight;
scrollBar.style.height = `${thumbHeight}px`;
// Calculate the scroll ratio (position of the content relative to its height)
const scrollRatio = innerContent.scrollTop / (contentHeight - visibleHeight);
// Position the scrollbar thumb based on the scroll ratio
scrollBar.style.top = `${scrollRatio * (scrollTrackHeight - thumbHeight)}px`;
} }
// Function to handle the initial page load position for both header and side content // Handle the mouse down event to begin dragging the scrollbar
function handleInitialPageLoad(header, sideContent, adminBarHeight) { scrollBar.addEventListener("mousedown", (e) => {
const scrolled = window.scrollY || document.documentElement.scrollTop; isDragging = true;
const headerHeight = header.offsetHeight; startY = e.clientY;
startScrollTop = innerContent.scrollTop;
// Ensure the side content is properly positioned below the header + admin bar on page load document.body.style.userSelect = "none"; // Disable text selection while dragging
sideContent.style.top = (headerHeight + adminBarHeight) + 'px'; });
// If the page is loaded with a scroll position greater than header + admin bar height, apply the 'lcp-fixed' class
if (scrolled > (headerHeight + adminBarHeight)) {
sideContent.classList.add('lcp-fixed');
} else {
sideContent.classList.remove('lcp-fixed');
}
// If the page is loaded with a scroll position greater than header + admin bar height, apply the 'lcp-stuck' class
if (header.classList.contains('lcp-sticky-on-scroll') && scrolled > (headerHeight + adminBarHeight)) {
header.classList.add('lcp-stuck');
}
const openLoginButtons = document.querySelectorAll('.lcpOpenLoginPopup');
// Handle mouse movement to drag the scrollbar and simulate scrolling
document.addEventListener("mousemove", (e) => {
if (!isDragging) return;
const deltaY = e.clientY - startY;
const contentHeight = innerContent.scrollHeight;
const visibleHeight = innerContent.clientHeight;
const scrollTrackHeight = scrollTrack.clientHeight;
const thumbHeight = scrollBar.clientHeight;
const scrollableDistance = contentHeight - visibleHeight;
const thumbDistance = scrollTrackHeight - thumbHeight;
// Calculate new scroll position for content based on dragging
const newScrollTop = (deltaY / thumbDistance) * scrollableDistance + startScrollTop;
innerContent.scrollTop = newScrollTop;
updateCustomScrollbar();
});
} // Handle mouse up event to stop dragging
document.addEventListener("mouseup", () => {
isDragging = false;
document.body.style.userSelect = ""; // Enable text selection again
});
// Highlight to share // Handle scroll events on the content to update the custom scrollbar
innerContent.addEventListener("scroll", updateCustomScrollbar);
document.addEventListener('mouseup', function() { // Initialize the custom scrollbar position when the page loads
// Get the selected text updateCustomScrollbar();
const selectedText = window.getSelection().toString();
// Check if the selected text is at least 100 characters
if (selectedText.length >= 100) {
// Get the position of the selection
const range = window.getSelection().getRangeAt(0);
const rect = range.getBoundingClientRect();
// Ensure the tooltip exists before trying to manipulate its style
const tooltip = document.getElementById('share-tooltip');
if (tooltip) {
// Show the tooltip at the position of the selection
tooltip.style.display = 'block';
tooltip.style.left = `${rect.left + window.scrollX}px`;
tooltip.style.top = `${rect.top + window.scrollY + window.getSelection().anchorNode.offsetHeight + 5}px`;
}
} else {
// Hide the tooltip if selection is less than 100 characters
const tooltip = document.getElementById('share-tooltip');
if (tooltip) {
tooltip.style.display = 'none';
}
}
});
// Share to Facebook
document.getElementById('facebook-share')?.addEventListener('click', function() {
const selectedText = window.getSelection().toString();
const facebookUrl = `https://www.facebook.com/sharer/sharer.php?u=&quote=${encodeURIComponent(selectedText)}`;
window.open(facebookUrl, '_blank');
});
// Share to Twitter
document.getElementById('twitter-share')?.addEventListener('click', function() {
const selectedText = window.getSelection().toString();
const twitterUrl = `https://twitter.com/intent/tweet?text=${encodeURIComponent(selectedText)}`;
window.open(twitterUrl, '_blank');
});
// Close the tooltip when clicked elsewhere
document.addEventListener('click', function(e) {
if (!e.target.closest('#share-tooltip') && !e.target.closest('.share-btn')) {
const tooltip = document.getElementById('share-tooltip');
if (tooltip) {
tooltip.style.display = 'none';
}
}
});

View File

@ -25,20 +25,24 @@ Version: 1.0
/* Side content - absolute or fixed position */ /* Side content - absolute or fixed position */
#lcp-sidecontent { #lcp-sidecontent {
position: absolute; /* or fixed depending on your JS logic */ position: absolute; /* Positioned relative to the parent with position: relative */
left: 0; left: 0;
background: #fff;
width: 340px; /* Fixed width of 340px */
height: 100%;
overflow: scroll;
z-index: 2;
border-right: 2px solid #eee;
outline: 0;
top: var(--my-top); /* Dynamically controlled top position via JS */ top: var(--my-top); /* Dynamically controlled top position via JS */
width: 340px; /* Fixed width */
height: 100%; /* Full height */
overflow: auto; /* Allow scrolling inside */
background: #fff;
border-right: 2px solid #eee;
z-index: 2;
outline: 0;
}
#lcp-sidecontent.lcp-fixed {
position:fixed
} }
/* Main content */ /* Main content */
.lcp-viewport.has-sidecontent #lcp-main-content { .has-sidecontent #lcp-main-wrap {
flex: 1; /* Main content takes up the rest of the space */ flex: 1; /* Main content takes up the rest of the space */
margin-left: 340px; /* Space for side content */ margin-left: 340px; /* Space for side content */
padding: 20px; padding: 20px;
@ -100,3 +104,46 @@ Version: 1.0
background: red; background: red;
} }
#lcp-sidecontent {
overflow: hidden; /* Hide native scrollbar */
}
#lcp-sidecontent-inner {
height: 100%;
overflow: auto; /* Enable scrolling for inner content */
padding-right: 15px; /* Space for the custom scrollbar */
}
#lcp-scroll-track {
position: absolute;
top: 0;
right: 0;
width: 5px;
height: 100%;
background-color: #e0e0e0;
}
#lcp-scroll-bar {
width: 100%;
background-color: #333;
cursor: pointer;
border-radius: 5px;
}