Compare commits
26 Commits
f356906bb1
...
dev
| Author | SHA1 | Date | |
|---|---|---|---|
| 7bba517b48 | |||
| d928a0e8fd | |||
| 21b00e1937 | |||
| 741d39a962 | |||
| 2df16e37a8 | |||
| 4394776735 | |||
| a8b4dc6b70 | |||
| 4b78f9f571 | |||
| b9e2660318 | |||
| 28139d2455 | |||
| 0d59719440 | |||
| 372d5aa2c1 | |||
| d65992a169 | |||
| 462cffdddc | |||
| 93cc7be3bf | |||
| 44c621e0da | |||
| 216d108289 | |||
| 1ccc6f0031 | |||
| f3fbe0fa32 | |||
| cfbb860bf9 | |||
| 94d2c7c8a2 | |||
| d5a5f4e87b | |||
| 961081128a | |||
| f19e779946 | |||
| 4936a3a742 | |||
| 1234341241 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -6,7 +6,6 @@ wp-includes/
|
||||
.DS_Store
|
||||
node_modules/
|
||||
.env
|
||||
build/
|
||||
dist/
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
|
||||
0
assets/css/admin-style.css
Normal file
0
assets/css/admin-style.css
Normal file
BIN
assets/fonts/fira-code/FiraCode-VariableFont_wght.woff2
Normal file
BIN
assets/fonts/fira-code/FiraCode-VariableFont_wght.woff2
Normal file
Binary file not shown.
BIN
assets/fonts/manrope/Manrope-VariableFont_wght.woff2
Normal file
BIN
assets/fonts/manrope/Manrope-VariableFont_wght.woff2
Normal file
Binary file not shown.
BIN
assets/fonts/pt-serif/PTSerif-Bold.woff2
Normal file
BIN
assets/fonts/pt-serif/PTSerif-Bold.woff2
Normal file
Binary file not shown.
BIN
assets/fonts/pt-serif/PTSerif-BoldItalic.woff2
Normal file
BIN
assets/fonts/pt-serif/PTSerif-BoldItalic.woff2
Normal file
Binary file not shown.
BIN
assets/fonts/pt-serif/PTSerif-Italic.woff2
Normal file
BIN
assets/fonts/pt-serif/PTSerif-Italic.woff2
Normal file
Binary file not shown.
BIN
assets/fonts/pt-serif/PTSerif-Regular.woff2
Normal file
BIN
assets/fonts/pt-serif/PTSerif-Regular.woff2
Normal file
Binary file not shown.
BIN
assets/fonts/work-sans/WorkSans-Bold.woff2
Normal file
BIN
assets/fonts/work-sans/WorkSans-Bold.woff2
Normal file
Binary file not shown.
BIN
assets/fonts/work-sans/WorkSans-Italic.woff2
Normal file
BIN
assets/fonts/work-sans/WorkSans-Italic.woff2
Normal file
Binary file not shown.
BIN
assets/fonts/work-sans/WorkSans-Regular.woff2
Normal file
BIN
assets/fonts/work-sans/WorkSans-Regular.woff2
Normal file
Binary file not shown.
BIN
assets/fonts/work-sans/WorkSans-SemiBold.woff2
Normal file
BIN
assets/fonts/work-sans/WorkSans-SemiBold.woff2
Normal file
Binary file not shown.
71
assets/js/highlight-to-share.js
Normal file
71
assets/js/highlight-to-share.js
Normal 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)}"e=${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';
|
||||
}
|
||||
});
|
||||
});
|
||||
77
assets/js/icon-import.js
Normal file
77
assets/js/icon-import.js
Normal file
@ -0,0 +1,77 @@
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
console.log('DOMContentLoaded event triggered');
|
||||
|
||||
const installButtons = document.querySelectorAll('.install-btn');
|
||||
const uninstallButtons = document.querySelectorAll('.uninstall-btn');
|
||||
|
||||
console.log('Install buttons:', installButtons);
|
||||
console.log('Uninstall buttons:', uninstallButtons);
|
||||
|
||||
// Handle Install button click
|
||||
installButtons.forEach(function (button) {
|
||||
console.log('Adding install listener to button', button);
|
||||
button.addEventListener('click', function (event) {
|
||||
event.preventDefault(); // Prevent default form submission or page reload
|
||||
console.log('Install button clicked');
|
||||
const iconSetId = this.getAttribute('data-icon-set-id');
|
||||
console.log('Icon Set ID:', iconSetId);
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('action', 'install_icon_set');
|
||||
formData.append('icon_set_id', iconSetId);
|
||||
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open('POST', mytheme_ajax.ajax_url, true);
|
||||
|
||||
xhr.onload = function () {
|
||||
if (xhr.status === 200) {
|
||||
const response = JSON.parse(xhr.responseText);
|
||||
console.log(response);
|
||||
if (response.success) {
|
||||
alert('Icon set installed successfully!');
|
||||
} else {
|
||||
alert('Failed to install icon set: ' + response.data.message);
|
||||
}
|
||||
} else {
|
||||
alert('There was an error with the request.');
|
||||
}
|
||||
};
|
||||
|
||||
xhr.send(formData);
|
||||
});
|
||||
});
|
||||
|
||||
// Handle Uninstall button click
|
||||
uninstallButtons.forEach(function (button) {
|
||||
console.log('Adding uninstall listener to button', button);
|
||||
button.addEventListener('click', function (event) {
|
||||
event.preventDefault(); // Prevent default form submission or page reload
|
||||
console.log('Uninstall button clicked');
|
||||
const iconSetId = this.getAttribute('data-icon-set-id');
|
||||
console.log('Icon Set ID for uninstall:', iconSetId);
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('action', 'uninstall_icon_set');
|
||||
formData.append('icon_set_id', iconSetId);
|
||||
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open('POST', mytheme_ajax.ajax_url, true);
|
||||
|
||||
xhr.onload = function () {
|
||||
if (xhr.status === 200) {
|
||||
const response = JSON.parse(xhr.responseText);
|
||||
console.log(response);
|
||||
if (response.success) {
|
||||
alert('Icon set uninstalled successfully!');
|
||||
} else {
|
||||
alert('Failed to uninstall icon set: ' + response.data.message);
|
||||
}
|
||||
} else {
|
||||
alert('There was an error with the request.');
|
||||
}
|
||||
};
|
||||
|
||||
xhr.send(formData);
|
||||
});
|
||||
});
|
||||
});
|
||||
61
assets/js/lcp-ui.js
Normal file
61
assets/js/lcp-ui.js
Normal file
@ -0,0 +1,61 @@
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
// Find all elements with the class "lcp-accordion"
|
||||
var accordions = document.querySelectorAll('.lcp-accordion');
|
||||
|
||||
accordions.forEach(function (accordion) {
|
||||
// Find all tabs within the current accordion
|
||||
var tabs = accordion.querySelectorAll('.lcp-accordion-tab');
|
||||
|
||||
tabs.forEach(function (tab) {
|
||||
var header = tab.querySelector('h3');
|
||||
var content = tab.querySelector('.lcp-accordion-content');
|
||||
|
||||
// Add click event to each header to toggle the content
|
||||
header.addEventListener('click', function () {
|
||||
// Toggle the 'active' class on the tab to show/hide content
|
||||
tab.classList.toggle('active');
|
||||
|
||||
// Optional: Close other open tabs (if only one tab should be open at a time)
|
||||
tabs.forEach(function (otherTab) {
|
||||
if (otherTab !== tab) {
|
||||
otherTab.classList.remove('active');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
});
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
const tabs = document.querySelectorAll('.tab-link');
|
||||
const panes = document.querySelectorAll('.tab-pane');
|
||||
|
||||
tabs.forEach(tab => {
|
||||
tab.addEventListener('click', function (event) {
|
||||
event.preventDefault();
|
||||
|
||||
// Remove active class from all tabs and panes
|
||||
tabs.forEach(link => link.classList.remove('active'));
|
||||
panes.forEach(pane => pane.classList.remove('active'));
|
||||
|
||||
// Add active class to the clicked tab
|
||||
tab.classList.add('active');
|
||||
|
||||
// Get the target pane
|
||||
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');
|
||||
} else {
|
||||
console.error(`Tab pane with ID '${targetPaneId}' not found.`);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
122
assets/js/lcp.js
Normal file
122
assets/js/lcp.js
Normal file
@ -0,0 +1,122 @@
|
||||
|
||||
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
// Get references to the DOM elements
|
||||
const header = document.getElementById('lcp-header-container');
|
||||
const sideContent = document.getElementById('lcp-sidecontent');
|
||||
|
||||
// Ensure elements exist before proceeding
|
||||
if (!header || !sideContent) return;
|
||||
|
||||
// Check if the header has the 'lcp-sticky' and 'lcp-sticky-on-scroll' class
|
||||
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;
|
||||
let fullHeaderHeight;
|
||||
|
||||
// If the admin-bar is present, the fullHeaderHeight is the headerHeight + 32px
|
||||
if (document.body.classList.contains('admin-bar')) {
|
||||
const adminBarHeight = document.getElementById('wpadminbar').offsetHeight;
|
||||
fullHeaderHeight = headerHeight + adminBarHeight;
|
||||
} else {
|
||||
fullHeaderHeight = headerHeight;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Function to handle the scroll event
|
||||
function handleScroll() {
|
||||
document.documentElement.style.setProperty('--lcp--full-header--height', fullHeaderHeight + "px");
|
||||
if (!headerIsSticky){
|
||||
const scrolled = window.scrollY || document.documentElement.scrollTop;
|
||||
|
||||
// Check if the page has scrolled past the height of the header
|
||||
if (scrolled >= headerHeight) {
|
||||
// Add the 'lcp-fixed' class and set 'top' to 0 for side content
|
||||
sideContent.classList.add('lcp-fixed');
|
||||
// sideContent.style.top = fullHeaderHeight + 'px';
|
||||
|
||||
// If the header has 'lcp-sticky-on-scroll', adjust height of side content to be 100vh - fullHeaderHeight
|
||||
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 (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 = 'calc(100vh - 32px)';
|
||||
// sideContent.style.top = '32px';
|
||||
|
||||
}
|
||||
} else {
|
||||
// Remove the 'lcp-fixed' class from side content and header if scrolled back above the header
|
||||
sideContent.classList.remove('lcp-fixed');
|
||||
// sideContent.style.top = ''; // Reset the 'top' style
|
||||
|
||||
// Reset height to 100vh when not fixed
|
||||
// sideContent.style.height = `calc(100vh - ${fullHeaderHeight}px)` ;
|
||||
|
||||
// If header has the 'lcp-sticky-on-scroll' class, remove 'lcp-fixed' from the header
|
||||
if (headerIsStickyOnScroll) {
|
||||
header.classList.remove('lcp-fixed');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 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");
|
||||
const scrollBar = document.getElementById("lcp-scroll-bar");
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
96
assets/js/react/components/DimensionValueControl.js
Normal file
96
assets/js/react/components/DimensionValueControl.js
Normal file
@ -0,0 +1,96 @@
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { BaseControl, __experimentalNumberControl as NumberControl, SelectControl, __experimentalHStack as HStack } from '@wordpress/components';
|
||||
import { useState, useEffect } from 'react';
|
||||
|
||||
/**
|
||||
* Control component with a number input and a select dropdown for units (px, rem, em, % etc.).
|
||||
* Accepts a default value as a string (e.g., "15px", "10rem", etc.).
|
||||
* Includes an optional 'auto' unit if includeAuto is true, and handles autoReturnsNull behavior.
|
||||
*/
|
||||
export function DimensionValueControl({ value = '10px', onChange, includeAuto = false, autoReturnsNull = false }) {
|
||||
// Options for select control (CSS units) including 'auto' if enabled
|
||||
const unitOptions = [
|
||||
{ label: __('px'), value: 'px' },
|
||||
{ label: __('%'), value: '%' },
|
||||
{ label: __('em'), value: 'em' },
|
||||
{ label: __('rem'), value: 'rem' },
|
||||
{ label: __('vw'), value: 'vw' },
|
||||
{ label: __('vh'), value: 'vh' },
|
||||
...(includeAuto ? [{ label: __('auto'), value: 'auto' }] : []), // Add 'auto' option if includeAuto is true
|
||||
];
|
||||
|
||||
// Parse the value string into a number and unit
|
||||
const parseValue = (value) => {
|
||||
const regex = /([0-9]+)([a-zA-Z%]+)?/; // Capture the number and the unit
|
||||
const match = value.match(regex);
|
||||
if (match) {
|
||||
return {
|
||||
numberValue: parseInt(match[1], 10), // Number part
|
||||
unitValue: match[2] || 'px' // Unit part (default to 'px' if no unit found)
|
||||
};
|
||||
}
|
||||
return { numberValue: 0, unitValue: 'px' }; // Fallback if invalid format
|
||||
};
|
||||
|
||||
// Use the parsed value to set initial state
|
||||
const { numberValue: initialNumber, unitValue: initialUnit } = parseValue(value);
|
||||
const [numberValue, setNumberValue] = useState(initialNumber);
|
||||
const [unitValue, setUnitValue] = useState(initialUnit);
|
||||
|
||||
// Combine the number and unit into a string like "15px"
|
||||
const dimensionValue = `${numberValue}${unitValue}`;
|
||||
|
||||
// Handle number change
|
||||
const onNumberChange = (newValue) => {
|
||||
setNumberValue(newValue);
|
||||
if (onChange && unitValue !== 'auto') {
|
||||
onChange(`${newValue}${unitValue}`); // Pass updated value back to parent
|
||||
}
|
||||
};
|
||||
|
||||
// Handle unit change
|
||||
const onUnitChange = (newUnit) => {
|
||||
if (newUnit === 'auto') {
|
||||
setNumberValue(null); // Reset the number value when 'auto' is selected
|
||||
}
|
||||
setUnitValue(newUnit);
|
||||
if (onChange) {
|
||||
const updatedValue = newUnit === 'auto'
|
||||
? (autoReturnsNull ? null : 'auto')
|
||||
: `${numberValue}${newUnit}`; // Pass 'auto' or null or updated value back to parent
|
||||
onChange(updatedValue);
|
||||
}
|
||||
};
|
||||
|
||||
// Effect to handle when value prop changes (useful for syncing)
|
||||
useEffect(() => {
|
||||
const { numberValue, unitValue } = parseValue(value);
|
||||
setNumberValue(numberValue);
|
||||
setUnitValue(unitValue);
|
||||
}, [value]);
|
||||
|
||||
return (
|
||||
<BaseControl className="lcp-dimension-value-control">
|
||||
<HStack>
|
||||
{/* Number input control, disabled when 'auto' is selected */}
|
||||
<NumberControl
|
||||
className="lcp-number-control"
|
||||
value={numberValue || ''}
|
||||
onChange={onNumberChange}
|
||||
min={0}
|
||||
step={0.1}
|
||||
spinControls={'none'}
|
||||
disabled={unitValue === 'auto'} // Disable number input if 'auto' is selected
|
||||
/>
|
||||
|
||||
{/* Select dropdown control for units */}
|
||||
<SelectControl
|
||||
className="lcp-select-control"
|
||||
value={unitValue}
|
||||
options={unitOptions}
|
||||
onChange={onUnitChange}
|
||||
/>
|
||||
</HStack>
|
||||
</BaseControl>
|
||||
);
|
||||
}
|
||||
59
assets/js/react/components/IconSelectControl.js
Normal file
59
assets/js/react/components/IconSelectControl.js
Normal file
@ -0,0 +1,59 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { SelectControl } from '@wordpress/components';
|
||||
|
||||
export function IconSelectControl(props) {
|
||||
const { iconSvgId, onIconChange } = props;
|
||||
|
||||
const [iconData, setIconData] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchIconData = async () => {
|
||||
try {
|
||||
const response = await fetch('/wp-json/lcp/v1/icons');
|
||||
const data = await response.json();
|
||||
if (Array.isArray(data) && data.length > 0) {
|
||||
setIconData(data); // Set the fetched data directly
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error fetching icons:', error);
|
||||
}
|
||||
};
|
||||
|
||||
fetchIconData();
|
||||
}, []);
|
||||
|
||||
const handleIconChange = (selectedIconId) => {
|
||||
const selectedIcon = iconData.find(icon => icon.iconSvgId === selectedIconId);
|
||||
if (selectedIcon && onIconChange) {
|
||||
// Send both icon ID and path (SVG) to the parent component
|
||||
onIconChange({
|
||||
iconSvgId: selectedIcon.iconSvgId, // Pass icon ID to parent
|
||||
iconSvgPath: selectedIcon.iconSvgPaths, // Pass icon paths to parent
|
||||
viewbox: selectedIcon.selectedIconViewbox // Pass the viewbox to parent
|
||||
});
|
||||
console.log("Selected Icon ID:", selectedIcon.iconSvgId); // Debugging output
|
||||
console.log("Selected Icon Path:", selectedIcon.iconSvgPaths); // Debugging output
|
||||
console.log("Selected Icon Viewbox:", selectedIcon.selectedIconViewbox); // Debugging output
|
||||
}
|
||||
};
|
||||
|
||||
if (iconData.length === 0) {
|
||||
return <p>{__('Loading icons...', 'lcp')}</p>; // Loading state
|
||||
}
|
||||
|
||||
const iconOptions = iconData.map((icon) => ({
|
||||
value: icon.iconSvgId, // Use icon ID as value for the SelectControl
|
||||
label: icon.name, // Directly use the icon's name as the label
|
||||
}));
|
||||
|
||||
|
||||
return (
|
||||
<SelectControl
|
||||
label={__('Select Icon', 'lcp')}
|
||||
value={iconSvgId} // Current selected icon ID
|
||||
options={iconOptions}
|
||||
onChange={handleIconChange} // Handle icon change
|
||||
/>
|
||||
);
|
||||
}
|
||||
103
assets/js/react/components/PaddingControl.js
Normal file
103
assets/js/react/components/PaddingControl.js
Normal file
@ -0,0 +1,103 @@
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { BaseControl, Button, RangeControl, __experimentalHStack as HStack, __experimentalVStack as VStack } from '@wordpress/components';
|
||||
import { DimensionValueControl } from './DimensionValueControl';
|
||||
|
||||
/**
|
||||
* Padding Control component to manage padding values for different screen sizes.
|
||||
*/
|
||||
export function PaddingControl() {
|
||||
return (
|
||||
<BaseControl className="lcp-padding-control">
|
||||
|
||||
|
||||
{/* Padding label and Unlink button */}
|
||||
<HStack>
|
||||
<span>{__('Padding')}</span>
|
||||
<Button
|
||||
variant="secondary"
|
||||
aria-label={__('Unlink sides')}
|
||||
onClick={() => {}}
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" focusable="false">
|
||||
<path d="M10 17.389H8.444A5.194 5.194 0 1 1 8.444 7H10v1.5H8.444a3.694 3.694 0 0 0 0 7.389H10v1.5ZM14 7h1.556a5.194 5.194 0 0 1 0 10.39H14v-1.5h1.556a3.694 3.694 0 0 0 0-7.39H14V7Zm-4.5 6h5v-1.5h-5V13Z"></path>
|
||||
</svg>
|
||||
</Button>
|
||||
</HStack>
|
||||
|
||||
{/* Extra Large Padding Controls */}
|
||||
{/* Will update all padding values for all screen sizes if updateAllScreenSizes is true */}
|
||||
|
||||
{/* Top and Bottom HStack */}
|
||||
<HStack style={{ flex: 1 }}>
|
||||
{/* Top and Bottom Icon */}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" className="spacing-sizes-control__icon" aria-hidden="true" focusable="false">
|
||||
<path d="m7.5 6h9v-1.5h-9zm0 13.5h9v-1.5h-9zm-3-3h1.5v-9h-1.5zm13.5-9v9h1.5v-9z" style={{ opacity: 0.25 }}></path>
|
||||
<path d="m7.5 6h9v-1.5h-9z"></path>
|
||||
<path d="m7.5 19.5h9v-1.5h-9z"></path>
|
||||
</svg>
|
||||
|
||||
{/* RangeControl wrapped in HStack with flex: 1 applied to its parent */}
|
||||
<HStack style={{ flex: 1 }}>
|
||||
<DimensionValueControl/>
|
||||
<RangeControl
|
||||
withInputField={false}
|
||||
value={10} // Placeholder value
|
||||
onChange={() => {}}
|
||||
min={0}
|
||||
max={50}
|
||||
/>
|
||||
</HStack>
|
||||
|
||||
{/* Custom Padding Button */}
|
||||
<Button
|
||||
style={{padding:0,background:'none',color:'var(--wp-components-color-foreground)'} }
|
||||
variant="primary"
|
||||
onClick={() => {}}
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" focusable="false">
|
||||
<path d="m19 7.5h-7.628c-.3089-.87389-1.1423-1.5-2.122-1.5-.97966 0-1.81309.62611-2.12197 1.5h-2.12803v1.5h2.12803c.30888.87389 1.14231 1.5 2.12197 1.5.9797 0 1.8131-.62611 2.122-1.5h7.628z"></path>
|
||||
<path d="m19 15h-2.128c-.3089-.8739-1.1423-1.5-2.122-1.5s-1.8131.6261-2.122 1.5h-7.628v1.5h7.628c.3089.8739 1.1423 1.5 2.122 1.5s1.8131-.6261 2.122-1.5h2.128z"></path>
|
||||
</svg>
|
||||
</Button>
|
||||
</HStack>
|
||||
|
||||
{/* Left and Right HStack */}
|
||||
<HStack style={{ flex: 1 }}>
|
||||
{/* Left and Right Icon */}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" className="spacing-sizes-control__icon" aria-hidden="true" focusable="false">
|
||||
<path d="m7.5 6h9v-1.5h-9zm0 13.5h9v-1.5h-9zm-3-3h1.5v-9h-1.5zm13.5-9v9h1.5v-9z" style={{ opacity: 0.25 }}></path>
|
||||
<path d="m7.5 6h9v-1.5h-9z"></path>
|
||||
<path d="m4.5 7.5v9h1.5v-9z"></path>
|
||||
<path d="m18 7.5v9h1.5v-9z"></path>
|
||||
</svg>
|
||||
|
||||
{/* RangeControl wrapped in HStack with flex: 1 applied to its parent */}
|
||||
|
||||
<RangeControl
|
||||
withInputField={false}
|
||||
value={10} // Placeholder value
|
||||
onChange={() => {}}
|
||||
min={0}
|
||||
max={50}
|
||||
/>
|
||||
|
||||
|
||||
{/* Custom Padding Button */}
|
||||
<Button
|
||||
variant="primary"
|
||||
onClick={() => {}}
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" focusable="false">
|
||||
<path d="m19 7.5h-7.628c-.3089-.87389-1.1423-1.5-2.122-1.5-.97966 0-1.81309.62611-2.12197 1.5h-2.12803v1.5h2.12803c.30888.87389 1.14231 1.5 2.12197 1.5.9797 0 1.8131-.62611 2.122-1.5h7.628z"></path>
|
||||
<path d="m19 15h-2.128c-.3089-.8739-1.1423-1.5-2.122-1.5s-1.8131.6261-2.122 1.5h-7.628v1.5h7.628c.3089.8739 1.1423 1.5 2.122 1.5s1.8131-.6261 2.122-1.5h2.128z"></path>
|
||||
</svg>
|
||||
</Button>
|
||||
</HStack>
|
||||
|
||||
{/* Additional controls can be added here in a VStack */}
|
||||
<VStack>
|
||||
{/* Placeholder for additional components */}
|
||||
</VStack>
|
||||
</BaseControl>
|
||||
);
|
||||
}
|
||||
57
assets/json/alphabetize.php
Normal file
57
assets/json/alphabetize.php
Normal file
@ -0,0 +1,57 @@
|
||||
<?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.";
|
||||
}
|
||||
|
||||
?>
|
||||
61
assets/json/converter.php
Normal file
61
assets/json/converter.php
Normal file
@ -0,0 +1,61 @@
|
||||
<?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";
|
||||
}
|
||||
?>
|
||||
57
assets/json/fixpaths.php
Normal file
57
assets/json/fixpaths.php
Normal file
@ -0,0 +1,57 @@
|
||||
<?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";
|
||||
|
||||
?>
|
||||
63
assets/json/icons/fix.php
Normal file
63
assets/json/icons/fix.php
Normal file
@ -0,0 +1,63 @@
|
||||
<?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";
|
||||
|
||||
?>
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
67
assets/json/icons/icon-definitions.json
Normal file
67
assets/json/icons/icon-definitions.json
Normal file
@ -0,0 +1,67 @@
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"setName": "Font Awesome - Regular",
|
||||
"setFamily": "Font Awesome",
|
||||
"version": "6.7.1",
|
||||
"fileName": "/font-awesome/v6.7.1/font-awesome-v6.7.1-regular-svgs.json",
|
||||
"default": true
|
||||
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"setName": "Font Awesome - Solid",
|
||||
"setFamily": "Font Awesome",
|
||||
"version": "6.7.1",
|
||||
"fileName": "/font-awesome/v6.7.1/font-awesome-v6.7.1-solid-svgs.json"
|
||||
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"setName": "Font Awesome - Brands",
|
||||
"setFamily": "Font Awesome",
|
||||
"version": "6.7.1",
|
||||
"fileName": "/font-awesome/v6.7.1/font-awesome-v6.7.1-brands-svgs.json"
|
||||
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"setName": "Material Icons - Baseline",
|
||||
"setFamily": "Material Icons",
|
||||
"version": "1.0.32",
|
||||
"fileName": "/material-icons/v1.0.32/material-icons-v1.0.32-baseline-svgs.json"
|
||||
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"setName": "Material Icons - Outline",
|
||||
"setFamily": "Material Icons",
|
||||
"version": "1.0.32",
|
||||
"fileName": "/material-icons/v1.0.32/material-icons-v1.0.32-outline-svgs.json"
|
||||
|
||||
},
|
||||
{
|
||||
"id":6,
|
||||
"setName": "Material Icons - Twotone",
|
||||
"setFamily": "Material Icons",
|
||||
"version": "1.0.32",
|
||||
"fileName": "/material-icons/v1.0.32/material-icons-v1.0.32-twotone-svgs.json"
|
||||
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"setName": "Material Icons - Sharp",
|
||||
"setFamily": "Material Icons",
|
||||
"version": "1.0.32",
|
||||
"fileName": "/material-icons/v1.0.32/material-icons-v1.0.32-sharp-svgs.json"
|
||||
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"setName": "Material Icons - Round",
|
||||
"setFamily": "Material Icons",
|
||||
"version": "1.0.32",
|
||||
"fileName": "/material-icons/v1.0.32/material-icons-v1.0.32-round-svgs.json"
|
||||
|
||||
}
|
||||
]
|
||||
86
assets/json/icons/material-icons/v1.0.32/caps.php
Normal file
86
assets/json/icons/material-icons/v1.0.32/caps.php
Normal file
@ -0,0 +1,86 @@
|
||||
<?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";
|
||||
}
|
||||
}
|
||||
?>
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
4206
assets/json/input.svg
Normal file
4206
assets/json/input.svg
Normal file
File diff suppressed because one or more lines are too long
464
functions.php
464
functions.php
@ -1,5 +1,465 @@
|
||||
<?php
|
||||
function my_block_theme_setup() {
|
||||
|
||||
|
||||
|
||||
|
||||
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';
|
||||
new Lcp_Blocks();
|
||||
|
||||
|
||||
// Include backend php
|
||||
include get_template_directory() . '/includes/classes/backend.php';
|
||||
|
||||
|
||||
function lcp_block_theme_setup() {
|
||||
add_theme_support( 'block-templates' );
|
||||
}
|
||||
add_action( 'after_setup_theme', 'my_block_theme_setup' );
|
||||
add_action( 'after_setup_theme', 'lcp_block_theme_setup' );
|
||||
/* Add Styles */
|
||||
function lcp_header_height_style() {
|
||||
// Fetch the lcp_header_height value from wp_options.
|
||||
$header_height = get_option('lcp_header_height', 0); // Default to 0 if not found
|
||||
|
||||
// Ensure we have a valid value
|
||||
if ($header_height) {
|
||||
// Output the inline style tag with the CSS variable for header height
|
||||
echo "<style>:root { --lcp--header--height: {$header_height}px; }</style>";
|
||||
}
|
||||
}
|
||||
add_action('wp_enqueue_scripts', 'lcp_header_height_style',1);
|
||||
|
||||
|
||||
function lcp_enqueue() {
|
||||
// Enqueue the theme's main stylesheet (style.css)
|
||||
wp_enqueue_style('lcp-style', get_stylesheet_uri());
|
||||
wp_enqueue_script('lcp-script', get_template_directory_uri() . '/assets/js/lcp.js');
|
||||
wp_enqueue_script('lcp-ui-script', get_template_directory_uri() . '/assets/js/lcp-ui.js');
|
||||
|
||||
}
|
||||
|
||||
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 */
|
||||
function add_key_points_meta_box() {
|
||||
add_meta_box(
|
||||
'key_points_meta_box', // ID of the meta box
|
||||
'Key Points', // Title of the meta box
|
||||
'render_key_points_meta_box', // Callback function to display the meta box
|
||||
'post', // Post type (you can change it to other post types)
|
||||
'normal', // Context (normal, side, advanced)
|
||||
'default' // Priority
|
||||
);
|
||||
}
|
||||
// Add meta box if setting is turned on
|
||||
$options = get_option('lcp_theme_settings', array());
|
||||
$enable_key_points_meta = isset($options['enable_key_points_meta']) ? $options['enable_key_points_meta'] : 0;
|
||||
|
||||
// Check if 'enable_key_points_meta' is enabled (1), then add the meta box
|
||||
if ($enable_key_points_meta) {
|
||||
// Hook into add_meta_boxes to register the custom meta box
|
||||
add_action('add_meta_boxes', 'add_key_points_meta_box');
|
||||
}
|
||||
|
||||
// Sanitize the SVGs data
|
||||
function lcp_custom_svgs_sanitize($input) {
|
||||
// Ensure the input is an array
|
||||
if (is_array($input)) {
|
||||
foreach ($input as $key => $svg) {
|
||||
// Sanitize the name and path for each SVG
|
||||
if (isset($svg['name'])) {
|
||||
$input[$key]['name'] = sanitize_text_field($svg['name']);
|
||||
}
|
||||
if (isset($svg['path'])) {
|
||||
$input[$key]['path'] = sanitize_textarea_field($svg['path']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $input;
|
||||
}
|
||||
|
||||
// Existing function to render the theme settings page
|
||||
|
||||
// Callback function to render the meta box
|
||||
function render_key_points_meta_box($post) {
|
||||
// Retrieve the stored key points (serialized data)
|
||||
$key_points_serialized = get_post_meta($post->ID, '_key_points', true);
|
||||
$key_points = !empty($key_points_serialized) ? unserialize($key_points_serialized) : [];
|
||||
?>
|
||||
<div id="key-points-repeater">
|
||||
<ul id="key-points-list">
|
||||
<?php foreach ($key_points as $index => $point) : ?>
|
||||
<li class="key-point">
|
||||
<input type="text" name="key_points[<?php echo $index; ?>]" value="<?php echo esc_attr($point); ?>" class="key-point-input" />
|
||||
<button type="button" class="remove-key-point">Remove</button>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<button type="button" id="add-key-point">Add Key Point</button>
|
||||
</div>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
const addButton = document.getElementById('add-key-point');
|
||||
const keyPointsList = document.getElementById('key-points-list');
|
||||
|
||||
// Function to add a new key point input field
|
||||
addButton.addEventListener('click', function () {
|
||||
const index = keyPointsList.children.length;
|
||||
const newItem = document.createElement('li');
|
||||
newItem.classList.add('key-point');
|
||||
|
||||
newItem.innerHTML = `
|
||||
<input type="text" name="key_points[${index}]" value="" class="key-point-input" />
|
||||
<button type="button" class="remove-key-point">Remove</button>
|
||||
`;
|
||||
keyPointsList.appendChild(newItem);
|
||||
});
|
||||
|
||||
// Function to remove a key point input field
|
||||
keyPointsList.addEventListener('click', function (e) {
|
||||
if (e.target && e.target.classList.contains('remove-key-point')) {
|
||||
e.target.closest('.key-point').remove();
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
|
||||
// Save the meta box data
|
||||
function save_key_points_meta_box($post_id) {
|
||||
// Check if this is an autosave or if the nonce is missing
|
||||
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return $post_id;
|
||||
if (!isset($_POST['key_points'])) return $post_id;
|
||||
|
||||
// Sanitize and store the key points as a serialized array
|
||||
$key_points = array_map('sanitize_text_field', $_POST['key_points']);
|
||||
update_post_meta($post_id, 'key_points', serialize($key_points)); // Use serialize instead of json_encode
|
||||
}
|
||||
add_action('save_post', 'save_key_points_meta_box');
|
||||
|
||||
|
||||
|
||||
// Hook the function to the theme activation process
|
||||
|
||||
|
||||
// Function to drop the lcp_icons table when the theme is deactivated
|
||||
function drop_lcp_icons_table() {
|
||||
global $wpdb;
|
||||
|
||||
// Table name with WordPress prefix
|
||||
$table_name = $wpdb->prefix . 'lcp_icons';
|
||||
|
||||
// SQL query to drop the table
|
||||
$sql = "DROP TABLE IF EXISTS $table_name;";
|
||||
|
||||
// Execute the query
|
||||
$wpdb->query($sql);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* 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() {
|
||||
// Path to the JSON file
|
||||
$json_path = get_template_directory() . '/assets/json/icons/icon-definitions.json';
|
||||
|
||||
// Check if the file exists
|
||||
if (file_exists($json_path)) {
|
||||
// Get the contents of the JSON file
|
||||
$json_data = file_get_contents($json_path);
|
||||
|
||||
// Decode JSON data into a PHP array
|
||||
$icon_sets = json_decode($json_data, true);
|
||||
|
||||
// Loop through the icon sets and output HTML
|
||||
foreach ($icon_sets as $icon_set) {
|
||||
?>
|
||||
<div class="icon-set">
|
||||
<h3><?php echo esc_html($icon_set['setFamily'] . ' - ' . $icon_set['setName']); ?></h3>
|
||||
|
||||
<!-- Add data-icon-set-id attribute to the Install and Uninstall buttons -->
|
||||
<button class="install-btn" data-icon-set-id="<?php echo esc_attr($icon_set['id']); ?>">Install</button>
|
||||
<button class="uninstall-btn" data-icon-set-id="<?php echo esc_attr($icon_set['id']); ?>">Uninstall</button>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
} else {
|
||||
echo '<p>' . esc_html__('No icon definitions found.', 'lcp') . '</p>';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Enqueue the dashboard styles only on the icon-management page
|
||||
function mytheme_enqueue_dashboard_styles($hook) {
|
||||
|
||||
|
||||
// Enqueue CSS for the dashboard
|
||||
wp_enqueue_style(
|
||||
'mytheme-dashboard-css',
|
||||
get_template_directory_uri() . '/assets/css/dashboard.css'
|
||||
);
|
||||
}
|
||||
add_action('admin_enqueue_scripts', 'mytheme_enqueue_dashboard_styles');
|
||||
|
||||
|
||||
// Handle the AJAX request for installing icon sets
|
||||
function lcp_install_icon_set($defaults = false) {
|
||||
$json_path = get_template_directory() . '/assets/json/icons/icon-definitions.json';
|
||||
|
||||
if ($defaults) {
|
||||
// Import only the default icons
|
||||
if (file_exists($json_path)) {
|
||||
$json_data = file_get_contents($json_path);
|
||||
$icon_sets = json_decode($json_data, true);
|
||||
|
||||
// Loop through all icon sets and filter for default icons
|
||||
foreach ($icon_sets as $icon_set) {
|
||||
if (isset($icon_set['default']) && $icon_set['default'] === true) {
|
||||
$file_name = $icon_set['fileName']; // Assuming the JSON structure has 'fileName' key
|
||||
$icon_file_path = get_template_directory() . '/assets/json/icons/' . $file_name;
|
||||
|
||||
if (file_exists($icon_file_path)) {
|
||||
$icon_data = file_get_contents($icon_file_path);
|
||||
$icon_json = json_decode($icon_data, true);
|
||||
|
||||
// Check if svgs exist and process them
|
||||
if (isset($icon_json[0]['svgs']) && is_array($icon_json[0]['svgs'])) {
|
||||
foreach ($icon_json[0]['svgs'] as $svg) {
|
||||
global $wpdb;
|
||||
$table_name = $wpdb->prefix . 'lcp_icons';
|
||||
|
||||
// Insert the SVG data into the database
|
||||
$wpdb->insert(
|
||||
$table_name,
|
||||
array(
|
||||
'icon_name' => $svg['name'],
|
||||
'icon_set_id' => $icon_set['id'],
|
||||
'icon_family' => $icon_set['setFamily'],
|
||||
'icon_version' => $icon_set['version'],
|
||||
'paths' => ($svg['paths']),
|
||||
'viewbox' => sanitize_text_field($svg['viewBox']),
|
||||
'icon_id' => sanitize_text_field($svg['id']),
|
||||
)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
wp_send_json_error(array('message' => 'SVGs data not found in the JSON file.'));
|
||||
}
|
||||
} else {
|
||||
wp_send_json_error(array('message' => 'SVG file for default set not found.'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
wp_send_json_error(array('message' => 'Icon definitions file not found.'));
|
||||
}
|
||||
} elseif (isset($_POST['icon_set_id'])) {
|
||||
// Default behavior - check for icon_set_id in $_POST
|
||||
if (!isset($_POST['icon_set_id'])) {
|
||||
wp_send_json_error(array('message' => 'Invalid icon set ID.'));
|
||||
}
|
||||
|
||||
$icon_set_id = intval($_POST['icon_set_id']);
|
||||
|
||||
// Create the database table if it doesn't exist
|
||||
mytheme_create_icons_table();
|
||||
|
||||
// Read the icon definitions JSON file
|
||||
if (file_exists($json_path)) {
|
||||
$json_data = file_get_contents($json_path);
|
||||
$icon_sets = json_decode($json_data, true);
|
||||
|
||||
// Search for the selected icon set by ID
|
||||
$selected_icon_set = null;
|
||||
foreach ($icon_sets as $icon_set) {
|
||||
if ($icon_set['id'] === $icon_set_id) {
|
||||
$selected_icon_set = $icon_set;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If the icon set is found
|
||||
if ($selected_icon_set) {
|
||||
$file_name = $selected_icon_set['fileName']; // Assuming the JSON structure has 'fileName' key
|
||||
$icon_file_path = get_template_directory() . '/assets/json/icons/' . $file_name;
|
||||
|
||||
// Now read the corresponding SVG file for the icon set
|
||||
if (file_exists($icon_file_path)) {
|
||||
$icon_data = file_get_contents($icon_file_path);
|
||||
$icon_json = json_decode($icon_data, true);
|
||||
|
||||
// Check the structure of the decoded JSON
|
||||
if (is_array($icon_json)) {
|
||||
error_log(print_r($icon_json, true)); // Logs to PHP error log for inspection
|
||||
}
|
||||
|
||||
// Loop through svgs if it exists and is an array
|
||||
if (isset($icon_json[0]['svgs']) && is_array($icon_json[0]['svgs'])) {
|
||||
foreach ($icon_json[0]['svgs'] as $svg) {
|
||||
global $wpdb;
|
||||
$table_name = $wpdb->prefix . 'lcp_icons';
|
||||
|
||||
// Insert each SVG data into the database
|
||||
$wpdb->insert(
|
||||
$table_name,
|
||||
array(
|
||||
'icon_name' => $svg['name'],
|
||||
'icon_set_id' => $selected_icon_set['id'],
|
||||
'icon_family' => $selected_icon_set['setFamily'],
|
||||
'icon_version' => $selected_icon_set['version'],
|
||||
'paths' => ($svg['paths']),
|
||||
'viewbox' => sanitize_text_field($svg['viewBox']),
|
||||
'icon_id' => sanitize_text_field($svg['id']),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
wp_send_json_success(array('message' => 'Icon set installed and rows added with actual data.'));
|
||||
} else {
|
||||
wp_send_json_error(array('message' => 'SVGs data not found in the JSON file.'));
|
||||
}
|
||||
} else {
|
||||
wp_send_json_error(array('message' => 'SVG file not found.'));
|
||||
}
|
||||
} else {
|
||||
wp_send_json_error(array('message' => 'Icon set not found.'));
|
||||
}
|
||||
} else {
|
||||
wp_send_json_error(array('message' => 'Icon definitions not found.'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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() {
|
||||
global $wpdb;
|
||||
|
||||
$table_name = $wpdb->prefix . 'lcp_icons';
|
||||
$charset_collate = $wpdb->get_charset_collate();
|
||||
|
||||
// SQL to create the table if it doesn't exist
|
||||
$sql = "CREATE TABLE IF NOT EXISTS $table_name (
|
||||
id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, -- Auto-increment for the ID
|
||||
icon_name VARCHAR(255),
|
||||
icon_set_id VARCHAR(255),
|
||||
icon_family VARCHAR(255),
|
||||
icon_version VARCHAR(50),
|
||||
paths TEXT,
|
||||
viewbox VARCHAR(50),
|
||||
icon_id VARCHAR(255) UNIQUE, -- Unique identifier for each SVG (based on SVG 'id')
|
||||
PRIMARY KEY (id)
|
||||
) $charset_collate;";
|
||||
|
||||
// Include the necessary WordPress file to run dbDelta
|
||||
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
|
||||
dbDelta($sql);
|
||||
}
|
||||
|
||||
|
||||
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() {
|
||||
// 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.'));
|
||||
}
|
||||
|
||||
// Get the icon set ID from the request
|
||||
$icon_set_id = intval($_POST['icon_set_id']); // Ensure it's an integer
|
||||
|
||||
global $wpdb;
|
||||
|
||||
// Define the table name
|
||||
$table_name = $wpdb->prefix . 'lcp_icons';
|
||||
|
||||
// Delete all rows where the icon_set_id matches the passed ID
|
||||
$deleted_rows = $wpdb->delete(
|
||||
$table_name,
|
||||
array('icon_set_id' => $icon_set_id), // Condition to match rows by icon_set_id
|
||||
array('%d') // Sanitize the value as an integer
|
||||
);
|
||||
|
||||
// Check if rows were deleted successfully
|
||||
if ($deleted_rows) {
|
||||
wp_send_json_success(array('message' => 'Icon set uninstalled and icons removed from the database.'));
|
||||
} else {
|
||||
wp_send_json_error(array('message' => 'No icons found for the specified icon set ID.'));
|
||||
}
|
||||
}
|
||||
|
||||
add_action('wp_ajax_uninstall_icon_set', 'mytheme_uninstall_icon_set');
|
||||
|
||||
|
||||
|
||||
18
includes/blocks/lcp-button/.editorconfig
Normal file
18
includes/blocks/lcp-button/.editorconfig
Normal 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
|
||||
30
includes/blocks/lcp-button/.gitignore
vendored
Normal file
30
includes/blocks/lcp-button/.gitignore
vendored
Normal 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
|
||||
101
includes/blocks/lcp-button/build/block.json
Normal file
101
includes/blocks/lcp-button/build/block.json
Normal file
@ -0,0 +1,101 @@
|
||||
{
|
||||
"$schema": "https://schemas.wp.org/trunk/block.json",
|
||||
"apiVersion": 3,
|
||||
"name": "lcp/button",
|
||||
"version": "0.1.0",
|
||||
"title": "Button",
|
||||
"category": "widgets",
|
||||
"icon": "smiley",
|
||||
"description": "A button for various functions or custom urls",
|
||||
"example": {},
|
||||
"supports": {
|
||||
"html": false
|
||||
},
|
||||
"attributes": {
|
||||
"buttonAction": {
|
||||
"type": "string",
|
||||
"default": "customUrl"
|
||||
},
|
||||
"customUrl": {
|
||||
"type": "string",
|
||||
"default": "#"
|
||||
},
|
||||
"buttonText": {
|
||||
"type": "string",
|
||||
"default": "Button Text"
|
||||
},
|
||||
"displayIcon": {
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"iconSource": {
|
||||
"type": "string",
|
||||
"default": "manualSvgPath"
|
||||
},
|
||||
"iconSvgPath": {
|
||||
"type": "string",
|
||||
"default": ""
|
||||
},
|
||||
"iconSvgId": {
|
||||
"type": "string",
|
||||
"default": ""
|
||||
},
|
||||
"iconSvgViewbox": {
|
||||
"type": "string",
|
||||
"default": "0 0 510 510"
|
||||
},
|
||||
"popUpId": {
|
||||
"type": "number"
|
||||
},
|
||||
"manualIconSvgPath": {
|
||||
"type": "string",
|
||||
"default": ""
|
||||
},
|
||||
"buttonHeight": {
|
||||
"type": "string",
|
||||
"default": ""
|
||||
},
|
||||
"buttonPadding": {
|
||||
"type": "object",
|
||||
"default": {
|
||||
"extraLarge": {
|
||||
"top": "10px",
|
||||
"right": "10px",
|
||||
"bottom": "10px",
|
||||
"left": "10px"
|
||||
},
|
||||
"large": {
|
||||
"top": "10px",
|
||||
"right": "10px",
|
||||
"bottom": "10px",
|
||||
"left": "10px"
|
||||
},
|
||||
"medium": {
|
||||
"top": "10px",
|
||||
"right": "10px",
|
||||
"bottom": "10px",
|
||||
"left": "10px"
|
||||
},
|
||||
"small": {
|
||||
"top": "10px",
|
||||
"right": "10px",
|
||||
"bottom": "10px",
|
||||
"left": "10px"
|
||||
}
|
||||
}
|
||||
},
|
||||
"iconHeight": {
|
||||
"type": "string",
|
||||
"default": ""
|
||||
},
|
||||
"iconWidth": {
|
||||
"type": "string",
|
||||
"default": ""
|
||||
}
|
||||
},
|
||||
"textdomain": "lcp",
|
||||
"editorScript": "file:./index.js",
|
||||
"editorStyle": "file:./index.css",
|
||||
"style": "file:./style-index.css",
|
||||
"viewScript": "file:./view.js"
|
||||
}
|
||||
1
includes/blocks/lcp-button/build/index-rtl.css
Normal file
1
includes/blocks/lcp-button/build/index-rtl.css
Normal file
@ -0,0 +1 @@
|
||||
.wp-block-create-block-button{border:1px dotted red}.lcp-button{background-color:var(--wp--preset--color--accent);border:none;color:#fff;cursor:pointer;display:inline-block;font-size:var(--wp--preset--font-size--small);font-weight:700;margin:auto 5px;padding:10px;text-decoration:none;white-space:nowrap}.lcp-button .lcp-icon{height:1.2em;margin-left:10px;max-height:100%;vertical-align:middle;width:auto;fill:#fff}
|
||||
1
includes/blocks/lcp-button/build/index.asset.php
Normal file
1
includes/blocks/lcp-button/build/index.asset.php
Normal file
@ -0,0 +1 @@
|
||||
<?php return array('dependencies' => array('react', 'react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-element', 'wp-i18n'), 'version' => '00e12da1bdf9e61c448a');
|
||||
1
includes/blocks/lcp-button/build/index.css
Normal file
1
includes/blocks/lcp-button/build/index.css
Normal file
@ -0,0 +1 @@
|
||||
.wp-block-create-block-button{border:1px dotted red}.lcp-button{background-color:var(--wp--preset--color--accent);border:none;color:#fff;cursor:pointer;display:inline-block;font-size:var(--wp--preset--font-size--small);font-weight:700;margin:auto 5px;padding:10px;text-decoration:none;white-space:nowrap}.lcp-button .lcp-icon{height:1.2em;margin-right:10px;max-height:100%;vertical-align:middle;width:auto;fill:#fff}
|
||||
1
includes/blocks/lcp-button/build/index.js
Normal file
1
includes/blocks/lcp-button/build/index.js
Normal file
File diff suppressed because one or more lines are too long
1
includes/blocks/lcp-button/build/style-index-rtl.css
Normal file
1
includes/blocks/lcp-button/build/style-index-rtl.css
Normal file
@ -0,0 +1 @@
|
||||
.wp-block-create-block-button{background-color:#21759b;color:#fff;padding:2px}
|
||||
1
includes/blocks/lcp-button/build/style-index.css
Normal file
1
includes/blocks/lcp-button/build/style-index.css
Normal file
@ -0,0 +1 @@
|
||||
.wp-block-create-block-button{background-color:#21759b;color:#fff;padding:2px}
|
||||
1
includes/blocks/lcp-button/build/view.asset.php
Normal file
1
includes/blocks/lcp-button/build/view.asset.php
Normal file
@ -0,0 +1 @@
|
||||
<?php return array('dependencies' => array(), 'version' => '39bd3d2fc52e7ff1ed91');
|
||||
1
includes/blocks/lcp-button/build/view.js
Normal file
1
includes/blocks/lcp-button/build/view.js
Normal file
@ -0,0 +1 @@
|
||||
console.log("Hello World! (from create-block-button block)");
|
||||
@ -0,0 +1,96 @@
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { BaseControl, __experimentalNumberControl as NumberControl, SelectControl, __experimentalHStack as HStack } from '@wordpress/components';
|
||||
import { useState, useEffect } from 'react';
|
||||
|
||||
/**
|
||||
* Control component with a number input and a select dropdown for units (px, rem, em, % etc.).
|
||||
* Accepts a default value as a string (e.g., "15px", "10rem", etc.).
|
||||
* Includes an optional 'auto' unit if includeAuto is true, and handles autoReturnsNull behavior.
|
||||
*/
|
||||
export function DimensionValueControl({ value = '10px', onChange, includeAuto = false, autoReturnsNull = false }) {
|
||||
// Options for select control (CSS units) including 'auto' if enabled
|
||||
const unitOptions = [
|
||||
{ label: __('px'), value: 'px' },
|
||||
{ label: __('%'), value: '%' },
|
||||
{ label: __('em'), value: 'em' },
|
||||
{ label: __('rem'), value: 'rem' },
|
||||
{ label: __('vw'), value: 'vw' },
|
||||
{ label: __('vh'), value: 'vh' },
|
||||
...(includeAuto ? [{ label: __('auto'), value: 'auto' }] : []), // Add 'auto' option if includeAuto is true
|
||||
];
|
||||
|
||||
// Parse the value string into a number and unit
|
||||
const parseValue = (value) => {
|
||||
const regex = /([0-9]+)([a-zA-Z%]+)?/; // Capture the number and the unit
|
||||
const match = value.match(regex);
|
||||
if (match) {
|
||||
return {
|
||||
numberValue: parseInt(match[1], 10), // Number part
|
||||
unitValue: match[2] || 'px' // Unit part (default to 'px' if no unit found)
|
||||
};
|
||||
}
|
||||
return { numberValue: 0, unitValue: 'px' }; // Fallback if invalid format
|
||||
};
|
||||
|
||||
// Use the parsed value to set initial state
|
||||
const { numberValue: initialNumber, unitValue: initialUnit } = parseValue(value);
|
||||
const [numberValue, setNumberValue] = useState(initialNumber);
|
||||
const [unitValue, setUnitValue] = useState(initialUnit);
|
||||
|
||||
// Combine the number and unit into a string like "15px"
|
||||
const dimensionValue = `${numberValue}${unitValue}`;
|
||||
|
||||
// Handle number change
|
||||
const onNumberChange = (newValue) => {
|
||||
setNumberValue(newValue);
|
||||
if (onChange && unitValue !== 'auto') {
|
||||
onChange(`${newValue}${unitValue}`); // Pass updated value back to parent
|
||||
}
|
||||
};
|
||||
|
||||
// Handle unit change
|
||||
const onUnitChange = (newUnit) => {
|
||||
if (newUnit === 'auto') {
|
||||
setNumberValue(null); // Reset the number value when 'auto' is selected
|
||||
}
|
||||
setUnitValue(newUnit);
|
||||
if (onChange) {
|
||||
const updatedValue = newUnit === 'auto'
|
||||
? (autoReturnsNull ? null : 'auto')
|
||||
: `${numberValue}${newUnit}`; // Pass 'auto' or null or updated value back to parent
|
||||
onChange(updatedValue);
|
||||
}
|
||||
};
|
||||
|
||||
// Effect to handle when value prop changes (useful for syncing)
|
||||
useEffect(() => {
|
||||
const { numberValue, unitValue } = parseValue(value);
|
||||
setNumberValue(numberValue);
|
||||
setUnitValue(unitValue);
|
||||
}, [value]);
|
||||
|
||||
return (
|
||||
<BaseControl className="lcp-dimension-value-control">
|
||||
<HStack>
|
||||
{/* Number input control, disabled when 'auto' is selected */}
|
||||
<NumberControl
|
||||
className="lcp-number-control"
|
||||
value={numberValue || ''}
|
||||
onChange={onNumberChange}
|
||||
min={0}
|
||||
step={0.1}
|
||||
spinControls={'none'}
|
||||
disabled={unitValue === 'auto'} // Disable number input if 'auto' is selected
|
||||
/>
|
||||
|
||||
{/* Select dropdown control for units */}
|
||||
<SelectControl
|
||||
className="lcp-select-control"
|
||||
value={unitValue}
|
||||
options={unitOptions}
|
||||
onChange={onUnitChange}
|
||||
/>
|
||||
</HStack>
|
||||
</BaseControl>
|
||||
);
|
||||
}
|
||||
59
includes/blocks/lcp-button/components/IconSelectControl.js
Normal file
59
includes/blocks/lcp-button/components/IconSelectControl.js
Normal file
@ -0,0 +1,59 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { SelectControl } from '@wordpress/components';
|
||||
|
||||
export function IconSelectControl(props) {
|
||||
const { iconSvgId, onIconChange } = props;
|
||||
|
||||
const [iconData, setIconData] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchIconData = async () => {
|
||||
try {
|
||||
const response = await fetch('/wp-json/lcp/v1/icons');
|
||||
const data = await response.json();
|
||||
if (Array.isArray(data) && data.length > 0) {
|
||||
setIconData(data); // Set the fetched data directly
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error fetching icons:', error);
|
||||
}
|
||||
};
|
||||
|
||||
fetchIconData();
|
||||
}, []);
|
||||
|
||||
const handleIconChange = (selectedIconId) => {
|
||||
const selectedIcon = iconData.find(icon => icon.iconSvgId === selectedIconId);
|
||||
if (selectedIcon && onIconChange) {
|
||||
// Send both icon ID and path (SVG) to the parent component
|
||||
onIconChange({
|
||||
iconSvgId: selectedIcon.iconSvgId, // Pass icon ID to parent
|
||||
iconSvgPath: selectedIcon.iconSvgPaths, // Pass icon paths to parent
|
||||
viewbox: selectedIcon.selectedIconViewbox // Pass the viewbox to parent
|
||||
});
|
||||
console.log("Selected Icon ID:", selectedIcon.iconSvgId); // Debugging output
|
||||
console.log("Selected Icon Path:", selectedIcon.iconSvgPaths); // Debugging output
|
||||
console.log("Selected Icon Viewbox:", selectedIcon.selectedIconViewbox); // Debugging output
|
||||
}
|
||||
};
|
||||
|
||||
if (iconData.length === 0) {
|
||||
return <p>{__('Loading icons...', 'lcp')}</p>; // Loading state
|
||||
}
|
||||
|
||||
const iconOptions = iconData.map((icon) => ({
|
||||
value: icon.iconSvgId, // Use icon ID as value for the SelectControl
|
||||
label: icon.name, // Directly use the icon's name as the label
|
||||
}));
|
||||
|
||||
|
||||
return (
|
||||
<SelectControl
|
||||
label={__('Select Icon', 'lcp')}
|
||||
value={iconSvgId} // Current selected icon ID
|
||||
options={iconOptions}
|
||||
onChange={handleIconChange} // Handle icon change
|
||||
/>
|
||||
);
|
||||
}
|
||||
103
includes/blocks/lcp-button/components/PaddingControl.js
Normal file
103
includes/blocks/lcp-button/components/PaddingControl.js
Normal file
@ -0,0 +1,103 @@
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { BaseControl, Button, RangeControl, __experimentalHStack as HStack, __experimentalVStack as VStack } from '@wordpress/components';
|
||||
import { DimensionValueControl } from './DimensionValueControl';
|
||||
|
||||
/**
|
||||
* Padding Control component to manage padding values for different screen sizes.
|
||||
*/
|
||||
export function PaddingControl() {
|
||||
return (
|
||||
<BaseControl className="lcp-padding-control">
|
||||
|
||||
|
||||
{/* Padding label and Unlink button */}
|
||||
<HStack>
|
||||
<span>{__('Padding')}</span>
|
||||
<Button
|
||||
variant="secondary"
|
||||
aria-label={__('Unlink sides')}
|
||||
onClick={() => {}}
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" focusable="false">
|
||||
<path d="M10 17.389H8.444A5.194 5.194 0 1 1 8.444 7H10v1.5H8.444a3.694 3.694 0 0 0 0 7.389H10v1.5ZM14 7h1.556a5.194 5.194 0 0 1 0 10.39H14v-1.5h1.556a3.694 3.694 0 0 0 0-7.39H14V7Zm-4.5 6h5v-1.5h-5V13Z"></path>
|
||||
</svg>
|
||||
</Button>
|
||||
</HStack>
|
||||
|
||||
{/* Extra Large Padding Controls */}
|
||||
{/* Will update all padding values for all screen sizes if updateAllScreenSizes is true */}
|
||||
|
||||
{/* Top and Bottom HStack */}
|
||||
<HStack style={{ flex: 1 }}>
|
||||
{/* Top and Bottom Icon */}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" className="spacing-sizes-control__icon" aria-hidden="true" focusable="false">
|
||||
<path d="m7.5 6h9v-1.5h-9zm0 13.5h9v-1.5h-9zm-3-3h1.5v-9h-1.5zm13.5-9v9h1.5v-9z" style={{ opacity: 0.25 }}></path>
|
||||
<path d="m7.5 6h9v-1.5h-9z"></path>
|
||||
<path d="m7.5 19.5h9v-1.5h-9z"></path>
|
||||
</svg>
|
||||
|
||||
{/* RangeControl wrapped in HStack with flex: 1 applied to its parent */}
|
||||
<HStack style={{ flex: 1 }}>
|
||||
<DimensionValueControl/>
|
||||
<RangeControl
|
||||
withInputField={false}
|
||||
value={10} // Placeholder value
|
||||
onChange={() => {}}
|
||||
min={0}
|
||||
max={50}
|
||||
/>
|
||||
</HStack>
|
||||
|
||||
{/* Custom Padding Button */}
|
||||
<Button
|
||||
style={{padding:0,background:'none',color:'var(--wp-components-color-foreground)'} }
|
||||
variant="primary"
|
||||
onClick={() => {}}
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" focusable="false">
|
||||
<path d="m19 7.5h-7.628c-.3089-.87389-1.1423-1.5-2.122-1.5-.97966 0-1.81309.62611-2.12197 1.5h-2.12803v1.5h2.12803c.30888.87389 1.14231 1.5 2.12197 1.5.9797 0 1.8131-.62611 2.122-1.5h7.628z"></path>
|
||||
<path d="m19 15h-2.128c-.3089-.8739-1.1423-1.5-2.122-1.5s-1.8131.6261-2.122 1.5h-7.628v1.5h7.628c.3089.8739 1.1423 1.5 2.122 1.5s1.8131-.6261 2.122-1.5h2.128z"></path>
|
||||
</svg>
|
||||
</Button>
|
||||
</HStack>
|
||||
|
||||
{/* Left and Right HStack */}
|
||||
<HStack style={{ flex: 1 }}>
|
||||
{/* Left and Right Icon */}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" className="spacing-sizes-control__icon" aria-hidden="true" focusable="false">
|
||||
<path d="m7.5 6h9v-1.5h-9zm0 13.5h9v-1.5h-9zm-3-3h1.5v-9h-1.5zm13.5-9v9h1.5v-9z" style={{ opacity: 0.25 }}></path>
|
||||
<path d="m7.5 6h9v-1.5h-9z"></path>
|
||||
<path d="m4.5 7.5v9h1.5v-9z"></path>
|
||||
<path d="m18 7.5v9h1.5v-9z"></path>
|
||||
</svg>
|
||||
|
||||
{/* RangeControl wrapped in HStack with flex: 1 applied to its parent */}
|
||||
|
||||
<RangeControl
|
||||
withInputField={false}
|
||||
value={10} // Placeholder value
|
||||
onChange={() => {}}
|
||||
min={0}
|
||||
max={50}
|
||||
/>
|
||||
|
||||
|
||||
{/* Custom Padding Button */}
|
||||
<Button
|
||||
variant="primary"
|
||||
onClick={() => {}}
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" focusable="false">
|
||||
<path d="m19 7.5h-7.628c-.3089-.87389-1.1423-1.5-2.122-1.5-.97966 0-1.81309.62611-2.12197 1.5h-2.12803v1.5h2.12803c.30888.87389 1.14231 1.5 2.12197 1.5.9797 0 1.8131-.62611 2.122-1.5h7.628z"></path>
|
||||
<path d="m19 15h-2.128c-.3089-.8739-1.1423-1.5-2.122-1.5s-1.8131.6261-2.122 1.5h-7.628v1.5h7.628c.3089.8739 1.1423 1.5 2.122 1.5s1.8131-.6261 2.122-1.5h2.128z"></path>
|
||||
</svg>
|
||||
</Button>
|
||||
</HStack>
|
||||
|
||||
{/* Additional controls can be added here in a VStack */}
|
||||
<VStack>
|
||||
{/* Placeholder for additional components */}
|
||||
</VStack>
|
||||
</BaseControl>
|
||||
);
|
||||
}
|
||||
69
includes/blocks/lcp-button/lcp-button.php
Normal file
69
includes/blocks/lcp-button/lcp-button.php
Normal file
@ -0,0 +1,69 @@
|
||||
<?php
|
||||
/**
|
||||
* Plugin Name: Button
|
||||
* 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: button
|
||||
*
|
||||
* @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 create_block_button_block_init() {
|
||||
register_block_type( __DIR__ . '/build' );
|
||||
}
|
||||
add_action( 'init', 'create_block_button_block_init' );
|
||||
|
||||
|
||||
/* REST API */
|
||||
function register_icons_rest_api_endpoint() {
|
||||
register_rest_route( 'lcp/v1', '/icons', array(
|
||||
'methods' => 'GET',
|
||||
'callback' => 'get_icons_data_from_db',
|
||||
'permission_callback' => '__return_true', // Public access; modify this if real permissions needed
|
||||
) );
|
||||
}
|
||||
|
||||
add_action( 'rest_api_init', 'register_icons_rest_api_endpoint' );
|
||||
|
||||
function get_icons_data_from_db() {
|
||||
global $wpdb;
|
||||
|
||||
// Query the lcp_icons table
|
||||
$results = $wpdb->get_results(
|
||||
"SELECT icon_id, icon_name, paths, viewbox FROM {$wpdb->prefix}lcp_icons"
|
||||
);
|
||||
|
||||
// If no icons are found, return an empty array
|
||||
if ( empty( $results ) ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Format the results for the frontend
|
||||
$icons = array_map( function( $icon ) {
|
||||
return [
|
||||
'iconSvgId' => $icon->icon_id, // Icon ID
|
||||
'iconSvgPaths' => $icon->paths, // SVG paths (can be multiple)
|
||||
'selectedIconViewbox' => $icon->viewbox, // ViewBox for the SVG
|
||||
'name' => $icon->icon_name, // Add name field
|
||||
];
|
||||
}, $results );
|
||||
|
||||
return $icons;
|
||||
}
|
||||
|
||||
20
includes/blocks/lcp-button/package.json
Normal file
20
includes/blocks/lcp-button/package.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "button",
|
||||
"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.6.0"
|
||||
}
|
||||
}
|
||||
55
includes/blocks/lcp-button/readme.txt
Normal file
55
includes/blocks/lcp-button/readme.txt
Normal file
@ -0,0 +1,55 @@
|
||||
=== Button ===
|
||||
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/button` 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.
|
||||
101
includes/blocks/lcp-button/src/block.json
Normal file
101
includes/blocks/lcp-button/src/block.json
Normal file
@ -0,0 +1,101 @@
|
||||
{
|
||||
"$schema": "https://schemas.wp.org/trunk/block.json",
|
||||
"apiVersion": 3,
|
||||
"name": "lcp/button",
|
||||
"version": "0.1.0",
|
||||
"title": "Button",
|
||||
"category": "widgets",
|
||||
"icon": "smiley",
|
||||
"description": "A button for various functions or custom urls",
|
||||
"example": {},
|
||||
"supports": {
|
||||
"html": false
|
||||
},
|
||||
"attributes": {
|
||||
"buttonAction": {
|
||||
"type": "string",
|
||||
"default": "customUrl"
|
||||
},
|
||||
"customUrl": {
|
||||
"type": "string",
|
||||
"default": "#"
|
||||
},
|
||||
"buttonText": {
|
||||
"type": "string",
|
||||
"default": "Button Text"
|
||||
},
|
||||
"displayIcon": {
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"iconSource": {
|
||||
"type": "string",
|
||||
"default": "manualSvgPath"
|
||||
},
|
||||
"iconSvgPath": {
|
||||
"type": "string",
|
||||
"default": ""
|
||||
},
|
||||
"iconSvgId": {
|
||||
"type": "string",
|
||||
"default": ""
|
||||
},
|
||||
"iconSvgViewbox": {
|
||||
"type": "string",
|
||||
"default": "0 0 510 510"
|
||||
},
|
||||
"popUpId": {
|
||||
"type": "number"
|
||||
},
|
||||
"manualIconSvgPath":{
|
||||
"type": "string",
|
||||
"default": ""
|
||||
},
|
||||
"buttonHeight":{
|
||||
"type": "string",
|
||||
"default": ""
|
||||
},
|
||||
"buttonPadding":{
|
||||
"type": "object",
|
||||
"default": {
|
||||
"extraLarge": {
|
||||
"top": "10px",
|
||||
"right": "10px",
|
||||
"bottom": "10px",
|
||||
"left": "10px"
|
||||
},
|
||||
"large": {
|
||||
"top": "10px",
|
||||
"right": "10px",
|
||||
"bottom": "10px",
|
||||
"left": "10px"
|
||||
},
|
||||
"medium": {
|
||||
"top": "10px",
|
||||
"right": "10px",
|
||||
"bottom": "10px",
|
||||
"left": "10px"
|
||||
},
|
||||
"small": {
|
||||
"top": "10px",
|
||||
"right": "10px",
|
||||
"bottom": "10px",
|
||||
"left": "10px"
|
||||
}
|
||||
}
|
||||
},
|
||||
"iconHeight": {
|
||||
"type": "string",
|
||||
"default": ""
|
||||
},
|
||||
"iconWidth": {
|
||||
"type": "string",
|
||||
"default": ""
|
||||
}
|
||||
},
|
||||
"textdomain": "lcp",
|
||||
"editorScript": "file:./index.js",
|
||||
"editorStyle": "file:./index.css",
|
||||
"style": "file:./style-index.css",
|
||||
"viewScript": "file:./view.js"
|
||||
}
|
||||
145
includes/blocks/lcp-button/src/edit.js
Normal file
145
includes/blocks/lcp-button/src/edit.js
Normal file
@ -0,0 +1,145 @@
|
||||
import { __ } from '@wordpress/i18n';
|
||||
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 { IconSelectControl } from '../components/IconSelectControl';
|
||||
import { PaddingControl } from '../components/PaddingControl';
|
||||
import { DimensionValueControl } from '../components/DimensionValueControl';
|
||||
|
||||
export default function Edit(props) {
|
||||
const { attributes, setAttributes } = props;
|
||||
const { buttonAction, iconHeight, buttonText, iconSvgId, iconSvgPath, iconSvgViewbox, displayIcon, iconSource, customUrl, buttonPadding } = attributes;
|
||||
|
||||
// Handle icon selection from dropdown
|
||||
const handleIconChanges = (selectedIcon) => {
|
||||
console.log("Icon changed:", selectedIcon);
|
||||
if (selectedIcon && selectedIcon.iconSvgPath) {
|
||||
setAttributes({
|
||||
iconSvgPath: selectedIcon.iconSvgPath,
|
||||
iconSvgId: selectedIcon.iconSvgId,
|
||||
iconSvgViewbox: selectedIcon.viewbox
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handleToggleChange = (value) => {
|
||||
setAttributes({ displayIcon: value });
|
||||
};
|
||||
|
||||
const handleCustomUrlChange = (value) => {
|
||||
setAttributes({ customUrl: value });
|
||||
};
|
||||
|
||||
const handlePaddingChange = (value) => {
|
||||
if (typeof value === 'number') {
|
||||
value = `${value}px`;
|
||||
}
|
||||
setAttributes({ buttonPadding: value });
|
||||
};
|
||||
|
||||
// Handle changes to icon height (from the DimensionValueControl)
|
||||
const handleIconHeightChange = (newHeight) => {
|
||||
console.log("New icon height:", newHeight); // Debugging line
|
||||
setAttributes({ iconHeight: newHeight }); // Update the iconHeight attribute
|
||||
};
|
||||
|
||||
const iconSourceOptions = [
|
||||
{ value: 'manualSvgPath', label: 'SVG Path' },
|
||||
{ value: 'iconSelector', label: 'Icon Library' },
|
||||
];
|
||||
|
||||
const buttonActionOptions = [
|
||||
{ value: 'customUrl', label: 'Custom URL' },
|
||||
{ value: 'showLoginForm', label: 'Show Login Form' },
|
||||
{ value: 'logOut', label: 'Open Popup' },
|
||||
{ value: 'shareCurrentPost', label: 'Share Current Post' },
|
||||
{ value: 'displaySidecontent', label: 'Display Sidecontent' }
|
||||
];
|
||||
|
||||
return (
|
||||
<>
|
||||
<InspectorControls>
|
||||
<PanelBody title={__("Button Settings")}>
|
||||
<PaddingControl
|
||||
onChange={handlePaddingChange}
|
||||
/>
|
||||
<SelectControl
|
||||
label={__("Button Action")}
|
||||
value={buttonAction}
|
||||
options={buttonActionOptions}
|
||||
onChange={(value) => setAttributes({ buttonAction: value })}
|
||||
/>
|
||||
{buttonAction === 'customUrl' && (
|
||||
<TextControl
|
||||
label={__("Custom URL")}
|
||||
value={customUrl}
|
||||
onChange={handleCustomUrlChange}
|
||||
/>
|
||||
)}
|
||||
<TextControl
|
||||
label={__("Button Text")}
|
||||
value={buttonText}
|
||||
onChange={(value) => setAttributes({ buttonText: value })}
|
||||
/>
|
||||
<ToggleControl
|
||||
label="Display Icon"
|
||||
checked={displayIcon}
|
||||
onChange={handleToggleChange}
|
||||
/>
|
||||
<DimensionValueControl
|
||||
value={iconHeight} // Pass the current iconHeight to the DimensionValueControl
|
||||
onChange={(newHeight) => setAttributes({ iconHeight: newHeight })} // Update iconHeight when it changes
|
||||
includeAuto={true}
|
||||
autoReturnsNull={true}
|
||||
/>
|
||||
{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) => setAttributes({ iconSvgPath: value })}
|
||||
/>
|
||||
)}
|
||||
{iconSource === 'iconSelector' && (
|
||||
<IconSelectControl
|
||||
iconSvgId={iconSvgId}
|
||||
onIconChange={handleIconChanges}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</PanelBody>
|
||||
</InspectorControls>
|
||||
|
||||
<div {...useBlockProps()}>
|
||||
{buttonAction === 'customUrl' ? (
|
||||
<a href={customUrl} className="lcp-button" style={{ padding: buttonPadding || '10px' }}>
|
||||
{displayIcon && iconSvgPath && (
|
||||
<svg style={{ height: iconHeight }} className="lcp-icon" xmlns="http://www.w3.org/2000/svg" viewBox={iconSvgViewbox || "0 0 576 576"} dangerouslySetInnerHTML={{ __html: iconSvgPath }} />
|
||||
)}
|
||||
<span className="lcp-button-text">
|
||||
{buttonText || 'Button'}
|
||||
</span>
|
||||
</a>
|
||||
) : (
|
||||
<button className="lcp-button" style={{ padding: buttonPadding || '10px' }}>
|
||||
{displayIcon && iconSvgPath && (
|
||||
<svg style={{ height: iconHeight }} className="lcp-icon" xmlns="http://www.w3.org/2000/svg" viewBox={iconSvgViewbox || "0 0 576 576"} dangerouslySetInnerHTML={{ __html: iconSvgPath }} />
|
||||
)}
|
||||
<span className="lcp-button-text">
|
||||
{buttonText || 'Button'}
|
||||
</span>
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
32
includes/blocks/lcp-button/src/editor.scss
Normal file
32
includes/blocks/lcp-button/src/editor.scss
Normal file
@ -0,0 +1,32 @@
|
||||
/**
|
||||
* The following styles get applied inside the editor only.
|
||||
*
|
||||
* Replace them with your own styles or remove the file completely.
|
||||
*/
|
||||
|
||||
.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;
|
||||
}
|
||||
39
includes/blocks/lcp-button/src/index.js
Normal file
39
includes/blocks/lcp-button/src/index.js
Normal 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,
|
||||
} );
|
||||
35
includes/blocks/lcp-button/src/save.js
Normal file
35
includes/blocks/lcp-button/src/save.js
Normal file
@ -0,0 +1,35 @@
|
||||
import { useBlockProps } from '@wordpress/block-editor';
|
||||
|
||||
export default function save(props) {
|
||||
const { attributes } = props;
|
||||
const {displayIcon, buttonText, buttonPadding,iconHeight,iconSvgPath, iconSvgViewbox, buttonAction, customUrl } = attributes; // Destructure buttonText, iconSvgPath, and iconSvgViewbox
|
||||
|
||||
// Get the block props for the button
|
||||
const blockProps = useBlockProps.save();
|
||||
|
||||
// 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 && (
|
||||
<svg style={{ height: iconHeight }} className="lcp-icon" xmlns="http://www.w3.org/2000/svg" viewBox={iconSvgViewbox || "0 0 576 576"} dangerouslySetInnerHTML={{ __html: iconSvgPath }} />
|
||||
)}
|
||||
<span className="lcp-button-text">
|
||||
{buttonText || 'Button'}
|
||||
</span>
|
||||
</a>
|
||||
) : (
|
||||
<button className="lcp-button" style={{ padding: buttonPadding || '10px' }}>
|
||||
{displayIcon && iconSvgPath && (
|
||||
<svg style={{ height: iconHeight }} className="lcp-icon" xmlns="http://www.w3.org/2000/svg" viewBox={iconSvgViewbox || "0 0 576 576"} dangerouslySetInnerHTML={{ __html: iconSvgPath }} />
|
||||
)}
|
||||
<span className="lcp-button-text">
|
||||
{buttonText || 'Button'}
|
||||
</span>
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
13
includes/blocks/lcp-button/src/style.scss
Normal file
13
includes/blocks/lcp-button/src/style.scss
Normal file
@ -0,0 +1,13 @@
|
||||
/**
|
||||
* 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-button {
|
||||
background-color: #21759b;
|
||||
color: #fff;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
25
includes/blocks/lcp-button/src/view.js
Normal file
25
includes/blocks/lcp-button/src/view.js
Normal file
@ -0,0 +1,25 @@
|
||||
/**
|
||||
* 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 create-block-button block)' );
|
||||
/* eslint-enable no-console */
|
||||
18
includes/blocks/lcp-dynamic-container/.editorconfig
Normal file
18
includes/blocks/lcp-dynamic-container/.editorconfig
Normal 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
|
||||
30
includes/blocks/lcp-dynamic-container/.gitignore
vendored
Normal file
30
includes/blocks/lcp-dynamic-container/.gitignore
vendored
Normal 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
|
||||
141
includes/blocks/lcp-dynamic-container/build/block.json
Normal file
141
includes/blocks/lcp-dynamic-container/build/block.json
Normal file
@ -0,0 +1,141 @@
|
||||
{
|
||||
"$schema": "https://schemas.wp.org/trunk/block.json",
|
||||
"apiVersion": 3,
|
||||
"name": "lcp/dynamic-container",
|
||||
"version": "0.1.0",
|
||||
"title": "Dynamic Container",
|
||||
"category": "widgets",
|
||||
"icon": "smiley",
|
||||
"description": "A general purpose container that uses dynamic rendering",
|
||||
"example": {},
|
||||
"supports": {
|
||||
"anchor": true,
|
||||
"align": [
|
||||
"left",
|
||||
"right",
|
||||
"wide",
|
||||
"full"
|
||||
],
|
||||
"background": {
|
||||
"backgroundImage": true,
|
||||
"backgroundSize": true,
|
||||
"__experimentalDefaultControls": {
|
||||
"backgroundImage": true
|
||||
}
|
||||
},
|
||||
"color": {
|
||||
"gradients": true,
|
||||
"background": true,
|
||||
"link": true,
|
||||
"__experimentalDefaultControls": {
|
||||
"background": true,
|
||||
"text": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"attributes": {
|
||||
"maxWidthExtraLarge": {
|
||||
"type": "string"
|
||||
},
|
||||
"maxWidthLarge": {
|
||||
"type": "string"
|
||||
},
|
||||
"maxWidthMedium": {
|
||||
"type": "string"
|
||||
},
|
||||
"maxWidthSmall": {
|
||||
"type": "string"
|
||||
},
|
||||
"minHeightExtraLarge": {
|
||||
"type": "string"
|
||||
},
|
||||
"minHeightLarge": {
|
||||
"type": "string"
|
||||
},
|
||||
"minHeightMedium": {
|
||||
"type": "string"
|
||||
},
|
||||
"minHeightSmall": {
|
||||
"type": "string"
|
||||
},
|
||||
"isBox": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"backgroundColor": {
|
||||
"type": "string"
|
||||
},
|
||||
"entranceAnimation": {
|
||||
"type": "string"
|
||||
},
|
||||
"exitAnimation": {
|
||||
"type": "string"
|
||||
},
|
||||
"overflow": {
|
||||
"type": "string"
|
||||
},
|
||||
"padding": {
|
||||
"type": "object",
|
||||
"default": {
|
||||
"extraLarge": {
|
||||
"top": "0",
|
||||
"right": "0",
|
||||
"bottom": "0",
|
||||
"left": "0"
|
||||
},
|
||||
"large": {
|
||||
"top": "0",
|
||||
"right": "0",
|
||||
"bottom": "0",
|
||||
"left": "0"
|
||||
},
|
||||
"medium": {
|
||||
"top": "0",
|
||||
"right": "0",
|
||||
"bottom": "0",
|
||||
"left": "0"
|
||||
},
|
||||
"small": {
|
||||
"top": "0",
|
||||
"right": "0",
|
||||
"bottom": "0",
|
||||
"left": "0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"margin": {
|
||||
"type": "object",
|
||||
"default": {
|
||||
"extraLarge": {
|
||||
"top": "12px",
|
||||
"right": "0",
|
||||
"bottom": "12px",
|
||||
"left": "0"
|
||||
},
|
||||
"large": {
|
||||
"top": "12px",
|
||||
"right": "0",
|
||||
"bottom": "12px",
|
||||
"left": "0"
|
||||
},
|
||||
"medium": {
|
||||
"top": "12px",
|
||||
"right": "0",
|
||||
"bottom": "12px",
|
||||
"left": "0"
|
||||
},
|
||||
"small": {
|
||||
"top": "12px",
|
||||
"right": "0",
|
||||
"bottom": "12px",
|
||||
"left": "0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"textdomain": "lcp",
|
||||
"editorScript": "file:./index.js",
|
||||
"editorStyle": "file:./index.css",
|
||||
"style": "file:./style-index.css",
|
||||
"viewScript": "file:./view.js"
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
<?php return array('dependencies' => array('react', 'react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-i18n'), 'version' => '40a5279a7e8774abfe4c');
|
||||
1
includes/blocks/lcp-dynamic-container/build/index.js
Normal file
1
includes/blocks/lcp-dynamic-container/build/index.js
Normal file
File diff suppressed because one or more lines are too long
@ -0,0 +1 @@
|
||||
.wp-block-create-block-lcp-viewport{background-color:#21759b;color:#fff;padding:2px}
|
||||
@ -0,0 +1 @@
|
||||
.wp-block-create-block-lcp-viewport{background-color:#21759b;color:#fff;padding:2px}
|
||||
@ -0,0 +1 @@
|
||||
<?php return array('dependencies' => array(), 'version' => 'd4e4a494008d04e1eb42');
|
||||
1
includes/blocks/lcp-dynamic-container/build/view.js
Normal file
1
includes/blocks/lcp-dynamic-container/build/view.js
Normal file
@ -0,0 +1 @@
|
||||
console.log("Hello World! (from create-block-lcp-viewport block)");
|
||||
195
includes/blocks/lcp-dynamic-container/lcp-dynamic-container.php
Normal file
195
includes/blocks/lcp-dynamic-container/lcp-dynamic-container.php
Normal file
@ -0,0 +1,195 @@
|
||||
<?php /**
|
||||
* Function to generate random class and add dynamic padding styles
|
||||
*/
|
||||
if (!function_exists('lcp_random_string')) {
|
||||
|
||||
function lcp_random_string($length = 8, $css_compliant = false, $include_character_types = '') {
|
||||
// Define character sets
|
||||
$lowercase = 'abcdefghijklmnopqrstuvwxyz';
|
||||
$uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||
$numbers = '0123456789';
|
||||
$special_chars = '!@#$%^&*()_+-=[]{}|;:,.<>?';
|
||||
$all_chars = $lowercase . $uppercase . $numbers . $special_chars;
|
||||
|
||||
// Default to using all characters if no specific types are provided
|
||||
if (empty($include_character_types)) {
|
||||
$include_character_types = 'all';
|
||||
}
|
||||
|
||||
// Build the allowed character set
|
||||
$char_set = '';
|
||||
|
||||
if ($include_character_types === 'all') {
|
||||
// Include everything
|
||||
$char_set = $all_chars;
|
||||
} else {
|
||||
// Add specific types requested
|
||||
if (strpos($include_character_types, 'lowercase') !== false) {
|
||||
$char_set .= $lowercase;
|
||||
}
|
||||
if (strpos($include_character_types, 'uppercase') !== false) {
|
||||
$char_set .= $uppercase;
|
||||
}
|
||||
if (strpos($include_character_types, 'numbers') !== false) {
|
||||
$char_set .= $numbers;
|
||||
}
|
||||
if (strpos($include_character_types, 'special') !== false) {
|
||||
$char_set .= $special_chars;
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that the string is valid for CSS (starts with a letter and can only include letters, digits, hyphens, or underscores)
|
||||
$css_char_set = $lowercase . $uppercase . $numbers . '-_';
|
||||
|
||||
// Random string generation logic
|
||||
$random_string = '';
|
||||
$first_char = '';
|
||||
|
||||
// If CSS compliant, start with a letter (either lowercase or uppercase)
|
||||
if ($css_compliant) {
|
||||
// Ensure the first character is a letter (CSS compliant start)
|
||||
$first_char = $lowercase[rand(0, strlen($lowercase) - 1)];
|
||||
$random_string .= $first_char;
|
||||
$length--; // Decrease length by 1 as we already added the first char
|
||||
}
|
||||
|
||||
// Fill the rest of the string with random characters from the valid set (CSS compliant)
|
||||
for ($i = 0; $i < $length; $i++) {
|
||||
// Use only characters that are CSS compliant (letters, digits, hyphens, or underscores)
|
||||
$random_string .= $css_char_set[rand(0, strlen($css_char_set) - 1)];
|
||||
}
|
||||
|
||||
// Return the string
|
||||
return $random_string;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function render_lcp_container( $attributes, $content ) {
|
||||
// Debugging: Check the passed attributes
|
||||
//var_dump($attributes);
|
||||
|
||||
// Generate a random class name (optional, could be customized)
|
||||
$random_class = lcp_random_string(12,true);
|
||||
|
||||
// Get the padding and backgroundColor attributes
|
||||
$padding = isset( $attributes['padding'] ) ? $attributes['padding'] : array();
|
||||
$background_color = isset( $attributes['backgroundColor'] ) ? $attributes['backgroundColor'] : '#ffffff'; // Default color
|
||||
|
||||
// Debugging: Check padding and background color
|
||||
error_log(print_r($padding, true));
|
||||
error_log(print_r($background_color, true));
|
||||
|
||||
// Check if all padding values are the same across all sizes
|
||||
$same_padding = true;
|
||||
$padding_top = $padding['extraLarge']['top'];
|
||||
$padding_right = $padding['extraLarge']['right'];
|
||||
$padding_bottom = $padding['extraLarge']['bottom'];
|
||||
$padding_left = $padding['extraLarge']['left'];
|
||||
|
||||
// Compare the padding for all other sizes (large, medium, small)
|
||||
foreach ( ['large', 'medium', 'small'] as $size ) {
|
||||
if (
|
||||
$padding[$size]['top'] !== $padding_top ||
|
||||
$padding[$size]['right'] !== $padding_right ||
|
||||
$padding[$size]['bottom'] !== $padding_bottom ||
|
||||
$padding[$size]['left'] !== $padding_left
|
||||
) {
|
||||
$same_padding = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare the inline style or media queries
|
||||
$style = '';
|
||||
|
||||
// Add background-color to the inline style
|
||||
$style .= sprintf( 'background-color: %s;', esc_attr( $background_color ) );
|
||||
|
||||
if ( $same_padding ) {
|
||||
// If all padding values are the same, use inline style
|
||||
$style .= sprintf(
|
||||
'padding-top: %s; padding-right: %s; padding-bottom: %s; padding-left: %s;',
|
||||
esc_attr( $padding_top ),
|
||||
esc_attr( $padding_right ),
|
||||
esc_attr( $padding_bottom ),
|
||||
esc_attr( $padding_left )
|
||||
);
|
||||
} else {
|
||||
// If padding is different, generate media queries for different sizes
|
||||
$style .= sprintf(
|
||||
'@media (min-width: 1200px) { .%s { padding-top: %s; padding-right: %s; padding-bottom: %s; padding-left: %s; } }',
|
||||
esc_attr( $random_class ),
|
||||
esc_attr( $padding['extraLarge']['top'] ),
|
||||
esc_attr( $padding['extraLarge']['right'] ),
|
||||
esc_attr( $padding['extraLarge']['bottom'] ),
|
||||
esc_attr( $padding['extraLarge']['left'] )
|
||||
);
|
||||
|
||||
$style .= sprintf(
|
||||
'@media (min-width: 1024px) { .%s { padding-top: %s; padding-right: %s; padding-bottom: %s; padding-left: %s; } }',
|
||||
esc_attr( $random_class ),
|
||||
esc_attr( $padding['large']['top'] ),
|
||||
esc_attr( $padding['large']['right'] ),
|
||||
esc_attr( $padding['large']['bottom'] ),
|
||||
esc_attr( $padding['large']['left'] )
|
||||
);
|
||||
|
||||
$style .= sprintf(
|
||||
'@media (min-width: 768px) { .%s { padding-top: %s; padding-right: %s; padding-bottom: %s; padding-left: %s; } }',
|
||||
esc_attr( $random_class ),
|
||||
esc_attr( $padding['medium']['top'] ),
|
||||
esc_attr( $padding['medium']['right'] ),
|
||||
esc_attr( $padding['medium']['bottom'] ),
|
||||
esc_attr( $padding['medium']['left'] )
|
||||
);
|
||||
|
||||
$style .= sprintf(
|
||||
'@media (max-width: 767px) { .%s { padding-top: %s; padding-right: %s; padding-bottom: %s; padding-left: %s; } }',
|
||||
esc_attr( $random_class ),
|
||||
esc_attr( $padding['small']['top'] ),
|
||||
esc_attr( $padding['small']['right'] ),
|
||||
esc_attr( $padding['small']['bottom'] ),
|
||||
esc_attr( $padding['small']['left'] )
|
||||
);
|
||||
}
|
||||
|
||||
// Generate the <style> tag with the final CSS (either inline or media queries)
|
||||
$style_tag = '';
|
||||
if ( ! empty( $style ) ) {
|
||||
$style_tag = sprintf( '<style>.%s { %s }</style>', esc_attr( $random_class ), $style );
|
||||
}
|
||||
|
||||
// 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
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function to return the media query breakpoint based on the size
|
||||
*/
|
||||
function get_media_query_breakpoint( $size ) {
|
||||
// Define breakpoints for each size
|
||||
$breakpoints = array(
|
||||
'extraLarge' => '1200px',
|
||||
'large' => '1024px',
|
||||
'medium' => '768px',
|
||||
'small' => '480px',
|
||||
);
|
||||
|
||||
return isset( $breakpoints[$size] ) ? $breakpoints[$size] : '480px';
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to initialize the block
|
||||
*/
|
||||
function lcp_dynamic_container_block_init() {
|
||||
register_block_type( __DIR__ . '/build', array(
|
||||
'render_callback' => 'render_lcp_dynamic_container', // Add the render callback here
|
||||
));
|
||||
}
|
||||
add_action( 'init', 'lcp_dynamic_container_block_init' );
|
||||
20
includes/blocks/lcp-dynamic-container/package.json
Normal file
20
includes/blocks/lcp-dynamic-container/package.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "lcp-viewport",
|
||||
"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.4.0"
|
||||
}
|
||||
}
|
||||
55
includes/blocks/lcp-dynamic-container/readme.txt
Normal file
55
includes/blocks/lcp-dynamic-container/readme.txt
Normal file
@ -0,0 +1,55 @@
|
||||
=== Lcp Viewport ===
|
||||
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/lcp-viewport` 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.
|
||||
136
includes/blocks/lcp-dynamic-container/src/block.json
Normal file
136
includes/blocks/lcp-dynamic-container/src/block.json
Normal file
@ -0,0 +1,136 @@
|
||||
{
|
||||
"$schema": "https://schemas.wp.org/trunk/block.json",
|
||||
"apiVersion": 3,
|
||||
"name": "lcp/dynamic-container",
|
||||
"version": "0.1.0",
|
||||
"title": "Dynamic Container",
|
||||
"category": "widgets",
|
||||
"icon": "smiley",
|
||||
"description": "A general purpose container that uses dynamic rendering",
|
||||
"example": {},
|
||||
"supports": {
|
||||
"anchor": true,
|
||||
"align": [ "left", "right", "wide", "full" ],
|
||||
"background": {
|
||||
"backgroundImage": true,
|
||||
"backgroundSize": true,
|
||||
"__experimentalDefaultControls": {
|
||||
"backgroundImage": true
|
||||
}
|
||||
},
|
||||
"color": {
|
||||
"gradients": true,
|
||||
"background": true,
|
||||
"link": true,
|
||||
"__experimentalDefaultControls": {
|
||||
"background": true,
|
||||
"text": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"attributes": {
|
||||
"maxWidthExtraLarge": {
|
||||
"type": "string"
|
||||
},
|
||||
"maxWidthLarge": {
|
||||
"type": "string"
|
||||
},
|
||||
"maxWidthMedium": {
|
||||
"type": "string"
|
||||
},
|
||||
"maxWidthSmall": {
|
||||
"type": "string"
|
||||
},
|
||||
"minHeightExtraLarge": {
|
||||
"type": "string"
|
||||
},
|
||||
"minHeightLarge": {
|
||||
"type": "string"
|
||||
},
|
||||
"minHeightMedium": {
|
||||
"type": "string"
|
||||
},
|
||||
"minHeightSmall": {
|
||||
"type": "string"
|
||||
},
|
||||
"isBox": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"backgroundColor": {
|
||||
"type": "string"
|
||||
},
|
||||
"entranceAnimation": {
|
||||
"type": "string"
|
||||
},
|
||||
"exitAnimation": {
|
||||
"type": "string"
|
||||
},
|
||||
|
||||
"overflow": {
|
||||
"type": "string"
|
||||
},
|
||||
"padding": {
|
||||
"type": "object",
|
||||
"default": {
|
||||
"extraLarge": {
|
||||
"top": "0",
|
||||
"right": "0",
|
||||
"bottom": "0",
|
||||
"left": "0"
|
||||
},
|
||||
"large": {
|
||||
"top": "0",
|
||||
"right": "0",
|
||||
"bottom": "0",
|
||||
"left": "0"
|
||||
},
|
||||
"medium": {
|
||||
"top": "0",
|
||||
"right": "0",
|
||||
"bottom": "0",
|
||||
"left": "0"
|
||||
},
|
||||
"small": {
|
||||
"top": "0",
|
||||
"right": "0",
|
||||
"bottom": "0",
|
||||
"left": "0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"margin": {
|
||||
"type": "object",
|
||||
"default": {
|
||||
"extraLarge": {
|
||||
"top": "12px",
|
||||
"right": "0",
|
||||
"bottom": "12px",
|
||||
"left": "0"
|
||||
},
|
||||
"large": {
|
||||
"top": "12px",
|
||||
"right": "0",
|
||||
"bottom": "12px",
|
||||
"left": "0"
|
||||
},
|
||||
"medium": {
|
||||
"top": "12px",
|
||||
"right": "0",
|
||||
"bottom": "12px",
|
||||
"left": "0"
|
||||
},
|
||||
"small": {
|
||||
"top": "12px",
|
||||
"right": "0",
|
||||
"bottom": "12px",
|
||||
"left": "0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"textdomain": "lcp",
|
||||
"editorScript": "file:./index.js",
|
||||
"editorStyle": "file:./index.css",
|
||||
"style": "file:./style-index.css",
|
||||
"viewScript": "file:./view.js"}
|
||||
211
includes/blocks/lcp-dynamic-container/src/edit.js
Normal file
211
includes/blocks/lcp-dynamic-container/src/edit.js
Normal file
@ -0,0 +1,211 @@
|
||||
import { useBlockProps, InnerBlocks, InspectorControls } from '@wordpress/block-editor';
|
||||
import { __experimentalToggleGroupControl as ToggleGroupControl,
|
||||
__experimentalToggleGroupControlOption as ToggleGroupControlOption, __experimentalUnitControl as UnitControl, BaseControl, ToggleControl, ColorPalette, Popover, Button } from '@wordpress/components';
|
||||
import { useState, useEffect } from 'react';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @param {Object} props - The props for the block.
|
||||
* @return {Element} Element to render.
|
||||
*/
|
||||
export default function Edit({ attributes, setAttributes }) {
|
||||
const blockProps = useBlockProps();
|
||||
const { padding, maxWidthLarge, maxWidthMedium, maxWidthSmall, minHeightLarge, minHeightMedium, minHeightSmall, backgroundColor } = attributes; // Destructure necessary attributes
|
||||
|
||||
// State for independent padding toggle
|
||||
const [isIndependentLarge, setIsIndependentLarge] = useState(false);
|
||||
|
||||
// Toggle to show or hide the color picker popover
|
||||
const [showColorPopover, setShowColorPopover] = useState(false);
|
||||
const [selectedColor, setSelectedColor] = useState(backgroundColor || '#ffffff'); // Default color
|
||||
|
||||
// Toggle padding for individual sizes
|
||||
const handleToggleChange = () => {
|
||||
setIsIndependentLarge(!isIndependentLarge);
|
||||
};
|
||||
|
||||
// Update padding for all sizes
|
||||
const updatePaddingForAllSizes = (newValue) => {
|
||||
const newPadding = {
|
||||
extraLarge: { top: newValue, right: newValue, bottom: newValue, left: newValue },
|
||||
large: { top: newValue, right: newValue, bottom: newValue, left: newValue },
|
||||
medium: { top: newValue, right: newValue, bottom: newValue, left: newValue },
|
||||
small: { top: newValue, right: newValue, bottom: newValue, left: newValue }
|
||||
};
|
||||
setAttributes({ padding: newPadding });
|
||||
};
|
||||
|
||||
// Handle individual padding changes
|
||||
const handlePaddingChange = (size, position, newValue) => {
|
||||
const updatedPadding = { ...padding };
|
||||
updatedPadding[size][position] = newValue;
|
||||
setAttributes({ padding: updatedPadding });
|
||||
};
|
||||
|
||||
// Handle color change
|
||||
const handleColorChange = (color) => {
|
||||
setSelectedColor(color);
|
||||
setAttributes({ backgroundColor: color }); // Update background color
|
||||
};
|
||||
|
||||
// Handle maxWidth change for different sizes
|
||||
const handleMaxWidthChange = (value, size) => {
|
||||
setAttributes({ [`maxWidth${size}`]: value });
|
||||
};
|
||||
|
||||
// Handle minHeight change for different sizes
|
||||
const handleMinHeightChange = (value, size) => {
|
||||
setAttributes({ [`minHeight${size}`]: value });
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
console.log("Updated attributes:", attributes);
|
||||
}, [attributes]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<InspectorControls>
|
||||
<ToggleGroupControl
|
||||
label="my label"
|
||||
value="vertical"
|
||||
isBlock
|
||||
__nextHasNoMarginBottom
|
||||
__next40pxDefaultSize
|
||||
>
|
||||
<ToggleGroupControlOption value="horizontal" label="Horizontal" />
|
||||
<ToggleGroupControlOption value="vertical" label="Vertical" />
|
||||
</ToggleGroupControl>
|
||||
{/* BaseControl for padding */}
|
||||
<BaseControl label="Padding - Desktop">
|
||||
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
||||
<span style={{ marginRight: '10px' }}>Padding</span>
|
||||
<ToggleControl
|
||||
label="Use Independent Padding"
|
||||
checked={isIndependentLarge}
|
||||
onChange={handleToggleChange}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Padding controls */}
|
||||
{isIndependentLarge ? (
|
||||
<div style={{ display: 'grid', padding: '10px', gridTemplateColumns: '1fr 1fr', gap: '10px', justifyItems: 'center' }}>
|
||||
{/* Padding controls for top, left, right, bottom */}
|
||||
<fieldset style={{ gridColumn: 'span 2', width: '116px' }}>
|
||||
<legend>Top</legend>
|
||||
<UnitControl
|
||||
value={padding.extraLarge?.top || '10px'}
|
||||
onChange={(newValue) => handlePaddingChange('extraLarge', 'top', newValue)}
|
||||
/>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>Left</legend>
|
||||
<UnitControl
|
||||
value={padding.extraLarge?.left || '10px'}
|
||||
onChange={(newValue) => handlePaddingChange('extraLarge', 'left', newValue)}
|
||||
/>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>Right</legend>
|
||||
<UnitControl
|
||||
value={padding.extraLarge?.right || '10px'}
|
||||
onChange={(newValue) => handlePaddingChange('extraLarge', 'right', newValue)}
|
||||
/>
|
||||
</fieldset>
|
||||
<fieldset style={{ gridColumn: 'span 2', width: '116px' }}>
|
||||
<legend>Bottom</legend>
|
||||
<UnitControl
|
||||
value={padding.extraLarge?.bottom || '10px'}
|
||||
onChange={(newValue) => handlePaddingChange('extraLarge', 'bottom', newValue)}
|
||||
/>
|
||||
</fieldset>
|
||||
</div>
|
||||
) : (
|
||||
<UnitControl
|
||||
label="Padding Value"
|
||||
value={999} // You can replace this with an attribute value
|
||||
onChange={updatePaddingForAllSizes}
|
||||
/>
|
||||
)}
|
||||
</BaseControl>
|
||||
|
||||
{/* Max Width Controls */}
|
||||
<BaseControl label="Max Width">
|
||||
<div style={{ display: 'flex', flexDirection: 'column' }}>
|
||||
<UnitControl
|
||||
label="Large"
|
||||
value={maxWidthLarge}
|
||||
onChange={(value) => handleMaxWidthChange(value, 'Large')}
|
||||
defaultUnit="px"
|
||||
/>
|
||||
<UnitControl
|
||||
label="Medium"
|
||||
value={maxWidthMedium}
|
||||
onChange={(value) => handleMaxWidthChange(value, 'Medium')}
|
||||
defaultUnit="px"
|
||||
/>
|
||||
<UnitControl
|
||||
label="Small"
|
||||
value={maxWidthSmall}
|
||||
onChange={(value) => handleMaxWidthChange(value, 'Small')}
|
||||
defaultUnit="px"
|
||||
/>
|
||||
</div>
|
||||
</BaseControl>
|
||||
|
||||
{/* Min Height Controls */}
|
||||
<BaseControl label="Min Height">
|
||||
<div style={{ display: 'flex', flexDirection: 'column' }}>
|
||||
<UnitControl
|
||||
label="Large"
|
||||
value={minHeightLarge}
|
||||
onChange={(value) => handleMinHeightChange(value, 'Large')}
|
||||
defaultUnit="px"
|
||||
/>
|
||||
<UnitControl
|
||||
label="Medium"
|
||||
value={minHeightMedium}
|
||||
onChange={(value) => handleMinHeightChange(value, 'Medium')}
|
||||
defaultUnit="px"
|
||||
/>
|
||||
<UnitControl
|
||||
label="Small"
|
||||
value={minHeightSmall}
|
||||
onChange={(value) => handleMinHeightChange(value, 'Small')}
|
||||
defaultUnit="px"
|
||||
/>
|
||||
</div>
|
||||
</BaseControl>
|
||||
|
||||
{/* Background color picker */}
|
||||
<BaseControl label={__('Background Color')}>
|
||||
<div>
|
||||
<Button onClick={() => setShowColorPopover(!showColorPopover)}>
|
||||
{__('Choose Background Color')}
|
||||
</Button>
|
||||
|
||||
{showColorPopover && (
|
||||
<Popover position="bottom center">
|
||||
<ColorPalette
|
||||
value={selectedColor}
|
||||
onChange={handleColorChange}
|
||||
colors={[{ name: "Primary", slug: "primary", color: "#3E5062" }, { name: "Secondary", slug: "secondary", color: "#2B3843" }, { name: "Light Color - 1", slug: "light-color-1", color: "#ECF0F5" }, { name: "Dark Gray", slug: "dark-gray", color: "#333333" }, { name: "Accent", slug: "accent", color: "#61FFB6" }]}
|
||||
disableCustomColors={false}
|
||||
/>
|
||||
</Popover>
|
||||
)}
|
||||
|
||||
{/* Color indicator */}
|
||||
<div style={{ backgroundColor: selectedColor, width: '30px', height: '30px', marginTop: '10px', borderRadius: '50%' }}></div>
|
||||
</div>
|
||||
</BaseControl>
|
||||
</InspectorControls>
|
||||
|
||||
<div {...blockProps} style={{ maxWidth: maxWidthLarge, minHeight: minHeightLarge }}>
|
||||
<InnerBlocks />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
9
includes/blocks/lcp-dynamic-container/src/editor.scss
Normal file
9
includes/blocks/lcp-dynamic-container/src/editor.scss
Normal 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-lcp-viewport {
|
||||
border: 1px dotted #f00;
|
||||
}
|
||||
39
includes/blocks/lcp-dynamic-container/src/index.js
Normal file
39
includes/blocks/lcp-dynamic-container/src/index.js
Normal 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,
|
||||
} );
|
||||
12
includes/blocks/lcp-dynamic-container/src/save.js
Normal file
12
includes/blocks/lcp-dynamic-container/src/save.js
Normal file
@ -0,0 +1,12 @@
|
||||
import { useBlockProps, InnerBlocks } from '@wordpress/block-editor';
|
||||
|
||||
export default function Save() {
|
||||
// Block props
|
||||
const blockProps = useBlockProps.save();
|
||||
|
||||
return (
|
||||
<div {...blockProps}>
|
||||
<InnerBlocks.Content />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
12
includes/blocks/lcp-dynamic-container/src/style.scss
Normal file
12
includes/blocks/lcp-dynamic-container/src/style.scss
Normal file
@ -0,0 +1,12 @@
|
||||
/**
|
||||
* 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-lcp-viewport {
|
||||
background-color: #21759b;
|
||||
color: #fff;
|
||||
padding: 2px;
|
||||
}
|
||||
25
includes/blocks/lcp-dynamic-container/src/view.js
Normal file
25
includes/blocks/lcp-dynamic-container/src/view.js
Normal file
@ -0,0 +1,25 @@
|
||||
/**
|
||||
* 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 create-block-lcp-viewport block)' );
|
||||
/* eslint-enable no-console */
|
||||
18
includes/blocks/lcp-footer-container/.editorconfig
Normal file
18
includes/blocks/lcp-footer-container/.editorconfig
Normal 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
|
||||
30
includes/blocks/lcp-footer-container/.gitignore
vendored
Normal file
30
includes/blocks/lcp-footer-container/.gitignore
vendored
Normal 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
|
||||
29
includes/blocks/lcp-footer-container/build/block.json
Normal file
29
includes/blocks/lcp-footer-container/build/block.json
Normal file
@ -0,0 +1,29 @@
|
||||
{
|
||||
"$schema": "https://schemas.wp.org/trunk/block.json",
|
||||
"apiVersion": 3,
|
||||
"name": "lcp/footer-container",
|
||||
"version": "0.1.0",
|
||||
"title": "Footer Container",
|
||||
"category": "widgets",
|
||||
"icon": "smiley",
|
||||
"description": "A container for inserting the footer",
|
||||
"example": {},
|
||||
"supports": {
|
||||
"color": {
|
||||
"background": true,
|
||||
"text": false,
|
||||
"link": false
|
||||
}
|
||||
},
|
||||
"attributes": {
|
||||
"sticky": {
|
||||
"type": "string",
|
||||
"default": "never"
|
||||
}
|
||||
},
|
||||
"textdomain": "lcp",
|
||||
"editorScript": "file:./index.js",
|
||||
"editorStyle": "file:./index.css",
|
||||
"style": "file:./style-index.css",
|
||||
"viewScript": "file:./view.js"
|
||||
}
|
||||
1
includes/blocks/lcp-footer-container/build/index-rtl.css
Normal file
1
includes/blocks/lcp-footer-container/build/index-rtl.css
Normal file
@ -0,0 +1 @@
|
||||
.wp-block-create-block-lcp-viewport{border:1px dotted red}
|
||||
@ -0,0 +1 @@
|
||||
<?php return array('dependencies' => array('react', 'react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-i18n'), 'version' => 'f3a49fcf497c8df94623');
|
||||
1
includes/blocks/lcp-footer-container/build/index.css
Normal file
1
includes/blocks/lcp-footer-container/build/index.css
Normal file
@ -0,0 +1 @@
|
||||
.wp-block-create-block-lcp-viewport{border:1px dotted red}
|
||||
1
includes/blocks/lcp-footer-container/build/index.js
Normal file
1
includes/blocks/lcp-footer-container/build/index.js
Normal file
@ -0,0 +1 @@
|
||||
(()=>{"use strict";var e,t={717:()=>{const e=window.wp.blocks,t=window.wp.i18n,n=window.wp.blockEditor,l=window.wp.components,o=window.React,r=window.ReactJSXRuntime,i=JSON.parse('{"UU":"lcp/footer-container"}');(0,e.registerBlockType)(i.UU,{edit:function({attributes:e,setAttributes:i}){const[s,a]=(0,o.useState)(!1),[d,p]=(0,o.useState)("10px"),[c,x]=(0,o.useState)("10px"),[g,h]=(0,o.useState)("10px"),[u,v]=(0,o.useState)("10px"),{sticky:f}=e,j=(0,n.useBlockProps)();return(0,r.jsxs)("div",{...j,children:[(0,r.jsxs)(n.InspectorControls,{children:[(0,r.jsx)(l.SelectControl,{label:(0,t.__)("Sticky Behavior","lcp"),value:f,options:[{label:(0,t.__)("Never","lcp"),value:"never"},{label:(0,t.__)("On Scroll","lcp"),value:"onScroll"},{label:(0,t.__)("Always","lcp"),value:"always"}],onChange:e=>{i({sticky:e})}}),(0,r.jsxs)(l.BaseControl,{label:"Padding - Desktop",children:[(0,r.jsxs)("div",{style:{display:"flex",flexDirection:"row"},children:[(0,r.jsx)("span",{style:{marginRight:"10px"},children:"Padding"}),(0,r.jsx)(l.ToggleControl,{label:"Use Independent Padding",checked:s,onChange:()=>{a(!s)}})]}),s?(0,r.jsxs)("div",{style:{display:"grid",padding:"10px",gridTemplateColumns:"1fr 1fr",gap:"10px",justifyItems:"center"},children:[(0,r.jsxs)("fieldset",{style:{gridColumn:"span 2",width:"116px"},children:[(0,r.jsx)("legend",{children:"Top"}),(0,r.jsx)(l.__experimentalUnitControl,{value:d,onChange:e=>{p(e),i({paddingTop:e})}})]}),(0,r.jsxs)("fieldset",{children:[(0,r.jsx)("legend",{children:"Left"}),(0,r.jsx)(l.__experimentalUnitControl,{value:u,onChange:e=>{v(e),i({paddingLeft:e})}})]}),(0,r.jsxs)("fieldset",{children:[(0,r.jsx)("legend",{children:"Right"}),(0,r.jsx)(l.__experimentalUnitControl,{value:c,onChange:e=>{x(e),i({paddingRight:e})}})]}),(0,r.jsxs)("fieldset",{style:{gridColumn:"span 2",width:"116px"},children:[(0,r.jsx)("legend",{children:"Bottom"}),(0,r.jsx)(l.__experimentalUnitControl,{value:g,onChange:e=>{h(e),i({paddingBottom:e})}})]})]}):(0,r.jsx)(l.__experimentalUnitControl,{label:"Padding Value",value:999,onChange:e=>{i({padding:{extraLarge:{top:e,right:e,bottom:e,left:e},large:{top:e,right:e,bottom:e,left:e},medium:{top:e,right:e,bottom:e,left:e},small:{top:e,right:e,bottom:e,left:e}}})}})]})]}),(0,r.jsx)(n.InnerBlocks,{template:[["core/template-part",{slug:"footer"}]]})]})},save:function({attributes:e}){const{sticky:t}=e,l=n.useBlockProps.save();return(0,r.jsx)("div",{...l,className:"lcp",id:"lcp-footer-container",children:(0,r.jsx)(n.InnerBlocks.Content,{})})}})}},n={};function l(e){var o=n[e];if(void 0!==o)return o.exports;var r=n[e]={exports:{}};return t[e](r,r.exports,l),r.exports}l.m=t,e=[],l.O=(t,n,o,r)=>{if(!n){var i=1/0;for(p=0;p<e.length;p++){n=e[p][0],o=e[p][1],r=e[p][2];for(var s=!0,a=0;a<n.length;a++)(!1&r||i>=r)&&Object.keys(l.O).every((e=>l.O[e](n[a])))?n.splice(a--,1):(s=!1,r<i&&(i=r));if(s){e.splice(p--,1);var d=o();void 0!==d&&(t=d)}}return t}r=r||0;for(var p=e.length;p>0&&e[p-1][2]>r;p--)e[p]=e[p-1];e[p]=[n,o,r]},l.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e={57:0,350:0};l.O.j=t=>0===e[t];var t=(t,n)=>{var o,r,i=n[0],s=n[1],a=n[2],d=0;if(i.some((t=>0!==e[t]))){for(o in s)l.o(s,o)&&(l.m[o]=s[o]);if(a)var p=a(l)}for(t&&t(n);d<i.length;d++)r=i[d],l.o(e,r)&&e[r]&&e[r][0](),e[r]=0;return l.O(p)},n=self.webpackChunklcp_viewport=self.webpackChunklcp_viewport||[];n.forEach(t.bind(null,0)),n.push=t.bind(null,n.push.bind(n))})();var o=l.O(void 0,[350],(()=>l(717)));o=l.O(o)})();
|
||||
@ -0,0 +1 @@
|
||||
.wp-block-create-block-lcp-viewport{background-color:#21759b;color:#fff;padding:2px}
|
||||
@ -0,0 +1 @@
|
||||
.wp-block-create-block-lcp-viewport{background-color:#21759b;color:#fff;padding:2px}
|
||||
@ -0,0 +1 @@
|
||||
<?php return array('dependencies' => array(), 'version' => 'd4e4a494008d04e1eb42');
|
||||
1
includes/blocks/lcp-footer-container/build/view.js
Normal file
1
includes/blocks/lcp-footer-container/build/view.js
Normal file
@ -0,0 +1 @@
|
||||
console.log("Hello World! (from create-block-lcp-viewport block)");
|
||||
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
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 lcp_footer_container_block_init() {
|
||||
register_block_type( __DIR__ . '/build' , array(
|
||||
'parent' => array( 'lcp/viewport', 'lcp/main-area' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
add_action( 'init', 'lcp_footer_container_block_init' );
|
||||
20
includes/blocks/lcp-footer-container/package.json
Normal file
20
includes/blocks/lcp-footer-container/package.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "lcp-viewport",
|
||||
"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.4.0"
|
||||
}
|
||||
}
|
||||
55
includes/blocks/lcp-footer-container/readme.txt
Normal file
55
includes/blocks/lcp-footer-container/readme.txt
Normal file
@ -0,0 +1,55 @@
|
||||
=== Lcp Viewport ===
|
||||
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/lcp-viewport` 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.
|
||||
30
includes/blocks/lcp-footer-container/src/block.json
Normal file
30
includes/blocks/lcp-footer-container/src/block.json
Normal file
@ -0,0 +1,30 @@
|
||||
{
|
||||
"$schema": "https://schemas.wp.org/trunk/block.json",
|
||||
"apiVersion": 3,
|
||||
"name": "lcp/footer-container",
|
||||
"version": "0.1.0",
|
||||
"title": "Footer Container",
|
||||
"category": "widgets",
|
||||
"icon": "smiley",
|
||||
|
||||
"description": "A container for inserting the footer",
|
||||
"example": {},
|
||||
"supports": {
|
||||
"color": {
|
||||
"background": true,
|
||||
"text": false,
|
||||
"link": false
|
||||
}
|
||||
},
|
||||
"attributes": {
|
||||
"sticky": {
|
||||
"type": "string",
|
||||
"default": "never"
|
||||
}
|
||||
},
|
||||
"textdomain": "lcp",
|
||||
"editorScript": "file:./index.js",
|
||||
"editorStyle": "file:./index.css",
|
||||
"style": "file:./style-index.css",
|
||||
"viewScript": "file:./view.js"
|
||||
}
|
||||
153
includes/blocks/lcp-footer-container/src/edit.js
Normal file
153
includes/blocks/lcp-footer-container/src/edit.js
Normal file
@ -0,0 +1,153 @@
|
||||
/**
|
||||
* 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, InnerBlocks, InspectorControls } from '@wordpress/block-editor';
|
||||
import { SelectControl, BaseControl, ToggleControl,__experimentalUnitControl as UnitControl } from '@wordpress/components';
|
||||
import { useState, useEffect } from 'react';
|
||||
/**
|
||||
* 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({ attributes, setAttributes }) {
|
||||
|
||||
const [isIndependentLarge, setIsIndependentLarge] = useState(false);
|
||||
|
||||
const [paddingTop, setPaddingTop] = useState('10px');
|
||||
const [paddingRight, setPaddingRight] = useState('10px');
|
||||
const [paddingBottom, setPaddingBottom] = useState('10px');
|
||||
const [paddingLeft, setPaddingLeft] = useState('10px');
|
||||
|
||||
const { sticky } = attributes;
|
||||
|
||||
// Block props for the outer block
|
||||
const blockProps = useBlockProps();
|
||||
|
||||
// Handle the change of the sticky attribute
|
||||
const handleStickyChange = (value) => {
|
||||
setAttributes({ sticky: value });
|
||||
};
|
||||
const handleToggleChange = () => {
|
||||
setIsIndependentLarge(!isIndependentLarge);
|
||||
};
|
||||
|
||||
const updatePaddingForAllSizes = (newValue) => {
|
||||
const newPadding = {
|
||||
extraLarge: { top: newValue, right: newValue, bottom: newValue, left: newValue },
|
||||
large: { top: newValue, right: newValue, bottom: newValue, left: newValue },
|
||||
medium: { top: newValue, right: newValue, bottom: newValue, left: newValue },
|
||||
small: { top: newValue, right: newValue, bottom: newValue, left: newValue }
|
||||
};
|
||||
|
||||
// Update the padding attribute with the new padding object
|
||||
setAttributes({ padding: newPadding });
|
||||
};
|
||||
return (
|
||||
<div {...blockProps}>
|
||||
{/* Inspector Controls: Add a SelectControl to change the sticky attribute */}
|
||||
<InspectorControls>
|
||||
<SelectControl
|
||||
label={__('Sticky Behavior', 'lcp')}
|
||||
value={sticky}
|
||||
options={[
|
||||
{ label: __('Never', 'lcp'), value: 'never' },
|
||||
{ label: __('On Scroll', 'lcp'), value: 'onScroll' },
|
||||
{ label: __('Always', 'lcp'), value: 'always' },
|
||||
]}
|
||||
onChange={handleStickyChange}
|
||||
/>
|
||||
<BaseControl label="Padding - Desktop">
|
||||
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
||||
<span style={{ marginRight: '10px' }}>Padding</span>
|
||||
<ToggleControl
|
||||
label="Use Independent Padding"
|
||||
checked={isIndependentLarge}
|
||||
onChange={handleToggleChange}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Padding controls */}
|
||||
{isIndependentLarge ? (
|
||||
<div style={{ display: 'grid', padding: '10px', gridTemplateColumns: '1fr 1fr', gap: '10px', justifyItems: 'center' }}>
|
||||
{/* Padding controls for top, left, right, bottom */}
|
||||
<fieldset style={{ gridColumn: 'span 2', width: '116px' }}>
|
||||
<legend>Top</legend>
|
||||
<UnitControl
|
||||
value={paddingTop}
|
||||
onChange={(newValue) => {
|
||||
setPaddingTop(newValue);
|
||||
setAttributes({ paddingTop: newValue });
|
||||
}}
|
||||
/>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>Left</legend>
|
||||
<UnitControl
|
||||
value={paddingLeft}
|
||||
onChange={(newValue) => {
|
||||
setPaddingLeft(newValue);
|
||||
setAttributes({ paddingLeft: newValue });
|
||||
}}
|
||||
/>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>Right</legend>
|
||||
<UnitControl
|
||||
value={paddingRight}
|
||||
onChange={(newValue) => {
|
||||
setPaddingRight(newValue);
|
||||
setAttributes({ paddingRight: newValue });
|
||||
}}
|
||||
/>
|
||||
</fieldset>
|
||||
<fieldset style={{ gridColumn: 'span 2', width: '116px' }}>
|
||||
<legend>Bottom</legend>
|
||||
<UnitControl
|
||||
value={paddingBottom}
|
||||
onChange={(newValue) => {
|
||||
setPaddingBottom(newValue);
|
||||
setAttributes({ paddingBottom: newValue });
|
||||
}}
|
||||
/>
|
||||
</fieldset>
|
||||
</div>
|
||||
) : (
|
||||
<UnitControl
|
||||
label="Padding Value"
|
||||
value={999}
|
||||
onChange={updatePaddingForAllSizes}
|
||||
/>
|
||||
)}
|
||||
</BaseControl>
|
||||
</InspectorControls>
|
||||
|
||||
|
||||
<InnerBlocks
|
||||
template= {[
|
||||
["core/template-part", {slug:'footer'}]]
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
9
includes/blocks/lcp-footer-container/src/editor.scss
Normal file
9
includes/blocks/lcp-footer-container/src/editor.scss
Normal 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-lcp-viewport {
|
||||
border: 1px dotted #f00;
|
||||
}
|
||||
39
includes/blocks/lcp-footer-container/src/index.js
Normal file
39
includes/blocks/lcp-footer-container/src/index.js
Normal 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,
|
||||
} );
|
||||
33
includes/blocks/lcp-footer-container/src/save.js
Normal file
33
includes/blocks/lcp-footer-container/src/save.js
Normal file
@ -0,0 +1,33 @@
|
||||
/**
|
||||
* 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, InnerBlocks } from '@wordpress/block-editor';
|
||||
|
||||
/**
|
||||
* 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({ attributes }) {
|
||||
// Destructure the 'sticky' attribute from the block attributes
|
||||
const { sticky } = attributes;
|
||||
|
||||
// Block props
|
||||
const blockProps = useBlockProps.save();
|
||||
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<div {...blockProps} className={"lcp"} id="lcp-footer-container">
|
||||
<InnerBlocks.Content />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
12
includes/blocks/lcp-footer-container/src/style.scss
Normal file
12
includes/blocks/lcp-footer-container/src/style.scss
Normal file
@ -0,0 +1,12 @@
|
||||
/**
|
||||
* 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-lcp-viewport {
|
||||
background-color: #21759b;
|
||||
color: #fff;
|
||||
padding: 2px;
|
||||
}
|
||||
25
includes/blocks/lcp-footer-container/src/view.js
Normal file
25
includes/blocks/lcp-footer-container/src/view.js
Normal file
@ -0,0 +1,25 @@
|
||||
/**
|
||||
* 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 create-block-lcp-viewport block)' );
|
||||
/* eslint-enable no-console */
|
||||
18
includes/blocks/lcp-gallery/.editorconfig
Normal file
18
includes/blocks/lcp-gallery/.editorconfig
Normal 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
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user