Compare commits

...

3 Commits

27 changed files with 30632 additions and 89 deletions

View 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
View 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
View 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";
?>

View File

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

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

View File

@ -0,0 +1,34 @@
[
{
"id": 1,
"setName": "Font Awesome - Regular",
"setFamily": "Font Awesome",
"version": "6.7.1",
"file": "/font-awesome/v6.1.7/font-awesome-v6.7.1-regular-svgs.json"
},
{
"id": 2,
"setName": "Font Awesome - Solid",
"setFamily": "Font Awesome",
"version": "6.7.1",
"fileName": "/font-awesome/v6.1.7/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.1.7/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"
}
]

View File

@ -0,0 +1,63 @@
<?php
// Path to the input JSON file
$inputFile = 'material-icons-baseline.json';
// Path to the output JSON file
$outputFile = 'material-icons-baseline-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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View 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

4206
assets/json/input.svg Normal file

File diff suppressed because one or more lines are too long

View File

@ -28,6 +28,8 @@ function lcp_enqueue() {
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());
@ -156,5 +158,224 @@ function save_key_points_meta_box($post_id) {
}
add_action('save_post', 'save_key_points_meta_box');
/* INSERT ICONS TO DB */
// Function to load the JSON file and insert SVG data into the database
function load_material_icons_into_db($jsonData) {
// 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: Create the table if it doesn't exist
global $wpdb;
$table_name = $wpdb->prefix . 'lcp_icons'; // Table name with WordPress prefix
// Create the table if it does not exist
$sql = "
CREATE TABLE IF NOT EXISTS $table_name (
id VARCHAR(255) NOT NULL, -- Use the id from the JSON file
set_name VARCHAR(255) NOT NULL,
set_family VARCHAR(255) NOT NULL,
name VARCHAR(255) NOT NULL,
paths LONGTEXT NOT NULL,
viewbox VARCHAR(255) NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);
// Step 4: Insert data into the database
foreach ($data as $iconSet) {
// Extract values for the set_name and set_family from the top-level object
$setName = sanitize_text_field($iconSet['name']);
$setFamily = sanitize_text_field($iconSet['family']);
// Insert each SVG in the 'svgs' array
if (isset($iconSet['svgs']) && is_array($iconSet['svgs'])) {
foreach ($iconSet['svgs'] as $svg) {
$name = sanitize_text_field($svg['name']);
// Unescape the paths field (HTML entities or Unicode escapes)
$paths = html_entity_decode($svg['paths']); // Decode HTML entities (like &quot; or &amp;)
$paths = stripslashes($paths); // Remove any additional escaping, such as slashes
$viewbox = sanitize_text_field($svg['viewBox']);
$id = sanitize_text_field($svg['id']); // Use the id from the JSON object
// Prepare the data for insertion
$data = array(
'id' => $id, // Use the id from the JSON object
'set_name' => $setName,
'set_family' => $setFamily,
'name' => $name,
'paths' => $paths,
'viewbox' => $viewbox,
);
// Insert into the database
$wpdb->insert($table_name, $data);
}
}
}
echo '<p>Icons have been imported into the database.</p>';
}
// 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);
}
// Hook the function to the theme deactivation process
// Register the function to run when the theme is switched (deactivated)
add_action('switch_theme', 'drop_lcp_icons_table');
/* BACKEND ICON ADDER */
function icon_sets_dashboard_callback() {
// Get the file path to the JSON file
$json_file_path = get_template_directory() . '/assets/json/icons/icon-definitions.json';
// Check if the file exists
if (file_exists($json_file_path)) {
// Read the file contents and decode the JSON
$json_data = file_get_contents($json_file_path);
$icon_sets = json_decode($json_data, true);
if ($icon_sets) {
// Group icon sets by setFamily
$grouped_sets = [];
foreach ($icon_sets as $set) {
// Check if the set has the setFamily key
$setFamily = isset($set['setFamily']) ? $set['setFamily'] : 'Unknown';
// Initialize the family group if not already initialized
if (!isset($grouped_sets[$setFamily])) {
$grouped_sets[$setFamily] = [];
}
// Handle both 'file' and 'fileName'
// Check if 'file' is set or fallback to 'fileName'
$setFile = isset($set['file']) ? $set['file'] : (isset($set['fileName']) ? $set['fileName'] : '');
// Ensure we are correctly adding the set data
$grouped_sets[$setFamily][] = [
'id' => $set['id'],
'setName' => $set['setName'],
'file' => $setFile
];
}
// Output the HTML for the dashboard
echo '<div class="wrap">';
echo '<h1>' . esc_html('Icon Sets Dashboard') . '</h1>';
// Loop through each setFamily and create a section with checkboxes
foreach ($grouped_sets as $setFamily => $sets) {
echo '<div class="lcp-icon-set">';
echo '<h2>' . esc_html($setFamily) . '</h2>';
echo '<ul>';
// Loop through each setName and create a checkbox
foreach ($sets as $set) {
$checkbox_id = 'icon_set_' . $set['id'];
echo '<li><input type="checkbox" id="' . esc_attr($checkbox_id) . '" name="icon_sets[]" value="' . esc_attr($set['file']) . '" data-icon-set-id="' . esc_attr($set['id']) . '">';
echo '<label for="' . esc_attr($checkbox_id) . '">' . esc_html($set['setName']) . '</label></li>';
}
echo '</ul>';
echo '</div>';
}
// Add submit button
echo '<form method="POST" action="">'; // Ensure the form method is POST
echo '<input type="submit" name="submit_icon_sets" value="Import Selected Icons" class="button-primary">';
echo '</form>';
echo '</div>';
// Handle form submission
if (isset($_POST['submit_icon_sets'])) {
// Debugging: Check if form is actually submitting data
echo '<pre>';
var_dump($_POST['icon_sets']); // Check if checkboxes are selected
echo '</pre>';
// Debugging: Display selected icon sets
if (isset($_POST['icon_sets']) && !empty($_POST['icon_sets'])) {
echo '<p>Selected icon sets:</p>';
echo '<pre>';
var_dump($_POST['icon_sets']); // Output the selected icon set values
echo '</pre>';
// Loop through selected icon sets and process the corresponding JSON files
foreach ($_POST['icon_sets'] as $file) {
// Look for the icon set that matches the selected file path
foreach ($icon_sets as $set) {
// Check if the 'file' or 'fileName' matches the selected file
if ($set['file'] == $file || (isset($set['fileName']) && $set['fileName'] == $file)) {
// Get the JSON file for the selected set
$jsonFilePath = get_template_directory() . '/assets/json/icons' . (isset($set['file']) ? $set['file'] : $set['fileName']);
// Debugging: Print the json file path being used
echo '<p>Loading file: ' . esc_html($jsonFilePath) . '</p>';
if (file_exists($jsonFilePath)) {
$jsonData = file_get_contents($jsonFilePath);
load_material_icons_into_db($jsonData); // Pass the JSON data to the function
} else {
echo '<p>Error: File ' . esc_html($jsonFilePath) . ' not found.</p>';
}
break;
}
}
}
} else {
echo '<p>No icon sets selected.</p>';
}
}
} else {
echo '<p>No icon sets found in the JSON file.</p>';
}
} else {
echo '<p>Icon definitions JSON file not found.</p>';
}
}
function register_icon_dashboard_page() {
add_menu_page(
'Icon Sets', // Page Title
'Icon Sets', // Menu Title
'manage_options', // Capability required
'icon-sets-dashboard', // Menu slug
'icon_sets_dashboard_callback', // Callback function
'dashicons-admin-generic', // Icon
60 // Position in the menu
);
}
add_action('admin_menu', 'register_icon_dashboard_page');

