changes to blocks and styles

This commit is contained in:
Jeremy Rangel
2024-12-27 22:56:39 -08:00
parent 93cc7be3bf
commit 462cffdddc
39 changed files with 959 additions and 228 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -55,4 +55,62 @@ document.addEventListener('DOMContentLoaded', function() {
});
});
});
});
});
// REPEATERS
// Example html:
// <div class="my-repeater-container">
// <div class="my-repeater-row">
// <input type="text" name="field_1[]">
// <input type="text" name="field_2[]">
// <input type="text" name="field_3[]">
//<button class="delete-repeater-row">Delete Row</button>
//</div>
//<button class="new-repeater-row">Click to add a new row</button>
//</div>
document.addEventListener('DOMContentLoaded', function () {
// Get all repeater containers
const repeaterContainers = document.querySelectorAll('.my-repeater-container');
// Loop through each repeater container and initialize the functionality
repeaterContainers.forEach(function (container) {
const newRowButton = container.querySelector('.new-repeater-row');
const rowTemplate = container.querySelector('.my-repeater-row');
// Hide the row template (we will clone it)
rowTemplate.style.display = 'none';
// Add event listener for the 'Add New Row' button
newRowButton.addEventListener('click', function () {
// Clone the row template
const newRow = rowTemplate.cloneNode(true);
// Make sure the new row is visible
newRow.style.display = 'flex'; // or 'block' based on your layout
// Reset input values in the new row
const inputs = newRow.querySelectorAll('input');
inputs.forEach(input => input.value = '');
// Add the new row to the repeater container
container.insertBefore(newRow, newRowButton);
});
// Handle deleting rows
container.addEventListener('click', function (e) {
if (e.target && e.target.classList.contains('delete-repeater-row')) {
const rowToDelete = e.target.closest('.my-repeater-row');
if (rowToDelete) {
rowToDelete.remove();
}
}
});
});
});

View File

@ -0,0 +1,71 @@
document.addEventListener("DOMContentLoaded", function () {
// Get reference to the popup element
const popup = document.getElementById('popup');
const facebookShareLink = document.getElementById('facebook-share');
const twitterShareLink = document.getElementById('twitter-share');
// Function to check if selection intersects with any <p> tag
function isSelectionInParagraph(selection) {
const range = selection.getRangeAt(0); // Get the selected range
const paragraphs = document.querySelectorAll('p'); // Get all <p> elements
for (let p of paragraphs) {
// Check if the selected range intersects with this <p> tag
const pRect = p.getBoundingClientRect();
const rangeRect = range.getBoundingClientRect();
// Check if the range and the <p> element's bounding boxes overlap
if (rangeRect.top < pRect.bottom && rangeRect.bottom > pRect.top &&
rangeRect.left < pRect.right && rangeRect.right > pRect.left) {
return true; // Selection intersects with this <p> tag
}
}
return false; // No intersection with any <p> tag
}
// Function to show the popup near the selected text
function showPopup(e) {
const selection = window.getSelection();
// Check if any text is selected and if it is inside or intersects with a <p> tag
if (selection.toString().length > 0 && isSelectionInParagraph(selection)) {
// Get the bounding rectangle of the selected text
const range = selection.getRangeAt(0);
const rect = range.getBoundingClientRect();
// Position the popup above the selection (adjust for spacing)
popup.style.left = `${rect.left + window.scrollX}px`;
popup.style.top = `${rect.top + window.scrollY - popup.offsetHeight - 5}px`;
// Show the popup
popup.style.display = 'block';
// Set up share links with the selected text and page URL
const selectedText = selection.toString();
const pageUrl = window.location.href;
// Facebook share link
facebookShareLink.setAttribute('href', `https://www.facebook.com/sharer/sharer.php?u=${encodeURIComponent(pageUrl)}&quote=${encodeURIComponent(selectedText)}`);
// Twitter/X share link
twitterShareLink.setAttribute('href', `https://twitter.com/intent/tweet?text=${encodeURIComponent(selectedText)}&url=${encodeURIComponent(pageUrl)}`);
} else {
// Hide the popup if no text is selected or it's not inside or overlapping a <p> tag
popup.style.display = 'none';
}
}
// Listen for mouse-up event (when selection ends)
document.addEventListener('mouseup', showPopup);
// Optionally, listen for touchend event for mobile devices
document.addEventListener('touchend', showPopup);
// Hide the popup if user clicks anywhere else
document.addEventListener('click', function(event) {
if (!popup.contains(event.target) && !window.getSelection().toString()) {
popup.style.display = 'none';
}
});
});

23
assets/json/icons.json Normal file
View File

@ -0,0 +1,23 @@
[
{
"family": "Font Awesome",
"svgs": [
{
"id": "comment-dots",
"name": "Comment Dots",
"path": "<path d='M168.2 384.9c-15-5.4-31.7-3.1-44.6 6.4c-8.2 6-22.3 14.8-39.4 22.7c5.6-14.7 9.9-31.3 11.3-49.4c1-12.9-3.3-25.7-11.8-35.5C60.4 302.8 48 272 48 240c0-79.5 83.3-160 208-160s208 80.5 208 160s-83.3 160-208 160c-31.6 0-61.3-5.5-87.8-15.1zM26.3 423.8c-1.6 2.7-3.3 5.4-5.1 8.1l-.3 .5c-1.6 2.3-3.2 4.6-4.8 6.9c-3.5 4.7-7.3 9.3-11.3 13.5c-4.6 4.6-5.9 11.4-3.4 17.4c2.5 6 8.3 9.9 14.8 9.9c5.1 0 10.2-.3 15.3-.8l.7-.1c4.4-.5 8.8-1.1 13.2-1.9c.8-.1 1.6-.3 2.4-.5c17.8-3.5 34.9-9.5 50.1-16.1c22.9-10 42.4-21.9 54.3-30.6c31.8 11.5 67 17.9 104.1 17.9c141.4 0 256-93.1 256-208S397.4 32 256 32S0 125.1 0 240c0 45.1 17.7 86.8 47.7 120.9c-1.9 24.5-11.4 46.3-21.4 62.9zM144 272a32 32 0 1 0 0-64 32 32 0 1 0 0 64zm144-32a32 32 0 1 0 -64 0 32 32 0 1 0 64 0zm80 32a32 32 0 1 0 0-64 32 32 0 1 0 0 64z'/>"
},
{
"id": "newspaper",
"name": "Newspaper",
"path": "<path d='M168 80c-13.3 0-24 10.7-24 24l0 304c0 8.4-1.4 16.5-4.1 24L440 432c13.3 0 24-10.7 24-24l0-304c0-13.3-10.7-24-24-24L168 80zM72 480c-39.8 0-72-32.2-72-72L0 112C0 98.7 10.7 88 24 88s24 10.7 24 24l0 296c0 13.3 10.7 24 24 24s24-10.7 24-24l0-304c0-39.8 32.2-72 72-72l272 0c39.8 0 72 32.2 72 72l0 304c0 39.8-32.2 72-72 72L72 480zM176 136c0-13.3 10.7-24 24-24l96 0c13.3 0 24 10.7 24 24l0 80c0 13.3-10.7 24-24 24l-96 0c-13.3 0-24-10.7-24-24l0-80zm200-24l32 0c13.3 0 24 10.7 24 24s-10.7 24-24 24l-32 0c-13.3 0-24-10.7-24-24s10.7-24 24-24zm0 80l32 0c13.3 0 24 10.7 24 24s-10.7 24-24 24l-32 0c-13.3 0-24-10.7-24-24s10.7-24 24-24zM200 272l208 0c13.3 0 24 10.7 24 24s-10.7 24-24 24l-208 0c-13.3 0-24-10.7-24-24s10.7-24 24-24zm0 80l208 0c13.3 0 24 10.7 24 24s-10.7 24-24 24l-208 0c-13.3 0-24-10.7-24-24s10.7-24 24-24z'/>"
},
{
"id": "map",
"name": "Map",
"path": "<path d='M565.6 36.2C572.1 40.7 576 48.1 576 56l0 336c0 10-6.2 18.9-15.5 22.4l-168 64c-5.2 2-10.9 2.1-16.1 .3L192.5 417.5l-160 61c-7.4 2.8-15.7 1.8-22.2-2.7S0 463.9 0 456L0 120c0-10 6.1-18.9 15.5-22.4l168-64c5.2-2 10.9-2.1 16.1-.3L383.5 94.5l160-61c7.4-2.8 15.7-1.8 22.2 2.7zM48 136.5l0 284.6 120-45.7 0-284.6L48 136.5zM360 422.7l0-285.4-144-48 0 285.4 144 48zm48-1.5l120-45.7 0-284.6L408 136.5l0 284.6z'/>"
}
]
}
]

