Added lcp-ui.js and changes to blocks
This commit is contained in:
@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
@ -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 );
|
||||
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user