View File

@ -0,0 +1,44 @@
import { __ } from '@wordpress/i18n';
import { BaseControl, __experimentalNumberControl as NumberControl, SelectControl, __experimentalHStack as HStack } from '@wordpress/components';
/**
* Control component with a number input and a select dropdown for units (px, rem, em, % etc.).
*/
export function DimensionValueControl() {
// Example options for select control (CSS units)
const unitOptions = [
{ label: __('px'), value: 'px' },
{ label: __('%'), value: '%' },
{ label: __('em'), value: 'em' },
{ label: __('rem'), value: 'rem' },
{ label: __('vw'), value: 'vw' },
{ label: __('vh'), value: 'vh' }
];
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
value={10} // Placeholder value
onChange={() => {}} // No-op for onChange
min={0}
step={1}
/>
{/* 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
options={unitOptions}
onChange={() => {}} // No-op for onChange
/>
</HStack>
</div>
</BaseControl>
);
}

View File

@ -10,10 +10,10 @@ export function IconSelectControl(props) {
useEffect(() => {
const fetchIconData = async () => {
try {
const response = await fetch('/wp-content/themes/local-content-pro/assets/json/icons.json');
const response = await fetch('/wp-json/lcp/v1/icons');
const data = await response.json();
if (data && data.length > 0) {
setIconData(data[0].svgs); // Assuming the structure is correct
if (Array.isArray(data) && data.length > 0) {
setIconData(data); // Set the fetched data directly
}
} catch (error) {
console.error('Error fetching icons:', error);
@ -24,15 +24,17 @@ export function IconSelectControl(props) {
}, []);
const handleIconChange = (selectedIconId) => {
const selectedIcon = iconData.find(icon => icon.id === 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.id, // Pass icon ID to parent
iconSvgPath: selectedIcon.path // Pass icon path (SVG) to parent
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.id); // Debugging output
console.log("Selected Icon Path:", selectedIcon.path); // Debugging output
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
}
};
@ -41,20 +43,11 @@ export function IconSelectControl(props) {
}
const iconOptions = iconData.map((icon) => ({
value: icon.id, // Use icon ID as value for the SelectControl
label: (
<div style={{ display: 'flex', alignItems: 'center' }}>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox={icon.viewBox || "0 0 512 512"} // Default viewBox if not present
style={{ width: '20px', height: '20px' }} // Control icon size
dangerouslySetInnerHTML={{ __html: icon.path }} // Insert SVG path
/>
<span style={{ marginLeft: '8px' }}>{icon.name}</span> {/* Show icon name */}
</div>
),
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')}

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

