mirror of
https://github.com/lubusIN/blablablocks-tabs-block.git
synced 2026-02-28 10:07:24 +08:00
464 lines
16 KiB
PHP
464 lines
16 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Helpers Tabs Block.
|
|
*/
|
|
|
|
if (! defined('ABSPATH')) {
|
|
exit; // Exit if accessed directly.
|
|
}
|
|
|
|
/**
|
|
* Extract tab data from inner blocks.
|
|
*
|
|
* @param array $inner_blocks Inner blocks array.
|
|
* @return array
|
|
*/
|
|
if (! function_exists('blabtabl_extract_tab_data')) {
|
|
function blabtabl_extract_tab_data(array $inner_blocks): array
|
|
{
|
|
return array_map(static function ($inner_block, $index) {
|
|
$attrs = $inner_block['attrs'] ?? [];
|
|
$hasInnerblock = !empty($inner_block['innerBlocks']);
|
|
return [
|
|
'id' => 'tab-' . ($attrs['tabId'] ?? $index),
|
|
'label' => $attrs['tabname'] ?? '',
|
|
'hasInnerblock' => $hasInnerblock,
|
|
];
|
|
}, $inner_blocks, array_keys($inner_blocks));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Resolves a spacing size value into a usable CSS value.
|
|
*
|
|
* @param mixed $value The input spacing size value.
|
|
* @param mixed $defaultValue The default value.
|
|
* @return string A valid CSS spacing size value.
|
|
*/
|
|
if (! function_exists('blabtabl_resolve_spacing_size')) {
|
|
function blabtabl_resolve_spacing_size($value, $defaultValue = '0px')
|
|
{
|
|
if (is_string($value)) {
|
|
if (strpos($value, 'var:') === 0) {
|
|
// Convert "var:some|value" into "var(--wp--some--value)"
|
|
$cssVariable = str_replace('|', '--', str_replace('var:', '--wp--', $value));
|
|
return "var($cssVariable)";
|
|
}
|
|
return $value; // If it's a valid CSS string, return as-is
|
|
}
|
|
|
|
if (is_numeric($value)) {
|
|
return "{$value}px"; // Convert numbers to pixel values
|
|
}
|
|
|
|
// use defaultValue if value is invalid or undefined
|
|
return $defaultValue;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Generates CSS gap styles for the tabs block.
|
|
*
|
|
* @param array $attributes Block attributes.
|
|
* @return string A string of CSS variables.
|
|
*/
|
|
if (! function_exists('blabtabl_get_gap_styles')) {
|
|
function blabtabl_get_gap_styles($attributes)
|
|
{
|
|
$blockGap = $attributes['style']['spacing']['blockGap'] ?? '0.5em';
|
|
$orientation = $attributes['orientation'] ?? 'horizontal';
|
|
|
|
// Get main and cross axis gaps
|
|
if (is_string($blockGap)) {
|
|
$main = $cross = blabtabl_get_gap_css_value($blockGap);
|
|
} else {
|
|
$main = blabtabl_get_gap_css_value($blockGap['top'] ?? '0.5em');
|
|
$cross = blabtabl_get_gap_css_value($blockGap['left'] ?? '0.5em');
|
|
}
|
|
|
|
// Swap for vertical orientation
|
|
[$listGap, $tabsGap] = $orientation === 'vertical' ? [$main, $cross] : [$cross, $main];
|
|
|
|
return [
|
|
'--bbb-tabs-list-gap' => $listGap,
|
|
'--bbb-tabs-gap' => $tabsGap
|
|
];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Converts a gap value to a valid CSS value.
|
|
* Handles preset values (e.g., "var:preset|spacing|40") by converting them to CSS variables.
|
|
*
|
|
* @param string $value The gap value to convert.
|
|
* @return string The converted CSS value.
|
|
*/
|
|
if (! function_exists('blabtabl_get_gap_css_value')) {
|
|
function blabtabl_get_gap_css_value($value)
|
|
{
|
|
if (preg_match('/^var:preset\|spacing\|\d+$/', $value)) {
|
|
return 'var(--wp--preset--spacing--' . substr($value, strrpos($value, '|') + 1) . ')';
|
|
}
|
|
return $value;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Helper function to resolve color value based on slug
|
|
*
|
|
* @param mixed $colorValue - Color value (can be string, array with 'color' and 'slug', or null)
|
|
* @param string $fallback - Fallback color value
|
|
* @return string - CSS color value or custom property
|
|
*/
|
|
if (! function_exists('blabtabl_resolve_color_value')) {
|
|
function blabtabl_resolve_color_value($colorValue, $fallback = '')
|
|
{
|
|
// If it's null or empty, return fallback
|
|
if (empty($colorValue)) {
|
|
return $fallback;
|
|
}
|
|
|
|
// If it's a string, return as-is (direct color value)
|
|
if (is_string($colorValue)) {
|
|
return $colorValue;
|
|
}
|
|
|
|
// If it's an array (normalized color object from JS)
|
|
if (is_array($colorValue)) {
|
|
// If we have a slug, use the WordPress preset color custom property
|
|
if (!empty($colorValue['slug'])) {
|
|
return "var(--wp--preset--color--{$colorValue['slug']})";
|
|
}
|
|
|
|
// Otherwise use the direct color value
|
|
if (!empty($colorValue['color'])) {
|
|
return $colorValue['color'];
|
|
}
|
|
}
|
|
|
|
return $fallback;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns typography classnames depending on whether there are named font sizes/families.
|
|
*
|
|
* @param array $attributes The block attributes.
|
|
* @return string The typography color classnames to be applied to the block elements.
|
|
*/
|
|
if (! function_exists('blabtabl_get_typography_classes')) {
|
|
function blabtabl_get_typography_classes($attributes)
|
|
{
|
|
$typography_classes = [];
|
|
|
|
if (! empty($attributes['fontSize'])) {
|
|
$typography_classes[] = sprintf('has-%s-font-size', esc_attr($attributes['fontSize']));
|
|
}
|
|
|
|
if (! empty($attributes['fontFamily'])) {
|
|
$typography_classes[] = sprintf('has-%s-font-family', esc_attr($attributes['fontFamily']));
|
|
}
|
|
|
|
return implode(' ', $typography_classes);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns typography styles to be included in an HTML style tag.
|
|
*
|
|
* @param array $attributes The block attributes.
|
|
* @return string A string of typography CSS declarations.
|
|
*/
|
|
if (! function_exists('blabtabl_get_typography_styles')) {
|
|
function blabtabl_get_typography_styles($attributes)
|
|
{
|
|
$styles = [];
|
|
$typography = $attributes['style']['typography'] ?? [];
|
|
|
|
$properties = [
|
|
'fontSize' => 'font-size',
|
|
'fontFamily' => 'font-family',
|
|
'fontWeight' => 'font-weight',
|
|
'fontStyle' => 'font-style',
|
|
'lineHeight' => 'line-height',
|
|
'letterSpacing' => 'letter-spacing',
|
|
'textTransform' => 'text-transform',
|
|
'textDecoration' => 'text-decoration'
|
|
];
|
|
|
|
foreach ($properties as $attr => $cssProperty) {
|
|
if (!empty($typography[$attr])) {
|
|
$value = $typography[$attr];
|
|
|
|
// Special handling for fontSize
|
|
if ($attr === 'fontSize') {
|
|
$value = wp_get_typography_font_size_value(['size' => $value]);
|
|
}
|
|
|
|
$styles[] = "{$cssProperty}: {$value};";
|
|
}
|
|
}
|
|
|
|
return implode('', $styles);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns border color classnames depending on whether there are named or custom border colors.
|
|
*
|
|
* @param array $attributes The block attributes.
|
|
* @return string The border color classnames to be applied to the block elements.
|
|
*/
|
|
if (! function_exists('blabtabl_get_border_color_classes')) {
|
|
function blabtabl_get_border_color_classes($attributes)
|
|
{
|
|
$border_color_classes = [];
|
|
$has_custom_border_color = ! empty($attributes['style']['border']['color']);
|
|
$has_named_border_color = ! empty($attributes['borderColor']);
|
|
|
|
if ($has_custom_border_color || $has_named_border_color) {
|
|
$border_color_classes[] = 'has-border-color';
|
|
}
|
|
|
|
if ($has_named_border_color) {
|
|
$border_color_classes[] = sprintf('has-%s-border-color', esc_attr($attributes['borderColor']));
|
|
}
|
|
|
|
return implode(' ', $border_color_classes);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Build the complete border CSS (width, color, style, radius).
|
|
*/
|
|
if (! function_exists('blabtabl_get_tabs_border_styles')) {
|
|
function blabtabl_get_tabs_border_styles(array $attributes): string
|
|
{
|
|
$styles = [];
|
|
|
|
// Border radius
|
|
$radius = _wp_array_get($attributes, ['style', 'border', 'radius'], null);
|
|
if ($radius) {
|
|
if (is_array($radius)) {
|
|
$corners = array_map(fn($v) => is_numeric($v) ? "{$v}px" : $v, [
|
|
$radius['topLeft'] ?? 0,
|
|
$radius['topRight'] ?? 0,
|
|
$radius['bottomRight'] ?? 0,
|
|
$radius['bottomLeft'] ?? 0
|
|
]);
|
|
$styles[] = sprintf('border-radius: %s;', implode(' ', $corners));
|
|
} else {
|
|
$val = is_numeric($radius) ? "{$radius}px" : $radius;
|
|
$styles[] = "border-radius: {$val};";
|
|
}
|
|
}
|
|
|
|
// Border properties - check shorthand first, then individual sides
|
|
foreach (['width', 'color', 'style'] as $prop) {
|
|
// Check shorthand property (without side)
|
|
$shorthandValue = _wp_array_get($attributes, ['style', 'border', $prop], '');
|
|
if ($shorthandValue) {
|
|
// Handle color presets for shorthand
|
|
if ($prop === 'color' && str_starts_with($shorthandValue, 'var:preset|color|')) {
|
|
$shorthandValue = 'var(--wp--preset--color--' . substr($shorthandValue, strrpos($shorthandValue, '|') + 1) . ')';
|
|
}
|
|
// Add px to numeric widths for shorthand
|
|
if ($prop === 'width' && is_numeric($shorthandValue)) {
|
|
$shorthandValue .= 'px';
|
|
}
|
|
$styles[] = "border-{$prop}: {$shorthandValue};";
|
|
} else {
|
|
// Check individual sides
|
|
foreach (['top', 'right', 'bottom', 'left'] as $side) {
|
|
$value = _wp_array_get($attributes, ['style', 'border', $side, $prop], '');
|
|
if ($value) {
|
|
// Handle color presets
|
|
if ($prop === 'color' && str_starts_with($value, 'var:preset|color|')) {
|
|
$value = 'var(--wp--preset--color--' . substr($value, strrpos($value, '|') + 1) . ')';
|
|
}
|
|
// Add px to numeric widths
|
|
if ($prop === 'width' && is_numeric($value)) {
|
|
$value .= 'px';
|
|
}
|
|
$styles[] = "border-{$side}-{$prop}: {$value};";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return implode(' ', $styles);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Generates a set of CSS variable mappings based on provided attributes.
|
|
* The returned array excludes variables with invalid or undefined values.
|
|
*
|
|
* @param array $attributes The attributes used to customize styles.
|
|
* @return array An array with CSS variable definitions.
|
|
*/
|
|
if (! function_exists('blabtabl_generate_styles')) {
|
|
function blabtabl_generate_styles($attributes = [])
|
|
{
|
|
$styles = blabtabl_get_gap_styles($attributes);
|
|
|
|
// Padding
|
|
$padding = $attributes['tabPadding'] ?? [];
|
|
$styles['--bbb-tab-padding'] = sprintf(
|
|
'%s %s %s %s',
|
|
blabtabl_resolve_spacing_size($padding['top'] ?? null, '5px'),
|
|
blabtabl_resolve_spacing_size($padding['right'] ?? null, '15px'),
|
|
blabtabl_resolve_spacing_size($padding['bottom'] ?? null, '5px'),
|
|
blabtabl_resolve_spacing_size($padding['left'] ?? null, '15px')
|
|
);
|
|
|
|
// Colors for different states
|
|
$colorDefaults = [
|
|
'default' => ['text' => '#000', 'bg' => '#fff', 'icon' => '#000'],
|
|
'hover' => ['text' => '#fff', 'bg' => '#000', 'icon' => '#fff'],
|
|
'active' => ['text' => '#fff', 'bg' => '#000', 'icon' => '#fff']
|
|
];
|
|
|
|
foreach ($colorDefaults as $state => $defaults) {
|
|
|
|
// Text color
|
|
$textColor = $attributes['tabTextColor'][$state] ?? null;
|
|
$styles["--bbb-tab-text-{$state}-color"] = blabtabl_resolve_color_value(
|
|
$textColor,
|
|
$defaults['text']
|
|
);
|
|
|
|
// Background color
|
|
$backgroundColor = $attributes['tabBackgroundColor'][$state] ?? null;
|
|
$styles["--bbb-tab-background-{$state}-color"] = blabtabl_resolve_color_value(
|
|
$backgroundColor,
|
|
$defaults['bg']
|
|
);
|
|
|
|
// Icon color
|
|
$iconColor = $attributes['tabIconColor'][$state] ?? null;
|
|
$styles["--bbb-tab-icon-{$state}-color"] = blabtabl_resolve_color_value(
|
|
$iconColor,
|
|
$defaults['icon']
|
|
);
|
|
}
|
|
|
|
// Other styles
|
|
$styles['--bbb-tab-buttons-justify-content'] = $attributes['justification'] ?? 'left';
|
|
$styles['--bbb-tab-icon-size'] = ($attributes['iconSize'] ?? 24) . 'px';
|
|
|
|
return $styles;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Build the style for a Tabs container.
|
|
*
|
|
* @param array $attributes Block attributes.
|
|
* @return string A string of CSS declarations.
|
|
*/
|
|
if (! function_exists('blabtabl_get_tabs_container_styles')) {
|
|
function blabtabl_get_tabs_container_styles(array $attributes): string
|
|
{
|
|
$styles = [];
|
|
|
|
// Border styles
|
|
$styles[] = blabtabl_get_tabs_border_styles($attributes);
|
|
|
|
// Background
|
|
$color = $attributes['style']['color'] ?? [];
|
|
if (!empty($color['background'])) {
|
|
$styles[] = "background-color: {$color['background']};";
|
|
}
|
|
if (!empty($color['gradient'])) {
|
|
$styles[] = "background: {$color['gradient']};";
|
|
}
|
|
|
|
// Padding
|
|
$padding = $attributes['style']['spacing']['padding'] ?? [];
|
|
$styles[] = sprintf(
|
|
'padding: %s %s %s %s;',
|
|
blabtabl_resolve_spacing_size($padding['top'] ?? null, '0px'),
|
|
blabtabl_resolve_spacing_size($padding['right'] ?? null, '0px'),
|
|
blabtabl_resolve_spacing_size($padding['bottom'] ?? null, '0px'),
|
|
blabtabl_resolve_spacing_size($padding['left'] ?? null, '0px')
|
|
);
|
|
|
|
// Margin for horizontal justification
|
|
if (($attributes['orientation'] ?? 'horizontal') === 'horizontal') {
|
|
$margins = [
|
|
'left' => 'margin: 0 0 auto;',
|
|
'center' => 'margin: 0 auto;',
|
|
'right' => 'margin: 0 0 0 auto;',
|
|
'stretch' => 'margin: 0;'
|
|
];
|
|
$justification = $attributes['justification'] ?? 'left';
|
|
|
|
if (isset($margins[$justification])) {
|
|
$styles[] = $margins[$justification];
|
|
}
|
|
}
|
|
|
|
// width
|
|
if (($attributes['orientation'] ?? 'horizontal') === 'vertical') {
|
|
$width = $attributes['width'] ?? '50';
|
|
$styles[] = "min-width: {$width}%;";
|
|
}
|
|
|
|
return trim(implode(' ', array_filter($styles)));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns color classnames depending on whether there are named or background colors.
|
|
*
|
|
* @param array $attributes The block attributes.
|
|
* @return string The color classnames to be applied to the block elements.
|
|
*/
|
|
if (! function_exists('blabtabl_get_color_classes')) {
|
|
function blabtabl_get_color_classes($attributes)
|
|
{
|
|
$classes = [];
|
|
|
|
// Check if any background is set
|
|
$hasBackground = !empty($attributes['backgroundColor']) ||
|
|
!empty($attributes['style']['color']['background']) ||
|
|
!empty($attributes['gradient']) ||
|
|
!empty($attributes['style']['color']['gradient']);
|
|
|
|
if ($hasBackground) {
|
|
$classes[] = 'has-background';
|
|
}
|
|
|
|
// Named background color
|
|
if (!empty($attributes['backgroundColor'])) {
|
|
$classes[] = "has-{$attributes['backgroundColor']}-background-color";
|
|
}
|
|
|
|
// Named gradient
|
|
if (!empty($attributes['gradient'])) {
|
|
$classes[] = "has-{$attributes['gradient']}-gradient-background";
|
|
}
|
|
|
|
return implode(' ', $classes);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Build the border style for Tab button.
|
|
*
|
|
* @param array $attributes Block attributes.
|
|
* @return string A string of CSS declarations.
|
|
*/
|
|
if (! function_exists('blabtabl_get_tab_button_border_styles')) {
|
|
function blabtabl_get_tab_button_border_styles(array $attributes): string
|
|
{
|
|
$styles = [];
|
|
|
|
// Tab Border styles
|
|
$styles[] = blabtabl_get_tabs_border_styles(['style' => $attributes['tabBorder'] ?? []]);
|
|
|
|
return trim(implode(' ', array_filter($styles)));
|
|
}
|
|
}
|