Added lcp-ui.js and changes to blocks

This commit is contained in:
Jeremy Rangel
2024-12-30 17:39:30 -08:00
parent b9e2660318
commit 4b78f9f571
18 changed files with 55007 additions and 107450 deletions

View File

@ -1,44 +1,96 @@
import { __ } from '@wordpress/i18n';
import { BaseControl, __experimentalNumberControl as NumberControl, SelectControl, __experimentalHStack as HStack } from '@wordpress/components';
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() {
// Example options for select control (CSS units)
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' }
{ label: __('vh'), value: 'vh' },
...(includeAuto ? [{ label: __('auto'), value: 'auto' }] : []), // Add 'auto' option if includeAuto is true
];
return (
<BaseControl className="lcp-dimension-value-control" // Custom class for styling parent
>
<div style={{ position: 'relative', padding: '5px', border:'1px solid red'}}>
<HStack>
{/* Number input control */}
<NumberControl
className="lcp-number-control" // Custom class for styling parent
// 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
};
value={10} // Placeholder value
onChange={() => {}} // No-op for onChange
// 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={1}
/>
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" // Custom class for styling parent
style={{ marginBottom: '0' }} // Applying in-line style for margin value={'px'} // Placeholder value
className="lcp-select-control"
value={unitValue}
options={unitOptions}
onChange={() => {}} // No-op for onChange
onChange={onUnitChange}
/>
</HStack>
</div>
</BaseControl>
);
}

View File

