diff --git a/assets/css/admin-style.css b/assets/css/admin-style.css new file mode 100644 index 0000000..e69de29 diff --git a/functions.php b/functions.php index a13e8e2..9949caa 100644 --- a/functions.php +++ b/functions.php @@ -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/classes/blocks.php'; new Lcp_Blocks(); + + + function lcp_block_theme_setup() { add_theme_support( 'block-templates' ); } @@ -26,6 +27,15 @@ function 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 function lcp_enqueue_svg_repeater_script($hook) { // Only enqueue on the theme settings page @@ -164,6 +174,11 @@ add_action('save_post', 'save_key_points_meta_box'); + + + + + /* BACKEND PAGES */ // Create backend pages @@ -250,7 +265,7 @@ function lcp_custom_svgs_field() { ?'; + $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 //var_dump($attributes); // 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 $padding = isset( $attributes['padding'] ) ? $attributes['padding'] : array(); diff --git a/includes/blocks/lcp-gallery/components/LightGallery.js b/includes/blocks/lcp-gallery/components/LightGallery.js new file mode 100644 index 0000000..251a0df --- /dev/null +++ b/includes/blocks/lcp-gallery/components/LightGallery.js @@ -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 ( + + {/* Gallery Items */} + + layers of blue. + + + + + + + ); +}; + +export default LcpGallery; diff --git a/includes/blocks/lcp-gallery/components/lightGallery.js b/includes/blocks/lcp-gallery/components/lightGallery.js deleted file mode 100644 index 90f4f4e..0000000 --- a/includes/blocks/lcp-gallery/components/lightGallery.js +++ /dev/null @@ -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 ( - <> - - - ); -}; \ No newline at end of file diff --git a/includes/blocks/lcp-gallery/components/style.css b/includes/blocks/lcp-gallery/components/style.css deleted file mode 100644 index ebd16ca..0000000 --- a/includes/blocks/lcp-gallery/components/style.css +++ /dev/null @@ -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 */ \ No newline at end of file diff --git a/includes/blocks/lcp-gallery/lcp-gallery.php b/includes/blocks/lcp-gallery/lcp-gallery.php index 9646257..4a98a14 100644 --- a/includes/blocks/lcp-gallery/lcp-gallery.php +++ b/includes/blocks/lcp-gallery/lcp-gallery.php @@ -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 function get_media_ids($attributes) { - // Ensure 'galleryItems' exists in the attributes array - if (isset($attributes['galleryItems']) && $attributes['source'] == "manual") { + // Manual Source + if ($attributes['source'] == "manual" && isset($attributes['galleryItems'])) { // Extract 'id' from each item in the 'galleryItems' array $media_ids = array_map(function($item) { return $item['id']; // Return the 'id' value from each array item }, $attributes['galleryItems']); // Use $attributes['galleryItems'] here + // Check if we need to include the post thumbnail if ($attributes['includePostThumbnail']) { // Get the featured image (post thumbnail) ID @@ -104,14 +141,30 @@ function get_media_ids($attributes) { array_unshift($media_ids, $featured_media_id); } } - // Return the array of media IDs + + // Post Meta Source 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 []; } + //Get the gallery items from the media IDs function get_gallery_items_data($media_ids) { $gallery_items = array(); @@ -390,42 +443,42 @@ function render_lcp_gallery_block($attributes) { -// Generate styles for the gallery based on the unique class -$classes = 'lcp-gallery '; // Start with lcp-gallery class -$classes .= $unique_class; + // Generate styles for the gallery based on the unique class + $classes = 'lcp-gallery '; // Start with lcp-gallery class + $classes .= $unique_class; -// Check if 'initialLayout' is set to 'grid' and add grid column classes if applicable -if (isset($attributes['initialLayout']) && $attributes['initialLayout'] === 'grid') { - // Image aspect ratios - $classes .= ' aspect-' . esc_attr($attributes['itemsAspectRatio']); - // Grid classes - $classes .= ' grid'; - // Grid columns - if (isset($attributes['gridColumnsLarge'])) { - $classes .= ' large-' . esc_attr($attributes['gridColumnsLarge']) . '-columns'; + // Check if 'initialLayout' is set to 'grid' and add grid column classes if applicable + if (isset($attributes['initialLayout']) && $attributes['initialLayout'] === 'grid') { + // Image aspect ratios + $classes .= ' aspect-' . esc_attr($attributes['itemsAspectRatio']); + // Grid classes + $classes .= ' grid'; + // Grid columns + if (isset($attributes['gridColumnsLarge'])) { + $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) -$styles = build_gallery_styles($attributes, $unique_class); + // Build the styles using the unique class (if necessary) + $styles = build_gallery_styles($attributes, $unique_class); -// Return the complete gallery HTML with the unique class and the settings as a JSON string -return " -
- {$gallery_items_html} -
"; + // Return the complete gallery HTML with the unique class and the settings as a JSON string + return " +
+ {$gallery_items_html} +
"; } /* Initialize Gallery Block */ function lcp_gallery_block_init() { diff --git a/includes/blocks/lcp-gallery/package.json b/includes/blocks/lcp-gallery/package.json index 64b4470..d84d3e4 100644 --- a/includes/blocks/lcp-gallery/package.json +++ b/includes/blocks/lcp-gallery/package.json @@ -1,8 +1,8 @@ { "name": "gallery", "version": "0.1.0", - "description": "Example block scaffolded with Create Block tool.", - "author": "The WordPress Contributors", + "description": "A dynamic gallery block", + "author": "Rangel Digital", "license": "GPL-2.0-or-later", "main": "build/index.js", "scripts": { diff --git a/includes/blocks/lcp-gallery/src/edit.js b/includes/blocks/lcp-gallery/src/edit.js index e5fb534..3de96af 100644 --- a/includes/blocks/lcp-gallery/src/edit.js +++ b/includes/blocks/lcp-gallery/src/edit.js @@ -1,6 +1,13 @@ import { __ } from '@wordpress/i18n'; -import { useBlockProps, InspectorControls, MediaUpload, MediaUploadCheck } from '@wordpress/block-editor'; -import { useState, useEffect } from 'react'; +import { + InspectorControls, + MediaUpload, + MediaUploadCheck +} from '@wordpress/block-editor'; +import { useState, + useEffect, + FC +} from 'react'; import { useSelect } from '@wordpress/data'; import { PanelBody, @@ -18,12 +25,48 @@ import { import metadata from './block.json'; import './editor.scss'; -import LightGallery from 'lightgallery/react'; -import 'lightgallery/css/lightgallery.css'; -import 'lightgallery/css/lg-zoom.css'; -import 'lightgallery/css/lg-thumbnail.css'; -import lgThumbnail from 'lightgallery/plugins/thumbnail'; -import lgZoom from 'lightgallery/plugins/zoom'; +//Import the LcpGallery component +import LcpGallery from '../components/LightGallery'; + + +const galleryElements = [ + { + 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: ( +
+