@ -28,3 +28,42 @@ 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 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 id, 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->id, // Icon ID
'iconSvgPaths' => $icon->paths, // SVG paths (can be multiple)
'selectedIconViewbox' => $icon->viewbox, // ViewBox for the SVG
'name' => $icon->name, // Add name field
];
}, $results );
return $icons;
}

View File

@ -45,11 +45,27 @@
"type": "string",
"default": ""
},
"iconSvgViewbox": {
"type": "string",
"default": "0 0 510 510"
},
"popUpId": {
"type": "number"
},
"manualIconSvgPath":{
"type": "string"
},
"buttonPadding":{
"type": "string",
"default": "10px"
},
"iconHeight": {
"type": "string",
"default": "15px"
},
"iconWidth": {
"type": "string",
"default": "15px"
}
},
"textdomain": "lcp",

View File

@ -4,18 +4,22 @@ import { PanelBody, SelectControl, TextControl, TextareaControl, ToggleControl }
import { useState, useEffect } from '@wordpress/element';
import './editor.scss';
import { IconSelectControl } from '../components/IconSelectControl';
import { PaddingControl } from '../components/PaddingControl';
export default function Edit(props) {
const { attributes, setAttributes } = props;
const { buttonAction, buttonText, iconSvgId, iconSvgPath, displayIcon, iconSource, customUrl } = attributes;
const { buttonAction, 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
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
});
}
};
@ -28,6 +32,14 @@ export default function Edit(props) {
setAttributes({ customUrl: value });
};
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'
}
setAttributes({ buttonPadding: value });
};
const iconSourceOptions = [
{ value: 'manualSvgPath', label: 'SVG Path' },
{ value: 'iconSelector', label: 'Icon Library' },
@ -45,7 +57,11 @@ export default function Edit(props) {
<>
<InspectorControls>
<PanelBody title={__("Button Settings")}>
{/* Button Function */}
{/* Pass the necessary props to PaddingControl */}
<PaddingControl
/>
{/* Button Action */}
<SelectControl
label={__("Button Action")}
value={buttonAction}
@ -95,29 +111,29 @@ export default function Edit(props) {
</PanelBody>
</InspectorControls>
<>
{buttonAction === 'customUrl' ? (
// Render an anchor tag if buttonAction is 'customUrl'
<a href={customUrl} className="lcp-button">
{/* Conditionally render the icon if displayIcon is true and iconSvgPath is available */}
{displayIcon && iconSvgPath && (
<svg className = "lcp-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 576" dangerouslySetInnerHTML={{ __html: iconSvgPath }} />
)}
{/* Render the button text */}
{buttonText || 'Button'} {/* Use buttonText or fallback */}
</a>
) : (
// Render a button if buttonAction is not 'customUrl'
<button className="lcp-button">
{/* Conditionally render the icon if displayIcon is true and iconSvgPath is available */}
{displayIcon && iconSvgPath && (
<svg className = "lcp-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 576" dangerouslySetInnerHTML={{ __html: iconSvgPath }} />
)}
{/* Render the button text */}
{buttonText || 'Button'} {/* Use buttonText or fallback */}
</button>
)}
</>
<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 }} />
)}
{/* Render the button text */}
{buttonText || 'Button'} {/* Use buttonText or fallback */}
</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 }} />
)}
{/* Render the button text */}
{buttonText || 'Button'} {/* Use buttonText or fallback */}
</button>
)}
</div>
</>
);
}