@ -35,7 +35,7 @@ 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 needed
'permission_callback' => '__return_true', // Public access; modify this if real permissions needed
) );
}
@ -46,7 +46,7 @@ function get_icons_data_from_db() {
// Query the lcp_icons table
$results = $wpdb->get_results(
"SELECT id, name, paths, viewbox FROM {$wpdb->prefix}lcp_icons"
"SELECT icon_id, icon_name, paths, viewbox FROM {$wpdb->prefix}lcp_icons"
);
// If no icons are found, return an empty array
@ -57,10 +57,10 @@ function get_icons_data_from_db() {
// Format the results for the frontend
$icons = array_map( function( $icon ) {
return [
'iconSvgId' => $icon->id, // Icon ID
'iconSvgId' => $icon->icon_id, // Icon ID
'iconSvgPaths' => $icon->paths, // SVG paths (can be multiple)
'selectedIconViewbox' => $icon->viewbox, // ViewBox for the SVG
'name' => $icon->name, // Add name field
'name' => $icon->icon_name, // Add name field
];
}, $results );

View File

@ -55,17 +55,43 @@
"manualIconSvgPath":{
"type": "string"
},
"buttonHeight":{
"type": "string"
},
"buttonPadding":{
"type": "string",
"default": "10px"
"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": "15px"
"type": "string"
},
"iconWidth": {
"type": "string",
"default": "15px"
"type": "string"
}
},
"textdomain": "lcp",

View File

@ -5,21 +5,20 @@ 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, buttonText, iconSvgId, iconSvgPath, iconSvgViewbox, displayIcon, iconSource, customUrl, buttonPadding } = attributes;
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) {
console.log("Selected Icon Path: ", selectedIcon.iconSvgPath); // Log the selected icon path for debugging
console.log("Selected Icon Viewbox: ", selectedIcon.viewbox); // Log the selected icon viewbox for debugging
setAttributes({
iconSvgPath: selectedIcon.iconSvgPath, // Set the SVG path in the attributes
iconSvgId: selectedIcon.iconSvgId, // Set the icon ID
iconSvgViewbox: selectedIcon.viewbox // Set the icon viewbox in the attributes
iconSvgPath: selectedIcon.iconSvgPath,
iconSvgId: selectedIcon.iconSvgId,
iconSvgViewbox: selectedIcon.viewbox
});
}
};
@ -33,13 +32,18 @@ export default function Edit(props) {
};
const handlePaddingChange = (value) => {
// If the padding value is a number, make sure to append 'px' to it
if (typeof value === 'number') {
value = `${value}px`; // Convert to string with 'px'
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' },
@ -57,11 +61,9 @@ export default function Edit(props) {
<>
<InspectorControls>
<PanelBody title={__("Button Settings")}>
{/* Pass the necessary props to PaddingControl */}
<PaddingControl
onChange={handlePaddingChange}
/>
{/* Button Action */}
<SelectControl
label={__("Button Action")}
value={buttonAction}
@ -85,6 +87,12 @@ export default function Edit(props) {
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
@ -96,14 +104,14 @@ export default function Edit(props) {
{iconSource === 'manualSvgPath' && (
<TextareaControl
label="Icon SVG Path"
value={iconSvgPath} // Use the correct attribute `iconSvgPath`
value={iconSvgPath}
onChange={(value) => setAttributes({ iconSvgPath: value })}
/>
)}
{iconSource === 'iconSelector' && (
<IconSelectControl
iconSvgId={iconSvgId} // Pass current iconSvgId
onIconChange={handleIconChanges} // Handle icon selection
iconSvgId={iconSvgId}
onIconChange={handleIconChanges}
/>
)}
</>
@ -113,24 +121,22 @@ export default function Edit(props) {
<div {...useBlockProps()}>
{buttonAction === 'customUrl' ? (
// Render an anchor tag if buttonAction is 'customUrl'
<a href={customUrl} className="lcp-button" style={{ padding: buttonPadding || '10px' }}>
{/* Conditionally render the icon if displayIcon is true and iconSvgPath is available */}
{displayIcon && iconSvgPath && (
<svg className="lcp-icon" xmlns="http://www.w3.org/2000/svg" viewBox={iconSvgViewbox || "0 0 576 576"} dangerouslySetInnerHTML={{ __html: iconSvgPath }} />
<svg style={{ height: iconHeight }} className="lcp-icon" xmlns="http://www.w3.org/2000/svg" viewBox={iconSvgViewbox || "0 0 576 576"} dangerouslySetInnerHTML={{ __html: iconSvgPath }} />
)}
{/* Render the button text */}
{buttonText || 'Button'} {/* Use buttonText or fallback */}
<span className="lcp-button-text">
{buttonText || 'Button'}
</span>
</a>
) : (
// Render a button if buttonAction is not 'customUrl'
<button className="lcp-button" style={{ padding: buttonPadding || '10px' }}>
{/* Conditionally render the icon if displayIcon is true and iconSvgPath is available */}
{displayIcon && iconSvgPath && (
<svg className="lcp-icon" xmlns="http://www.w3.org/2000/svg" viewBox={iconSvgViewbox || "0 0 576 576"} dangerouslySetInnerHTML={{ __html: iconSvgPath }} />
<svg style={{ height: iconHeight }} className="lcp-icon" xmlns="http://www.w3.org/2000/svg" viewBox={iconSvgViewbox || "0 0 576 576"} dangerouslySetInnerHTML={{ __html: iconSvgPath }} />
)}
{/* Render the button text */}
{buttonText || 'Button'} {/* Use buttonText or fallback */}
<span className="lcp-button-text">
{buttonText || 'Button'}
</span>
</button>
)}
</div>

View File

@ -2,35 +2,34 @@ import { useBlockProps } from '@wordpress/block-editor';
export default function save(props) {
const { attributes } = props;
const { buttonText, iconSvgPath, iconSvgViewbox, buttonAction, customUrl } = attributes; // Destructure buttonText, iconSvgPath, and iconSvgViewbox
const { 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 (
<>
{buttonAction === 'customUrl' ? (
// Render an anchor tag if buttonAction is 'customUrl'
<a href={customUrl} {...blockProps} className="lcp-button">
{/* Conditionally render the icon if iconSvgPath is set */}
{iconSvgPath && (
<svg className="lcp-icon" viewBox={iconSvgViewbox || "0 0 576 576"} dangerouslySetInnerHTML={{ __html: iconSvgPath }} />
)}
{/* Render the button text */}
{buttonText || 'Button'} {/* Use buttonText or fallback */}
</a>
) : (
// Render a button if buttonAction is not 'customUrl'
<button {...blockProps} className="lcp-button">
{/* Conditionally render the icon if iconSvgPath is set */}
{iconSvgPath && (
<svg className="lcp-icon" viewBox={iconSvgViewbox || "0 0 576 576"} dangerouslySetInnerHTML={{ __html: iconSvgPath }} />
)}
{/* Render the button text */}
{buttonText || 'Button'} {/* Use buttonText or fallback */}
</button>
)}
</>
<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>
);
}