Changes to blocks and added basic framework for Newsletters

This commit is contained in:
Jeremy Rangel
2025-01-02 01:29:51 -08:00
parent d928a0e8fd
commit 7bba517b48
20 changed files with 417 additions and 149 deletions

View File

@ -30,7 +30,7 @@ document.addEventListener('DOMContentLoaded', function () {
// Function to handle the scroll event
function handleScroll() {
document.documentElement.style.setProperty('--lcp--full-header--height', fullHeaderHeight + "px");
if (!headerIsSticky){
const scrolled = window.scrollY || document.documentElement.scrollTop;
// Check if the page has scrolled past the height of the header
@ -48,11 +48,11 @@ document.addEventListener('DOMContentLoaded', function () {
// sideContent.style.top = `${fullHeaderHeight}px`;
} else if (headerIsSticky) {
// If the header is sticky but not 'sticky-on-scroll', keep the side content height adjusted
sideContent.style.height = `calc(100vh - ${fullHeaderHeight}px)`;
// sideContent.style.height = `calc(100vh - ${fullHeaderHeight}px)`;
} else {
// Set side content height to 100vh when not sticky
sideContent.style.height = 'calc(100vh - 32px)';
// sideContent.style.height = 'calc(100vh - 32px)';
// sideContent.style.top = '32px';
}
@ -62,7 +62,7 @@ document.addEventListener('DOMContentLoaded', function () {
// sideContent.style.top = ''; // Reset the 'top' style
// Reset height to 100vh when not fixed
sideContent.style.height = `calc(100vh - ${fullHeaderHeight}px)` ;
// sideContent.style.height = `calc(100vh - ${fullHeaderHeight}px)` ;
// If header has the 'lcp-sticky-on-scroll' class, remove 'lcp-fixed' from the header
if (headerIsStickyOnScroll) {
@ -70,7 +70,7 @@ document.addEventListener('DOMContentLoaded', function () {
}
}
}
}
// Also trigger the scroll handler once on load in case the page is already scrolled

View File

@ -4,7 +4,8 @@
"setName": "Font Awesome - Regular",
"setFamily": "Font Awesome",
"version": "6.7.1",
"fileName": "/font-awesome/v6.7.1/font-awesome-v6.7.1-regular-svgs.json"
"fileName": "/font-awesome/v6.7.1/font-awesome-v6.7.1-regular-svgs.json",
"default": true
},
{

View File

@ -3,7 +3,8 @@
include get_template_directory() . '/includes/classes/wp-hooks.php';
include get_template_directory() . '/includes/classes/lcp-newsletters.php';
//include get_template_directory(). '/includes/blocks/lcp-gallery/lcp-gallery.php';
include get_template_directory() . '/includes/classes/blocks.php';
@ -18,11 +19,24 @@ function lcp_block_theme_setup() {
add_theme_support( 'block-templates' );
}
add_action( 'after_setup_theme', 'lcp_block_theme_setup' );
/* Add Styles */
function lcp_header_height_style() {
// Fetch the lcp_header_height value from wp_options.
$header_height = get_option('lcp_header_height', 0); // Default to 0 if not found
// Ensure we have a valid value
if ($header_height) {
// Output the inline style tag with the CSS variable for header height
echo "<style>:root { --lcp--header--height: {$header_height}px; }</style>";
}
}
add_action('wp_enqueue_scripts', 'lcp_header_height_style',1);
function lcp_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');
wp_enqueue_script('lcp-script', get_template_directory_uri() . '/assets/js/lcp.js');
wp_enqueue_script('lcp-ui-script', get_template_directory_uri() . '/assets/js/lcp-ui.js');
}
@ -161,10 +175,6 @@ function drop_lcp_icons_table() {
}
// Hook the function to the theme deactivation process
// Register the function to run when the theme is switched (deactivated)
add_action('switch_theme', 'drop_lcp_icons_table');
@ -241,13 +251,64 @@ add_action('admin_enqueue_scripts', 'mytheme_enqueue_dashboard_styles');
// Handle the AJAX request for installing icon sets
function mytheme_install_icon_set() {
function lcp_install_icon_set($defaults = false) {
$json_path = get_template_directory() . '/assets/json/icons/icon-definitions.json';
if ($defaults) {
// Import only the default icons
if (file_exists($json_path)) {
$json_data = file_get_contents($json_path);
$icon_sets = json_decode($json_data, true);
// Loop through all icon sets and filter for default icons
foreach ($icon_sets as $icon_set) {
if (isset($icon_set['default']) && $icon_set['default'] === true) {
$file_name = $icon_set['fileName']; // Assuming the JSON structure has 'fileName' key
$icon_file_path = get_template_directory() . '/assets/json/icons/' . $file_name;
if (file_exists($icon_file_path)) {
$icon_data = file_get_contents($icon_file_path);
$icon_json = json_decode($icon_data, true);
// Check if svgs exist and process them
if (isset($icon_json[0]['svgs']) && is_array($icon_json[0]['svgs'])) {
foreach ($icon_json[0]['svgs'] as $svg) {
global $wpdb;
$table_name = $wpdb->prefix . 'lcp_icons';
// Insert the SVG data into the database
$wpdb->insert(
$table_name,
array(
'icon_name' => $svg['name'],
'icon_set_id' => $icon_set['id'],
'icon_family' => $icon_set['setFamily'],
'icon_version' => $icon_set['version'],
'paths' => ($svg['paths']),
'viewbox' => sanitize_text_field($svg['viewBox']),
'icon_id' => sanitize_text_field($svg['id']),
)
);
}
} else {
wp_send_json_error(array('message' => 'SVGs data not found in the JSON file.'));
}
} else {
wp_send_json_error(array('message' => 'SVG file for default set not found.'));
}
}
}
} else {
wp_send_json_error(array('message' => 'Icon definitions file not found.'));
}
} elseif (isset($_POST['icon_set_id'])) {
// Default behavior - check for icon_set_id in $_POST
if (!isset($_POST['icon_set_id'])) {
wp_send_json_error(array('message' => 'Invalid icon set ID.'));
}
$icon_set_id = intval($_POST['icon_set_id']);
$json_path = get_template_directory() . '/assets/json/icons/icon-definitions.json';
// Create the database table if it doesn't exist
mytheme_create_icons_table();
@ -268,7 +329,6 @@ function mytheme_install_icon_set() {
// If the icon set is found
if ($selected_icon_set) {
// Dynamically build the icon file path using the fileName from icon-definitions.json
$file_name = $selected_icon_set['fileName']; // Assuming the JSON structure has 'fileName' key
$icon_file_path = get_template_directory() . '/assets/json/icons/' . $file_name;
@ -277,14 +337,13 @@ function mytheme_install_icon_set() {
$icon_data = file_get_contents($icon_file_path);
$icon_json = json_decode($icon_data, true);
// Debugging: Check the structure of the decoded JSON
// Check the structure of the decoded JSON
if (is_array($icon_json)) {
error_log(print_r($icon_json, true)); // Logs to PHP error log for inspection
}
// Loop through svgs if it exists and is an array
if (isset($icon_json[0]['svgs']) && is_array($icon_json[0]['svgs'])) {
// Insert rows with actual data from the SVG file
foreach ($icon_json[0]['svgs'] as $svg) {
global $wpdb;
$table_name = $wpdb->prefix . 'lcp_icons';
@ -293,13 +352,13 @@ function mytheme_install_icon_set() {
$wpdb->insert(
$table_name,
array(
'icon_name' => $svg['name'], // Using the name from the SVG JSON
'icon_name' => $svg['name'],
'icon_set_id' => $selected_icon_set['id'],
'icon_family' => $selected_icon_set['setFamily'], // Get family dynamically from the selected icon set
'icon_version' => $selected_icon_set['version'], // Get version dynamically from the selected icon set
'paths' => ($svg['paths']), // SVG paths from the JSON
'viewbox' => sanitize_text_field($svg['viewBox']), // Viewbox for the SVG
'icon_id' => sanitize_text_field($svg['id']) // Using the actual icon ID from the JSON
'icon_family' => $selected_icon_set['setFamily'],
'icon_version' => $selected_icon_set['version'],
'paths' => ($svg['paths']),
'viewbox' => sanitize_text_field($svg['viewBox']),
'icon_id' => sanitize_text_field($svg['id']),
)
);
}
@ -317,12 +376,13 @@ function mytheme_install_icon_set() {
} else {
wp_send_json_error(array('message' => 'Icon definitions not found.'));
}
}
}
add_action('wp_ajax_install_icon_set', 'mytheme_install_icon_set');
add_action('wp_ajax_install_icon_set', 'lcp_install_icon_set');
// Function to create the icons table in the database if it doesn't exist
// Function to create the icons table in the database if it doesn't exist
function mytheme_create_icons_table() {
global $wpdb;
@ -403,15 +463,3 @@ function mytheme_uninstall_icon_set() {
add_action('wp_ajax_uninstall_icon_set', 'mytheme_uninstall_icon_set');
/* Add Styles */
function lcp_header_height_style() {
// Fetch the lcp_header_height value from wp_options.
$header_height = get_option('lcp_header_height', 0); // Default to 0 if not found
// Ensure we have a valid value
if ($header_height) {
// Output the inline style tag with the CSS variable for header height
echo "<style>:root { --lcp--header--height: {$header_height}px; }</style>";
}
}
add_action('wp_head', 'lcp_header_height_style');

View File

@ -1 +1 @@
<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-i18n'), 'version' => 'c0cad1dbf39c1f85add9');
<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-i18n'), 'version' => '9fbf94ac3507c2365b0a');

View File

@ -1 +1 @@
(()=>{"use strict";var e,n={650:()=>{const e=window.wp.blocks,n=(window.wp.i18n,window.wp.blockEditor),r=window.ReactJSXRuntime,o=JSON.parse('{"UU":"lcp/sidecontent"}');(0,e.registerBlockType)(o.UU,{edit:function(){return(0,n.useBlockProps)(),(0,r.jsx)("div",{...n.useBlockProps,children:(0,r.jsx)("div",{id:"lcp-sidecontent",children:(0,r.jsx)(n.InnerBlocks,{renderAppender:()=>(0,r.jsx)(n.InnerBlocks.ButtonBlockAppender,{})})})})},save:function(){const e=n.useBlockProps.save();return(0,r.jsxs)("div",{...e,id:"lcp-sidecontent",children:[(0,r.jsx)("div",{id:"lcp-sidecontent-inner",children:(0,r.jsx)(n.InnerBlocks.Content,{})}),(0,r.jsx)("div",{id:"lcp-scroll-track",children:(0,r.jsx)("div",{id:"lcp-scroll-bar"})})]})}})}},r={};function o(e){var i=r[e];if(void 0!==i)return i.exports;var s=r[e]={exports:{}};return n[e](s,s.exports,o),s.exports}o.m=n,e=[],o.O=(n,r,i,s)=>{if(!r){var t=1/0;for(p=0;p<e.length;p++){r=e[p][0],i=e[p][1],s=e[p][2];for(var c=!0,l=0;l<r.length;l++)(!1&s||t>=s)&&Object.keys(o.O).every((e=>o.O[e](r[l])))?r.splice(l--,1):(c=!1,s<t&&(t=s));if(c){e.splice(p--,1);var d=i();void 0!==d&&(n=d)}}return n}s=s||0;for(var p=e.length;p>0&&e[p-1][2]>s;p--)e[p]=e[p-1];e[p]=[r,i,s]},o.o=(e,n)=>Object.prototype.hasOwnProperty.call(e,n),(()=>{var e={57:0,350:0};o.O.j=n=>0===e[n];var n=(n,r)=>{var i,s,t=r[0],c=r[1],l=r[2],d=0;if(t.some((n=>0!==e[n]))){for(i in c)o.o(c,i)&&(o.m[i]=c[i]);if(l)var p=l(o)}for(n&&n(r);d<t.length;d++)s=t[d],o.o(e,s)&&e[s]&&e[s][0](),e[s]=0;return o.O(p)},r=self.webpackChunklcp_sidecontent=self.webpackChunklcp_sidecontent||[];r.forEach(n.bind(null,0)),r.push=n.bind(null,r.push.bind(r))})();var i=o.O(void 0,[350],(()=>o(650)));i=o.O(i)})();
(()=>{"use strict";var e,n={650:()=>{const e=window.wp.blocks,n=(window.wp.i18n,window.wp.blockEditor),r=window.ReactJSXRuntime,o=JSON.parse('{"UU":"lcp/sidecontent"}');(0,e.registerBlockType)(o.UU,{edit:function(){return(0,n.useBlockProps)(),(0,r.jsx)("div",{...n.useBlockProps,children:(0,r.jsx)("div",{id:"lcp-sidecontent",children:(0,r.jsx)(n.InnerBlocks,{renderAppender:()=>(0,r.jsx)(n.InnerBlocks.ButtonBlockAppender,{})})})})},save:function(){const e=n.useBlockProps.save();return(0,r.jsx)("div",{...e,id:"lcp-sidecontent",children:(0,r.jsx)(n.InnerBlocks.Content,{})})}})}},r={};function o(e){var t=r[e];if(void 0!==t)return t.exports;var s=r[e]={exports:{}};return n[e](s,s.exports,o),s.exports}o.m=n,e=[],o.O=(n,r,t,s)=>{if(!r){var i=1/0;for(d=0;d<e.length;d++){r=e[d][0],t=e[d][1],s=e[d][2];for(var c=!0,l=0;l<r.length;l++)(!1&s||i>=s)&&Object.keys(o.O).every((e=>o.O[e](r[l])))?r.splice(l--,1):(c=!1,s<i&&(i=s));if(c){e.splice(d--,1);var p=t();void 0!==p&&(n=p)}}return n}s=s||0;for(var d=e.length;d>0&&e[d-1][2]>s;d--)e[d]=e[d-1];e[d]=[r,t,s]},o.o=(e,n)=>Object.prototype.hasOwnProperty.call(e,n),(()=>{var e={57:0,350:0};o.O.j=n=>0===e[n];var n=(n,r)=>{var t,s,i=r[0],c=r[1],l=r[2],p=0;if(i.some((n=>0!==e[n]))){for(t in c)o.o(c,t)&&(o.m[t]=c[t]);if(l)var d=l(o)}for(n&&n(r);p<i.length;p++)s=i[p],o.o(e,s)&&e[s]&&e[s][0](),e[s]=0;return o.O(d)},r=self.webpackChunklcp_sidecontent=self.webpackChunklcp_sidecontent||[];r.forEach(n.bind(null,0)),r.push=n.bind(null,r.push.bind(r))})();var t=o.O(void 0,[350],(()=>o(650)));t=o.O(t)})();

View File

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

View File

@ -23,6 +23,10 @@
"hasStickyHeader": {
"type": "boolean",
"default": false
},
"headerContainerStickyType": {
"type": "string",
"default": ""
}
},
"textdomain": "lcp-viewport",

View File

@ -1 +1 @@
<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-element', 'wp-i18n'), 'version' => 'a54c989d69efb5b39b31');
<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => 'b8ff5a7ac1d726017948');

View File

@ -1 +1 @@
(()=>{"use strict";var e,t={199:()=>{const e=window.wp.blocks,t=window.wp.i18n,o=window.wp.blockEditor,c=window.wp.components,n=window.wp.element,r=window.wp.data,i=window.ReactJSXRuntime,s=JSON.parse('{"UU":"lcp/viewport"}');(0,e.registerBlockType)(s.UU,{edit:function({attributes:s,setAttributes:l,clientId:a}){const{hasSidecontent:d,hasStickyHeader:p}=s,[u,w]=(0,n.useState)(!1),[k,h]=(0,n.useState)(!1),[v,f]=(0,n.useState)(!1),[b,B]=(0,n.useState)(null),x=(0,o.useBlockProps)({className:d?"has-sidecontent":""}),j=[d?["lcp/sidecontent"]:null,["lcp/header-container"],["lcp/main-area"],["lcp/footer-container"]].filter(Boolean);(0,n.useEffect)((()=>{if(d){const t=(0,e.createBlock)("lcp/sidecontent",{});wp.data.dispatch("core/block-editor").insertBlocks(t,1,a)}}),[d,a]),(0,n.useEffect)((()=>{const e=(0,r.subscribe)((()=>{const e=wp.data.select("core/block-editor").getBlocks();if(k||v)return;const t=e.find((e=>e.clientId!==a&&!wp.data.select("core/block-editor").getBlockParents(e.clientId).includes(a)));t&&(B(t),w(!0),f(!0))}));return()=>{e()}}),[a,k,v]);const m=()=>{if(b){const e=wp.data.select("core/block-editor").getBlocks(a).find((e=>"lcp/main-area"===e.name));e&&(console.log(e),wp.data.dispatch("core/block-editor").insertBlocks(b,e.clientId,0))}w(!1)};return(0,n.useEffect)((()=>{v&&h(!1)}),[v]),(0,r.useSelect)((e=>e("core/block-editor").getBlocks(x.clientId)),[x.clientId]),(0,i.jsxs)("div",{...x,children:[(0,i.jsx)(o.InspectorControls,{children:(0,i.jsx)(c.ToggleControl,{label:(0,t.__)("Include Side Content","lcp-viewport"),checked:d,onChange:e=>l({hasSidecontent:e})})}),(0,i.jsx)("div",{id:"lcp-viewport-outer",children:(0,i.jsx)("div",{id:"lcp-viewport-inner",children:(0,i.jsx)(o.InnerBlocks,{renderAppender:()=>(0,i.jsx)(o.InnerBlocks.ButtonBlockAppender,{}),template:j})})}),u&&!k&&(0,i.jsxs)(c.Modal,{title:(0,t.__)("Block Outside Viewport","lcp-viewport"),onRequestClose:m,className:"block-outside-popup",children:[(0,i.jsx)("p",{children:(0,t.__)("You added a block outside of the lcp/viewport container. Please make sure the block is inside the appropriate area.","lcp-viewport")}),(0,i.jsx)(c.Button,{isPrimary:!0,onClick:m,children:(0,t.__)("Close","lcp-viewport")}),(0,i.jsx)(c.Button,{isSecondary:!0,onClick:()=>{h(!0),w(!1)},children:(0,t.__)("Ignore","lcp-viewport")})]})]})},save:function({attributes:e}){const{hasSidecontent:t,hasStickyHeader:c}=e;o.useBlockProps.save();let n="";return t&&(n+="lcp-has-sidecontent "),c&&(n+="lcp-has-sticky-header"),(0,i.jsx)("div",{className:n,id:"lcp-viewport-outer",children:(0,i.jsx)("div",{id:"lcp-viewport-inner",className:n,children:(0,i.jsx)(o.InnerBlocks.Content,{})})})}})}},o={};function c(e){var n=o[e];if(void 0!==n)return n.exports;var r=o[e]={exports:{}};return t[e](r,r.exports,c),r.exports}c.m=t,e=[],c.O=(t,o,n,r)=>{if(!o){var i=1/0;for(d=0;d<e.length;d++){o=e[d][0],n=e[d][1],r=e[d][2];for(var s=!0,l=0;l<o.length;l++)(!1&r||i>=r)&&Object.keys(c.O).every((e=>c.O[e](o[l])))?o.splice(l--,1):(s=!1,r<i&&(i=r));if(s){e.splice(d--,1);var a=n();void 0!==a&&(t=a)}}return t}r=r||0;for(var d=e.length;d>0&&e[d-1][2]>r;d--)e[d]=e[d-1];e[d]=[o,n,r]},c.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e={57:0,350:0};c.O.j=t=>0===e[t];var t=(t,o)=>{var n,r,i=o[0],s=o[1],l=o[2],a=0;if(i.some((t=>0!==e[t]))){for(n in s)c.o(s,n)&&(c.m[n]=s[n]);if(l)var d=l(c)}for(t&&t(o);a<i.length;a++)r=i[a],c.o(e,r)&&e[r]&&e[r][0](),e[r]=0;return c.O(d)},o=self.webpackChunklcp_viewport=self.webpackChunklcp_viewport||[];o.forEach(t.bind(null,0)),o.push=t.bind(null,o.push.bind(o))})();var n=c.O(void 0,[350],(()=>c(199)));n=c.O(n)})();
(()=>{"use strict";var e,t={798:()=>{const e=window.wp.blocks,t=window.wp.i18n,o=window.wp.blockEditor,n=(window.wp.hooks,window.wp.components),c=window.wp.element,r=window.wp.data,i=window.ReactJSXRuntime,s=JSON.parse('{"UU":"lcp/viewport"}');(0,e.registerBlockType)(s.UU,{edit:function({attributes:s,setAttributes:l,clientId:a}){const{hasSidecontent:d,headerContainerStickyType:p}=s,[u,w]=(0,c.useState)(!1),[h,k]=(0,c.useState)(!1),[v,f]=(0,c.useState)(!1),[b,B]=(0,c.useState)(null),m=(0,o.useBlockProps)({className:d?"has-sidecontent":""}),x=[d?["lcp/sidecontent"]:null,["lcp/header-container"],["lcp/main-area"],["lcp/footer-container"]].filter(Boolean);(0,c.useEffect)((()=>{if(d){const t=(0,e.createBlock)("lcp/sidecontent",{});wp.data.dispatch("core/block-editor").insertBlocks(t,1,a)}}),[d,a]),(0,c.useEffect)((()=>{const e=(0,r.subscribe)((()=>{const e=wp.data.select("core/block-editor").getBlocks();if(h||v)return;const t=e.find((e=>e.clientId!==a&&!wp.data.select("core/block-editor").getBlockParents(e.clientId).includes(a)));t&&(B(t),w(!0),f(!0))}));return()=>{e()}}),[a,h,v]);const y=()=>{if(b){const e=wp.data.select("core/block-editor").getBlocks(a).find((e=>"lcp/main-area"===e.name));e&&(console.log(e),wp.data.dispatch("core/block-editor").insertBlocks(b,e.clientId,0))}w(!1)};(0,c.useEffect)((()=>{v&&k(!1)}),[v]);const j=(0,r.useSelect)((e=>e("core/block-editor").getBlocks(a)),[a]);return(0,c.useEffect)((()=>{const e=j.find((e=>"lcp/header-container"===e.name));j.find((e=>"lcp/header-sidecontent"===e.name)),e&&e.attributes&&void 0!==e.attributes.sticky&&l({headerContainerStickyType:e.attributes.sticky})}),[j,a,l]),(0,i.jsxs)("div",{...m,children:[(0,i.jsx)(o.InspectorControls,{children:(0,i.jsx)(n.ToggleControl,{label:(0,t.__)("Include Side Content","lcp-viewport"),checked:d,onChange:e=>l({hasSidecontent:e})})}),(0,i.jsx)("div",{id:"lcp-viewport-outer",children:(0,i.jsx)("div",{id:"lcp-viewport-inner",children:(0,i.jsx)(o.InnerBlocks,{renderAppender:()=>(0,i.jsx)(o.InnerBlocks.ButtonBlockAppender,{}),template:x})})}),u&&!h&&(0,i.jsxs)(n.Modal,{title:(0,t.__)("Block Outside Viewport","lcp-viewport"),onRequestClose:y,className:"block-outside-popup",children:[(0,i.jsx)("p",{children:(0,t.__)("You added a block outside of the lcp/viewport container. Please make sure the block is inside the appropriate area.","lcp-viewport")}),(0,i.jsx)(n.Button,{isPrimary:!0,onClick:y,children:(0,t.__)("Close","lcp-viewport")}),(0,i.jsx)(n.Button,{isSecondary:!0,onClick:()=>{k(!0),w(!1)},children:(0,t.__)("Ignore","lcp-viewport")})]})]})},save:function({attributes:e}){const{hasSidecontent:t,headerContainerStickyType:n}=e;o.useBlockProps.save();let c="";return t&&(c+="lcp-has-sidecontent "),"always"===n?c+="lcp-has-sticky-header ":"onScroll"===n&&(c+="lcp-has-sticky-on-scroll-header "),(0,i.jsx)("div",{className:c,id:"lcp-viewport-outer",children:(0,i.jsx)("div",{id:"lcp-viewport-inner",className:c,children:(0,i.jsx)(o.InnerBlocks.Content,{})})})}})}},o={};function n(e){var c=o[e];if(void 0!==c)return c.exports;var r=o[e]={exports:{}};return t[e](r,r.exports,n),r.exports}n.m=t,e=[],n.O=(t,o,c,r)=>{if(!o){var i=1/0;for(d=0;d<e.length;d++){o=e[d][0],c=e[d][1],r=e[d][2];for(var s=!0,l=0;l<o.length;l++)(!1&r||i>=r)&&Object.keys(n.O).every((e=>n.O[e](o[l])))?o.splice(l--,1):(s=!1,r<i&&(i=r));if(s){e.splice(d--,1);var a=c();void 0!==a&&(t=a)}}return t}r=r||0;for(var d=e.length;d>0&&e[d-1][2]>r;d--)e[d]=e[d-1];e[d]=[o,c,r]},n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e={57:0,350:0};n.O.j=t=>0===e[t];var t=(t,o)=>{var c,r,i=o[0],s=o[1],l=o[2],a=0;if(i.some((t=>0!==e[t]))){for(c in s)n.o(s,c)&&(n.m[c]=s[c]);if(l)var d=l(n)}for(t&&t(o);a<i.length;a++)r=i[a],n.o(e,r)&&e[r]&&e[r][0](),e[r]=0;return n.O(d)},o=self.webpackChunklcp_viewport=self.webpackChunklcp_viewport||[];o.forEach(t.bind(null,0)),o.push=t.bind(null,o.push.bind(o))})();var c=n.O(void 0,[350],(()=>n(798)));c=n.O(c)})();

View File

@ -28,3 +28,4 @@ function create_block_lcp_viewport_block_init() {
register_block_type( __DIR__ . '/build' );
}
add_action( 'init', 'create_block_lcp_viewport_block_init' );

View File

@ -23,6 +23,10 @@
"hasStickyHeader":{
"type":"boolean",
"default":false
},
"headerContainerStickyType":{
"type": "string",
"default": ""
}
},
"textdomain": "lcp-viewport",

View File

@ -1,5 +1,6 @@
import { __ } from '@wordpress/i18n';
import { useBlockProps, InnerBlocks, InspectorControls } from '@wordpress/block-editor';
import { useBlockProps, InnerBlocks, InspectorControls, BlockEditor } from '@wordpress/block-editor';
import {addFilter} from '@wordpress/hooks';
import { ToggleControl } from '@wordpress/components';
import { useEffect, useState } from '@wordpress/element';
import { createBlock } from '@wordpress/blocks'; // Used for creating new blocks
@ -8,7 +9,7 @@ import { Modal, Button } from '@wordpress/components'; // Import Modal for popup
import './editor.scss';
export default function Edit({ attributes, setAttributes, clientId }) {
const { hasSidecontent, hasStickyHeader } = attributes;
const { hasSidecontent, headerContainerStickyType } = attributes;
// Popup visibility state
const [isPopupVisible, setIsPopupVisible] = useState(false);
@ -113,8 +114,25 @@ export default function Edit({ attributes, setAttributes, clientId }) {
// Use useSelect to subscribe to the state of inner blocks
const innerBlocks = useSelect((select) => {
return select('core/block-editor').getBlocks(blockProps.clientId);
}, [blockProps.clientId]);
return select('core/block-editor').getBlocks(clientId);
}, [clientId]);
// useEffect to log "Header present" when the lcp/header-container block is found
useEffect(() => {
const headerBlock = innerBlocks.find((block) => block.name === 'lcp/header-container');
const sidecontentBlock = innerBlocks.find((block) => block.name === 'lcp/header-sidecontent');
// Check if the block is found and the 'sticky' attribute has changed
if (headerBlock && headerBlock.attributes && headerBlock.attributes.sticky !== undefined) {
// Update the state with the new sticky value
setAttributes({ headerContainerStickyType: headerBlock.attributes.sticky });
}
// Check if there is already a sidecontent block and remove it if so
if (sidecontentBlock) {
}
}, [innerBlocks, clientId, setAttributes]); // Trigger the effect whenever the blocks change
return (
<div {...blockProps}>

View File

@ -10,16 +10,22 @@ import { useBlockProps, InnerBlocks } from '@wordpress/block-editor';
* @return {Element} Element to render.
*/
export default function Save({ attributes }) {
const { hasSidecontent, hasStickyHeader } = attributes; // Retrieve the hasSidecontent and hasStickyHeader attributes
const { hasSidecontent, headerContainerStickyType } = attributes; // Retrieve the attributes
const blockProps = useBlockProps.save();
// Conditionally add the 'has-sidecontent' and 'lcp-has-sticky-header' classes
// Conditionally add classes based on attributes
let classNames = '';
// Add 'has-sidecontent' class if attribute is true
if (hasSidecontent) {
classNames += 'lcp-has-sidecontent ';
}
if (hasStickyHeader) {
classNames += 'lcp-has-sticky-header';
// Conditionally add sticky header classes based on the headerContainerStickyStyle value
if (headerContainerStickyType === 'always') {
classNames += 'lcp-has-sticky-header ';
} else if (headerContainerStickyType === 'onScroll') {
classNames += 'lcp-has-sticky-on-scroll-header ';
}
return (

View File

@ -234,7 +234,7 @@ add_action( 'wp_footer', function() {
// Register the settings page with tabs
function render_lcp_theme_settings_page() {
?>
<div class="wrap">
@ -244,26 +244,35 @@ function render_lcp_theme_settings_page() {
<div class="tab-container">
<!-- Tabs -->
<ul class="tabs">
<li class="tab-link active" data-tab="icons">Icons</li>
<li class="tab-link active" data-tab="custom-meta">Custom Meta</li>
<li class="tab-link" data-tab="icons">Icons</li>
<li class="tab-link" data-tab="custom-code">Custom Code</li>
</ul>
<!-- Tab Panes -->
<div id="icons" class="tab-pane active">
<!-- Icons Tab -->
<div id="icons" class="tab-pane">
<!-- Icons Tab Content -->
<h2>Custom SVG Icons</h2>
<form method="post" action="options.php">
<?php
// Output necessary settings fields for the 'Icons' tab
settings_fields('lcp_theme_settings_group');
do_settings_sections('lcp_theme_settings_page'); // This outputs all the fields defined by add_settings_field
// This outputs all the fields defined by add_settings_field
mytheme_display_icon_sets();
?>
<?php submit_button(); ?>
</form>
</div>
<!-- Custom Meta Tab Pane -->
<div id="custom-meta" class="tab-pane active">
<?php
settings_fields('lcp_theme_settings_group');
do_settings_sections('lcp_theme_settings_page');
?>
</div>
<div id="custom-code" class="tab-pane">
<!-- Custom Code Tab Content -->
<h2>Custom Code Settings</h2>
@ -299,8 +308,9 @@ function render_lcp_theme_settings_page() {
// Hooks
/* HIGHLIGHT-TO-SHARE */
// Render the highlight-to-share popup
function highlight_to_share_popup() {
echo "
<div class=\"popup\" id=\"popup\">
@ -311,6 +321,8 @@ function highlight_to_share_popup() {
";
}
/* HOOKS */
//Move to custom hooks class or file in future
function lcp_wp_head_hooks(){
// Define lcp_theme_settings array from wp_options
$options = get_option('lcp_theme_settings', array());

View File

@ -0,0 +1,152 @@
<?php
// Hook to run when the theme or plugin is activated
function lcp_create_newsletter_tables() {
global $wpdb;
// Table names with prefix 'lcp'
$table_name_contacts = $wpdb->prefix . 'lcp_newsletter_subscribers';
$table_name_campaign_lists = $wpdb->prefix . 'lcp_newsletter_lists';
$table_name_communications = $wpdb->prefix . 'lcp_communications';
$charset_collate = $wpdb->get_charset_collate();
// SQL to create the subscribers table
$sql_contacts = "
CREATE TABLE $table_name_contacts (
id BIGINT(20) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
email VARCHAR(255) NOT NULL,
user_id BIGINT(20) UNSIGNED UNIQUE,
first_name VARCHAR(255),
last_name VARCHAR(255),
subscription_date DATETIME DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY email_unique (email)
) $charset_collate;
";
// SQL to create the subscriptions table (if needed, for storing subscription data)
$sql_subscriptions = "
CREATE TABLE $table_name_campaign_lists (
id BIGINT(20) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
subscriber_id BIGINT(20) UNSIGNED NOT NULL,
newsletter_name VARCHAR(255) NOT NULL,
subscription_date DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (subscriber_id) REFERENCES $table_name_subscribers(id) ON DELETE CASCADE
) $charset_collate;
";
$sql_communications = "
CREATE TABLE $table_name (
id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
contact_id BIGINT(20) UNSIGNED NOT NULL,
status ENUM('scheduled', 'sent', 'failed') NOT NULL DEFAULT 'scheduled',
send_datetime DATETIME DEFAULT NULL,
attempts INT(10) UNSIGNED NOT NULL DEFAULT 0,
error_message TEXT DEFAULT NULL,
PRIMARY KEY (id),
KEY newsletter_id (newsletter_id)
) $charset_collate;
";
// Run the SQL queries to create the tables
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql_contacts);
dbDelta($sql_communications);
;
}
add_action('after_switch_theme', 'lcp_create_newsletter_tables'); // or use 'register_activation_hook()' for a plugin
// Register Custom Post Type for 'lcp_newsletters'
function lcp_register_newsletters_cpt() {
$args = array(
'label' => 'Newsletters',
'description' => 'Custom post type for newsletters',
'public' => true,
'show_ui' => true,
'show_in_menu' => true,
'show_in_rest' => true, // Enable for REST API
'supports' => array('title', 'editor', 'custom-fields'), // Supports custom fields
'has_archive' => true,
'rewrite' => array('slug' => 'newsletters'),
'show_in_graphql' => true,
'hierarchical' => false, // Set false as newsletters are usually single-level posts
);
register_post_type('lcp_newsletters', $args);
}
add_action('init', 'lcp_register_newsletters_cpt');
// Register Custom Taxonomy for 'newsletter_campaigns'
function lcp_register_newsletter_campaigns_taxonomy() {
$args = array(
'hierarchical' => true,
'label' => 'Newsletter Campaigns',
'show_ui' => true,
'show_in_rest' => true,
'show_admin_column' => true,
'rewrite' => array('slug' => 'newsletter-campaigns'),
);
register_taxonomy('newsletter_campaigns', array('lcp_newsletters'), $args);
}
add_action('init', 'lcp_register_newsletter_campaigns_taxonomy');
// Add the 'send_datetime' meta field for the 'lcp_newsletters' CPT
function lcp_add_send_datetime_meta_box() {
add_meta_box(
'send_datetime_meta_box', // Meta box ID
'Send Date and Time', // Title
'lcp_render_send_datetime_meta_box', // Callback function to render content
'lcp_newsletters', // Post type to attach the meta box to
'side', // Context (side bar)
'high' // Priority
);
}
add_action('add_meta_boxes', 'lcp_add_send_datetime_meta_box');
// Render the 'send_datetime' field
function lcp_render_send_datetime_meta_box($post) {
wp_nonce_field(basename(__FILE__), 'send_datetime_nonce'); // Add nonce for security
$send_datetime = get_post_meta($post->ID, '_send_datetime', true); // Get current value from post meta
echo '<input type="datetime-local" id="send_datetime" name="send_datetime" value="' . esc_attr($send_datetime) . '" />';
}
// Save the 'send_datetime' field
function lcp_save_send_datetime_meta_box($post_id) {
if (!isset($_POST['send_datetime_nonce']) || !wp_verify_nonce($_POST['send_datetime_nonce'], basename(__FILE__))) {
return $post_id; // Nonce check failed, do not save
}
$send_datetime = isset($_POST['send_datetime']) ? sanitize_text_field($_POST['send_datetime']) : '';
if (!empty($send_datetime)) {
update_post_meta($post_id, '_send_datetime', $send_datetime); // Save send_datetime as post meta
} else {
delete_post_meta($post_id, '_send_datetime'); // Delete meta if empty
}
}
add_action('save_post', 'lcp_save_send_datetime_meta_box');
function lcp_restrict_blocks_for_newsletters($allowed_blocks, $post) {
// Check if the post type is 'lcp_newsletters'
if ($post->post_type === 'lcp_newsletters') {
// Define the allowed blocks for 'lcp_newsletters'
$allowed_blocks = array(
'core/paragraph',
'core/heading',
'core/list',
'core/image',
'core/quote',
'core/button',
// Add any other blocks you want to allow
);
}
return $allowed_blocks;
}
add_filter('allowed_block_types', 'lcp_restrict_blocks_for_newsletters', 10, 2);

View File

@ -0,0 +1,15 @@
<?php
// Register the function to run when the theme is switched (deactivated)
add_action('switch_theme', 'drop_lcp_icons_table');
// Hook into theme activation to call the function
function lcp_activate() {
// Call the function to import the default icon sets
lcp_install_icon_set(true);
}
// Add the action hook to run the function when the theme is activated
add_action('after_switch_theme', 'lcp_activate');

View File

@ -0,0 +1,14 @@
<?php
/**
* Title: Viewport With Sidecontent
* Slug: localcontentpro/viewport-with-sidecontent
* Categories: banner
* Description: A viewport with side content
*
* @package WordPress
* @subpackage Local_Content_Pro
* @since Local Content Pro 1.0
*/
?>

View File

@ -34,30 +34,43 @@ Version: 1.0
min-height:calc(100vh - 32px)
}
/* Main Content */
.lcp-has-sidecontent #lcp-main-container > * > *{ padding:20px
}
#lcp-main-container {
margin-top: var(--lcp--header--height)
}
/* Side content */
#lcp-sidecontent {
overflow:auto;
position: absolute;
left: 0;
top: 0;
width: 340px;
height: 100%;
overflow: hidden;
background: #fff;
border-right: 2px solid #eee;
z-index: 2;
outline: 0;
}
#lcp-sidecontent-inner {
height: 100%;
overflow: auto; /* Enable scrolling for inner content */
padding:0 10px
#lcp-viewport-outer.lcp-has-sticky-header #lcp-sidecontent {
top: var(--lcp--header--height);
position:fixed!important;
height: calc(100vh - var(--lcp--header--height))
}
.admin-bar #lcp-viewport-outer.lcp-has-sticky-header #lcp-sidecontent {
top: calc(var(--lcp--header--height) + 32px);
height: calc(100vh - var(--lcp--header--height) - 32px)
}
#lcp-sidecontent-inner > * {
margin-top: 10px;}
@ -69,6 +82,17 @@ Version: 1.0
@media only screen and (max-width: 1199px) {
#lcp-sidecontent:not(.lcp-open) {display:none}
#lcp-sidecontent.lcp-open {
display: block;
position: fixed;
overflow:auto;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
z-index: 999;
}
}
/* Main content an Footer */
@ -89,7 +113,10 @@ Version: 1.0
width: 100%
}
#lcp-sidecontent {top:var(--lcp---header--height)}
.admin-bar #lcp-sidecontent {
#lcp-sidecontent {
top: calc(var(--lcp--header--height) );
}
.admin-bar #lcp-sidecontent.lcp-fixed {
top: calc(var(--lcp--header--height) + 32px);
}
@ -103,7 +130,7 @@ Version: 1.0
#lcp-header-container.lcp-sticky-on-scroll.lcp-fixed {
position: fixed;
top:0;
top:32px;
left: 0;
right: 0;
z-index: 3;
@ -142,40 +169,6 @@ Version: 1.0
#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;
}
/* Highlight-to-share popup */
.popup {
position: absolute;

View File

@ -1,6 +1,9 @@
{
"$schema": "https://schemas.wp.org/trunk/theme.json",
"version": 3,
"patterns": [
],
"settings": {
"appearanceTools": true,
"color": {

View File

@ -13,7 +13,8 @@ const excludedDirs = [
'package.json',
'package-lock.json',
'theme.zip',
'.git'
'.git',
'react'
];
// Helper function to check if a file or directory should be excluded