Changes to lcp-button

This commit is contained in:
Jeremy Rangel
2024-12-31 18:53:46 -08:00
parent 2df16e37a8
commit 741d39a962
94 changed files with 1159 additions and 138 deletions

View 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"
}

View 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}

View 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');

View 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}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
.wp-block-create-block-button{background-color:#21759b;color:#fff;padding:2px}

View File

@ -0,0 +1 @@
.wp-block-create-block-button{background-color:#21759b;color:#fff;padding:2px}

View File

@ -0,0 +1 @@
<?php return array('dependencies' => array(), 'version' => '39bd3d2fc52e7ff1ed91');

View File

@ -0,0 +1 @@
console.log("Hello World! (from create-block-button block)");

View 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>
);
}

View 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
/>
);
}

View 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>
);
}

View File

@ -6,17 +6,10 @@
"title": "Button",
"category": "widgets",
"icon": "smiley",
"description": "Example block scaffolded with Create Block tool.",
"description": "A button for various functions or custom urls",
"example": {},
"supports": {
"html": false,
"color": {
"background": true,
"link": true,
"text": true,
"gradients": true,
"button": true
}
"html": false
},
"attributes": {
"buttonAction": {
@ -32,14 +25,16 @@
"default": "Button Text"
},
"displayIcon": {
"type": "boolean"
"type": "boolean",
"default": true
},
"iconSource": {
"type": "string",
"default": "manualSvgPath"
},
"iconSvgPath": {
"type": "string"
"type": "string",
"default": ""
},
"iconSvgId": {
"type": "string",
@ -53,10 +48,12 @@
"type": "number"
},
"manualIconSvgPath":{
"type": "string"
"type": "string",
"default": ""
},
"buttonHeight":{
"type": "string"
"type": "string",
"default": ""
},
"buttonPadding":{
"type": "object",
@ -88,10 +85,12 @@
}
},
"iconHeight": {
"type": "string"
"type": "string",
"default": ""
},
"iconWidth": {
"type": "string"
"type": "string",
"default": ""
}
},
"textdomain": "lcp",

View File

@ -2,7 +2,7 @@ import { useBlockProps } from '@wordpress/block-editor';
export default function save(props) {
const { attributes } = props;
const { buttonText, buttonPadding,iconHeight,iconSvgPath, iconSvgViewbox, buttonAction, customUrl } = attributes; // Destructure buttonText, iconSvgPath, and iconSvgViewbox
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();
@ -10,7 +10,7 @@ export default function save(props) {
// Conditionally render the link or button based on buttonAction
return (
<div {...useBlockProps()}>
<div {...blockProps}>
{buttonAction === 'customUrl' ? (
<a href={customUrl} className="lcp-button" style={{ padding: buttonPadding || '10px' }}>
{displayIcon && iconSvgPath && (