View File

@ -158,19 +158,3 @@ add_action('save_post', 'save_key_points_meta_box');
// Hook into wp_footer to add the login form in the footer

View File

@ -1,52 +1,66 @@
import { useState, useEffect } from 'react';
import { __ } from '@wordpress/i18n';
import { SelectControl } from '@wordpress/components';
export function IconSelectControl(props) {
const { iconSvgId, onIconChange } = props;
// Hardcoded icon data
const iconData = [
{
"uuid": "c0a8012345678f3d5b847ad0f8a890f1",
"iconId": "comment-dots",
"family": "Font Awesome",
"sub-family": "solid",
"name": "Comment Dots",
"path": "<path d='M168.2 384.9c-15-5.4-31.7-3.1-44.6 6.4c-8.2 6-22.3 14.8-39.4 22.7c5.6-14.7 9.9-31.3 11.3-49.4c1-12.9-3.3-25.7-11.8-35.5C60.4 302.8 48 272 48 240c0-79.5 83.3-160 208-160s208 80.5 208 160s-83.3 160-208 160c-31.6 0-61.3-5.5-87.8-15.1zM26.3 423.8c-1.6 2.7-3.3 5.4-5.1 8.1l-.3 .5c-1.6 2.3-3.2 4.6-4.8 6.9c-3.5 4.7-7.3 9.3-11.3 13.5c-4.6 4.6-5.9 11.4-3.4 17.4c2.5 6 8.3 9.9 14.8 9.9c5.1 0 10.2-.3 15.3-.8l.7-.1c4.4-.5 8.8-1.1 13.2-1.9c.8-.1 1.6-.3 2.4-.5c17.8-3.5 34.9-9.5 50.1-16.1c22.9-10 42.4-21.9 54.3-30.6c31.8 11.5 67 17.9 104.1 17.9c141.4 0 256-93.1 256-208S397.4 32 256 32S0 125.1 0 240c0 45.1 17.7 86.8 47.7 120.9c-1.9 24.5-11.4 46.3-21.4 62.9zM144 272a32 32 0 1 0 0-64 32 32 0 1 0 0 64zm144-32a32 32 0 1 0 -64 0 32 32 0 1 0 64 0zm80 32a32 32 0 1 0 0-64 32 32 0 1 0 0 64z'/>"
},
{
"uuid": "a1b2c3d4e5f6789abcdef0123456789ab",
"iconId": "newspaper",
"family": "Font Awesome",
"sub-family": "solid",
"name": "Newspaper",
"path": "<path d='M168 80c-13.3 0-24 10.7-24 24l0 304c0 8.4-1.4 16.5-4.1 24L440 432c13.3 0 24-10.7 24-24l0-304c0-13.3-10.7-24-24-24L168 80zM72 480c-39.8 0-72-32.2-72-72L0 112C0 98.7 10.7 88 24 88s24 10.7 24 24l0 296c0 13.3 10.7 24 24 24s24-10.7 24-24l0-304c0-39.8 32.2-72 72-72l272 0c39.8 0 72 32.2 72 72l0 304c0 39.8-32.2 72-72 72L72 480zM176 136c0-13.3 10.7-24 24-24l96 0c13.3 0 24 10.7 24 24l0 80c0 13.3-10.7 24-24 24l-96 0c-13.3 0-24-10.7-24-24l0-80zm200-24l32 0c13.3 0 24 10.7 24 24s-10.7 24-24 24l-32 0c-13.3 0-24-10.7-24-24s10.7-24 24-24zm0 80l32 0c13.3 0 24 10.7 24 24s-10.7 24-24 24l-32 0c-13.3 0-24-10.7-24-24s10.7-24 24-24zM200 272l208 0c13.3 0 24 10.7 24 24s-10.7 24-24 24l-208 0c-13.3 0-24-10.7-24-24s10.7-24 24-24zm0 80l208 0c13.3 0 24 10.7 24 24s-10.7 24-24 24l-208 0c-13.3 0-24-10.7-24-24s10.7-24 24-24z'/>"
}
];
const [iconData, setIconData] = useState([]);
useEffect(() => {
const fetchIconData = async () => {
try {
const response = await fetch('/wp-content/themes/local-content-pro/assets/json/icons.json');
const data = await response.json();
if (data && data.length > 0) {
setIconData(data[0].svgs); // Assuming the structure is correct
}
} catch (error) {
console.error('Error fetching icons:', error);
}
};
fetchIconData();
}, []);
// Handle icon selection from dropdown
const handleIconChange = (selectedIconId) => {
const selectedIcon = iconData.find(icon => icon.uuid === selectedIconId);
const selectedIcon = iconData.find(icon => icon.id === selectedIconId);
if (selectedIcon && onIconChange) {
// Send both icon ID and path (SVG) to the parent component
onIconChange({
iconSvgId: selectedIconId, // UUID of the selected icon
iconSvgPath: selectedIcon.path // SVG path of the selected icon
iconSvgId: selectedIcon.id, // Pass icon ID to parent
iconSvgPath: selectedIcon.path // Pass icon path (SVG) to parent
});
console.log("Selected Icon ID:", selectedIcon.id); // Debugging output
console.log("Selected Icon Path:", selectedIcon.path); // Debugging output
}
};
if (iconData.length === 0) {
return <p>{__('Loading icons...', 'lcp')}</p>; // Loading state
}
const iconOptions = iconData.map((icon) => ({
value: icon.id, // Use icon ID as value for the SelectControl
label: (
<div style={{ display: 'flex', alignItems: 'center' }}>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox={icon.viewBox || "0 0 512 512"} // Default viewBox if not present
style={{ width: '20px', height: '20px' }} // Control icon size
dangerouslySetInnerHTML={{ __html: icon.path }} // Insert SVG path
/>
<span style={{ marginLeft: '8px' }}>{icon.name}</span> {/* Show icon name */}
</div>
),
}));
return (
<>
<SelectControl
label={__("Select Icon")}
value={iconSvgId}
options={iconData.map((icon) => ({
label: icon.name,
value: icon.uuid, // Store the UUID as the value
}))}
onChange={handleIconChange}
/>
</>
<SelectControl
label={__('Select Icon', 'lcp')}
value={iconSvgId} // Current selected icon ID
options={iconOptions}
onChange={handleIconChange} // Handle icon change
/>
);
}

