Compare commits

7 Commits
dev ... main

46 changed files with 1530 additions and 589 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 723 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 875 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 698 KiB

View File

@ -0,0 +1,32 @@
function lcpUpdateImageSizes(imageSizes) {
// Validate the input to ensure it's an array
if (!Array.isArray(imageSizes)) {
console.error('Invalid image sizes data');
return;
}
// Prepare the form data to send to WordPress to update the theme settings
const updateData = new FormData();
updateData.append('action', 'update_lcp_theme_settings'); // WordPress action hook
updateData.append('image_sizes', JSON.stringify(imageSizes)); // Send image sizes as a JSON string
updateData.append('nonce', customImageSizeAjax.nonce); // Send the nonce
console.log('Sending data to AJAX:', updateData); // Log the data for debugging
// Send the AJAX request
fetch(customImageSizeAjax.ajax_url, {
method: 'POST',
body: updateData, // Send form data directly
})
.then(response => response.json())
.then(data => {
if (data.success) {
console.log('Theme settings updated successfully.');
} else {
console.error('Failed to update theme settings:', data.message);
}
})
.catch(error => {
console.error('Error updating theme settings:', error);
});
}

View File

@ -0,0 +1,85 @@
document.addEventListener('DOMContentLoaded', function () {
// Check if the 'Import Demo Posts' button exists
const importButton = document.getElementById('import-demo-posts');
console.log(importButton); // This will log the button element to the console
if (importButton) {
// Check if the lcp_demo_posts option exists
if (lcp_ajax_obj.lcp_demo_posts && lcp_ajax_obj.lcp_demo_posts.post_ids && lcp_ajax_obj.lcp_demo_posts.post_ids.length > 0) {
// Disable the 'Import Demo Posts' button if demo posts have already been imported
importButton.disabled = true;
importButton.textContent = 'Demo Posts Already Imported'; // Optional: Change button text
} else {
// Add event listener to import demo posts if the button is enabled
importButton.addEventListener('click', function () {
console.log("Clicked"); // This should be triggered on button click
const formData = new FormData();
// Append action and nonce to the form data
formData.append('action', 'lcp_import_demo_posts');
formData.append('lcp_import_nonce', lcp_ajax_obj.nonce);
// Send the AJAX request to import demo posts
fetch(lcp_ajax_obj.ajax_url, {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
if (data.success) {
alert(data.data); // Success message
importButton.disabled = true;
importButton.textContent = 'Demo Posts Imported'; // Optional: Change button text
} else {
alert('Error: ' + (data.data || 'Unknown error')); // Error message
}
})
.catch(error => {
console.error('Error:', error);
alert('An error occurred while processing your request.');
});
});
}
}
// Check if the 'Delete Demo Posts' button exists
const deleteButton = document.getElementById('delete-demo-posts');
if (deleteButton) {
deleteButton.addEventListener('click', function () {
const formData = new FormData();
// Append action and nonce to the form data for deletion
formData.append('action', 'lcp_delete_demo_posts'); // Use the correct action here
formData.append('lcp_import_nonce', lcp_ajax_obj.nonce); // Pass nonce for security
// Send the AJAX request to delete demo posts
fetch(lcp_ajax_obj.ajax_url, {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
if (data.success) {
alert(data.data); // Success message
deleteButton.disabled = true;
deleteButton.textContent = 'Demo Posts Deleted';
// Re-enable the "Import Demo Posts" button and reset its text
const importButton = document.getElementById('import-demo-posts');
if (importButton) {
importButton.disabled = false;
importButton.textContent = 'Import Demo Posts';
}
} else {
alert('Error: ' + (data.data || 'Unknown error'));
}
})
.catch(error => {
console.error('Error:', error);
alert('An error occurred while processing your request.');
});
});
}
});

View File