+ Photo by Dan +

+

Published on November 13, 2018

+
+ ), + }, + { + 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: ( +
+

+ Photo by Kyle Peyton +

+

Published on September 14, 2016

+
+ ), + }, +] + + + + // Aspect ratio options const aspectRatioOptions = [ @@ -41,9 +84,9 @@ const { apiFetch } = wp; apiFetch({ path: '/custom/v1/get-gallery-supported-plugins-data' }) .then((data) => { - console.log(data); // Log the entire data object - if (data.jetengine_active) { - console.log('Jet Engine is activated'); + console.log(data); // Log the entire data object + if (data.jetengine_active) { + console.log('Jet Engine is activated'); // Other logic here } }) @@ -125,12 +168,7 @@ export default function Edit(props) { // Handle Updating LightGallery settings 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 || { 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 const { isTemplate, postType, postId } = useSelect((select) => { @@ -263,25 +269,57 @@ const { isTemplate, postType, postId } = useSelect((select) => { if (isTemplate) { sourceOptions = [ { value: 'manual', label: __('Manually Select', metadata.textdomain) }, - { value: 'lcp_post_gallery', label: __('Post Gallery', metadata.textdomain) }, - { value: 'meta_field', label: __('Meta field of current post', metadata.textdomain) }, - { value: 'linked_table', label: __('Linked Table', metadata.textdomain) } ]; + { value: 'lcpPostGallery', label: __('Post Gallery', metadata.textdomain) }, + { value: 'metaField', label: __('Meta field of current post', metadata.textdomain) }, + { value: 'linkedTable', label: __('Linked Table', metadata.textdomain) } ]; // Add logic to adjust block's behavior when editing a template } else { sourceOptions = [ { 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 } - - // 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 ( <> - + + {/* The Gallery */} + + {/* Settings and Style Tabs */} { options={sourceOptions} /> {source === 'manual' && } - {source === 'meta_field' && ( + {source === 'metaField' && ( setAttributes({ sourceMetaField: newValue })} /> )} - {source === 'linked_table' && ( + {source === 'linkedTable' && ( <> { label={__('Enable Zoom', 'lcp')} checked={lgSettings.zoom} onChange={(value) => { + // Update autoplay setAttributes({ lgSettings: { ...lgSettings, zoom: value, // Update the zoom setting plugins: value - ? [...lgSettings.plugins, 'lgZoom'] // Add lgZoom plugin if enabled - : lgSettings.plugins.filter(plugin => plugin !== 'lgZoom'), // Remove lgZoom plugin if disabled + ? [...lgSettings.plugins, 'lgZoom'] // Add lgFullScreen plugin if enabled + : lgSettings.plugins.filter(plugin => plugin !== 'lgZoom'), // Remove lgFullScreen plugin if disabled }, }); }} @@ -814,8 +853,6 @@ const { isTemplate, postType, postId } = useSelect((select) => { - - ); } diff --git a/includes/blocks/lcp-header-container/header-container.php b/includes/blocks/lcp-header-container/lcp-header-container.php similarity index 78% rename from includes/blocks/lcp-header-container/header-container.php rename to includes/blocks/lcp-header-container/lcp-header-container.php index 90c2cf7..e7a2356 100644 --- a/includes/blocks/lcp-header-container/header-container.php +++ b/includes/blocks/lcp-header-container/lcp-header-container.php @@ -24,10 +24,10 @@ if ( ! defined( 'ABSPATH' ) ) { * * @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( - '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' ); diff --git a/includes/blocks/lcp-main-area/main-area.php b/includes/blocks/lcp-main-area/lcp-main-area.php similarity index 91% rename from includes/blocks/lcp-main-area/main-area.php rename to includes/blocks/lcp-main-area/lcp-main-area.php index 564e070..c0ccf71 100644 --- a/includes/blocks/lcp-main-area/main-area.php +++ b/includes/blocks/lcp-main-area/lcp-main-area.php @@ -24,7 +24,7 @@ if ( ! defined( 'ABSPATH' ) ) { * * @see https://developer.wordpress.org/reference/functions/register_block_type/ */ -function main_content_init() { +function lcp_main_content_init() { register_block_type( __DIR__ . '/build' ); } -add_action( 'init', 'main_content_init' ); +add_action( 'init', 'lcp_main_content_init' ); diff --git a/includes/blocks/lcp-main-area/src/edit.js b/includes/blocks/lcp-main-area/src/edit.js index 918d1b7..9598ad4 100644 --- a/includes/blocks/lcp-main-area/src/edit.js +++ b/includes/blocks/lcp-main-area/src/edit.js @@ -37,7 +37,7 @@ export default function Edit(props) { {/* Main block content */} -
+
diff --git a/includes/blocks/lcp-main-area/src/editor.scss b/includes/blocks/lcp-main-area/src/editor.scss index 6e6850f..e00cb23 100644 --- a/includes/blocks/lcp-main-area/src/editor.scss +++ b/includes/blocks/lcp-main-area/src/editor.scss @@ -7,3 +7,7 @@ .wp-block-create-block-lcp-viewport { border: 1px dotted #f00; } + +#lcp-main-wrap { + margin-left:340px +} \ No newline at end of file diff --git a/includes/blocks/lcp-main-area/src/save.js b/includes/blocks/lcp-main-area/src/save.js index 9db314c..5f1e2ee 100644 --- a/includes/blocks/lcp-main-area/src/save.js +++ b/includes/blocks/lcp-main-area/src/save.js @@ -23,7 +23,7 @@ export default function Save( {attributes} ) { maxWidth: maxWidth, }; return ( -
+
diff --git a/includes/blocks/lcp-sidecontent/src/block.json b/includes/blocks/lcp-sidecontent/src/block.json index dbee1c0..443c4b3 100644 --- a/includes/blocks/lcp-sidecontent/src/block.json +++ b/includes/blocks/lcp-sidecontent/src/block.json @@ -9,7 +9,10 @@ "description": "A separate content area to be nested inside the LCP viewport", "example": {}, "supports": { - "html": false + "color": { + "background": true, + "text": false + } }, "textdomain": "lcp", "editorScript": "file:./index.js", diff --git a/includes/blocks/lcp-sidecontent/src/edit.js b/includes/blocks/lcp-sidecontent/src/edit.js index a371e92..bf21cc9 100644 --- a/includes/blocks/lcp-sidecontent/src/edit.js +++ b/includes/blocks/lcp-sidecontent/src/edit.js @@ -11,7 +11,7 @@ import { __ } from '@wordpress/i18n'; * * @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. @@ -30,15 +30,23 @@ import './editor.scss'; * @return {Element} Element to render. */ export default function Edit() { - return (
-

- { __( 'Lcp Sidecontent – hello from the editor!', 'lcp' ) } -

- + // Custom appender logic (you can customize this as needed) + const renderAppender = () => { + return ; + }; + + return ( +
+
+
+
); } diff --git a/includes/blocks/lcp-sidecontent/src/editor.scss b/includes/blocks/lcp-sidecontent/src/editor.scss index 40805c6..b5963a9 100644 --- a/includes/blocks/lcp-sidecontent/src/editor.scss +++ b/includes/blocks/lcp-sidecontent/src/editor.scss @@ -7,3 +7,16 @@ .wp-block-create-block-lcp-sidecontent { 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 */ +} \ No newline at end of file diff --git a/includes/blocks/lcp-sidecontent/src/save.js b/includes/blocks/lcp-sidecontent/src/save.js index 9458626..d377f59 100644 --- a/includes/blocks/lcp-sidecontent/src/save.js +++ b/includes/blocks/lcp-sidecontent/src/save.js @@ -21,8 +21,17 @@ export default function Save() { return (
+
+ - -
+
+
+
+ +
+
+ +
+ ); } diff --git a/includes/blocks/lcp-sidecontent/src/view.js b/includes/blocks/lcp-sidecontent/src/view.js index 87fd95d..6792717 100644 --- a/includes/blocks/lcp-sidecontent/src/view.js +++ b/includes/blocks/lcp-sidecontent/src/view.js @@ -21,5 +21,5 @@ */ /* eslint-disable no-console */ -console.log( 'Hello World! (from create-block-lcp-sidecontent block)' ); + /* eslint-enable no-console */ diff --git a/includes/blocks/lcp-viewport/src/edit.js b/includes/blocks/lcp-viewport/src/edit.js index 25c61dd..6a78fa3 100644 --- a/includes/blocks/lcp-viewport/src/edit.js +++ b/includes/blocks/lcp-viewport/src/edit.js @@ -6,8 +6,10 @@ import './editor.scss'; export default function Edit({ attributes, setAttributes }) { const { hasSidecontent } = attributes; - // Block props - const blockProps = useBlockProps(); + // Block props with custom className management + const blockProps = useBlockProps({ + className: hasSidecontent ? 'has-sidecontent' : '', // Custom class + }); // Custom template logic based on hasSidecontent const template = [ @@ -31,15 +33,15 @@ export default function Edit({ attributes, setAttributes }) { /> -

- {__('Lcp Viewport – hello from the editor!', 'lcp-viewport')} -

- - {/* Render the InnerBlocks with conditional template */} - +
+
+ {/* Render the InnerBlocks with conditional template */} + +
+
); } diff --git a/includes/blocks/lcp-viewport/src/save.js b/includes/blocks/lcp-viewport/src/save.js index 60fd583..1c54df8 100644 --- a/includes/blocks/lcp-viewport/src/save.js +++ b/includes/blocks/lcp-viewport/src/save.js @@ -13,13 +13,13 @@ export default function Save({ attributes }) { const { hasSidecontent } = attributes; // Retrieve the hasSidecontent attribute const blockProps = useBlockProps.save(); - // Conditionally add the .lcp-has-sidecontent class if hasSidecontent is true - const hasSidecontentClass = hasSidecontent ? 'class="lcp-has-sidecontent"' : null; + // Conditionally add the 'has-sidecontent' class if hasSidecontent is true + const className = hasSidecontent ? 'has-sidecontent' : ''; return ( -
-
- +
+
+
); diff --git a/includes/blocks/lcp-viewport/src/style.scss b/includes/blocks/lcp-viewport/src/style.scss index 9bee04d..c37218a 100644 --- a/includes/blocks/lcp-viewport/src/style.scss +++ b/includes/blocks/lcp-viewport/src/style.scss @@ -5,3 +5,9 @@ * 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 */ + +} \ No newline at end of file diff --git a/includes/classes/blocks.php b/includes/classes/blocks.php index 195ee63..eece656 100644 --- a/includes/classes/blocks.php +++ b/includes/classes/blocks.php @@ -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-viewport/lcp-viewport.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-header-container/header-container.php'; - include $this->template_directory. '/includes/blocks/lcp-container/lcp-dynamic-container.php'; - include $this->template_directory. '/includes/blocks/lcp-key-points/key-points.php'; + include $this->template_directory. '/includes/blocks/lcp-main-area/lcp-main-area.php'; + include $this->template_directory. '/includes/blocks/lcp-header-container/lcp-header-container.php'; + include $this->template_directory. '/includes/blocks/lcp-dynamic-container/lcp-dynamic-container.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'; } diff --git a/script.js b/script.js index efbd905..61fc935 100644 --- a/script.js +++ b/script.js @@ -1,197 +1,109 @@ -document.addEventListener('DOMContentLoaded', function() { - - - -// 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 +document.addEventListener('DOMContentLoaded', function () { + // Get references to the DOM elements const header = document.getElementById('lcp-header-container'); 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 - window.addEventListener('scroll', debouncedScroll); - - // Add the resize event listener - 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; + // Ensure elements exist before proceeding + if (!header || !sideContent) return; + + // Measure the height of the header once the DOM is loaded const headerHeight = header.offsetHeight; - // Add 'lcp-fixed' class to side content if scrolled beyond the header height + admin bar height - if (scrolled > (headerHeight + adminBarHeight)) { - sideContent.classList.add('lcp-fixed'); - } else { - sideContent.classList.remove('lcp-fixed'); - } + // Set the height of #lcp-sidecontent to 100vh minus the header height + sideContent.style.height = `calc(100vh - ${headerHeight}px)`; - // Check if the header has the 'lcp-sticky-on-scroll' class and toggle the lcp-sticky class - if (header.classList.contains('lcp-sticky-on-scroll')) { - if (scrolled > (headerHeight + adminBarHeight)) { - header.classList.add('lcp-stuck'); // Slide the header down + // Function to handle the scroll event + function handleScroll() { + const scrolled = window.scrollY || document.documentElement.scrollTop; + + // 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 { - 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 -function handleInitialPageLoad(header, sideContent, adminBarHeight) { - const scrolled = window.scrollY || document.documentElement.scrollTop; - const headerHeight = header.offsetHeight; - - // Ensure the side content is properly positioned below the header + admin bar on page load - 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 the mouse down event to begin dragging the scrollbar +scrollBar.addEventListener("mousedown", (e) => { + isDragging = true; + startY = e.clientY; + startScrollTop = innerContent.scrollTop; + document.body.style.userSelect = "none"; // Disable text selection while dragging +}); +// 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() { - // Get the selected text - 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="e=${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'; - } - } - }); - - \ No newline at end of file +// Initialize the custom scrollbar position when the page loads +updateCustomScrollbar(); diff --git a/style.css b/style.css index 67d2537..bae05c0 100644 --- a/style.css +++ b/style.css @@ -25,20 +25,24 @@ Version: 1.0 /* Side content - absolute or fixed position */ #lcp-sidecontent { - position: absolute; /* or fixed depending on your JS logic */ + position: absolute; /* Positioned relative to the parent with position: relative */ 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 */ + 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 */ -.lcp-viewport.has-sidecontent #lcp-main-content { +.has-sidecontent #lcp-main-wrap { flex: 1; /* Main content takes up the rest of the space */ margin-left: 340px; /* Space for side content */ padding: 20px; @@ -100,3 +104,46 @@ Version: 1.0 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; +} \ No newline at end of file