View File

@ -1,18 +0,0 @@
[
{
"uuid": "c0a8012345678f3d5b847ad0f8a890f1",
"iconId": "comment-dots",
"family": "Font Awesome",
"sub-family": "solid",
"name": "Comment Dots",
"path": "<path d='M168.2 384.9c-15-5.4-31.7-3.1-44.6 6.4c-8.2 6-22.3 14.8-39.4 22.7c5.6-14.7 9.9-31.3 11.3-49.4c1-12.9-3.3-25.7-11.8-35.5C60.4 302.8 48 272 48 240c0-79.5 83.3-160 208-160s208 80.5 208 160s-83.3 160-208 160c-31.6 0-61.3-5.5-87.8-15.1zM26.3 423.8c-1.6 2.7-3.3 5.4-5.1 8.1l-.3 .5c-1.6 2.3-3.2 4.6-4.8 6.9c-3.5 4.7-7.3 9.3-11.3 13.5c-4.6 4.6-5.9 11.4-3.4 17.4c2.5 6 8.3 9.9 14.8 9.9c5.1 0 10.2-.3 15.3-.8l.7-.1c4.4-.5 8.8-1.1 13.2-1.9c.8-.1 1.6-.3 2.4-.5c17.8-3.5 34.9-9.5 50.1-16.1c22.9-10 42.4-21.9 54.3-30.6c31.8 11.5 67 17.9 104.1 17.9c141.4 0 256-93.1 256-208S397.4 32 256 32S0 125.1 0 240c0 45.1 17.7 86.8 47.7 120.9c-1.9 24.5-11.4 46.3-21.4 62.9zM144 272a32 32 0 1 0 0-64 32 32 0 1 0 0 64zm144-32a32 32 0 1 0 -64 0 32 32 0 1 0 64 0zm80 32a32 32 0 1 0 0-64 32 32 0 1 0 0 64z'/>"
},
{
"uuid": "a1b2c3d4e5f6789abcdef0123456789ab",
"iconId": "newspaper",
"family": "Font Awesome",
"sub-family": "solid",
"name": "Newspaper",
"path": "<path d='M168 80c-13.3 0-24 10.7-24 24l0 304c0 8.4-1.4 16.5-4.1 24L440 432c13.3 0 24-10.7 24-24l0-304c0-13.3-10.7-24-24-24L168 80zM72 480c-39.8 0-72-32.2-72-72L0 112C0 98.7 10.7 88 24 88s24 10.7 24 24l0 296c0 13.3 10.7 24 24 24s24-10.7 24-24l0-304c0-39.8 32.2-72 72-72l272 0c39.8 0 72 32.2 72 72l0 304c0 39.8-32.2 72-72 72L72 480zM176 136c0-13.3 10.7-24 24-24l96 0c13.3 0 24 10.7 24 24l0 80c0 13.3-10.7 24-24 24l-96 0c-13.3 0-24-10.7-24-24l0-80zm200-24l32 0c13.3 0 24 10.7 24 24s-10.7 24-24 24l-32 0c-13.3 0-24-10.7-24-24s10.7-24 24-24zm0 80l32 0c13.3 0 24 10.7 24 24s-10.7 24-24 24l-32 0c-13.3 0-24-10.7-24-24s10.7-24 24-24zM200 272l208 0c13.3 0 24 10.7 24 24s-10.7 24-24 24l-208 0c-13.3 0-24-10.7-24-24s10.7-24 24-24zm0 80l208 0c13.3 0 24 10.7 24 24s-10.7 24-24 24l-208 0c-13.3 0-24-10.7-24-24s10.7-24 24-24z'/>"
}
]

View File

@ -1,23 +0,0 @@
[
{
"id": "comment-dots",
"family": "Font Awesome",
"sub-family": "solid",
"name": "Comment Dots",
"path": "<path d='M168.2 384.9c-15-5.4-31.7-3.1-44.6 6.4c-8.2 6-22.3 14.8-39.4 22.7c5.6-14.7 9.9-31.3 11.3-49.4c1-12.9-3.3-25.7-11.8-35.5C60.4 302.8 48 272 48 240c0-79.5 83.3-160 208-160s208 80.5 208 160s-83.3 160-208 160c-31.6 0-61.3-5.5-87.8-15.1zM26.3 423.8c-1.6 2.7-3.3 5.4-5.1 8.1l-.3 .5c-1.6 2.3-3.2 4.6-4.8 6.9c-3.5 4.7-7.3 9.3-11.3 13.5c-4.6 4.6-5.9 11.4-3.4 17.4c2.5 6 8.3 9.9 14.8 9.9c5.1 0 10.2-.3 15.3-.8l.7-.1c4.4-.5 8.8-1.1 13.2-1.9c.8-.1 1.6-.3 2.4-.5c17.8-3.5 34.9-9.5 50.1-16.1c22.9-10 42.4-21.9 54.3-30.6c31.8 11.5 67 17.9 104.1 17.9c141.4 0 256-93.1 256-208S397.4 32 256 32S0 125.1 0 240c0 45.1 17.7 86.8 47.7 120.9c-1.9 24.5-11.4 46.3-21.4 62.9zM144 272a32 32 0 1 0 0-64 32 32 0 1 0 0 64zm144-32a32 32 0 1 0 -64 0 32 32 0 1 0 64 0zm80 32a32 32 0 1 0 0-64 32 32 0 1 0 0 64z'/>"
},
{
"id": "newspaper",
"family": "Font Awesome",
"sub-family": "solid",
"name": "Newspaper",
"path": "<path d='M168 80c-13.3 0-24 10.7-24 24l0 304c0 8.4-1.4 16.5-4.1 24L440 432c13.3 0 24-10.7 24-24l0-304c0-13.3-10.7-24-24-24L168 80zM72 480c-39.8 0-72-32.2-72-72L0 112C0 98.7 10.7 88 24 88s24 10.7 24 24l0 296c0 13.3 10.7 24 24 24s24-10.7 24-24l0-304c0-39.8 32.2-72 72-72l272 0c39.8 0 72 32.2 72 72l0 304c0 39.8-32.2 72-72 72L72 480zM176 136c0-13.3 10.7-24 24-24l96 0c13.3 0 24 10.7 24 24l0 80c0 13.3-10.7 24-24 24l-96 0c-13.3 0-24-10.7-24-24l0-80zm200-24l32 0c13.3 0 24 10.7 24 24s-10.7 24-24 24l-32 0c-13.3 0-24-10.7-24-24s10.7-24 24-24zm0 80l32 0c13.3 0 24 10.7 24 24s-10.7 24-24 24l-32 0c-13.3 0-24-10.7-24-24s10.7-24 24-24zM200 272l208 0c13.3 0 24 10.7 24 24s-10.7 24-24 24l-208 0c-13.3 0-24-10.7-24-24s10.7-24 24-24zm0 80l208 0c13.3 0 24 10.7 24 24s-10.7 24-24 24l-208 0c-13.3 0-24-10.7-24-24s10.7-24 24-24z'/>"
},
{
"id": "map",
"family": "Font Awesome",
"sub-family": "solid",
"name": "Map",
"path": "<path d='M565.6 36.2C572.1 40.7 576 48.1 576 56l0 336c0 10-6.2 18.9-15.5 22.4l-168 64c-5.2 2-10.9 2.1-16.1 .3L192.5 417.5l-160 61c-7.4 2.8-15.7 1.8-22.2-2.7S0 463.9 0 456L0 120c0-10 6.1-18.9 15.5-22.4l168-64c5.2-2 10.9-2.1 16.1-.3L383.5 94.5l160-61c7.4-2.8 15.7-1.8 22.2 2.7zM48 136.5l0 284.6 120-45.7 0-284.6L48 136.5zM360 422.7l0-285.4-144-48 0 285.4 144 48zm48-1.5l120-45.7 0-284.6L408 136.5l0 284.6z'/>"
}
]