@ -21,7 +21,7 @@ document.addEventListener('DOMContentLoaded', function () {
formData.append('icon_set_id', iconSetId);
const xhr = new XMLHttpRequest();
xhr.open('POST', mytheme_ajax.ajax_url, true);
xhr.open('POST', lcp_ajax.ajax_url, true);
xhr.onload = function () {
if (xhr.status === 200) {
@ -55,7 +55,7 @@ document.addEventListener('DOMContentLoaded', function () {
formData.append('icon_set_id', iconSetId);
const xhr = new XMLHttpRequest();
xhr.open('POST', mytheme_ajax.ajax_url, true);
xhr.open('POST', lcp_ajax.ajax_url, true);
xhr.onload = function () {
if (xhr.status === 200) {

View File

@ -1,3 +1,5 @@
/* ACCORDION */
document.addEventListener('DOMContentLoaded', function () {
// Find all elements with the class "lcp-accordion"
var accordions = document.querySelectorAll('.lcp-accordion');
@ -31,10 +33,39 @@ document.addEventListener('DOMContentLoaded', function () {
});
/* TABS */
document.addEventListener('DOMContentLoaded', function () {
const tabs = document.querySelectorAll('.tab-link');
const panes = document.querySelectorAll('.tab-pane');
const tabContainer = document.querySelector('.lcp-tab-container'); // The parent container
// Only enable the hash functionality if the container has the class '.lcp-support-hash'
if (tabContainer && tabContainer.classList.contains('lcp-support-hash')) {
// Function to set the active tab based on the hash in the URL
function setActiveTabFromHash() {
const hash = window.location.hash; // Get the current URL hash
if (hash) {
const targetTab = document.querySelector(`.tab-link[data-tab="${hash.substring(1)}"]`); // Remove '#' from hash
const targetPane = document.getElementById(hash.substring(1));
// If both tab and pane exist, make them active
if (targetTab && targetPane) {
tabs.forEach(link => link.classList.remove('active'));
panes.forEach(pane => pane.classList.remove('active'));
targetTab.classList.add('active');
targetPane.classList.add('active');
} else {
console.error(`Tab or pane with ID '${hash}' not found.`);
}
}
}
// Set the active tab from the hash when the page loads
setActiveTabFromHash();
}
// Handle tab clicks
tabs.forEach(tab => {
tab.addEventListener('click', function (event) {
event.preventDefault();
@ -46,16 +77,174 @@ document.addEventListener('DOMContentLoaded', function () {
// Add active class to the clicked tab
tab.classList.add('active');
// Get the target pane
// Get the target pane and update URL hash
const targetPaneId = tab.dataset.tab;
const targetPane = document.getElementById(targetPaneId);
// Check if targetPane exists before trying to manipulate it
if (targetPane) {
targetPane.classList.add('active');
if (tabContainer && tabContainer.classList.contains('lcp-support-hash')){
window.location.hash = targetPaneId; // Update the URL hash
}
} else {
console.error(`Tab pane with ID '${targetPaneId}' not found.`);
}
});
});
});
/* REPEATER */
document.addEventListener('DOMContentLoaded', function() {
// Function to initialize each repeater instance
function initRepeater(repeater) {
const firstRow = repeater.querySelector('.lcp-repeater-row');
// Function to check if all required fields are filled
function isRequiredFieldsFilled(row) {
const requiredFields = row.querySelectorAll('[data-lcp-required="true"], [data-lcp-required-for-new-row="true"]');
let valid = true;
requiredFields.forEach(input => {
// Check input type and value for validation
if (input.type === 'number' && (input.value === '' || isNaN(input.value))) {
valid = false;
} else if (input.type === 'checkbox' && !input.checked) {
valid = false;
}
});
return valid;
}
// Function to create a new row by cloning the first row
function addRepeaterRow() {
const newRow = firstRow.cloneNode(true); // true means deep cloning (includes children)
const inputs = newRow.querySelectorAll('input');
inputs.forEach(input => input.value = ''); // Reset value for input fields
newRow.querySelector('input[type="checkbox"]').checked = false; // Uncheck the checkbox
repeater.insertBefore(newRow, repeater.querySelector('.lcp-repeater-add-row'));
toggleAddRowButton();
toggleSubmitButton();
}
// Function to toggle the "Add Row" button based on the required field for new rows
function toggleAddRowButton() {
const addRowButton = repeater.querySelector('.lcp-repeater-add-row');
const rows = repeater.querySelectorAll('.lcp-repeater-row');
let validForNewRow = true;
rows.forEach(row => {
const requiredForNewRowFields = row.querySelectorAll('[data-lcp-required-for-new-row="true"]');
requiredForNewRowFields.forEach(input => {
if (input.value === '' || (input.type === 'checkbox' && !input.checked)) {
validForNewRow = false;
}
});
});
addRowButton.disabled = !validForNewRow;
}
// Function to toggle the "Submit" button based on the validation of all rows
function toggleSubmitButton() {
const submitButton = repeater.querySelector('.lcp-repeater-submit');
const rows = repeater.querySelectorAll('.lcp-repeater-row');
let allValid = true;
rows.forEach(row => {
if (!isRequiredFieldsFilled(row)) {
allValid = false;
}
});
submitButton.disabled = !allValid;
}
// Function to handle form submission, ensuring all required fields are filled
function handleSubmit(event) {
const submitButton = event.target;
const actionType = submitButton.getAttribute('data-lcp-action'); // This will be used to pass data to the handler
const rows = repeater.querySelectorAll('.lcp-repeater-row');
let allValid = true;
rows.forEach(row => {
if (!isRequiredFieldsFilled(row)) {
allValid = false;
}
});
if (allValid) {
const repeaterData = [];
rows.forEach(function(row) {
const rowData = {};
const inputs = row.querySelectorAll('input');
inputs.forEach(function(input) {
const key = input.getAttribute('data-lcp-repeater-key');
let value;
if (input.type === 'checkbox') {
value = input.checked; // Boolean value for checkbox
} else {
value = input.value; // Text or number inputs
}
rowData[key] = value; // Add key-value pair to rowData
});
repeaterData.push(rowData); // Add rowData to the repeaterData array
});
// Now just pass the data off to the handler
if (typeof window[actionType] === 'function') {
window[actionType](repeaterData); // Calls the function (e.g., `lcpUpdateImageSizes`)
}
} else {
alert("Please fill in all required fields.");
}
}
// Event listener for adding a new row when a user clicks the "Add Row" button
const addRowButtons = repeater.querySelectorAll('.lcp-repeater-add-row');
addRowButtons.forEach(button => {
button.addEventListener('click', function() {
if (isRequiredFieldsFilled(firstRow)) {
addRepeaterRow();
} else {
alert('Please fill in the required fields to add a new row.');
}
});
});
// Event listener for submitting the repeater form
const submitButton = repeater.querySelector('.lcp-repeater-submit');
submitButton.addEventListener('click', handleSubmit);
// Initial validation for the add row button
toggleAddRowButton();
// Initial validation for the submit button
toggleSubmitButton();
// Added event listeners to handle any changes in input and trigger validation
repeater.addEventListener('input', function() {
toggleAddRowButton(); // Revalidate Add Row button
toggleSubmitButton(); // Revalidate Submit button
});
}
// Initialize each repeater on the page
const repeaters = document.querySelectorAll('.lcp-repeater');
repeaters.forEach(repeater => {
initRepeater(repeater);
});
});

View File

@ -89,7 +89,7 @@ document.addEventListener('DOMContentLoaded', function () {
}
// Add debounced scroll event listener
window.addEventListener('scroll', debounce(handleScroll, 20)); // 200ms debounce
window.addEventListener('scroll', debounce(handleScroll, 0)); // 200ms debounce
});

View File

@ -1,57 +0,0 @@
<?php
// Path to your icons.json file
$filePath = 'output.json';
// Read the content of the JSON file
$jsonData = file_get_contents($filePath);
// Decode the JSON data into a PHP array
$iconsData = json_decode($jsonData, true);
// Check if the data is decoded successfully
if (json_last_error() !== JSON_ERROR_NONE) {
die('Error decoding JSON data: ' . json_last_error_msg());
}
// Check if the data contains a 'family' key (indicating it has families with SVGs)
if (isset($iconsData[0]['family'])) {
// Handle the case with families and svgs (structure 1)
foreach ($iconsData as &$family) {
if (isset($family['svgs']) && is_array($family['svgs'])) {
// Sort the 'svgs' array alphabetically by the 'name' field
usort($family['svgs'], function($a, $b) {
return strcmp($a['name'], $b['name']);
});
}
}
// Sort the families by the 'family' field (if needed)
usort($iconsData, function($a, $b) {
return strcmp($a['family'], $b['family']);
});
} else {
// Handle the case without families (structure 2)
// Sort the flat array of icons alphabetically by the 'name' field
usort($iconsData, function($a, $b) {
return strcmp($a['name'], $b['name']);
});
}
// Encode the sorted data back to JSON
$sortedJsonData = json_encode($iconsData, JSON_PRETTY_PRINT);
// Check if encoding was successful
if (json_last_error() !== JSON_ERROR_NONE) {
die('Error encoding JSON data: ' . json_last_error_msg());
}
// Write the sorted JSON data back to the file
if (file_put_contents($filePath, $sortedJsonData)) {
echo "The icons data has been sorted and saved successfully!";
} else {
echo "Error writing the sorted data to the file.";
}
?>

View File

@ -1,61 +0,0 @@
<?php
// Function to generate a UUID (compliant with MySQL UUID)
function generateUUID() {
return bin2hex(random_bytes(16)); // Generate a random UUID
}
// Function to convert the raw SVG to JSON format
function convertSymbolsToJSON($svgContent) {
// Match all <symbol> elements and extract them
preg_match_all('/<symbol[^>]*>[\s\S]*?<\/symbol>/', $svgContent, $matches);
$jsonData = [];
foreach ($matches[0] as $symbol) {
// Extract 'id', 'viewBox', and 'path' attributes
preg_match('/id="([^"]+)"/', $symbol, $idMatches);
preg_match('/viewBox="([^"]+)"/', $symbol, $viewBoxMatches);
preg_match('/<path[^>]*d="([^"]+)"/', $symbol, $pathMatches);
// If we have a valid symbol, process it
if (isset($idMatches[1]) && isset($viewBoxMatches[1]) && isset($pathMatches[1])) {
// Generate a UUID for the symbol
$uniqueId = generateUUID();
// Capitalize the name by replacing hyphens with spaces and capitalizing each word
$name = ucwords(str_replace('-', ' ', $idMatches[1]));
// Build the symbol JSON object
$symbolJSON = [
"id" => $uniqueId,
"name" => $name,
"viewBox" => $viewBoxMatches[1],
"path" => "<path d='" . $pathMatches[1] . "'/>"
];
// Add the symbol JSON to the data array
$jsonData[] = $symbolJSON;
}
}
return $jsonData;
}
// Read the SVG file (assumes it's in the same directory)
$svgFilePath = 'input.svg'; // The input SVG file
if (file_exists($svgFilePath)) {
$svgContent = file_get_contents($svgFilePath);
// Convert symbols to JSON
$symbolsJson = convertSymbolsToJSON($svgContent);
// Output the JSON data to a file
$outputFilePath = 'output.json';
file_put_contents($outputFilePath, json_encode($symbolsJson, JSON_PRETTY_PRINT));
echo "JSON file has been created successfully: $outputFilePath\n";
} else {
echo "Error: SVG file not found.\n";
}
?>

View File

@ -0,0 +1,57 @@
{
"posts": [
{
"title": "Mysterious Weather Patterns Reported in Faketown",
"content": "Faketown, USA — In what can only be described as a strange turn of events, Faketown residents have been experiencing unpredictable weather patterns. Local meteorologists have been baffled as sudden temperature shifts have been occurring at all hours of the day. One moment, the sun is shining brightly, and the next, it's snowing. This bizarre occurrence is leaving many questioning whether this is a sign of something more ominous. 'Ive lived here my entire life, and Ive never seen anything like this,' said local resident Jane Doe.",
"excerpt": "Faketown residents have been experiencing unpredictable weather patterns, baffling local meteorologists.",
"category": "Local News",
"tags": ["weather", "Faketown", "mystery"],
"date": "2024-01-01",
"status": "publish",
"thumbnail": "demo-post-thumbnail-1.jpg"
},
{
"title": "Faketown Mayor Announces New Green Initiative",
"content": "In a recent press conference, Faketowns mayor, John Smith, unveiled an ambitious plan to tackle climate change within the city. The initiative aims to reduce carbon emissions by 40% over the next 10 years, primarily by encouraging the use of electric vehicles and expanding the city's public transportation system. 'We are committed to making Faketown a greener place,' said Mayor Smith. 'Our children and grandchildren deserve a sustainable future.' The plan includes installing charging stations for electric cars across the city and offering tax incentives for green energy solutions.",
"excerpt": "Faketowns mayor unveils a new green initiative to reduce carbon emissions by 40%.",
"category": "Politics",
"tags": ["green", "climate change", "Faketown"],
"date": "2024-01-02",
"status": "publish",
"thumbnail": "demo-post-thumbnail-2.jpg"
},
{
"title": "Local Chef Opens Revolutionary Restaurant in Faketown",
"content": "Faketown, USA — In a culinary first for Faketown, renowned chef Sarah Bellamy has opened a new restaurant that combines traditional American cuisine with exotic flavors from around the world. Located in the heart of Faketown, Bellamys restaurant has already become the talk of the town. The menu features a variety of dishes, including 'Fusion Fries' and 'Sushi Burger.' 'I wanted to create something completely unique, a blend of cultures,' said Bellamy. The restaurant offers both dine-in and delivery services, with plans to expand its menu soon.",
"excerpt": "Faketown's new restaurant is offering a fusion of global flavors with a local twist.",
"category": "Food & Drink",
"tags": ["restaurant", "food", "Faketown"],
"date": "2024-01-03",
"status": "publish",
"thumbnail": "demo-post-thumbnail-3.jpg"
},
{
"title": "Strange Creatures Spotted in Faketown's Forests",
"content": "In the deep forests surrounding Faketown, local hikers have begun reporting sightings of strange creatures. Descriptions vary, but many claim to have seen large, mysterious beings with glowing eyes. Some hikers have even reported hearing unusual sounds that have no obvious explanation. 'I was out for a hike last week when I saw something huge moving through the trees,' said Greg Johnson, a local resident. 'I dont know what it was, but it wasnt a bear.' Authorities are urging hikers to stay on well-trodden paths and report any strange occurrences.",
"excerpt": "Faketown residents report strange creatures spotted in nearby forests, baffling experts.",
"category": "Strange Happenings",
"tags": ["mystery", "Faketown", "creatures"],
"date": "2024-01-04",
"status": "publish",
"thumbnail": "demo-post-thumbnail-1.jpg"
},
{
"title": "Faketown's Annual Festival Breaks Attendance Records",
"content": "This year's annual Faketown Festival was a resounding success, breaking all previous attendance records. Held in the town square, the festival featured local bands, food trucks, and street performances. The highlight of the event was the traditional 'Faketown Parade,' which saw thousands of people lining the streets. 'Weve never seen this many people come out,' said event coordinator Lisa Thompson. The festivals success has sparked excitement about next years event, with many suggesting that Faketown could become a regional hub for arts and culture.",
"excerpt": "Faketowns annual festival saw record-breaking attendance, with thousands of people participating.",
"category": "Community Events",
"tags": ["festival", "community", "Faketown"],
"date": "2024-01-05",
"status": "publish",
"thumbnail": "demo-post-thumbnail-2.jpg"
}
]
}

View File

@ -1,57 +0,0 @@
<?php
// Path to the input JSON file
$inputFile = 'font-awesome-v6.1.7-solid-svgs.json';
// Step 1: Load the JSON data
$jsonData = file_get_contents($inputFile);
// Check if the file was read successfully
if ($jsonData === false) {
die("Error reading the JSON file.");
}
// Step 2: Decode the JSON data into a PHP array
$data = json_decode($jsonData, true);
// Check if JSON decoding was successful
if ($data === null) {
die("Error decoding the JSON data.");
}
// Step 3: Modify the structure by extracting the 'd' value and formatting the 'paths' tag
foreach ($data as $index => $iconSet) {
if (isset($iconSet['svgs']) && is_array($iconSet['svgs'])) {
foreach ($iconSet['svgs'] as $svgIndex => $svg) {
// Check if 'path' exists
if (isset($svg['path'])) {
// Extract the 'd' attribute value from the nested path string
preg_match('/d=[\'"]([^\'"]+)[\'"]/i', $svg['path'], $matches);
// If we found the 'd' value, format the paths correctly
if (isset($matches[1])) {
$dValue = $matches[1]; // Get the actual 'd' value from the path
// Escape the 'd' value for JSON format (escape double quotes inside the string)
$escapedDValue = str_replace('"', '\\"', $dValue);
// Now, add the proper <path> tag to the 'paths' field
$svg['paths'] = "<path d=\"{$escapedDValue}\"/>";
}
unset($svg['path']); // Optionally remove the original 'path' key
}
// Save the modified svg back to the array
$data[$index]['svgs'][$svgIndex] = $svg;
}
}
}
// Optional: Save the modified JSON to a new file
$outputFile = 'solid-fixed-paths.json';
file_put_contents($outputFile, json_encode($data, JSON_PRETTY_PRINT));
// Output the success message
echo "Successfully modified and saved the JSON file with 'path' converted to 'paths'.\n";
?>

View File

@ -1,63 +0,0 @@
<?php
// Path to the input JSON file
$inputFile = 'material-icons-twotone.json';
// Path to the output JSON file
$outputFile = 'material-icons-twotone-unescaped-with-ids.json';
// Function to generate a MySQL-style UUID
function generateUUID() {
// Generates a version 4 UUID (random)
return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
mt_rand(0, 0xffff), mt_rand(0, 0xffff),
mt_rand(0, 0xffff),
mt_rand(0, 0x0fff) | 0x4000,
mt_rand(0, 0x3fff) | 0x8000,
mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
);
}
// Step 1: Load the JSON data
$jsonData = file_get_contents($inputFile);
// Check if the file was read successfully
if ($jsonData === false) {
die("Error reading the JSON file.");
}
// Step 2: Decode the JSON data into a PHP array
$data = json_decode($jsonData, true);
// Check if JSON decoding was successful
if ($data === null) {
die("Error decoding the JSON data.");
}
// Step 3: Iterate through each item and unescape the 'paths' key, and generate a new 'id'
foreach ($data as &$icon) {
// Unescape only HTML entities (without affecting forward slashes)
$icon['paths'] = html_entity_decode($icon['paths'], ENT_QUOTES | ENT_HTML5);
// Generate a new MySQL-style UUID for each 'id'
$icon['id'] = generateUUID();
}
// Step 4: Encode the modified data back into JSON format
$newJsonData = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
// Check if encoding was successful
if ($newJsonData === false) {
die("Error encoding the JSON data.");
}
// Step 5: Save the modified JSON data to the output file
file_put_contents($outputFile, $newJsonData);
// Check if file writing was successful
if (file_put_contents($outputFile, $newJsonData) === false) {
die("Error saving the modified JSON data.");
}
echo "Paths have been unescaped, IDs have been added, and saved to '$outputFile'.\n";
?>

View File

@ -1,86 +0,0 @@
<?php
// Function to capitalize the 'name' field (capitalizes acronyms fully)
function capitalizeName($name) {
// Define a pattern to match acronyms (words in uppercase with no spaces)
$acronymPattern = '/\b[A-Z]{2,}\b/';
// Capitalize each word, and keep acronyms fully uppercase
$name = preg_replace_callback('/\b\w+\b/', function ($matches) use ($acronymPattern) {
$word = $matches[0];
// If it's an acronym (all uppercase), return as is
if (preg_match($acronymPattern, $word)) {
return strtoupper($word);
}
// Otherwise capitalize the first letter of each word and lowercase the rest
return ucfirst(strtolower($word));
}, $name);
return $name;
}
// Function to generate a MySQL UUID format (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
function generateMysqlUuid() {
// Generate a UUID using PHP's random_bytes for a total of 16 random bytes
$data = random_bytes(16);
// Set the version to 4 (random UUID)
$data[6] = chr(ord($data[6]) & 0x0f | 0x40); // Version 4
// Set the variant to RFC4122
$data[8] = chr(ord($data[8]) & 0x3f | 0x80); // RFC4122 variant
// Now unpack the data into 5 parts for formatting as UUID
$hexData = unpack('H8a/H4b/H4c/H4d/H12e', $data);
// Return the UUID in the format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
return $hexData['a'] . '-' . $hexData['b'] . '-' . $hexData['c'] . '-' . $hexData['d'] . '-' . $hexData['e'];
}
// Get the current directory of the script
$currentDir = __DIR__;
// Get all JSON files in the current directory
$jsonFiles = glob($currentDir . '/*.json');
// Iterate over each JSON file
foreach ($jsonFiles as $file) {
// Read the content of the file
$jsonContent = file_get_contents($file);
// Decode JSON to array
$data = json_decode($jsonContent, true);
// Check if the data is valid
if (json_last_error() === JSON_ERROR_NONE) {
// Process each SVG object
foreach ($data as &$set) {
if (isset($set['svgs'])) {
foreach ($set['svgs'] as &$svg) {
// Capitalize the 'name' field
if (isset($svg['name'])) {
$svg['name'] = capitalizeName($svg['name']);
}
// Generate a new MySQL UUID for the 'id' field
if (isset($svg['id'])) {
$svg['id'] = generateMysqlUuid();
}
}
}
}
// Re-encode the modified data to JSON
$newJsonContent = json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
// Define the output file name (you can change this as needed)
$outputFile = $currentDir . '/modified_' . basename($file);
// Save the updated content back to a new file
file_put_contents($outputFile, $newJsonContent);
echo "Processed and saved to: " . basename($outputFile) . "\n";
} else {
echo "Invalid JSON in file: " . basename($file) . "\n";
}
}
?>

View File

@ -4,7 +4,7 @@
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';
@ -45,14 +45,6 @@ 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');
/* KEY POINTS */
@ -178,36 +170,10 @@ function drop_lcp_icons_table() {
/* BACKEND ICON ADDER */
// Register the dashboard page in the admin menu
function mytheme_register_dashboard_page() {
add_menu_page(
'Icon Management', // Page Title
'Icon Management', // Menu Title
'manage_options', // Capability
'icon-management', // Menu Slug
'mytheme_dashboard_page', // Callback function
'dashicons-images-alt2', // Icon for the menu item
60 // Position
);
}
add_action('admin_menu', 'mytheme_register_dashboard_page');
// Callback function to display the dashboard page content
function mytheme_dashboard_page() {
?>
<div class="wrap">
<h1><?php esc_html_e('Icon Management Dashboard', 'mytheme'); ?></h1>
<div id="icon-dashboard-container">
<?php mytheme_display_icon_sets(); ?>
</div> <!-- This will be populated by PHP -->
</div>
<?php
}
// Function to read and display icon sets from the JSON file
// Function to read and display icon sets from the JSON file
function mytheme_display_icon_sets() {
function lcp_display_icon_sets() {
// Path to the JSON file
$json_path = get_template_directory() . '/assets/json/icons/icon-definitions.json';
@ -238,16 +204,16 @@ function mytheme_display_icon_sets() {
// Enqueue the dashboard styles only on the icon-management page
function mytheme_enqueue_dashboard_styles($hook) {
function lcp_enqueue_dashboard_styles($hook) {
// Enqueue CSS for the dashboard
wp_enqueue_style(
'mytheme-dashboard-css',
'lcp-dashboard-css',
get_template_directory_uri() . '/assets/css/dashboard.css'
);
}
add_action('admin_enqueue_scripts', 'mytheme_enqueue_dashboard_styles');
add_action('admin_enqueue_scripts', 'lcp_enqueue_dashboard_styles');
// Handle the AJAX request for installing icon sets
@ -311,7 +277,7 @@ function lcp_install_icon_set($defaults = false) {
$icon_set_id = intval($_POST['icon_set_id']);
// Create the database table if it doesn't exist
mytheme_create_icons_table();
lcp_create_icons_table();
// Read the icon definitions JSON file
if (file_exists($json_path)) {
@ -384,7 +350,7 @@ 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 mytheme_create_icons_table() {
function lcp_create_icons_table() {
global $wpdb;
$table_name = $wpdb->prefix . 'lcp_icons';
@ -409,29 +375,10 @@ function mytheme_create_icons_table() {
}
function mytheme_enqueue_dashboard_scripts($hook) {
// Only load the script on the icon-management page
// Enqueue JavaScript for AJAX
wp_enqueue_script(
'icon-import-script',
get_template_directory_uri() . '/assets/js/icon-import.js',
array(), // No dependencies for vanilla JS
null,
true
);
// Pass the AJAX URL to the script
wp_localize_script('icon-import-script', 'mytheme_ajax', array(
'ajax_url' => admin_url('admin-ajax.php')
));
}
add_action('admin_enqueue_scripts', 'mytheme_enqueue_dashboard_scripts');
// Handle the AJAX request for uninstalling icon sets
function mytheme_uninstall_icon_set() {
function lcp_uninstall_icon_set() {
// Ensure icon set ID is passed in the request
if (!isset($_POST['icon_set_id'])) {
wp_send_json_error(array('message' => 'Invalid icon set ID.'));
@ -460,6 +407,761 @@ function mytheme_uninstall_icon_set() {
}
}
add_action('wp_ajax_uninstall_icon_set', 'mytheme_uninstall_icon_set');
add_action('wp_ajax_uninstall_icon_set', 'lcp_uninstall_icon_set');
/* Import Demo Posts */
function lcp_import_demo_posts() {
$json_data = file_get_contents(get_template_directory() . '/assets/json/demo-posts.json');
// Check if the JSON data is successfully fetched and decoded
if (empty($json_data)) {
return;
}
$posts = json_decode($json_data, true)['posts'];
if (empty($posts)) {
return;
}
// Arrays to store post IDs and media (thumbnail) IDs
$post_ids = [];
$media_ids = [];
foreach ($posts as $post) {
// Prepare post data
$post_data = array(
'post_title' => wp_strip_all_tags($post['title']),
'post_content' => $post['content'],
'post_excerpt' => isset($post['excerpt']) ? $post['excerpt'] : '',
'post_status' => isset($post['status']) ? $post['status'] : 'draft', // Default to 'draft' if no status
'post_date' => isset($post['date']) ? $post['date'] : current_time('mysql'),
'post_type' => 'post',
'post_author' => 1, // Change if you have specific user IDs
);
// Insert the post into the database
$post_id = wp_insert_post($post_data);
// If there was an issue inserting the post, skip this one
if (is_wp_error($post_id)) {
continue;
}
// Store the post ID in the array
$post_ids[] = $post_id;
// Assign categories (if they exist)
if (!empty($post['category'])) {
$category = term_exists($post['category'], 'category');
if ($category) {
wp_set_post_terms($post_id, array($category['term_id']), 'category');
} else {
// If category doesn't exist, create it
$category_id = wp_create_term($post['category'], 'category');
wp_set_post_terms($post_id, array($category_id['term_id']), 'category');
}
}
// Assign tags (if they exist)
if (!empty($post['tags'])) {
wp_set_post_terms($post_id, $post['tags'], 'post_tag');
}
// Handle thumbnail (featured image)
if (!empty($post['thumbnail'])) {
$thumbnail_url = get_template_directory_uri() . '/assets/img/demo-post-thumbnails/' . $post['thumbnail'];
// Download the image and add it to the media library
$thumbnail_id = media_handle_sideload(
array(
'name' => basename($thumbnail_url),
'tmp_name' => download_url($thumbnail_url)
),
$post_id
);
// If the image was uploaded successfully, set it as the post's featured image
if (!is_wp_error($thumbnail_id)) {
set_post_thumbnail($post_id, $thumbnail_id);
// Store the media ID in the array
$media_ids[] = $thumbnail_id;
}
}
// You can add additional meta fields if necessary
// Example:
// update_post_meta($post_id, 'some_meta_key', 'some_value');
}
// After all posts are imported, update the 'lcp_demo_posts' option
$demo_posts_data = array(
'post_ids' => $post_ids,
'media_ids' => $media_ids,
);
update_option('lcp_demo_posts', $demo_posts_data);
// Optionally, you can log the post and media IDs
// var_dump($post_ids, $media_ids); // Uncomment this line if you need to inspect the result
}
/* Delete the Demo Posts */
// Get the lcp_demo_posts option and delete all the posts from there
function lcp_delete_demo_posts() {
// Get the lcp_demo_posts option
$demo_posts_data = get_option('lcp_demo_posts');
// Check if the option exists and contains data
if (!empty($demo_posts_data) && isset($demo_posts_data['post_ids']) && isset($demo_posts_data['media_ids'])) {
// Loop through and delete posts
foreach ($demo_posts_data['post_ids'] as $post_id) {
// Delete post, force delete if necessary (set true for delete permanently)
wp_delete_post($post_id, true); // true will permanently delete
}
// Loop through and delete media (attachments)
foreach ($demo_posts_data['media_ids'] as $media_id) {
// Delete attachment (media file)
wp_delete_attachment($media_id, true); // true will permanently delete
}
// After deletion, remove the option from wp_options table
delete_option('lcp_demo_posts');
// Optionally, you can log the deletion for confirmation
// error_log('Demo posts and media have been deleted.');
} else {
// If the option doesn't exist, or it's empty
error_log('No demo posts data found or already deleted.');
}
}
/* Localize */
add_action('wp_ajax_lcp_import_demo_posts', 'lcp_import_demo_posts_ajax_handler');
// Define the function to handle the AJAX request
function lcp_import_demo_posts_ajax_handler() {
// Check for permissions (optional: can be used to ensure only admins can trigger this)
if (!current_user_can('manage_options')) {
wp_send_json_error('You do not have sufficient permissions to perform this action.');
}
// Call the existing function that imports the demo posts
lcp_import_demo_posts();
// Send a success response back to the browser
wp_send_json_success('Demo posts imported successfully.');
}
add_action('wp_ajax_lcp_delete_demo_posts', 'lcp_delete_demo_posts_ajax_handler');
// Define the function to handle the delete demo posts AJAX request
function lcp_delete_demo_posts_ajax_handler() {
// Verify nonce for security
if (!isset($_POST['lcp_import_nonce']) || !wp_verify_nonce($_POST['lcp_import_nonce'], 'lcp_import_demo_posts_nonce')) {
wp_send_json_error('Invalid nonce');
}
// Check if the current user has permissions to manage options
if (!current_user_can('manage_options')) {
wp_send_json_error('You do not have sufficient permissions to perform this action.');
}
// Call the function that deletes the demo posts
lcp_delete_demo_posts();
// Send a success response back to the browser
wp_send_json_success('Demo posts deleted successfully.');
}
// Set a visited post cookies
// Hooked into send_headers via wp-hooks.php
function lcp_set_visited_posts_cookie() {
// Only track posts on single post pages
if (is_single()) {
// Get the current post's ID and post type
$current_post_id = get_the_ID();
$post_type = get_post_type();
$visit_time = time(); // Get the current time as a Unix timestamp
// Check if the cookie exists
if (isset($_COOKIE['lcp_visited_posts'])) {
// Decode the cookie's JSON value
$visited_posts = json_decode(stripslashes($_COOKIE['lcp_visited_posts']), true);
// Check if decoding was successful and if the format is correct
if (json_last_error() !== JSON_ERROR_NONE || !is_array($visited_posts)) {
// If the cookie is not valid, delete the cookie and start over
setcookie('lcp_visited_posts', '', time() - 3600, '/'); // Expire the cookie
$visited_posts = []; // Initialize an empty array
}
} else {
// Initialize an empty array if the cookie doesn't exist
$visited_posts = [];
}
// If the post type is not already in the cookie, initialize it as an empty array
if (!isset($visited_posts[$post_type])) {
$visited_posts[$post_type] = [];
}
// Add the current post ID and the visit timestamp as an array entry
// Ensure that the post ID isn't already added for this post type
$found = false;
foreach ($visited_posts[$post_type] as &$post) {
if (array_key_exists($current_post_id, $post)) {
$post[$current_post_id] = $visit_time; // Update the timestamp if post already exists
$found = true;
break;
}
}
// If post wasn't found, add it as a new entry
if (!$found) {
$visited_posts[$post_type][] = [$current_post_id => $visit_time];
}
// Encode the updated visited posts array to JSON
$cookie_value = json_encode($visited_posts);
// Set the cookie with a 30-day expiration time (this must be done before any output)
setcookie('lcp_visited_posts', $cookie_value, time() + (30 * 24 * 60 * 60), '/'); // '/' makes the cookie available across the whole site
}
}
/* CUSTOM IMAGE SIZES */
function lcp_update_image_sizes() {
// Verify nonce for security
if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'custom_image_sizes_nonce')) {
wp_send_json_error(array('message' => 'Nonce validation failed.'));
return;
}
// Check if image_sizes data is provided
if (isset($_POST['image_sizes'])) {
$image_sizes = json_decode(stripslashes($_POST['image_sizes']), true); // Decode JSON data
// Make sure that the image_sizes data is valid
if (!is_array($image_sizes)) {
wp_send_json_error(array('message' => 'Invalid image sizes data.'));
return;
}
// Process the data (e.g., update options)
update_option('lcp_image_sizes', $image_sizes);
// Return success message
wp_send_json_success(array('message' => 'Image sizes updated successfully.'));
} else {
wp_send_json_error(array('message' => 'No image sizes data received.'));
}
}
add_action('wp_ajax_update_lcp_theme_settings', 'lcp_update_image_sizes');
add_action('wp_ajax_nopriv_update_lcp_theme_settings', 'lcp_update_image_sizes');
function lcp_register_custom_image_sizes() {
// Retrieve the 'lcp_image_sizes' option, which is already unserialized by WordPress
$custom_image_sizes = get_option('lcp_image_sizes');
// Check if the option exists and is an array (because WordPress auto-unserializes the data)
if ($custom_image_sizes && is_array($custom_image_sizes)) {
// Loop through the array and register each image size
foreach ($custom_image_sizes as $size) {
// Ensure the size has the correct keys and valid values
if (isset($size['name'], $size['width'], $size['height'], $size['crop']) && !empty($size['name'])) {
// Sanitize the name, but ensure it's not just a number like '1'
$name = sanitize_key($size['name']);
$width = (int) $size['width']; // Cast to integer
$height = (int) $size['height']; // Cast to integer
$crop = (bool) $size['crop']; // Convert to boolean
// Register the custom image size
add_image_size($name, $width, $height, $crop);
}
}
}
}
// Hook into WordPress to register custom sizes
add_action('after_setup_theme', 'lcp_register_custom_image_sizes');
/* CUSTOM POST TYPES */
// Register the post meta field for the gallery
function to_register_meta_fields() {
register_post_meta('post', 'lcp_post_gallery', [
'type' => 'array',
'description' => 'Custom post gallery',
'single' => true,
'show_in_rest' => true,
]);
}
add_action('init', 'to_register_meta_fields');
// Add meta box for the gallery
function add_lcp_gallery_meta_box() {
add_meta_box(
'lcp_gallery_meta_box',
__('Post Gallery', 'textdomain'),
'render_lcp_gallery_meta_box',
'post',
'normal',
'high'
);
}
add_action('add_meta_boxes', 'add_lcp_gallery_meta_box');
// Render the meta box
function render_lcp_gallery_meta_box($post) {
// Add nonce for security
wp_nonce_field('lcp_gallery_meta_box', 'lcp_gallery_meta_box_nonce');
// Get existing gallery items
$gallery_items = get_post_meta($post->ID, 'lcp_gallery', true);
if (!is_array($gallery_items)) {
$gallery_items = array();
}
?>
<style>
#lcp-gallery-list li {
cursor: move;
padding: 10px;
margin-bottom: 10px;
background: #fff;
border: 1px solid #ddd;
position: relative;
}
#lcp-gallery-list li.dragging {
opacity: 0.5;
border: 2px dashed #999;
}
.drag-handle {
cursor: move;
padding: 5px;
margin-right: 10px;
color: #999;
}
#lcp-media-source-selector {
margin-bottom: 15px;
}
.gallery-item-fields {
margin-top: 10px;
}
.gallery-item-fields input[type="text"],
.gallery-item-fields textarea {
width: 100%;
margin-bottom: 5px;
}
.gallery-item-fields label {
display: block;
margin-top: 5px;
font-weight: bold;
}
.color-picker-wrapper {
display: flex;
align-items: center;
gap: 10px;
margin-top: 5px;
}
.color-picker-wrapper input[type="color"] {
padding: 0;
width: 50px;
height: 30px;
}
</style>
<div id="lcp-gallery-container">
<div id="lcp-media-source-selector">
<select id="lcp-media-source">
<option value="media_library">Media Library</option>
<option value="youtube">YouTube</option>
<option value="vimeo">Vimeo</option>
</select>
<button type="button" class="button" id="add-to-gallery">Add Media</button>
</div>
<ul id="lcp-gallery-list">
<?php
foreach ($gallery_items as $item) {
$media_source = isset($item['media_source']) ? $item['media_source'] : '';
$media_id = isset($item['media_id']) ? $item['media_id'] : '';
$url = isset($item['url']) ? $item['url'] : '';
$title = isset($item['title']) ? $item['title'] : '';
$caption = isset($item['caption']) ? $item['caption'] : '';
$background_color = isset($item['background_color']) ? $item['background_color'] : '';
echo '<li draggable="true" style="background-color: ' . esc_attr($background_color) . ';">';
echo '<span class="drag-handle dashicons dashicons-menu"></span>';
echo '<input type="hidden" name="lcp_gallery[]" value="' . esc_attr(json_encode($item)) . '">';
if ($media_source === 'media_library' && $media_id) {
$image = wp_get_attachment_image_src($media_id, 'thumbnail');
if ($image) {
echo '<img src="' . esc_url($image[0]) . '" alt="" style="max-width: 150px; height: auto;">';
}
} elseif ($media_source === 'youtube' && $url) {
echo '<div class="youtube-thumbnail" style="width: 150px; height: 150px; background: #f0f0f0; display: flex; align-items: center; justify-content: center;">';
echo '<span class="dashicons dashicons-youtube"></span>';
echo '</div>';
}
// Add fields for title, caption, and background color
echo '<div class="gallery-item-fields">';
echo '<label>Title</label>';
echo '<input type="text" class="gallery-item-title" value="' . esc_attr($title) . '" placeholder="Enter title">';
echo '<label>Caption</label>';
echo '<textarea class="gallery-item-caption" rows="3" placeholder="Enter caption">' . esc_textarea($caption) . '</textarea>';
echo '<label>Background Color</label>';
echo '<div class="color-picker-wrapper">';
echo '<input type="color" class="gallery-item-bgcolor" value="' . esc_attr($background_color) . '">';
echo '<button type="button" class="button update-bgcolor">Update Background</button>';
echo '</div>';
echo '</div>';
echo '<button type="button" class="button remove-gallery-item">Remove</button>';
echo '</li>';
}
?>
</ul>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Initialize gallery items array from PHP
let galleryItems = <?php echo json_encode($gallery_items); ?>;
console.log('Initial gallery items:', galleryItems);
// Function to update hidden input values and maintain state
function updateHiddenInputs() {
const list = document.querySelector('#lcp-gallery-list');
list.innerHTML = ''; // Clear the list
console.log('Updating gallery items:', galleryItems);
// Rebuild the list with current items
galleryItems.forEach((item, index) => {
const li = document.createElement('li');
li.draggable = true;
if (item.background_color) {
li.style.backgroundColor = item.background_color;
}
// Add drag handle
const dragHandle = document.createElement('span');
dragHandle.className = 'drag-handle dashicons dashicons-menu';
li.appendChild(dragHandle);
// Add hidden input with item data
const input = document.createElement('input');
input.type = 'hidden';
input.name = 'lcp_gallery[]';
input.value = JSON.stringify(item);
li.appendChild(input);
// Add thumbnail
if (item.media_source === 'media_library' && item.media_id) {
wp.media.attachment(item.media_id).fetch().then(function() {
const img = document.createElement('img');
img.src = wp.media.attachment(item.media_id).get('url');
img.style = 'max-width: 150px; height: auto;';
li.appendChild(img);
});
} else if (item.media_source === 'youtube' && item.url) {
const div = document.createElement('div');
div.className = 'youtube-thumbnail';
div.style = 'width: 150px; height: 150px; background: #f0f0f0; display: flex; align-items: center; justify-content: center;';
div.innerHTML = '<span class="dashicons dashicons-youtube"></span>';
li.appendChild(div);
}
// Add fields container
const fields = document.createElement('div');
fields.className = 'gallery-item-fields';
// Title field
const titleLabel = document.createElement('label');
titleLabel.textContent = 'Title';
fields.appendChild(titleLabel);
const titleInput = document.createElement('input');
titleInput.type = 'text';
titleInput.className = 'gallery-item-title';
titleInput.value = item.title || '';
titleInput.placeholder = 'Enter title';
titleInput.addEventListener('input', () => {
item.title = titleInput.value;
updateItemData(index, item);
});
fields.appendChild(titleInput);
// Caption field
const captionLabel = document.createElement('label');
captionLabel.textContent = 'Caption';
fields.appendChild(captionLabel);
const captionInput = document.createElement('textarea');
captionInput.className = 'gallery-item-caption';
captionInput.rows = 3;
captionInput.value = item.caption || '';
captionInput.placeholder = 'Enter caption';
captionInput.addEventListener('input', () => {
item.caption = captionInput.value;
updateItemData(index, item);
});
fields.appendChild(captionInput);
// Background color field
const colorLabel = document.createElement('label');
colorLabel.textContent = 'Background Color';
fields.appendChild(colorLabel);
const colorWrapper = document.createElement('div');
colorWrapper.className = 'color-picker-wrapper';
const colorInput = document.createElement('input');
colorInput.type = 'color';
colorInput.className = 'gallery-item-bgcolor';
colorInput.value = item.background_color || '#ffffff';
const updateColorBtn = document.createElement('button');
updateColorBtn.type = 'button';
updateColorBtn.className = 'button update-bgcolor';
updateColorBtn.textContent = 'Update Background';
updateColorBtn.addEventListener('click', () => {
const newColor = colorInput.value;
item.background_color = newColor;
li.style.backgroundColor = newColor;
updateItemData(index, item);
console.log('Color updated for item', index, ':', item);
});
colorInput.addEventListener('input', () => {
// Preview the color as user picks
li.style.backgroundColor = colorInput.value;
});
colorWrapper.appendChild(colorInput);
colorWrapper.appendChild(updateColorBtn);
fields.appendChild(colorWrapper);
li.appendChild(fields);
// Add remove button
const removeBtn = document.createElement('button');
removeBtn.type = 'button';
removeBtn.className = 'button remove-gallery-item';
removeBtn.textContent = 'Remove';
removeBtn.onclick = function() {
galleryItems.splice(index, 1);
console.log('Removed item at index', index, '. New gallery items:', galleryItems);
updateHiddenInputs();
};
li.appendChild(removeBtn);
// Add drag and drop event listeners
li.addEventListener('dragstart', handleDragStart);
li.addEventListener('dragend', handleDragEnd);
li.addEventListener('dragover', handleDragOver);
li.addEventListener('drop', handleDrop);
list.appendChild(li);
});
}
// Function to update a specific item's data
function updateItemData(index, item) {
galleryItems[index] = item;
const input = document.querySelector(`#lcp-gallery-list li:nth-child(${index + 1}) input[name^="lcp_gallery"]`);
if (input) {
input.value = JSON.stringify(item);
console.log('Updated item at index', index, ':', item);
console.log('Current gallery items:', galleryItems);
}
}
// Initialize the list with existing items
if (galleryItems.length > 0) {
console.log('Initializing gallery with existing items:', galleryItems);
updateHiddenInputs();
}
// Handle drag and drop
let draggedItem = null;
let draggedIndex = null;
function handleDragStart(e) {
draggedItem = this;
draggedIndex = Array.from(draggedItem.parentNode.children).indexOf(draggedItem);
this.classList.add('dragging');
e.dataTransfer.effectAllowed = 'move';
console.log('Started dragging item at index:', draggedIndex);
}
function handleDragEnd(e) {
this.classList.remove('dragging');
draggedItem = null;
draggedIndex = null;
}
function handleDragOver(e) {
e.preventDefault();
e.dataTransfer.dropEffect = 'move';
}
function handleDrop(e) {
e.preventDefault();
if (draggedItem === this) return;
const droppedIndex = Array.from(this.parentNode.children).indexOf(this);
console.log('Dropping item from index', draggedIndex, 'to index', droppedIndex);
// Reorder galleryItems array
const [movedItem] = galleryItems.splice(draggedIndex, 1);
galleryItems.splice(droppedIndex, 0, movedItem);
console.log('Reordered gallery items:', galleryItems);
updateHiddenInputs();
}
// Initialize the media frame
let mediaFrame;
document.getElementById('add-to-gallery').addEventListener('click', function(e) {
e.preventDefault();
const source = document.getElementById('lcp-media-source').value;
if (source === 'media_library') {
if (mediaFrame) {
mediaFrame.open();
return;
}
mediaFrame = wp.media({
title: 'Select Media',
button: {
text: 'Add to Gallery'
},
multiple: false
});
mediaFrame.on('select', function() {
const attachment = mediaFrame.state().get('selection').first().toJSON();
const item = {
media_source: 'media_library',
media_id: attachment.id,
title: '',
caption: '',
background_color: ''
};
galleryItems.push(item);
console.log('Added new media library item:', item);
console.log('Current gallery items:', galleryItems);
updateHiddenInputs();
});
mediaFrame.open();
} else {
const url = prompt('Enter ' + source + ' URL:');
if (url) {
const item = {
media_source: source,
url: url,
title: '',
caption: '',
background_color: ''
};
galleryItems.push(item);
console.log('Added new URL item:', item);
console.log('Current gallery items:', galleryItems);
updateHiddenInputs();
}
}
});
});
</script>
<?php
}
// Save the gallery meta data
function save_lcp_gallery_meta_box($post_id) {
// Check if our nonce is set
if (!isset($_POST['lcp_gallery_meta_box_nonce'])) {
return;
}
// Verify that the nonce is valid
if (!wp_verify_nonce($_POST['lcp_gallery_meta_box_nonce'], 'lcp_gallery_meta_box')) {
return;
}
// If this is an autosave, our form has not been submitted, so we don't want to do anything
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
return;
}
// Check the user's permissions
if (isset($_POST['post_type']) && 'page' == $_POST['post_type']) {
if (!current_user_can('edit_page', $post_id)) {
return;
}
} else {
if (!current_user_can('edit_post', $post_id)) {
return;
}
}
// Save the gallery data
if (isset($_POST['lcp_gallery'])) {
$gallery_items = array_map(function($item) {
return is_string($item) ? json_decode(wp_unslash($item), true) : $item;
}, $_POST['lcp_gallery']);
update_post_meta($post_id, 'lcp_gallery', $gallery_items);
} else {
delete_post_meta($post_id, 'lcp_gallery');
}
}
add_action('save_post', 'save_lcp_gallery_meta_box');
// Enqueue color picker
function lcp_gallery_admin_enqueue($hook) {
if ('post.php' != $hook && 'post-new.php' != $hook) {
return;
}
wp_enqueue_style('wp-color-picker');
wp_enqueue_script('wp-color-picker');
}
add_action('admin_enqueue_scripts', 'lcp_gallery_admin_enqueue');
// Add AJAX handler for gallery updates
add_action('wp_ajax_update_gallery_meta', 'handle_gallery_meta_update');
add_action('wp_ajax_nopriv_update_gallery_meta', 'handle_gallery_meta_update');
function handle_gallery_meta_update() {
// Verify nonce for security
if (!current_user_can('edit_posts')) {
wp_send_json_error('Permission denied');
return;
}
$post_id = isset($_POST['post_id']) ? intval($_POST['post_id']) : 0;
$gallery_items = isset($_POST['gallery_items']) ? json_decode(stripslashes($_POST['gallery_items']), true) : array();
// Update the post meta
$updated = update_post_meta($post_id, 'lcp_gallery', $gallery_items);
if ($updated) {
wp_send_json_success(array('message' => 'Gallery updated successfully'));
} else {
wp_send_json_error(array('message' => 'Failed to update gallery'));
}
}

View File

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

File diff suppressed because one or more lines are too long

View File

@ -10,7 +10,7 @@ export default function save(props) {
// Conditionally render the link or button based on buttonAction
return (
<div {...blockProps}>
<>
{buttonAction === 'customUrl' ? (
<a href={customUrl} className="lcp-button" style={{ padding: buttonPadding || '10px' }}>
{displayIcon && iconSvgPath && (
@ -30,6 +30,6 @@ export default function save(props) {
</span>
</button>
)}
</div>
</>
);
}

View File

@ -1 +1 @@
<?php return array('dependencies' => array('react', 'react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-i18n'), 'version' => '40a5279a7e8774abfe4c');
<?php return array('dependencies' => array('react', 'react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-i18n'), 'version' => '04e9c02e00cfeee61658');

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
.wp-block-create-block-lcp-viewport{background-color:#21759b;color:#fff;padding:2px}
.wp-block-create-block-lcp-viewport{background-color:#21759b;color:#fff;padding:2px}.lcp-dynamic-container.lcp-has-background-image{position:relative;width:100%}.lcp-dynamic-container.lcp-has-background-image>.lcp-background-image{height:100%;right:0;-o-object-fit:cover;object-fit:cover;-o-object-position:center center;object-position:center center;position:absolute;top:0;width:100%}

View File

@ -1 +1 @@
.wp-block-create-block-lcp-viewport{background-color:#21759b;color:#fff;padding:2px}
.wp-block-create-block-lcp-viewport{background-color:#21759b;color:#fff;padding:2px}.lcp-dynamic-container.lcp-has-background-image{position:relative;width:100%}.lcp-dynamic-container.lcp-has-background-image>.lcp-background-image{height:100%;left:0;-o-object-fit:cover;object-fit:cover;-o-object-position:center center;object-position:center center;position:absolute;top:0;width:100%}

View File

@ -65,7 +65,7 @@ if (!function_exists('lcp_random_string')) {
}
function render_lcp_container( $attributes, $content ) {
function render_lcp_dynamic_container( $attributes, $content ) {
// Debugging: Check the passed attributes
//var_dump($attributes);
@ -159,13 +159,39 @@ if (!function_exists('lcp_random_string')) {
if ( ! empty( $style ) ) {
$style_tag = sprintf( '<style>.%s { %s }</style>', esc_attr( $random_class ), $style );
}
// Set the post thumbnail
if ( has_post_thumbnail() ) {
// Get the post thumbnail URL for different sizes
$full_size_url = get_the_post_thumbnail_url( get_the_ID(), 'full' );
$medium_size_url = get_the_post_thumbnail_url( get_the_ID(), 'medium' );
$large_size_url = get_the_post_thumbnail_url( get_the_ID(), 'large' );
// Generate the <picture> element with <source> and <img> tags for responsiveness
$post_thumb = '<picture class="lcp-background-image">';
// Add source for large image (for screens >= 1200px)
$post_thumb .= '<source media="(min-width: 1200px)" srcset="' . esc_url( $large_size_url ) . '">';
// Add source for medium image (for screens >= 768px)
$post_thumb .= '<source media="(min-width: 768px)" srcset="' . esc_url( $medium_size_url ) . '">';
// Add fallback image (for smaller screens or if no match for media queries)
$post_thumb .= '<img src="' . esc_url( $full_size_url ) . '" alt="Responsive Background Image" class="responsive-background">';
$post_thumb .= '</picture>';
}
$has_background_image = (2 + 2 == 4) ? 'lcp-has-background-image' : '';
// Output the content wrapped in the div with the random class and padding styles
return $style_tag . sprintf(
'<div class="lcp-container %s">%s</div>',
esc_attr( $random_class ),
$content
'<div class="lcp-dynamic-container %s %s">%s%s</div>',
esc_attr( $random_class ), // The random class
esc_attr( $has_background_image), // Conditionally add 'lcp-has-background-image' class
$post_thumb, // Add the $post_thumb (responsive image) here,
$content // Keep the original content
);
}

View File

@ -1,12 +1,4 @@
import { useBlockProps, InnerBlocks } from '@wordpress/block-editor';
export default function Save() {
// Block props
const blockProps = useBlockProps.save();
return (
<div {...blockProps}>
<InnerBlocks.Content />
</div>
);
import { InnerBlocks } from '@wordpress/block-editor';
export default function save() {
return (<InnerBlocks.Content/>); // No content is saved in the database for dynamic blocks
}

View File

@ -10,3 +10,20 @@
color: #fff;
padding: 2px;
}
.lcp-dynamic-container.lcp-has-background-image {
position:relative;
width:100%;
}
.lcp-dynamic-container.lcp-has-background-image > .lcp-background-image {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover; /* Cover the container like a background */
object-position: center center; /* Center the image */
}

View File

@ -9,9 +9,16 @@
"description": "A dynamic or static gallery based on the Lightgallery javascript plugin",
"example": {},
"supports": {
"html": false
"html": false,
"color": {
"background": true,
"text": false
}
},
"attributes": {
"backgroundColor": {
"type": "string"
},
"parseElementForItems": {
"type": "boolean",
"default": false

View File

@ -125,6 +125,30 @@ function validate_media_ids($input) {
// Return an array of Media IDs
function get_media_ids($attributes) {
// If post_gallery meta field
if (!$attributes['sources'] == "postGallery") {
$post_id = get_the_ID();
$lcp_post_gallery = get_post_meta( $post_id, 'lcp_gallery', true );
// Check if the meta field is not empty and unserialize the value
if ( ! empty( $lcp_post_gallery ) ) {
// Unserialize the meta field value to convert it into an array
$gallery_array = $lcp_post_gallery;
// Initialize an empty array to hold the media IDs
$media_ids = array();
// Loop through the gallery array and extract the media_id values
foreach ( $gallery_array as $item ) {
// Check if the 'media_id' key exists
if ( isset( $item['media_id'] ) ) {
$media_ids[] = $item['media_id']; // Add the media_id to the array
}
}
}
return $media_ids;
}
// Manual Source
if ($attributes['source'] == "manual" && isset($attributes['galleryItems'])) {
// Extract 'id' from each item in the 'galleryItems' array

View File

@ -2,7 +2,10 @@ import { __ } from '@wordpress/i18n';
import {
InspectorControls,
MediaUpload,
MediaUploadCheck
MediaUploadCheck,
useBlockProps,
withColors,
PanelColorSettings
} from '@wordpress/block-editor';
import { useState,
useEffect,
@ -65,9 +68,6 @@ const galleryElements = [
]
// Aspect ratio options
const aspectRatioOptions = [
{ value: '1-1', label: __('1:1', metadata.textdomain) },
@ -125,8 +125,8 @@ const MultiMediaUpload = ({ onSelect }) => {
);
};
export default function Edit(props) {
const { attributes, setAttributes } = props;
function Edit(props) {
const { attributes, setAttributes, backgroundColor, setBackgroundColor } = props;
const {
galleryItems = [],
source,
@ -314,11 +314,17 @@ const { isTemplate, postType, postId } = useSelect((select) => {
togglePlugin('lgZoom', value); // Add/Remove lgZoom plugin based on toggle value
};
const blockProps = useBlockProps({
style: {
backgroundColor: backgroundColor?.color,
},
});
return (
<>
{/* The Gallery */}
<LightGallery {...attributes.lgSettings} />
<LcpGallery {...attributes.lgSettings} />
<InspectorControls>
{/* Settings and Style Tabs */}
@ -717,6 +723,16 @@ const { isTemplate, postType, postId } = useSelect((select) => {
if (name === 'style') {
return (
<PanelBody title={__('Style Settings')}>
<PanelColorSettings
title={__('Color settings', 'lcp')}
colorSettings={[
{
value: backgroundColor?.color,
onChange: setBackgroundColor,
label: __('Background color', 'lcp'),
},
]}
/>
{initialLayout === 'inline' && (
<>
<UnitControl
@ -857,3 +873,4 @@ const { isTemplate, postType, postId } = useSelect((select) => {
);
}
export default withColors('backgroundColor')(Edit);

View File

@ -1 +1 @@
<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-i18n'), 'version' => 'e74f7d37dca7635e59f9');
<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-i18n'), 'version' => '7b19c7f88a697fc64c09');

View File

@ -1 +1 @@
(()=>{"use strict";var e,n={998:()=>{const e=window.wp.blocks,n=window.wp.i18n,t=window.wp.blockEditor,r=window.wp.components,i=window.ReactJSXRuntime,s=JSON.parse('{"UU":"lcp/main-area"}');(0,e.registerBlockType)(s.UU,{edit:function(e){const{attributes:s,setAttributes:a}=e,{maxWidth:o="100%",expandVertical:l=!0}=s,c=(0,t.useBlockProps)(),p=(0,t.useInnerBlocksProps)(c);return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.InspectorControls,{children:(0,i.jsx)(r.PanelBody,{title:(0,n.__)("Max Width Settings","lcp"),initialOpen:!0,children:(0,i.jsxs)("div",{className:"max-width-settings",children:[(0,i.jsx)(r.__experimentalUnitControl,{onChange:e=>{a({maxWidth:e})},value:o,defaultUnit:"px"}),(0,i.jsx)(r.ToggleControl,{label:(0,n.__)("Enable Vertical Expansion","lcp"),checked:l,onChange:e=>{a({expandVertical:e})}})]})})}),(0,i.jsx)("div",{...p,id:"lcp-main-container",style:{minHeight:"200px"},children:(0,i.jsx)(t.InnerBlocks,{...p})})]})},save:function({attributes:e}){const{maxWidth:n="100%",expandVertical:r}=e,s=t.useBlockProps.save(),a=r?`${s.className} lcp-grow-vertical`:s.className,o={maxWidth:n};return(0,i.jsx)("div",{...s,id:"lcp-main-container",className:a,style:o,children:(0,i.jsx)(t.InnerBlocks.Content,{})})}})}},t={};function r(e){var i=t[e];if(void 0!==i)return i.exports;var s=t[e]={exports:{}};return n[e](s,s.exports,r),s.exports}r.m=n,e=[],r.O=(n,t,i,s)=>{if(!t){var a=1/0;for(p=0;p<e.length;p++){t=e[p][0],i=e[p][1],s=e[p][2];for(var o=!0,l=0;l<t.length;l++)(!1&s||a>=s)&&Object.keys(r.O).every((e=>r.O[e](t[l])))?t.splice(l--,1):(o=!1,s<a&&(a=s));if(o){e.splice(p--,1);var c=i();void 0!==c&&(n=c)}}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]=[t,i,s]},r.o=(e,n)=>Object.prototype.hasOwnProperty.call(e,n),(()=>{var e={57:0,350:0};r.O.j=n=>0===e[n];var n=(n,t)=>{var i,s,a=t[0],o=t[1],l=t[2],c=0;if(a.some((n=>0!==e[n]))){for(i in o)r.o(o,i)&&(r.m[i]=o[i]);if(l)var p=l(r)}for(n&&n(t);c<a.length;c++)s=a[c],r.o(e,s)&&e[s]&&e[s][0](),e[s]=0;return r.O(p)},t=self.webpackChunklcp_viewport=self.webpackChunklcp_viewport||[];t.forEach(n.bind(null,0)),t.push=n.bind(null,t.push.bind(t))})();var i=r.O(void 0,[350],(()=>r(998)));i=r.O(i)})();
(()=>{"use strict";var e,n={998:()=>{const e=window.wp.blocks,n=window.wp.i18n,t=window.wp.blockEditor,i=window.wp.components,r=window.ReactJSXRuntime,s=JSON.parse('{"UU":"lcp/main-area"}');(0,e.registerBlockType)(s.UU,{edit:function(e){const{attributes:s,setAttributes:a}=e,{maxWidth:o="100%",expandVertical:l=!0}=s,c=(0,t.useBlockProps)(),p=(0,t.useInnerBlocksProps)(c);return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.InspectorControls,{children:(0,r.jsx)(i.PanelBody,{title:(0,n.__)("Max Width Settings","lcp"),initialOpen:!0,children:(0,r.jsxs)("div",{className:"max-width-settings",children:[(0,r.jsx)(i.__experimentalUnitControl,{onChange:e=>{a({maxWidth:e})},value:o,defaultUnit:"px"}),(0,r.jsx)(i.ToggleControl,{label:(0,n.__)("Enable Vertical Expansion","lcp"),checked:l,onChange:e=>{a({expandVertical:e})}})]})})}),(0,r.jsx)("div",{...p,id:"lcp-main-container",style:{minHeight:"200px"},children:(0,r.jsx)(t.InnerBlocks,{...p})})]})},save:function({attributes:e}){const{maxWidth:n="100%",expandVertical:i}=e,s=t.useBlockProps.save(),a=i?`${s.className} lcp-grow-vertical`:s.className,o={maxWidth:n};return(0,r.jsx)("div",{...s,id:"lcp-main-container",className:a,style:o,children:(0,r.jsx)("div",{id:"lcp-main-container-inner",children:(0,r.jsx)(t.InnerBlocks.Content,{})})})}})}},t={};function i(e){var r=t[e];if(void 0!==r)return r.exports;var s=t[e]={exports:{}};return n[e](s,s.exports,i),s.exports}i.m=n,e=[],i.O=(n,t,r,s)=>{if(!t){var a=1/0;for(p=0;p<e.length;p++){t=e[p][0],r=e[p][1],s=e[p][2];for(var o=!0,l=0;l<t.length;l++)(!1&s||a>=s)&&Object.keys(i.O).every((e=>i.O[e](t[l])))?t.splice(l--,1):(o=!1,s<a&&(a=s));if(o){e.splice(p--,1);var c=r();void 0!==c&&(n=c)}}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]=[t,r,s]},i.o=(e,n)=>Object.prototype.hasOwnProperty.call(e,n),(()=>{var e={57:0,350:0};i.O.j=n=>0===e[n];var n=(n,t)=>{var r,s,a=t[0],o=t[1],l=t[2],c=0;if(a.some((n=>0!==e[n]))){for(r in o)i.o(o,r)&&(i.m[r]=o[r]);if(l)var p=l(i)}for(n&&n(t);c<a.length;c++)s=a[c],i.o(e,s)&&e[s]&&e[s][0](),e[s]=0;return i.O(p)},t=self.webpackChunklcp_viewport=self.webpackChunklcp_viewport||[];t.forEach(n.bind(null,0)),t.push=n.bind(null,t.push.bind(t))})();var r=i.O(void 0,[350],(()=>i(998)));r=i.O(r)})();

View File

@ -16,7 +16,9 @@ export default function Save( { attributes } ) {
return (
<div {...blockProps} id="lcp-main-container" className={className} style={style}>
<div id="lcp-main-container-inner">
<InnerBlocks.Content />
</div>
</div>
);
}

View File

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

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.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)})();
(()=>{"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)("div",{id:"lcp-sidecontent-inner",children:(0,r.jsx)(n.InnerBlocks.Content,{})})})}})}},r={};function o(e){var t=r[e];if(void 0!==t)return t.exports;var i=r[e]={exports:{}};return n[e](i,i.exports,o),i.exports}o.m=n,e=[],o.O=(n,r,t,i)=>{if(!r){var s=1/0;for(p=0;p<e.length;p++){r=e[p][0],t=e[p][1],i=e[p][2];for(var c=!0,l=0;l<r.length;l++)(!1&i||s>=i)&&Object.keys(o.O).every((e=>o.O[e](r[l])))?r.splice(l--,1):(c=!1,i<s&&(s=i));if(c){e.splice(p--,1);var d=t();void 0!==d&&(n=d)}}return n}i=i||0;for(var p=e.length;p>0&&e[p-1][2]>i;p--)e[p]=e[p-1];e[p]=[r,t,i]},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,i,s=r[0],c=r[1],l=r[2],d=0;if(s.some((n=>0!==e[n]))){for(t in c)o.o(c,t)&&(o.m[t]=c[t]);if(l)var p=l(o)}for(n&&n(r);d<s.length;d++)i=s[d],o.o(e,i)&&e[i]&&e[i][0](),e[i]=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 t=o.O(void 0,[350],(()=>o(650)));t=o.O(t)})();

View File

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

View File

@ -1 +1 @@
<?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');
<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => '432795d467d88e7a501f');

View File

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

View File

@ -44,80 +44,16 @@ export default function Edit({ attributes, setAttributes, clientId }) {
}
}, [hasSidecontent, clientId]); // Only runs when `hasSidecontent` or `clientId` changes
// Track block additions and show popup if block is outside the lcp/viewport
useEffect(() => {
const unsubscribe = subscribe(() => {
const blocks = wp.data.select('core/block-editor').getBlocks(); // Get all blocks
// If the popup is ignored, don't check for outside blocks
if (hasIgnoredPopup || blockAdded) return;
// Check if any block added is outside the lcp/viewport (excluding lcp/viewport itself)
const addedBlockOutside = blocks.find((block) => {
if (block.clientId === clientId) {
// Skip the current block (lcp/viewport)
return false;
}
const parent = wp.data.select('core/block-editor').getBlockParents(block.clientId);
// If the block is not inside lcp/viewport or its children, show popup
return !parent.includes(clientId);
});
if (addedBlockOutside) {
setAddedBlock(addedBlockOutside); // Store the added block
setIsPopupVisible(true); // Show the popup if block is outside
setBlockAdded(true); // Mark that a block has been added
}
});
// Cleanup the subscription on component unmount
return () => {
unsubscribe();
};
}, [clientId, hasIgnoredPopup, blockAdded]); // Reset check when block is added or state changes
// Handle the popup close
const closePopup = () => {
// Check if an added block exists
if (addedBlock) {
// Retrieve the parent block (main area)
const mainAreaBlock = wp.data.select('core/block-editor').getBlocks(clientId)
.find(block => block.name === 'lcp/main-area'); // Find the 'lcp/main-area' block
if (mainAreaBlock) {
console.log(mainAreaBlock)
// Insert the block into the 'lcp/main-area'
wp.data.dispatch('core/block-editor').insertBlocks(
addedBlock, // The block to insert
mainAreaBlock.clientId, // Specify the clientId of the main-area block
0 // Insert at the start (index 0) of the main-area block's InnerBlocks
);
}
}
// Close the popup after moving the block
setIsPopupVisible(false);
};
// Handle the "Ignore" button click to dismiss popup and not show again until next block addition
const ignorePopup = () => {
setHasIgnoredPopup(true); // Set the state to indicate the user has ignored the popup
setIsPopupVisible(false); // Close the popup
};
// Reset the "Ignore" state when a new block is added (for the next block addition)
useEffect(() => {
if (blockAdded) {
// Reset ignore state after a new block has been added
setHasIgnoredPopup(false);
}
}, [blockAdded]); // Trigger when blockAdded state changes
// Use useSelect to subscribe to the state of inner blocks
const innerBlocks = useSelect((select) => {
return select('core/block-editor').getBlocks(clientId);
}, [clientId]);
// useEffect to log "Header present" when the lcp/header-container block is found
// useEffect to handle sticky header
useEffect(() => {
const headerBlock = innerBlocks.find((block) => block.name === 'lcp/header-container');
const sidecontentBlock = innerBlocks.find((block) => block.name === 'lcp/header-sidecontent');

View File

@ -47,7 +47,16 @@ function lcp_custom_svgs_field() {
<?php
}
function custom_image_size_settings_page() {
add_options_page(
'Custom Image Sizes', // Page title
'Custom Image Sizes', // Menu title
'manage_options', // Capability
'custom-image-sizes', // Menu slug
'display_custom_image_size_form' // Callback function to display the form
);
}
add_action('admin_menu', 'custom_image_size_settings_page');
@ -241,12 +250,14 @@ function render_lcp_theme_settings_page() {
<h1>Theme Settings</h1>
<!-- Tab Structure -->
<div class="tab-container">
<div class="lcp-tab-container lcp-support-hash">
<!-- Tabs -->
<ul class="tabs">
<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>
<li class="tab-link" data-tab="images">Images</li>
<li class="tab-link" data-tab="misc">Miscellaneous</li>
</ul>
<!-- Tab Panes -->
@ -258,7 +269,7 @@ function render_lcp_theme_settings_page() {
<?php
// Output necessary settings fields for the 'Icons' tab
// This outputs all the fields defined by add_settings_field
mytheme_display_icon_sets();
lcp_display_icon_sets();
?>
@ -300,6 +311,47 @@ function render_lcp_theme_settings_page() {
<?php submit_button(); ?>
</form>
</div>
<div id="images" class="tab-pane">
<h3> Image Sizes </h3>
<div class="lcp-repeater">
<div class="lcp-repeater-row">
<input data-lcp-repeater-key="name" placeholder="Enter Name">
<input type="number" data-lcp-repeater-key="width" data-lcp-required="true" placeholder="Enter Width (pixels)">
<input type="number" data-lcp-repeater-key="height" data-lcp-required-for-new-row="true" placeholder="Enter Height (pixels)">
<label for="crop-toggle">Crop</label>
<input type="checkbox" data-lcp-repeater-key="crop">
</div>
<button class="lcp-button lcp-repeater-add-row" id="add-repeater-row">Add Row</button>
<button class="lcp-button lcp-repeater-submit" data-lcp-action="lcpUpdateImageSizes"id="submit-repeater">Submit Repeater</button>
</div>
</div>
<!-- Misc Settings Tab -->
<div id="misc" class="tab-pane">
<!-- Misc Settings -->
<h2>Miscellaneous Settings</h2>
<!-- Button to trigger the AJAX import demo posts -->
<h3> Demo Posts </h3>
<?php
// Get the 'lcp_demo_posts' option from the database
$demo_posts_data = get_option('lcp_demo_posts', false);
// Check if the lcp_demo_posts option exists
if ($demo_posts_data) {
echo '<span>' . count($demo_posts_data['post_ids']) . ' Demo posts have been imported.</span>';
// If demo posts have been imported, display the "Delete Demo Posts" button (this can be disabled or hidden based on your logic)
echo '<button class="lcp" id="delete-demo-posts" class="button">Delete Demo Posts</button>';
} else {
// If demo posts have NOT been imported, display the "Import Demo Posts" button
echo '<button class="lcp" id="import-demo-posts" class="button button-primary" >Import Demo Posts</button>';
}
?>
</div>
</div>
</div>
@ -321,23 +373,4 @@ 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());
// Echo highlight-to-share markup and enqueue javascript
// Highlight-to-share css is already in style.css
if ( isset($options['enable_highlight_to_share']) && $options['enable_highlight_to_share'] ) {
highlight_to_share_popup();
wp_enqueue_script( 'lcp-highlight-to-share', get_template_directory_uri() . '/assets/js/highlight-to-share.js', array(), null, true );
}
}
add_action('wp_head', 'lcp_wp_head_hooks');
/* ICONS */

View File

@ -1,15 +1,112 @@
<?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);
}
function lcp_theme_deactivate() {
lcp_delete_demo_posts();
}
// Register the function to run when the theme is switched (deactivated)
add_action('switch_theme', 'lcp_theme_deactivate');
// Add the action hook to run the function when the theme is activated
add_action('after_switch_theme', 'lcp_activate');
function lcp_enqueue_dashboard_scripts($hook) {
// Only load the script on the icon-management page
// Enqueue JavaScript for AJAX
wp_enqueue_script(
'icon-import-script',
get_template_directory_uri() . '/assets/js/icon-import.js',
array(), // No dependencies for vanilla JS
null,
true
);
// Pass the AJAX URL to the script
wp_localize_script('icon-import-script', 'lcp_ajax', array(
'ajax_url' => admin_url('admin-ajax.php')
));
}
add_action('admin_enqueue_scripts', 'lcp_enqueue_dashboard_scripts');
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');
wp_enqueue_script('lcp-ui', get_template_directory_uri() . '/assets/js/lcp-ui.js');
// Enqueue custom script to handle the Demo post import AJAX request
wp_enqueue_script('lcp-import-demo-posts-ajax', get_template_directory_uri() . '/assets/js/demo-posts-import.js', array(), null, true);
// Add the AJAX URL and nonce as JavaScript variables
wp_localize_script('lcp-import-demo-posts-ajax', 'lcp_ajax_obj', array(
'ajax_url' => admin_url('admin-ajax.php'), // This is the URL that well send the AJAX request to
'nonce' => wp_create_nonce('lcp_import_demo_posts_nonce') // Security nonce for validation
));
/* --- Image Sizes --- */
// Enqueue the JavaScript file
wp_enqueue_script('custom-image-sizes', get_template_directory_uri() . '/assets/js/custom-image-sizes.js', array(), null, true);
// Localize script to pass the nonce and ajaxurl to JavaScript
wp_localize_script('custom-image-sizes', 'customImageSizeAjax', array(
'ajax_url' => admin_url('admin-ajax.php'), // The URL to send the request to
'nonce' => wp_create_nonce('custom_image_sizes_nonce') // Create the nonce and pass it
));
}
add_action('admin_enqueue_scripts', 'lcp_backend_enqueue');
function lcp_send_headers_hooks(){
lcp_set_visited_posts_cookie();
}
add_action('send_headers','lcp_send_headers_hooks');
function lcp_after_setup_theme() {
lcp_register_custom_image_sizes();
}
add_action('after_setup_theme', 'lcp_after_setup_theme');
function lcp_init_hooks() {
lcp_register_pattern_categories();
lcp_register_patterns();
}
add_action('init', 'lcp_init_hooks');
// Register pattern categories
function lcp_register_pattern_categories() {
register_block_pattern_category( 'lcp/customss', array(
'label' => __( 'Theme Name: Local Content Pro', 'lcp' ),
'description' => __( 'Custom patterns for Local Content Pro.', 'lcp' )
) );
}
// Register block pattern
function lcp_register_patterns() {
register_block_pattern(
'lcp/post-content', // Unique slug
array(
'title' => __( 'Post Content', 'lcp' ),
'description' => __( 'A pattern for displaying post content', 'lcp' ),
'content' => file_get_contents( get_template_directory() . '/patterns/post-content.php' ),
)
);
}

1
parts/footer.html Normal file
View File

@ -0,0 +1 @@
<!-- wp:pattern {"slug":"twentytwentyfive/footer"} /-->

1
parts/header.html Normal file
View File

@ -0,0 +1 @@
<!-- wp:pattern {"slug":"twentytwentyfive/header"} /-->

27
patterns/post-content.php Normal file
View File

@ -0,0 +1,27 @@
<?php
/**
* Title: Post Content
* Slug: twentytwentyfive/banner-about-book
* Categories: banner
* Description: Banner with book description and accompanying image for promotion.
*
* @package WordPress
* @subpackage Twenty_Twenty_Five
* @since Twenty Twenty-Five 1.0
*/
?>
<!-- wp:comment-author-name {"fontSize":"small"} /-->
<!-- wp:group {"style":{"spacing":{"margin":{"top":"0px","bottom":"0px"}}},"layout":{"type":"flex"}} -->
<div class="wp-block-group" style="margin-top:0px;margin-bottom:0px">
<!-- wp:comment-date {"fontSize":"small"} /-->
<!-- wp:comment-edit-link {"fontSize":"small"} /-->
</div>
<!-- /wp:group -->
<!-- wp:comment-content /-->
<!-- wp:comment-reply-link {"fontSize":"small"} /-->

View File

@ -1,14 +0,0 @@
<?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

@ -2,9 +2,12 @@
Theme Name: Local Content Pro
Theme URI: https://localcontentpro.com
Description: A simple Block Theme for local content publishers.
Version: 1.0
Version: 0.0.1
*/
/* Main */
.lcp {display:block}
/* Main viewport container */
#lcp-viewport-outer {
overflow: hidden; /* Hide overflow */
@ -38,7 +41,7 @@ Version: 1.0
/* Main Content */
.lcp-has-sidecontent #lcp-main-container > * > *{ padding:20px
.lcp-has-sidecontent #lcp-main-container > *{ padding-left:40px
}
@ -50,15 +53,23 @@ Version: 1.0
overflow:auto;
position: absolute;
left: 0;
top: 0;
width: 340px;
height: 100%;
height: calc(100vh - var(--lcp--header--height));
background: #fff;
border-right: 2px solid #eee;
z-index: 2;
outline: 0;
}
}
#lcp-sidecontent #lcp-sidecontent-inner {
padding:10px
}
.admin-bar #lcp-sidecontent {
height:calc(100vh - var(--lcp--header--height) - 32px)
}
#lcp-sidecontent:not(.lcp-fixed) {
top:0
}
#lcp-viewport-outer.lcp-has-sticky-header #lcp-sidecontent {
top: var(--lcp--header--height);
position:fixed!important;
@ -113,10 +124,10 @@ Version: 1.0
width: 100%
}
#lcp-sidecontent {top:var(--lcp---header--height)}
#lcp-sidecontent {
#lcp-sidecontent:not(.lcp-fixed) {
top: calc(var(--lcp--header--height) );
}
.admin-bar #lcp-sidecontent.lcp-fixed {
#lcp-viewport-outer:not(.lcp-has-sticky-header).admin-bar #lcp-sidecontent.lcp-fixed {
top: calc(var(--lcp--header--height) + 32px);
}
@ -127,7 +138,12 @@ Version: 1.0
right: 0;
z-index: 3;
}
#lcp-header-sidecontent.lcp-fixed {
height:100vh
}
.admin-bar #lcp-sidecontent.lcp-fixed {
height:calc(100vh - 32px)
}
#lcp-header-container.lcp-sticky-on-scroll.lcp-fixed {
position: fixed;
top:32px;
@ -303,3 +319,12 @@ Version: 1.0
display: block;
}
#lcp-sidecontent {
scrollbar-color: red orange;
scrollbar-width: thin;
border-radius:5px
}

View File

@ -5,6 +5,7 @@
],
"settings": {
"appearanceTools": true,
"color": {
"defaultDuotone": false,
@ -43,18 +44,23 @@
},
{
"color": "#00E080",
"name": "Accent",
"slug": "accent"
"name": "Accent - 1",
"slug": "accent-1"
},
{
"color": "#00FC90",
"name": "Accent 2",
"slug": "accent-2"
"name": "Accent Light - 1",
"slug": "accent-light-1"
},
{
"color": "#232323",
"name": "Font 1",
"slug": "font-color-1"
},
{
"color": "#a0a0a0",
"name": "Font Light 1",
"slug": "font-light-1"
}
]
},
@ -200,6 +206,7 @@
"useRootPaddingAwareAlignments": true
},
"styles": {
"color": {
"background": "var:preset|color|base",
"text": "var:preset|color|contrast"
@ -213,7 +220,7 @@
},
"typography": {
"fontFamily": "var:preset|font-family|manrope",
"fontSize": "var:preset|font-size|large",
"fontSize": "var:preset|font-size|medium",
"fontWeight": "300",
"letterSpacing": "-0.1px",
"lineHeight": "1.4"

View File

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