View File

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

View File

@ -159,9 +159,9 @@ Version: 1.0
/* LCP Button */
.lcp-button {
display: inline-block;
background-color: var(--wp--preset--color--accent);
background-color: var(--wp--preset--color--accent-2);
border: none;
color: #fff;
color: var(--wp--preset--color--font-color-1);
text-decoration: none;
padding: 10px;
font-weight: bold;
@ -177,5 +177,32 @@ Version: 1.0
width: auto;
vertical-align: middle; /* Aligns the icon with the text vertically */
margin-right: 10px; /* Space between the icon and the text */
fill:white;
fill: var(--wp--preset--color--font-color-1);
}
/* Backend */
.lcp-dimension-value-control .lcp-number-control {margin:0;flex:3;border:0}
.lcp-dimension-value-control .components-input-control__backdrop{border:0!important}
.lcp-padding-control .lcp-dimension-value-control,.lcp-padding-control .components-range-control {flex:1!important}
.lcp-dimension-value-control .lcp-select-control{padding:0;flex:1}
.lcp-dimension-value-control .components-base-control__field {margin-bottom:0!important}
.lcp-padding-control .components-input-control__suffix {display:none!important}
.lcp-dimension-value-control .components-select-control__input {padding:5px!important}
.lcp-padding-control .lcp-dimension-value-control .lcp-number-control input,.components-select-control__input {height:25px!important;min-height:25px!important;line-height:13px!important}
.lcp-dimension-value-control .lcp-number-control input[type="number"]::-webkit-outer-spin-button,
.lcp-dimension-value-control .lcp-number-control input[type="number"]::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
/* For Firefox */
.lcp-dimension-value-control .lcp-number-control input[type="number"] {
-moz-appearance: textfield; /* Hide the spinner */
}
/* Optional: Remove the appearance in other browsers */
.lcp-dimension-value-control .lcp-number-control input[type="number"] {
appearance: none;
}

View File

@ -39,19 +39,19 @@
"slug": "light-gray-2"
},
{
"color": "#00F089",
"color": "#00E080",
"name": "Accent",
"slug": "accent"
},
{
"color": "#FBFAF3",
"name": "Accent 5",
"slug": "accent-5"
"color": "#00FC90",
"name": "Accent 2",
"slug": "accent-2"
},
{
"color": "color-mix(in srgb, currentColor 20%, transparent)",
"name": "Accent 6",
"slug": "accent-6"
"color": "#232323",
"name": "Font 1",
"slug": "font-color-1"
}
]
},