View File

@ -9,13 +9,24 @@
"description": "Example block scaffolded with Create Block tool.",
"example": {},
"supports": {
"html": false
"html": false,
"color": {
"background": true,
"link": true,
"text": true,
"gradients": true,
"button": true
}
},
"attributes": {
"buttonFunction": {
"buttonAction": {
"type": "string",
"default": "customUrl"
},
"customUrl": {
"type": "string",
"default": "#"
},
"buttonText": {
"type": "string",
"default": "Button Text"
@ -25,7 +36,7 @@
},
"iconSource": {
"type": "string",
"default": "svgPath"
"default": "manualSvgPath"
},
"iconSvgPath": {
"type": "string"
@ -36,9 +47,12 @@
},
"popUpId": {
"type": "number"
},
"manualIconSvgPath":{
"type": "string"
}
},
"textdomain": "button",
"textdomain": "lcp",
"editorScript": "file:./index.js",
"editorStyle": "file:./index.css",
"style": "file:./style-index.css",

View File

@ -3,95 +3,60 @@ import { useBlockProps, InspectorControls } from '@wordpress/block-editor';
import { PanelBody, SelectControl, TextControl, TextareaControl, ToggleControl } from '@wordpress/components';
import { useState, useEffect } from '@wordpress/element';
import './editor.scss';
import { useSelect } from '@wordpress/data';
import { IconSelectControl } from '../components/IconSelectControl';
// Sample JSON data for icons (with UUIDs)
const iconData = [
{
"uuid": "c0a8012345678f3d5b847ad0f8a890f1",
"iconId": "comment-dots",
"family": "Font Awesome",
"sub-family": "solid",
"name": "Comment Dots",
"path": "<path d='M168.2 384.9c-15-5.4-31.7-3.1-44.6 6.4c-8.2 6-22.3 14.8-39.4 22.7c5.6-14.7 9.9-31.3 11.3-49.4c1-12.9-3.3-25.7-11.8-35.5C60.4 302.8 48 272 48 240c0-79.5 83.3-160 208-160s208 80.5 208 160s-83.3 160-208 160c-31.6 0-61.3-5.5-87.8-15.1zM26.3 423.8c-1.6 2.7-3.3 5.4-5.1 8.1l-.3 .5c-1.6 2.3-3.2 4.6-4.8 6.9c-3.5 4.7-7.3 9.3-11.3 13.5c-4.6 4.6-5.9 11.4-3.4 17.4c2.5 6 8.3 9.9 14.8 9.9c5.1 0 10.2-.3 15.3-.8l.7-.1c4.4-.5 8.8-1.1 13.2-1.9c.8-.1 1.6-.3 2.4-.5c17.8-3.5 34.9-9.5 50.1-16.1c22.9-10 42.4-21.9 54.3-30.6c31.8 11.5 67 17.9 104.1 17.9c141.4 0 256-93.1 256-208S397.4 32 256 32S0 125.1 0 240c0 45.1 17.7 86.8 47.7 120.9c-1.9 24.5-11.4 46.3-21.4 62.9zM144 272a32 32 0 1 0 0-64 32 32 0 1 0 0 64zm144-32a32 32 0 1 0 -64 0 32 32 0 1 0 64 0zm80 32a32 32 0 1 0 0-64 32 32 0 1 0 0 64z'/>"
},
{
"uuid": "a1b2c3d4e5f6789abcdef0123456789ab",
"iconId": "newspaper",
"family": "Font Awesome",
"sub-family": "solid",
"name": "Newspaper",
"path": "<path d='M168 80c-13.3 0-24 10.7-24 24l0 304c0 8.4-1.4 16.5-4.1 24L440 432c13.3 0 24-10.7 24-24l0-304c0-13.3-10.7-24-24-24L168 80zM72 480c-39.8 0-72-32.2-72-72L0 112C0 98.7 10.7 88 24 88s24 10.7 24 24l0 296c0 13.3 10.7 24 24 24s24-10.7 24-24l0-304c0-39.8 32.2-72 72-72l272 0c39.8 0 72 32.2 72 72l0 304c0 39.8-32.2 72-72 72L72 480zM176 136c0-13.3 10.7-24 24-24l96 0c13.3 0 24 10.7 24 24l0 80c0 13.3-10.7 24-24 24l-96 0c-13.3 0-24-10.7-24-24l0-80zm200-24l32 0c13.3 0 24 10.7 24 24s-10.7 24-24 24l-32 0c-13.3 0-24-10.7-24-24s10.7-24 24-24zm0 80l32 0c13.3 0 24 10.7 24 24s-10.7 24-24 24l-32 0c-13.3 0-24-10.7-24-24s10.7-24 24-24zM200 272l208 0c13.3 0 24 10.7 24 24s-10.7 24-24 24l-208 0c-13.3 0-24-10.7-24-24s10.7-24 24-24zm0 80l208 0c13.3 0 24 10.7 24 24s-10.7 24-24 24l-208 0c-13.3 0-24-10.7-24-24s10.7-24 24-24z'/>"
}
];
export default function Edit(props) {
const { attributes, setAttributes } = props;
const { buttonFunction, popUpId, buttonText, iconSvgId, iconSvgPath, displayIcon, iconSource} = attributes; // iconSvgId holds the UUID and iconSvgPath holds the SVG path
const [popups, setPopups] = useState([]);
// Fetch published popups (lcp-popup CPT)
useEffect(() => {
const fetchPopups = async () => {
const response = await fetch('/wp-json/wp/v2/lcp-popup');
const data = await response.json();
setPopups(data);
};
fetchPopups();
}, []);
const { buttonAction, buttonText, iconSvgId, iconSvgPath, displayIcon, iconSource, customUrl } = attributes;
// Handle icon selection from dropdown
const handleIconChange = (selectedIconId) => {
console.log("an icon is selected");
// Find the selected icon from the iconData array using the UUID
const selectedIcon = iconData.find(icon => icon.uuid === selectedIconId);
if (selectedIcon) {
// Update both iconSvgId (UUID) and iconSvgPath (SVG path)
setAttributes({
iconSvgId: selectedIconId, // UUID of the selected icon
iconSvgPath: selectedIcon.path // SVG path of the selected icon
});
}
};
const handleIconChanges = (selectedIcon) => {
console.log("Icon changed:", selectedIcon);
if (selectedIcon && selectedIcon.iconSvgPath) {
console.log("Selected Icon Path: ", selectedIcon.iconSvgPath); // Log the selected icon path for debugging
setAttributes({
iconSvgPath: selectedIcon.iconSvgPath // Set the SVG path in the attributes
});
}
};
const handleToggleChange = (value) => {
setAttributes({ displayIcon: value });
};
const handleCustomUrlChange = (value) => {
setAttributes({ customUrl: value });
};
const iconSourceOptions = [
{ value: 'manualSvgPath', label: 'SVG Path' },
{ value: 'iconSelector', label: 'Select Icon' },
{ value: 'iconSelector', label: 'Icon Library' },
];
const buttonFunctionOptions = [
const buttonActionOptions = [
{ value: 'customUrl', label: 'Custom URL' },
{ value: 'openPopup', label: 'Open Popup' },
{ value: 'showLoginForm', label: 'Show Login Form' },
{ value: 'logOut', label: 'Open Popup' },
{ value: 'shareCurrentPost', label: 'Share Current Post' }
{ value: 'shareCurrentPost', label: 'Share Current Post' },
{ value: 'displaySidecontent', label: 'Display Sidecontent' }
];
return (
<>
<InspectorControls>
<PanelBody title={__("Button Settings")}>
{/* Button Function */}
<SelectControl
label={__("Popup")}
value={popUpId}
options={iconSourceOptions}
onChange={(value) => setAttributes({ iconSource })}
/>
{buttonFunction === 'openPopup' && (
<SelectControl
label={__("Popup")}
value={popUpId}
options={iconSourceOptions}
onChange={(value) => setAttributes({ iconSource })}
label={__("Button Action")}
value={buttonAction}
options={buttonActionOptions}
onChange={(value) => setAttributes({ buttonAction: value })}
/>
{buttonAction === 'customUrl' && (
<TextControl
label={__("Custom URL")}
value={customUrl}
onChange={handleCustomUrlChange}
/>
)}
<TextControl
@ -103,50 +68,56 @@ export default function Edit(props) {
label="Display Icon"
checked={displayIcon}
onChange={handleToggleChange}
/>
{displayIcon && (
<>
<SelectControl
label={__("Icon Source")}
value={iconSource}
options={iconSourceOptions}
onChange={(value) => setAttributes({ iconSource: value })}
/>
{iconSource === 'manualSvgPath' && (
<TextareaControl
label="Icon SVG Path"
value={iconSvgPath}
onChange={(value) => props.setAttributes({ iconSvgPath: value })}
/>
{displayIcon && (
<>
<SelectControl
label={__("Icon Source")}
value={iconSource}
options={iconSourceOptions}
onChange={(value) => setAttributes({ iconSource: value })}
/>
{iconSource === 'manualSvgPath' && (
<TextareaControl
label="Icon SVG Path"
value={iconSvgPath} // Use the correct attribute `iconSvgPath`
onChange={(value) => setAttributes({ iconSvgPath: value })}
/>
)}
{iconSource === 'iconSelector' && (
<>
<SelectControl
label={__("Icon")}
value={iconSvgId}
options={iconData.map((icon) => ({
label: icon.name,
value: icon.uuid, // Store the UUID as the value
}))}
onChange={handleIconChange}
/>
{iconSource === 'iconSelector' && (
<IconSelectControl
value={props.attributes.icon}
onChange={handleIconChange}
iconSvgId={iconSvgId} // Pass current iconSvgId
onIconChange={handleIconChanges} // Handle icon selection
/>
</>
)}
)}
</>
)}
</PanelBody>
</InspectorControls>
<div {...useBlockProps()}>
<div className="button-container">
<span>{buttonText}</span>
</div>
</div>
<>
{buttonAction === 'customUrl' ? (
// Render an anchor tag if buttonAction is 'customUrl'
<a href={customUrl} className="lcp-button">
{/* Conditionally render the icon if displayIcon is true and iconSvgPath is available */}
{displayIcon && iconSvgPath && (
<svg className = "lcp-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 576" dangerouslySetInnerHTML={{ __html: iconSvgPath }} />
)}
{/* Render the button text */}
{buttonText || 'Button'} {/* Use buttonText or fallback */}
</a>
) : (
// Render a button if buttonAction is not 'customUrl'
<button className="lcp-button">
{/* Conditionally render the icon if displayIcon is true and iconSvgPath is available */}
{displayIcon && iconSvgPath && (
<svg className = "lcp-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 576" dangerouslySetInnerHTML={{ __html: iconSvgPath }} />
)}
{/* Render the button text */}
{buttonText || 'Button'} {/* Use buttonText or fallback */}
</button>
)}
</>
</>
);
}

View File

@ -7,3 +7,26 @@
.wp-block-create-block-button {
border: 1px dotted #f00;
}
.lcp-button {
display: inline-block;
background-color: var(--wp--preset--color--accent);
border: none;
color: #fff;
text-decoration: none;
padding: 10px;
font-weight: bold;
font-size: var(--wp--preset--font-size--small);
white-space: nowrap;
cursor: pointer;
margin:auto 5px;
}
.lcp-button .lcp-icon {
height: 1.2em;
max-height:100%;
width: auto;
vertical-align: middle; /* Aligns the icon with the text vertically */
margin-right: 10px; /* Space between the icon and the text */
fill:white;
}

View File

@ -2,7 +2,7 @@ import { useBlockProps } from '@wordpress/block-editor';
export default function save(props) {
const { attributes } = props;
const { type, popUpId, buttonText, iconSvgPath } = attributes; // Destructure buttonText and iconSvgPath from attributes
const { type, popUpId, buttonText, iconSvgPath, buttonAction } = attributes; // Destructure buttonText and iconSvgPath from attributes
// Get the block props for the button
const blockProps = useBlockProps.save();
@ -12,14 +12,30 @@ export default function save(props) {
blockProps['data-open-popup'] = popUpId; // Add the data attribute dynamically
}
// Conditionally render the link or button based on buttonAction
return (
<button {...blockProps}>
{/* Conditionally render the icon if iconSvgPath is set */}
{iconSvgPath && (
<svg className="icon" viewBox="0 0 24 24" width="100" height="100" dangerouslySetInnerHTML={{ __html: iconSvgPath }} />
<>
{buttonAction === 'customUrl' ? (
// Render an anchor tag if buttonAction is 'customUrl'
<a href={attributes.customUrl} {...blockProps} className="lcp-button">
{/* Conditionally render the icon if iconSvgPath is set */}
{iconSvgPath && (
<svg className="lcp-icon" viewBox="0 0 576 576" dangerouslySetInnerHTML={{ __html: iconSvgPath }} />
)}
{/* Render the button text */}
{buttonText || 'Button'} {/* Use buttonText or fallback */}
</a>
) : (
// Render a button if buttonAction is not 'customUrl'
<button {...blockProps} className="lcp-button">
{/* Conditionally render the icon if iconSvgPath is set */}
{iconSvgPath && (
<svg className="lcp-icon" viewBox="0 0 576 576" dangerouslySetInnerHTML={{ __html: iconSvgPath }} />
)}
{/* Render the button text */}
{buttonText || 'Button'} {/* Use buttonText or fallback */}
</button>
)}
{/* Render the button text */}
{buttonText || 'Button'} {/* Use buttonText or fallback */}
</button>
</>
);
}

View File

@ -10,3 +10,4 @@
color: #fff;
padding: 2px;
}

View File

@ -426,6 +426,12 @@ function build_gallery_styles($attributes, $unique_class) {
// Render the block
function render_lcp_gallery_block($attributes) {
$media_ids = get_media_ids($attributes);
// Check if any Media IDs are present
// If not, return null
// Later, more logic will be needed to verify if there are any gallery items from other sources
if ($media_ids) {
// Generate a unique class for each gallery
$unique_class = lcp_random_string(12, true);
// Get the media IDs based on the attributes
@ -478,7 +484,10 @@ function render_lcp_gallery_block($attributes) {
return "
<div class= '{$classes}' data-lgSettings='" . esc_attr($gallery_settings_json) . "'>
{$gallery_items_html}
</div>";
</div>"; }
else {
return null;
}
}
/* Initialize Gallery Block */
function lcp_gallery_block_init() {

View File

@ -0,0 +1,18 @@
# This file is for unifying the coding style for different editors and IDEs
# editorconfig.org
# WordPress Coding Standards
# https://make.wordpress.org/core/handbook/coding-standards/
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = tab
[*.{yml,yaml}]
indent_style = space
indent_size = 2

View File

@ -0,0 +1,30 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Coverage directory used by tools like istanbul
coverage
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Output of `npm pack`
*.tgz
# Output of `wp-scripts plugin-zip`
*.zip
# dotenv environment variables file
.env

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,62 @@
<?php
/**
* Plugin Name: Todo List
* Description: Example block scaffolded with Create Block tool.
* Requires at least: 6.6
* Requires PHP: 7.2
* Version: 0.1.0
* Author: The WordPress Contributors
* License: GPL-2.0-or-later
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
* Text Domain: todo-list
*
* @package CreateBlock
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
/**
* Registers the block using the metadata loaded from the `block.json` file.
* Behind the scenes, it registers also all assets so they can be enqueued
* through the block editor in the corresponding context.
*
* @see https://developer.wordpress.org/reference/functions/register_block_type/
*/
function render_lcp_visualizer_block() {
$json_data = json_encode([
['x' => 0, 'y' => 10],
['x' => 1, 'y' => 20],
['x' => 2, 'y' => 15],
['x' => 3, 'y' => 25],
['x' => 4, 'y' => 30],
['x' => 5, 'y' => 40],
['x' => 6, 'y' => 45],
]);
return '<svg class="lcp-visualizer" data-visualizer-data="' . esc_attr($json_data) . '"></svg>';
}
function lcp_visualizer_block_init() {
register_block_type( __DIR__ . '/build', array(
'render_callback' => 'render_lcp_visualizer_block',
));
}
add_action( 'init', 'lcp_visualizer_block_init' );
function enqueue_d3_js() {
// Define the path to the D3.js file
$d3_js_path = get_template_directory_uri() . '/includes/blocks/lcp-visualizer/assets/js/d3.v7.min.js';
// Enqueue the D3.js file
wp_enqueue_script('d3-js', $d3_js_path, array(), null, false);
}
add_action('wp_enqueue_scripts', 'enqueue_d3_js');

View File

@ -0,0 +1,20 @@
{
"name": "todo-list",
"version": "0.1.0",
"description": "Example block scaffolded with Create Block tool.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
"main": "build/index.js",
"scripts": {
"build": "wp-scripts build",
"format": "wp-scripts format",
"lint:css": "wp-scripts lint-style",
"lint:js": "wp-scripts lint-js",
"packages-update": "wp-scripts packages-update",
"plugin-zip": "wp-scripts plugin-zip",
"start": "wp-scripts start"
},
"devDependencies": {
"@wordpress/scripts": "^30.7.0"
}
}

View File

@ -0,0 +1,55 @@
=== Todo List ===
Contributors: The WordPress Contributors
Tags: block
Tested up to: 6.6
Stable tag: 0.1.0
License: GPL-2.0-or-later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Example block scaffolded with Create Block tool.
== Description ==
This is the long description. No limit, and you can use Markdown (as well as in the following sections).
For backwards compatibility, if this section is missing, the full length of the short description will be used, and
Markdown parsed.
== Installation ==
This section describes how to install the plugin and get it working.
e.g.
1. Upload the plugin files to the `/wp-content/plugins/todo-list` directory, or install the plugin through the WordPress plugins screen directly.
1. Activate the plugin through the 'Plugins' screen in WordPress
== Frequently Asked Questions ==
= A question that someone might have =
An answer to that question.
= What about foo bar? =
Answer to foo bar dilemma.
== Screenshots ==
1. This screen shot description corresponds to screenshot-1.(png|jpg|jpeg|gif). Note that the screenshot is taken from
the /assets directory or the directory that contains the stable readme.txt (tags or trunk). Screenshots in the /assets
directory take precedence. For example, `/assets/screenshot-1.png` would win over `/tags/4.3/screenshot-1.png`
(or jpg, jpeg, gif).
2. This is the second screen shot
== Changelog ==
= 0.1.0 =
* Release
== Arbitrary section ==
You may provide arbitrary sections, in the same format as the ones above. This may be of use for extremely complicated
plugins where more information needs to be conveyed that doesn't fit into the categories of "description" or
"installation." Arbitrary sections will be shown below the built-in sections outlined above.

View File

@ -0,0 +1,19 @@
{
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 3,
"name": "lcp/visualizer",
"version": "0.1.0",
"title": "Visualizer",
"category": "widgets",
"icon": "smiley",
"description": "Block for charts and data visualization",
"example": {},
"supports": {
"html": false
},
"textdomain": "lcp",
"editorScript": "file:./index.js",
"editorStyle": "file:./index.css",
"style": "file:./style-index.css",
"viewScript": "file:./view.js"
}

View File

@ -0,0 +1,38 @@
/**
* Retrieves the translation of text.
*
* @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-i18n/
*/
import { __ } from '@wordpress/i18n';
/**
* React hook that is used to mark the block wrapper element.
* It provides all the necessary props like the class name.
*
* @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-block-editor/#useblockprops
*/
import { useBlockProps } from '@wordpress/block-editor';
/**
* Lets webpack process CSS, SASS or SCSS files referenced in JavaScript files.
* Those files can contain any CSS code that gets applied to the editor.
*
* @see https://www.npmjs.com/package/@wordpress/scripts#using-css
*/
import './editor.scss';
/**
* The edit function describes the structure of your block in the context of the
* editor. This represents what the editor will render when the block is used.
*
* @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-edit-save/#edit
*
* @return {Element} Element to render.
*/
export default function Edit() {
return (
<p { ...useBlockProps() }>
{ __( 'Todo List hello from the editor!', 'todo-list' ) }
</p>
);
}

View File

@ -0,0 +1,9 @@
/**
* The following styles get applied inside the editor only.
*
* Replace them with your own styles or remove the file completely.
*/
.wp-block-create-block-todo-list {
border: 1px dotted #f00;
}

View File

@ -0,0 +1,39 @@
/**
* Registers a new block provided a unique name and an object defining its behavior.
*
* @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/
*/
import { registerBlockType } from '@wordpress/blocks';
/**
* Lets webpack process CSS, SASS or SCSS files referenced in JavaScript files.
* All files containing `style` keyword are bundled together. The code used
* gets applied both to the front of your site and to the editor.
*
* @see https://www.npmjs.com/package/@wordpress/scripts#using-css
*/
import './style.scss';
/**
* Internal dependencies
*/
import Edit from './edit';
import save from './save';
import metadata from './block.json';
/**
* Every block starts by registering a new block type definition.
*
* @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/
*/
registerBlockType( metadata.name, {
/**
* @see ./edit.js
*/
edit: Edit,
/**
* @see ./save.js
*/
save,
} );

View File

@ -0,0 +1,22 @@
/**
* React hook that is used to mark the block wrapper element.
* It provides all the necessary props like the class name.
*
* @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-block-editor/#useblockprops
*/
/**
* The save function defines the way in which the different attributes should
* be combined into the final markup, which is then serialized by the block
* editor into `post_content`.
*
* @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-edit-save/#save
*
* @return {Element} Element to render.
*/
export default function save() {
return (
null
);
}

View File

@ -0,0 +1,24 @@
/**
* The following styles get applied both on the front of your site
* and in the editor.
*
* Replace them with your own styles or remove the file completely.
*/
.wp-block-create-block-todo-list {
background-color: #21759b;
color: #fff;
padding: 2px;
}
.line {
fill: none;
stroke-width: 2px;
}
.hover-line {
stroke-width: 4px;
}
.axis-label {
font-size: 12px;
}

View File

@ -0,0 +1,127 @@
/**
* Use this file for JavaScript code that you want to run in the front-end
* on posts/pages that contain this block.
*
* When this file is defined as the value of the `viewScript` property
* in `block.json` it will be enqueued on the front end of the site.
*
* Example:
*
* ```js
* {
* "viewScript": "file:./view.js"
* }
* ```
*
* If you're not making any changes to this file because your project doesn't need any
* JavaScript running in the front-end, then you should delete this file and remove
* the `viewScript` property from `block.json`.
*
* @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-metadata/#view-script
*/
/* eslint-disable no-console */
console.log( 'Hello World! (from lcp-visualizer)' );
/* eslint-enable no-console */
// JavaScript to initialize D3.js for all elements with the class .lcp-visualizer
document.addEventListener('DOMContentLoaded', function() {
const data = [
{ date: '2023-01-01', team: 'Manchester City', goals: 2 },
{ date: '2023-01-01', team: 'Liverpool', goals: 1 },
{ date: '2023-02-01', team: 'Manchester City', goals: 3 },
{ date: '2023-02-01', team: 'Liverpool', goals: 2 },
{ date: '2023-03-01', team: 'Manchester City', goals: 4 },
{ date: '2023-03-01', team: 'Liverpool', goals: 3 },
{ date: '2023-04-01', team: 'Manchester City', goals: 3 },
{ date: '2023-04-01', team: 'Liverpool', goals: 4 },
{ date: '2023-05-01', team: 'Manchester City', goals: 5 },
{ date: '2023-05-01', team: 'Liverpool', goals: 4 }
];
const parseDate = d3.timeParse("%Y-%m-%d");
data.forEach(d => {
d.date = parseDate(d.date);
d.goals = +d.goals;
});
const teams = Array.from(new Set(data.map(d => d.team)));
const color = d3.scaleOrdinal()
.domain(teams)
.range(d3.schemeCategory10);
const margin = { top: 20, right: 30, bottom: 40, left: 40 };
const width = 800 - margin.left - margin.right;
const height = 400 - margin.top - margin.bottom;
const svg = d3.select(".lcp-visualizer")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", `translate(${margin.left},${margin.top})`);
const x = d3.scaleTime()
.domain(d3.extent(data, d => d.date))
.range([0, width]);
const y = d3.scaleLinear()
.domain([0, d3.max(data, d => d.goals)])
.nice()
.range([height, 0]);
const line = d3.line()
.x(d => x(d.date))
.y(d => y(d.goals));
svg.append("g")
.attr("transform", `translate(0,${height})`)
.call(d3.axisBottom(x));
svg.append("g")
.call(d3.axisLeft(y));
const teamData = teams.map(team => {
return {
team: team,
values: data.filter(d => d.team === team)
};
});
const path = svg.selectAll(".line")
.data(teamData)
.enter().append("path")
.attr("class", "line")
.attr("d", d => line(d.values))
.attr("stroke", d => color(d.team));
// Hover effect
teamData.forEach(team => {
svg.selectAll(`circle.${team.team}`)
.data(team.values)
.enter().append("circle")
.attr("class", team.team)
.attr("cx", d => x(d.date))
.attr("cy", d => y(d.goals))
.attr("r", 4)
.attr("fill", color(team.team))
.on("mouseover", function(event, d) {
d3.select(this)
.transition()
.duration(200)
.attr("r", 6)
.attr("fill", "orange");
d3.select(`path.${d.team}`).classed("hover-line", true);
})
.on("mouseout", function(event, d) {
d3.select(this)
.transition()
.duration(200)
.attr("r", 4)
.attr("fill", color(d.team));
d3.select(`path.${d.team}`).classed("hover-line", false);
});
});
});

View File

@ -115,6 +115,15 @@ function lcp_register_settings() {
'lcp_theme_settings_section' // Section where this field belongs
);
add_settings_field(
'enable_highlight_to_share', // Field ID
'Enable Highlight-to-Share', // Field title
'lcp_enable_highlight_to_share', // Field callback function
'lcp_theme_settings_page', // Page where this field appears
'lcp_theme_settings_section' // Section where this field belongs
);
// Add fields for custom breakpoints
add_settings_field(
'mobile_breakpoint', // Field ID
@ -176,7 +185,7 @@ function lcp_inject_breakpoints_to_frontend() {
}
</style>";
}
add_action('wp_head', 'lcp_inject_breakpoints_to_frontend',5);
add_action('wp_head', 'lcp_inject_breakpoints_to_frontend');
@ -191,6 +200,15 @@ function lcp_enable_key_points_meta_field() {
}
function lcp_enable_highlight_to_share() {
// Retrieve current value for 'enable_highlight_to_share'
$options = get_option( 'lcp_theme_settings', array() );
$checked = isset( $options['enable_highlight_to_share'] ) ? $options['enable_highlight_to_share'] : false;
// Output the checkbox
echo '<input type="checkbox" name="lcp_theme_settings[enable_highlight_to_share]" value="1" ' . checked( $checked, 1, false ) . ' />';
}
@ -327,3 +345,27 @@ function render_lcp_theme_settings_page() {
// Hooks
function highlight_to_share_popup() {
echo "
<div class=\"popup\" id=\"popup\">
<p>Hey there! Share this:</p>
<a href=\"#\" id=\"facebook-share\">Facebook</a> |
<a href=\"#\" id=\"twitter-share\">Twitter/X</a>
</div>
";
}
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');

View File

@ -18,6 +18,8 @@ class Lcp_Blocks {
include $this->template_directory. '/includes/blocks/lcp-dynamic-container/lcp-dynamic-container.php';
include $this->template_directory. '/includes/blocks/lcp-key-points/lcp-key-points.php';
include $this->template_directory. '/includes/blocks/lcp-button/lcp-button.php';
include $this->template_directory. '/includes/blocks/lcp-visualizer/lcp-visualizer.php';
}
}

View File

@ -1,3 +1,6 @@
document.addEventListener('DOMContentLoaded', function () {
// Get references to the DOM elements
const header = document.getElementById('lcp-header-container');
@ -7,8 +10,8 @@ document.addEventListener('DOMContentLoaded', function () {
if (!header || !sideContent) return;
// Check if the header has the 'lcp-sticky' and 'lcp-sticky-on-scroll' class
const isSticky = header.classList.contains('lcp-sticky');
const isStickyOnScroll = header.classList.contains('lcp-sticky-on-scroll');
const headerIsSticky = header.classList.contains('lcp-sticky');
const headerIsStickyOnScroll = header.classList.contains('lcp-sticky-on-scroll');
// Measure the height of the header once the DOM is loaded
const headerHeight = header.offsetHeight;
@ -23,14 +26,15 @@ document.addEventListener('DOMContentLoaded', function () {
}
// Set the initial height of #lcp-sidecontent based on whether the header is sticky or not
if (isSticky) {
sideContent.style.height = `calc(100vh - ${headerHeight}px)`;
if (headerIsSticky) {
sideContent.style.height = `calc(100vh - ${fullHeaderHeight}px)`;
} else {
sideContent.style.height = `100vh`;
}
// Function to handle the scroll event
function handleScroll() {
console.log ("hey");
const scrolled = window.scrollY || document.documentElement.scrollTop;
// Check if the page has scrolled past the height of the header
@ -40,18 +44,21 @@ document.addEventListener('DOMContentLoaded', function () {
sideContent.style.top = '0';
// If the header has 'lcp-sticky-on-scroll', adjust height of side content to be 100vh - fullHeaderHeight
if (isStickyOnScroll) {
if (headerIsStickyOnScroll) {
sideContent.style.height = `calc(100vh - ${fullHeaderHeight}px)`;
// Add 'lcp-fixed' to the header
header.classList.add('lcp-fixed');
// Set the 'top' of the sideContent to the height of the header
sideContent.style.top = `${fullHeaderHeight}px`;
} else if (isSticky) {
} 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)`;
} else {
// Set side content height to 100vh when not sticky
sideContent.style.height = '100vh';
sideContent.style.height = 'calc(100vh - 32px)';
sideContent.style.top = '32px';
}
} else {
// Remove the 'lcp-fixed' class from side content and header if scrolled back above the header
@ -59,26 +66,45 @@ document.addEventListener('DOMContentLoaded', function () {
sideContent.style.top = ''; // Reset the 'top' style
// Reset height to 100vh when not fixed
sideContent.style.height = isSticky ? `calc(100vh - ${headerHeight}px)` : '100vh';
sideContent.style.height = `calc(100vh - ${fullHeaderHeight}px)` ;
// If header has the 'lcp-sticky-on-scroll' class, remove 'lcp-fixed' from the header
if (isStickyOnScroll) {
if (headerIsStickyOnScroll) {
header.classList.remove('lcp-fixed');
}
}
}
// Add the scroll event listener
window.addEventListener('scroll', handleScroll);
// Also trigger the scroll handler once on load in case the page is already scrolled
handleScroll();
function debounce(func, delay) {
let timeout;
return function() {
const context = this;
const args = arguments;
clearTimeout(timeout);
timeout = setTimeout(function() {
func.apply(context, args);
}, delay);
};
}
// Add debounced scroll event listener
window.addEventListener('scroll', debounce(handleScroll, 20)); // 200ms debounce
});
const sidecontent = document.getElementById("lcp-sidecontent");
const innerContent = document.getElementById("lcp-sidecontent-inner");
const scrollTrack = document.getElementById("lcp-scroll-track");
@ -143,3 +169,17 @@ innerContent.addEventListener("scroll", updateCustomScrollbar);
// Initialize the custom scrollbar position when the page loads
updateCustomScrollbar();

View File

@ -23,20 +23,22 @@ Version: 1.0
}
/* Side content - absolute or fixed position */
/* Side content */
#lcp-sidecontent {
position: absolute; /* Positioned relative to the parent with position: relative */
position: absolute;
left: 0;
top: var(--my-top); /* Dynamically controlled top position via JS */
width: 340px; /* Fixed width */
height: 100%; /* Full height */
overflow: auto; /* Allow scrolling inside */
top: var(--my-top);
width: 340px;
height: 100%;
overflow: auto;
background: #fff;
border-right: 2px solid #eee;
z-index: 2;
outline: 0;
}
#lcp-sidecontent.lcp-fixed {
position:fixed
}
@ -118,10 +120,7 @@ Version: 1.0
#lcp-sidecontent {
overflow: hidden; /* Hide native scrollbar */
}
#lcp-sidecontent-inner {
height: 100%;
@ -145,4 +144,38 @@ Version: 1.0
border-radius: 5px;
}
/* Highlight-to-share popup */
.popup {
position: absolute;
background-color: white;
color: black;
padding: 8px;
border-radius: 5px;
font-size: 14px;
display: none; /* Hidden by default */
z-index:8999
}
/* LCP Button */
.lcp-button {
display: inline-block;
background-color: var(--wp--preset--color--accent);
border: none;
color: #fff;
text-decoration: none;
padding: 10px;
font-weight: bold;
font-size: var(--wp--preset--font-size--small);
white-space: nowrap;
cursor: pointer;
}
.lcp-button .lcp-icon {
height: 1.2em;
max-height:100%;
width: auto;
vertical-align: middle; /* Aligns the icon with the text vertically */
margin-right: 10px; /* Space between the icon and the text */
fill:white;
}

View File

@ -112,10 +112,16 @@
"defaultFontSizes": false,
"fluid": true,
"fontSizes": [
{
"fluid": false,
"name": "Extra Small",
"size": "0.75rem",
"slug": "extra-small"
},
{
"fluid": false,
"name": "Small",
"size": "0.875rem",
"size": "0.9rem",
"slug": "small"
},
{