Date: Mon, 26 May 2025 21:12:32 +0800
Subject: [PATCH 091/124] fix: add fallback tooltip for theme.json data with no
name like blocksy
---
src/components/advanced-range-control/index.js | 2 +-
src/components/four-range-control/index.js | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/components/advanced-range-control/index.js b/src/components/advanced-range-control/index.js
index 08ea202c36..c8dc8a47fc 100644
--- a/src/components/advanced-range-control/index.js
+++ b/src/components/advanced-range-control/index.js
@@ -175,7 +175,7 @@ const AdvancedRangeControl = props => {
]
}, [] )
propsToPass.renderTooltipContent = value => {
- return props.marks[ value ]?.name || ''
+ return props.marks[ value ]?.name || props.marks[ value ]?.slug || ''
}
// Other necessary props for steps.
diff --git a/src/components/four-range-control/index.js b/src/components/four-range-control/index.js
index afb19b3bf4..73c05d3da5 100644
--- a/src/components/four-range-control/index.js
+++ b/src/components/four-range-control/index.js
@@ -339,7 +339,7 @@ const FourRangeControl = memo( props => {
]
}, [] )
newProps.renderTooltipContent = value => {
- return props.marks[ value ]?.name || ''
+ return props.marks[ value ]?.name || props.marks[ value ]?.slug || ''
}
// Other necessary props for steps.
From e853ebd73201120c9e78e6ee2ec5459a1dfd296d Mon Sep 17 00:00:00 2001
From: Alquen Sarmiento
Date: Tue, 27 May 2025 09:41:18 +0800
Subject: [PATCH 092/124] fix: bug fixes
---
.../advanced-range-control/index.js | 48 +++---
src/components/four-range-control/index.js | 150 +++++++++++++-----
src/global-settings.php | 20 ++-
3 files changed, 149 insertions(+), 69 deletions(-)
diff --git a/src/components/advanced-range-control/index.js b/src/components/advanced-range-control/index.js
index c8dc8a47fc..dbfc373777 100644
--- a/src/components/advanced-range-control/index.js
+++ b/src/components/advanced-range-control/index.js
@@ -118,19 +118,20 @@ const AdvancedRangeControl = props => {
// If no initial value, use the given default from the settings
const [ isMarkMode, setIsMarkMode ] = useState( false )
- // Set the markMode when at first render and when device type changes
- useEffect( () => {
- let isMarkValue = !! props.marks && isMarkModeDefault
- if ( props.marks && derivedValue ) {
+ let isMarkValue = !! props.marks && isMarkModeDefault
+ if ( props.marks && derivedValue ) {
// Check if the current value exists in the marks only by their CSS variable name
// to match in case the fallback size changes.
- const derivedValueCssVarName = getCSSVarName( derivedValue )
- const matchedMark = props.marks.find( mark => getCSSVarName( mark.value ) === derivedValueCssVarName )
- isMarkValue = !! matchedMark
- if ( matchedMark ) {
- derivedValue = matchedMark.value
- }
+ const derivedValueCssVarName = getCSSVarName( derivedValue )
+ const matchedMark = props.marks.find( mark => getCSSVarName( mark.value ) === derivedValueCssVarName )
+ isMarkValue = !! matchedMark
+ if ( matchedMark ) {
+ derivedValue = matchedMark.value
}
+ }
+
+ // Set the markMode when device type changes
+ useEffect( () => {
setIsMarkMode( isMarkValue )
}, [ deviceType ] )
@@ -202,18 +203,8 @@ const AdvancedRangeControl = props => {
let rangeOnChange = _onChange
if ( isMarkMode ) {
rangeValue = props.marks.findIndex( mark => {
- let _unit, _value
- // If the derivedValue is a CSS variable, compare with mark's CSS variable.
- // Otherwise, the derivedValue is custom, so compare with raw size and units
- if ( typeof derivedValue === 'string' && derivedValue.startsWith( 'var' ) ) {
- [ _value, _unit ] = extractNumbersAndUnits( mark.value )[ 0 ]
- } else {
- [ _value, _unit ] = extractNumbersAndUnits( mark.size )[ 0 ]
- const converted = convertToPxIfUnsupported( props.units, _unit, _value )
- _value = converted.value
- _unit = converted.unit
- }
- return _value === derivedValue && ( _unit === '' || _unit === unit )
+ const [ _value, _unit ] = extractNumbersAndUnits( mark.value )[ 0 ]
+ return _value === derivedValue
} )
rangeOnChange = ( value, property = 'value' ) => {
if ( value === '' ) {
@@ -266,6 +257,19 @@ const AdvancedRangeControl = props => {
// Set the value when changing from mark mode to custom
if ( isMarkMode && rangeValue !== -1 ) {
rangeOnChange( rangeValue, 'size' )
+ } else {
+ const rangeValue = props.marks.findIndex( mark => {
+ let _unit, _value
+
+ [ _value, _unit ] = extractNumbersAndUnits( mark.size )[ 0 ]
+ const converted = convertToPxIfUnsupported( props.units, _unit, _value )
+ _value = converted.value
+ _unit = converted.unit
+
+ return _value === derivedValue && ( _unit === '' || _unit === unit )
+ } )
+ const markValue = props.marks[ rangeValue ]?.value || '0'
+ _onChange( markValue )
}
setIsMarkMode( ! isMarkMode )
} }
diff --git a/src/components/four-range-control/index.js b/src/components/four-range-control/index.js
index 73c05d3da5..644ffef0e5 100644
--- a/src/components/four-range-control/index.js
+++ b/src/components/four-range-control/index.js
@@ -191,39 +191,40 @@ const FourRangeControl = memo( props => {
const [ isFourMarkMode, setIsFourMarkMode ] = useState( false )
- // Set the markMode when at first render and when device type changes
- useEffect( () => {
- // Is value at first render the same as a step value? If so, do mark mode
- // at the start, or show custom
- // If no initial value, use the given default from the settings
- const isMarkValue = {
- first: !! props.marks && isMarkModeDefault,
- top: !! props.marks && isMarkModeDefault,
- right: !! props.marks && isMarkModeDefault,
- bottom: !! props.marks && isMarkModeDefault,
- left: !! props.marks && isMarkModeDefault,
+ // Is value at first render the same as a step value? If so, do mark mode
+ // at the start, or show custom
+ // If no initial value, use the given default from the settings
+ const isMarkValue = {
+ first: !! props.marks && isMarkModeDefault,
+ top: !! props.marks && isMarkModeDefault,
+ right: !! props.marks && isMarkModeDefault,
+ bottom: !! props.marks && isMarkModeDefault,
+ left: !! props.marks && isMarkModeDefault,
+ }
+
+ if ( props.marks && firstValue ) {
+ // Check if the current value exists in the marks only by their CSS variable name
+ // to match in case the fallback size changes.
+ const firstValueCssVarName = getCSSVarName( firstValue )
+ const firstMatchedMark = props.marks.find( mark => getCSSVarName( mark.value ) === firstValueCssVarName )
+ isMarkValue.first = !! firstMatchedMark
+ if ( firstMatchedMark ) {
+ firstValue = firstMatchedMark.value
}
- if ( props.marks && firstValue ) {
- // Check if the current value exists in the marks only by their CSS variable name
- // to match in case the fallback size changes.
- const firstValueCssVarName = getCSSVarName( firstValue )
- const firstMatchedMark = props.marks.find( mark => getCSSVarName( mark.value ) === firstValueCssVarName )
- isMarkValue.first = !! firstMatchedMark
- if ( firstMatchedMark ) {
- firstValue = firstMatchedMark.value
+ [ 'top', 'right', 'bottom', 'left' ].forEach( side => {
+ const sideCssVarName = getCSSVarName( value[ side ] )
+ const matchedMark = props.marks.find( mark => getCSSVarName( mark.value ) === sideCssVarName )
+ isMarkValue[ side ] = !! matchedMark
+ if ( matchedMark ) {
+ value[ side ] = matchedMark.value
}
+ } )
+ }
- [ 'top', 'right', 'bottom', 'left' ].forEach( side => {
- const sideCssVarName = getCSSVarName( value[ side ] )
- const matchedMark = props.marks.find( mark => getCSSVarName( mark.value ) === sideCssVarName )
- isMarkValue[ side ] = !! matchedMark
- if ( matchedMark ) {
- value[ side ] = matchedMark.value
- }
- } )
- setIsFourMarkMode( isMarkValue )
- }
+ // Set the markMode when device type changes
+ useEffect( () => {
+ setIsFourMarkMode( isMarkValue )
}, [ deviceType ] )
const onChangeAll = _newValue => {
@@ -359,18 +360,8 @@ const FourRangeControl = memo( props => {
let rangeOnChange = initialOnChange
if ( props.marks && isMarkMode ) {
rangeValue = props.marks.findIndex( mark => {
- let _unit, _value
- // If the initialValue is a CSS variable, compare with mark's CSS variable.
- // Otherwise, the initialValue is custom, so compare with raw size and units
- if ( typeof initialValue === 'string' && initialValue.startsWith( 'var' ) ) {
- [ _value, _unit ] = extractNumbersAndUnits( mark.value )[ 0 ]
- } else {
- [ _value, _unit ] = extractNumbersAndUnits( mark.size )[ 0 ]
- const converted = convertToPxIfUnsupported( props.units, _unit, _value )
- _value = converted.value
- _unit = converted.unit
- }
- return _value === initialValue && ( _unit === '' || _unit === unit )
+ const [ _value, _unit ] = extractNumbersAndUnits( mark.value )[ 0 ]
+ return _value === initialValue
} )
rangeOnChange = ( value, property = 'value' ) => {
if ( value === '' ) {
@@ -506,6 +497,17 @@ const FourRangeControl = memo( props => {
// Set the value when changing from mark mode to custom
if ( isFourMarkMode.first && rangeValueFirst !== -1 ) {
rangeOnChangeFirst( rangeValueFirst, 'size' )
+ } else {
+ const rangeValue = props.marks.findIndex( mark => {
+ let _unit, _value
+ [ _value, _unit ] = extractNumbersAndUnits( mark.size )[ 0 ]
+ const converted = convertToPxIfUnsupported( props.units, _unit, _value )
+ _value = converted.value
+ _unit = converted.unit
+ return _value === firstValue && ( ! unit || _unit === '' || _unit === unit )
+ } )
+ const markValue = props.marks[ rangeValue ]?.value || '0'
+ onChangeAll( markValue )
}
setIsFourMarkMode( prev => ( { ...prev, first: ! prev.first } ) )
} }
@@ -569,6 +571,17 @@ const FourRangeControl = memo( props => {
onClick={ () => {
if ( isFourMarkMode.top && rangeValueTop !== -1 ) {
rangeOnChangeTop( rangeValueTop, 'size' )
+ } else {
+ const rangeValue = props.marks.findIndex( mark => {
+ let _unit, _value
+ [ _value, _unit ] = extractNumbersAndUnits( mark.size )[ 0 ]
+ const converted = convertToPxIfUnsupported( props.units, _unit, _value )
+ _value = converted.value
+ _unit = converted.unit
+ return _value === value.top && ( ! unit || _unit === '' || _unit === unit )
+ } )
+ const markValue = props.marks[ rangeValue ]?.value || '0'
+ onChangeVertical( markValue )
}
setIsFourMarkMode( prev => ( { ...prev, top: ! prev.top } ) )
} }
@@ -628,6 +641,17 @@ const FourRangeControl = memo( props => {
onClick={ () => {
if ( isFourMarkMode.left && rangeValueLeft !== -1 ) {
rangeOnChangeLeft( rangeValueLeft, 'size' )
+ } else {
+ const rangeValue = props.marks.findIndex( mark => {
+ let _unit, _value
+ [ _value, _unit ] = extractNumbersAndUnits( mark.size )[ 0 ]
+ const converted = convertToPxIfUnsupported( props.units, _unit, _value )
+ _value = converted.value
+ _unit = converted.unit
+ return _value === value.left && ( ! unit || _unit === '' || _unit === unit )
+ } )
+ const markValue = props.marks[ rangeValue ]?.value || '0'
+ onChangeHorizontal( markValue )
}
setIsFourMarkMode( prev => ( { ...prev, left: ! prev.left } ) )
} }
@@ -693,6 +717,17 @@ const FourRangeControl = memo( props => {
onClick={ () => {
if ( isFourMarkMode.top && rangeValueTop !== -1 ) {
rangeOnChangeTop( rangeValueTop, 'size' )
+ } else {
+ const rangeValue = props.marks.findIndex( mark => {
+ let _unit, _value
+ [ _value, _unit ] = extractNumbersAndUnits( mark.size )[ 0 ]
+ const converted = convertToPxIfUnsupported( props.units, _unit, _value )
+ _value = converted.value
+ _unit = converted.unit
+ return _value === value.top && ( ! unit || _unit === '' || _unit === unit )
+ } )
+ const markValue = props.marks[ rangeValue ]?.value || '0'
+ onChangeTop( markValue )
}
setIsFourMarkMode( prev => ( { ...prev, top: ! prev.top } ) )
} }
@@ -755,6 +790,17 @@ const FourRangeControl = memo( props => {
onClick={ () => {
if ( isFourMarkMode.right && rangeValueRight !== -1 ) {
rangeOnChangeRight( rangeValueRight, 'size' )
+ } else {
+ const rangeValue = props.marks.findIndex( mark => {
+ let _unit, _value
+ [ _value, _unit ] = extractNumbersAndUnits( mark.size )[ 0 ]
+ const converted = convertToPxIfUnsupported( props.units, _unit, _value )
+ _value = converted.value
+ _unit = converted.unit
+ return _value === value.right && ( ! unit || _unit === '' || _unit === unit )
+ } )
+ const markValue = props.marks[ rangeValue ]?.value || '0'
+ onChangeRight( markValue )
}
setIsFourMarkMode( prev => ( { ...prev, right: ! prev.right } ) )
} }
@@ -817,6 +863,17 @@ const FourRangeControl = memo( props => {
onClick={ () => {
if ( isFourMarkMode.bottom && rangeValueBottom !== -1 ) {
rangeOnChangeBottom( rangeValueBottom, 'size' )
+ } else {
+ const rangeValue = props.marks.findIndex( mark => {
+ let _unit, _value
+ [ _value, _unit ] = extractNumbersAndUnits( mark.size )[ 0 ]
+ const converted = convertToPxIfUnsupported( props.units, _unit, _value )
+ _value = converted.value
+ _unit = converted.unit
+ return _value === value.bottom && ( ! unit || _unit === '' || _unit === unit )
+ } )
+ const markValue = props.marks[ rangeValue ]?.value || '0'
+ onChangeBottom( markValue )
}
setIsFourMarkMode( prev => ( { ...prev, bottom: ! prev.bottom } ) )
} }
@@ -879,6 +936,17 @@ const FourRangeControl = memo( props => {
onClick={ () => {
if ( isFourMarkMode.left && rangeValueLeft !== -1 ) {
rangeOnChangeLeft( rangeValueLeft, 'size' )
+ } else {
+ const rangeValue = props.marks.findIndex( mark => {
+ let _unit, _value
+ [ _value, _unit ] = extractNumbersAndUnits( mark.size )[ 0 ]
+ const converted = convertToPxIfUnsupported( props.units, _unit, _value )
+ _value = converted.value
+ _unit = converted.unit
+ return _value === value.left && ( ! unit || _unit === '' || _unit === unit )
+ } )
+ const markValue = props.marks[ rangeValue ]?.value || '0'
+ onChangeLeft( markValue )
}
setIsFourMarkMode( prev => ( { ...prev, left: ! prev.left } ) )
} }
diff --git a/src/global-settings.php b/src/global-settings.php
index f2571a3133..490aff3f1f 100644
--- a/src/global-settings.php
+++ b/src/global-settings.php
@@ -697,6 +697,14 @@ public function form_paragraph_selector() {
return $selectors;
}
+ public function clean_font_size( $font_size, $font_size_unit = '' ) {
+ if ( is_string( $font_size ) && str_starts_with( $font_size, 'var' ) ) {
+ return $font_size;
+ }
+
+ return $font_size . $font_size_unit;
+ }
+
/**
* Creates a CSS style rule with an added !important if necessary.
*
@@ -753,7 +761,7 @@ public function generate_typography_styles( $selector, $styles ) {
$css['desktop'][] = $this->create_style( 'font-family', $this->get_font_family( $styles['fontFamily'] ) );
}
if ( isset( $styles['fontSize'] ) ) {
- $css['desktop'][] = $this->create_style( 'font-size', $styles['fontSize'] . $styles['fontSizeUnit'] );
+ $css['desktop'][] = $this->create_style( 'font-size', $this->clean_font_size( $styles['fontSize'], $styles['fontSizeUnit'] ) );
}
if ( isset( $styles['fontWeight'] ) ) {
$css['desktop'][] = $this->create_style( 'font-weight', $styles['fontWeight'] );
@@ -782,12 +790,12 @@ public function generate_typography_styles( $selector, $styles ) {
if ( isset( $styles['fontSize'] ) ) {
$clamp_desktop_value = $this->clamp_inherited_style( $styles['fontSize'], $inherit_max );
if ( ! empty( $clamp_desktop_value ) ) {
- $font_size = $this->create_style( 'font-size', $clamp_desktop_value . $styles['fontSizeUnit'] );
+ $font_size = $this->create_style( 'font-size', $this->clean_font_size( $clamp_desktop_value . $styles['fontSizeUnit'] ) );
}
}
}
if ( isset( $styles['tabletFontSize'] ) ) {
- $font_size = $this->create_style( 'font-size', $styles['tabletFontSize'] . $styles['tabletFontSizeUnit'] );
+ $font_size = $this->create_style( 'font-size', $this->clean_font_size( $styles['tabletFontSize'], $styles['tabletFontSizeUnit'] ) );
}
if ( ! empty( $font_size ) ) {
$css['tablet'][] = $font_size;
@@ -810,7 +818,7 @@ public function generate_typography_styles( $selector, $styles ) {
if ( isset( $styles['fontSize'] ) ) {
$clamp_desktop_value = $this->clamp_inherited_style( $styles['fontSize'], $inherit_max );
if ( ! empty( $clamp_desktop_value ) ) {
- $font_size = $this->create_style( 'font-size', $clamp_desktop_value . $styles['fontSizeUnit'] );
+ $font_size = $this->create_style( 'font-size', $this->clean_font_size( $clamp_desktop_value, $styles['fontSizeUnit'] ) );
}
}
@@ -818,7 +826,7 @@ public function generate_typography_styles( $selector, $styles ) {
if ( isset( $styles['tabletFontSize'] ) ) {
$clamp_tablet_value = $this->clamp_inherited_style( $styles['tabletFontSize'], $inherit_max );
if ( ! empty( $clamp_tablet_value ) ) {
- $font_size = $this->create_style( 'font-size', $clamp_tablet_value . $styles['tabletFontSizeUnit'] );
+ $font_size = $this->create_style( $this->clean_font_size( 'font-size', $clamp_tablet_value, $styles['tabletFontSizeUnit'] ) );
}
}
if ( empty( $clamp_tablet_value ) ) {
@@ -831,7 +839,7 @@ public function generate_typography_styles( $selector, $styles ) {
}
}
if ( isset( $styles['mobileFontSize'] ) ) {
- $font_size = $this->create_style( 'font-size', $styles['mobileFontSize'] . $styles['mobileFontSizeUnit'] );
+ $font_size = $this->create_style( 'font-size', $this->clean_font_size( $styles['mobileFontSize'], $styles['mobileFontSizeUnit'] ) );
}
if ( ! empty( $font_size ) ) {
$css['mobile'][] = $font_size;
From 3a660e2d07451ad5468bfa751218ecac911f37a1 Mon Sep 17 00:00:00 2001
From: Alquen Sarmiento
Date: Tue, 27 May 2025 17:49:52 +0800
Subject: [PATCH 093/124] fix: bug fix
---
src/global-settings.php | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/global-settings.php b/src/global-settings.php
index 490aff3f1f..2859bb62a2 100644
--- a/src/global-settings.php
+++ b/src/global-settings.php
@@ -790,7 +790,7 @@ public function generate_typography_styles( $selector, $styles ) {
if ( isset( $styles['fontSize'] ) ) {
$clamp_desktop_value = $this->clamp_inherited_style( $styles['fontSize'], $inherit_max );
if ( ! empty( $clamp_desktop_value ) ) {
- $font_size = $this->create_style( 'font-size', $this->clean_font_size( $clamp_desktop_value . $styles['fontSizeUnit'] ) );
+ $font_size = $this->create_style( 'font-size', $this->clean_font_size( $clamp_desktop_value, $styles['fontSizeUnit'] ) );
}
}
}
@@ -898,7 +898,7 @@ public function get_font_family( $font_name ) {
* @param {Object} options
*/
public function clamp_inherited_style( $value, $max = 999999, $min = -999999 ) {
- if ( isset( $value ) ) {
+ if ( isset( $value ) && is_numeric( $value ) ) {
$clamped_value = max( $min, min( $max, $value ) );
return $clamped_value !== $value ? $clamped_value : null;
}
From 218c7b6117c72b2619495351874b8b31e19079e6 Mon Sep 17 00:00:00 2001
From: Alquen Sarmiento
Date: Tue, 27 May 2025 21:58:46 +0800
Subject: [PATCH 094/124] fix: four range reactivity
---
src/components/four-range-control/index.js | 43 ++++++++++++++--------
1 file changed, 28 insertions(+), 15 deletions(-)
diff --git a/src/components/four-range-control/index.js b/src/components/four-range-control/index.js
index 644ffef0e5..0d0c191d0d 100644
--- a/src/components/four-range-control/index.js
+++ b/src/components/four-range-control/index.js
@@ -494,8 +494,10 @@ const FourRangeControl = memo( props => {
size="small"
variant="tertiary"
onClick={ () => {
- // Set the value when changing from mark mode to custom
- if ( isFourMarkMode.first && rangeValueFirst !== -1 ) {
+ const previousMarkMode = isFourMarkMode.first
+ setIsFourMarkMode( prev => ( { ...prev, first: ! prev.first } ) )
+
+ if ( previousMarkMode && rangeValueFirst !== -1 ) {
rangeOnChangeFirst( rangeValueFirst, 'size' )
} else {
const rangeValue = props.marks.findIndex( mark => {
@@ -509,7 +511,6 @@ const FourRangeControl = memo( props => {
const markValue = props.marks[ rangeValue ]?.value || '0'
onChangeAll( markValue )
}
- setIsFourMarkMode( prev => ( { ...prev, first: ! prev.first } ) )
} }
icon={ settings }
>
@@ -569,7 +570,10 @@ const FourRangeControl = memo( props => {
size="small"
variant="tertiary"
onClick={ () => {
- if ( isFourMarkMode.top && rangeValueTop !== -1 ) {
+ const previousMarkMode = isFourMarkMode.top
+ setIsFourMarkMode( prev => ( { ...prev, top: ! prev.top } ) )
+
+ if ( previousMarkMode && rangeValueTop !== -1 ) {
rangeOnChangeTop( rangeValueTop, 'size' )
} else {
const rangeValue = props.marks.findIndex( mark => {
@@ -583,7 +587,6 @@ const FourRangeControl = memo( props => {
const markValue = props.marks[ rangeValue ]?.value || '0'
onChangeVertical( markValue )
}
- setIsFourMarkMode( prev => ( { ...prev, top: ! prev.top } ) )
} }
icon={ settings }
>
@@ -639,7 +642,10 @@ const FourRangeControl = memo( props => {
size="small"
variant="tertiary"
onClick={ () => {
- if ( isFourMarkMode.left && rangeValueLeft !== -1 ) {
+ const previousMarkMode = isFourMarkMode.left
+ setIsFourMarkMode( prev => ( { ...prev, left: ! prev.left } ) )
+
+ if ( previousMarkMode && rangeValueLeft !== -1 ) {
rangeOnChangeLeft( rangeValueLeft, 'size' )
} else {
const rangeValue = props.marks.findIndex( mark => {
@@ -653,7 +659,6 @@ const FourRangeControl = memo( props => {
const markValue = props.marks[ rangeValue ]?.value || '0'
onChangeHorizontal( markValue )
}
- setIsFourMarkMode( prev => ( { ...prev, left: ! prev.left } ) )
} }
icon={ settings }
>
@@ -715,7 +720,10 @@ const FourRangeControl = memo( props => {
size="small"
variant="tertiary"
onClick={ () => {
- if ( isFourMarkMode.top && rangeValueTop !== -1 ) {
+ const previousMarkMode = isFourMarkMode.top
+ setIsFourMarkMode( prev => ( { ...prev, top: ! prev.top } ) )
+
+ if ( previousMarkMode && rangeValueTop !== -1 ) {
rangeOnChangeTop( rangeValueTop, 'size' )
} else {
const rangeValue = props.marks.findIndex( mark => {
@@ -729,7 +737,6 @@ const FourRangeControl = memo( props => {
const markValue = props.marks[ rangeValue ]?.value || '0'
onChangeTop( markValue )
}
- setIsFourMarkMode( prev => ( { ...prev, top: ! prev.top } ) )
} }
icon={ settings }
>
@@ -788,7 +795,10 @@ const FourRangeControl = memo( props => {
size="small"
variant="tertiary"
onClick={ () => {
- if ( isFourMarkMode.right && rangeValueRight !== -1 ) {
+ const previousMarkMode = isFourMarkMode.right
+ setIsFourMarkMode( prev => ( { ...prev, right: ! prev.right } ) )
+
+ if ( previousMarkMode && rangeValueRight !== -1 ) {
rangeOnChangeRight( rangeValueRight, 'size' )
} else {
const rangeValue = props.marks.findIndex( mark => {
@@ -802,7 +812,6 @@ const FourRangeControl = memo( props => {
const markValue = props.marks[ rangeValue ]?.value || '0'
onChangeRight( markValue )
}
- setIsFourMarkMode( prev => ( { ...prev, right: ! prev.right } ) )
} }
icon={ settings }
>
@@ -861,7 +870,10 @@ const FourRangeControl = memo( props => {
size="small"
variant="tertiary"
onClick={ () => {
- if ( isFourMarkMode.bottom && rangeValueBottom !== -1 ) {
+ const previousMarkMode = isFourMarkMode.bottom
+ setIsFourMarkMode( prev => ( { ...prev, bottom: ! prev.bottom } ) )
+
+ if ( previousMarkMode && rangeValueBottom !== -1 ) {
rangeOnChangeBottom( rangeValueBottom, 'size' )
} else {
const rangeValue = props.marks.findIndex( mark => {
@@ -875,7 +887,6 @@ const FourRangeControl = memo( props => {
const markValue = props.marks[ rangeValue ]?.value || '0'
onChangeBottom( markValue )
}
- setIsFourMarkMode( prev => ( { ...prev, bottom: ! prev.bottom } ) )
} }
icon={ settings }
>
@@ -934,7 +945,10 @@ const FourRangeControl = memo( props => {
size="small"
variant="tertiary"
onClick={ () => {
- if ( isFourMarkMode.left && rangeValueLeft !== -1 ) {
+ const previousMarkMode = isFourMarkMode.left
+ setIsFourMarkMode( prev => ( { ...prev, left: ! prev.left } ) )
+
+ if ( previousMarkMode && rangeValueLeft !== -1 ) {
rangeOnChangeLeft( rangeValueLeft, 'size' )
} else {
const rangeValue = props.marks.findIndex( mark => {
@@ -948,7 +962,6 @@ const FourRangeControl = memo( props => {
const markValue = props.marks[ rangeValue ]?.value || '0'
onChangeLeft( markValue )
}
- setIsFourMarkMode( prev => ( { ...prev, left: ! prev.left } ) )
} }
icon={ settings }
>
From 11a204e5bf632d97439900d844fc4e4ccd38caa9 Mon Sep 17 00:00:00 2001
From: Mikhaela Tapia
Date: Wed, 28 May 2025 11:46:28 +0800
Subject: [PATCH 095/124] init
---
src/block/design-library/edit.js | 323 +++++++----
.../color-scheme-preview/editor.scss | 12 +
src/components/color-scheme-preview/index.js | 7 +-
src/components/color-schemes-help/index.js | 16 +-
.../design-library-list/default.json | 30 ++
.../design-library-list-item.js | 312 +++++++++--
.../design-library-list/editor.scss | 119 ++--
src/components/design-library-list/index.js | 133 +++--
src/components/design-library-list/util.js | 204 +++++++
.../modal-design-library/block-list.js | 207 ++-----
.../modal-design-library/color-list.js | 87 ---
.../modal-design-library/editor.scss | 196 ++++++-
src/components/modal-design-library/modal.js | 506 +++++++++++-------
src/design-library/index.js | 72 +--
src/design-library/init.php | 390 +++++++++++---
src/hooks/use-block-color-schemes.js | 25 +-
src/init.php | 5 +
.../color-schemes/color-scheme-picker.js | 24 +
.../global-settings/color-schemes/index.js | 69 ++-
src/plugins/global-settings/editor-loader.js | 15 +
.../typography/editor-loader.js | 2 +-
src/util/admin.js | 8 +-
src/welcome/admin.js | 100 +++-
23 files changed, 1969 insertions(+), 893 deletions(-)
create mode 100644 src/components/design-library-list/default.json
create mode 100644 src/components/design-library-list/util.js
delete mode 100644 src/components/modal-design-library/color-list.js
diff --git a/src/block/design-library/edit.js b/src/block/design-library/edit.js
index a1f62895e4..78202a7b30 100644
--- a/src/block/design-library/edit.js
+++ b/src/block/design-library/edit.js
@@ -6,15 +6,13 @@ import {
i18n,
srcUrl,
settings,
+ cdnUrl,
} from 'stackable'
import {
Button,
ModalDesignLibrary,
} from '~stackable/components'
import { SVGStackableIcon } from '~stackable/icons'
-import {
- deprecateBlockBackgroundColorOpacity, deprecateContainerBackgroundColorOpacity, deprecateTypographyGradientColor,
-} from '~stackable/block-components'
import { substituteCoreIfDisabled, BLOCK_STATE } from '~stackable/util'
import { substitutionRules } from '../../blocks'
@@ -24,17 +22,61 @@ import { substitutionRules } from '../../blocks'
import { __ } from '@wordpress/i18n'
import { dispatch } from '@wordpress/data'
import {
- createBlock, parse, createBlocksFromInnerBlocksTemplate, getBlockVariations, getBlockType,
+ createBlock, createBlocksFromInnerBlocksTemplate, getBlockVariations, getBlockType,
} from '@wordpress/blocks'
-import { useState } from '@wordpress/element'
-import { addFilter, applyFilters } from '@wordpress/hooks'
-import { Placeholder } from '@wordpress/components'
+import { useRef, useState } from '@wordpress/element'
+import { applyFilters } from '@wordpress/hooks'
+import {
+ // eslint-disable-next-line @wordpress/no-unsafe-wp-apis
+ Placeholder, Modal, __experimentalVStack as VStack, Flex,
+} from '@wordpress/components'
import { useBlockProps } from '@wordpress/block-editor'
+import apiFetch from '@wordpress/api-fetch'
+const convertBlocksToArray = block => {
+ const innerBlocks = block.innerBlocks.map( innerBlock => convertBlocksToArray( innerBlock ) )
+ return [ block.name, block.attributes, innerBlocks ]
+}
+
+const checkIfImageUrl = async value => {
+ if ( typeof value !== 'string' ) {
+ return value
+ }
+
+ let attributeUrl, libraryUrl
+
+ try {
+ attributeUrl = new URL( value )
+ libraryUrl = new URL( cdnUrl )
+ } catch ( error ) {
+ return value
+ }
+
+ if ( attributeUrl.origin !== libraryUrl.origin || ! attributeUrl.pathname.startsWith( libraryUrl.pathname ) ) {
+ return value
+ }
+
+ const matches = attributeUrl.pathname.match( /\/([^/]+\.(jpe?g|gif|png|mp4|webp))$/i )
+
+ if ( matches ) {
+ const result = await apiFetch( {
+ path: '/stackable/v3/design_library_image',
+ method: 'POST',
+ // eslint-disable-next-line camelcase
+ data: { image_url: attributeUrl.href },
+ } )
+ if ( result.success ) {
+ return result.new_url
+ }
+
+ console.error( 'Stackable Design Library:', result.message ) // eslint-disable-line no-console
+ return value
+ }
+ return value
+}
// Replaces the current block with a block made out of attributes.
-const createBlockWithAttributes = ( blockName, attributes, innerBlocks, design ) => {
+const createBlockWithAttributes = async ( blockName, attributes, innerBlocks, substituteBlocks ) => {
const disabledBlocks = settings.stackable_block_states || {} // eslint-disable-line camelcase
- let hasSubstituted = false
// Recursively substitute core blocks to disabled Stackable blocks
const traverseBlocksAndSubstitute = blocks => {
@@ -45,13 +87,9 @@ const createBlockWithAttributes = ( blockName, attributes, innerBlocks, design )
// Check if the new substituted block is still disabled
while ( isDisabled && attempts > 0 ) {
- const previousBlockName = block[ 0 ]
- block = substituteCoreIfDisabled( ...block, substitutionRules )
+ const _blockName = block[ 1 ].originalName || block[ 0 ]
+ block = substituteCoreIfDisabled( _blockName, block[ 1 ], block[ 2 ], substitutionRules )
isDisabled = block[ 0 ] in disabledBlocks && disabledBlocks[ block[ 0 ] ] === BLOCK_STATE.DISABLED
- // If the previous block is different from the new block, substitution has been made
- if ( ! hasSubstituted && previousBlockName !== block[ 0 ] ) {
- hasSubstituted = true
- }
attempts--
}
@@ -63,83 +101,68 @@ const createBlockWithAttributes = ( blockName, attributes, innerBlocks, design )
if ( ! Array.isArray( block[ 2 ] ) ) {
block[ 2 ] = []
}
- return block
+
+ const _block = {
+ name: block[ 0 ],
+ attributes: block[ 1 ],
+ innerBlocks: block[ 2 ],
+ isValid: true,
+ }
+ return _block
} )
}
- // Substitute from the root of the design
- [ blockName, attributes, innerBlocks ] = traverseBlocksAndSubstitute( [ [ blockName, attributes, innerBlocks ] ] )[ 0 ]
+ if ( ! Array.isArray( disabledBlocks ) && substituteBlocks ) {
+ let block = convertBlocksToArray( {
+ name: blockName, attributes, innerBlocks,
+ } )
- if ( hasSubstituted ) {
- // eslint-disable-next-line no-alert
- alert( 'Notice: Disabled blocks in the design will be substituted with other Stackable or core blocks' )
+ block = traverseBlocksAndSubstitute( [ block ] )[ 0 ]
+ blockName = block.name
+ attributes = block.attributes
+ innerBlocks = block.innerBlocks
}
- // const { replaceBlock } = dispatch( 'core/block-editor' )
+ const cleanBlockAttributes = async blocks => {
+ for ( const block of blocks ) {
+ const blockName = block.name
- // For wireframes, we'll need to apply any default block attributes to
- // the blocks. We do this by ensuring that all uniqueIds are removed,
- // this prompts the block to generate a new one and give itself a
- // default styling.
- if ( design.uikit === 'Wireframes' ) {
- const hasVariations = getBlockVariations( blockName ).length > 0
- if ( ! hasVariations ) {
- attributes.uniqueId = ''
- }
+ // For blocks with variations, do not remove the uniqueId
+ // since that will prompt the layout picker to show.
+ const hasVariations = !! getBlockType( blockName ) && getBlockVariations( blockName ).length > 0
+ if ( ! hasVariations && block.attributes.uniqueId ) {
+ delete block.attributes.uniqueId
+ }
+
+ const customAttributes = block.attributes.customAttributes
- // Recursively remove all uniqueIds from all inner blocks.
- const removeUniqueId = blocks => {
- blocks.forEach( block => {
- const blockName = block[ 0 ]
+ const indexToDelete = customAttributes?.findIndex( attribute => attribute[ 0 ] === 'stk-design-library__bg-target' )
+ if ( customAttributes && indexToDelete !== -1 ) {
+ block.attributes.customAttributes.splice( indexToDelete, 1 )
+ }
- // For blocks with variations, do not remove the uniqueId
- // since that will prompt the layout picker to show.
- const hasVariations = !! getBlockType( blockName ) && getBlockVariations( blockName ).length > 0
- if ( ! hasVariations && block[ 1 ].uniqueId ) {
- delete block[ 1 ].uniqueId
+ for ( const attributeName in block.attributes ) {
+ if ( typeof block.attributes[ attributeName ] === 'string' ) {
+ const value = String( block.attributes[ attributeName ] )
+ block.attributes[ attributeName ] = await checkIfImageUrl( value )
}
+ }
- removeUniqueId( block[ 2 ] )
- } )
+ block.innerBlocks = await cleanBlockAttributes( block.innerBlocks )
}
- removeUniqueId( innerBlocks )
- }
-
- const shortBlockName = blockName.replace( /^\w+\//g, '' )
-
- // Recursively update the attributes of all inner blocks for the new Color Picker
- const migrateToNewColorPicker = blocks => {
- blocks?.forEach( block => {
- try {
- let newAttributes = block[ 1 ]
- newAttributes = deprecateContainerBackgroundColorOpacity.migrate( newAttributes )
- newAttributes = deprecateBlockBackgroundColorOpacity.migrate( newAttributes )
- newAttributes = deprecateTypographyGradientColor.migrate( '%s' )( newAttributes )
- block[ 1 ] = newAttributes
- migrateToNewColorPicker( block[ 2 ] )
- } catch ( error ) {
- }
- } )
+ return blocks
}
- migrateToNewColorPicker( innerBlocks )
-
- addFilter( `stackable.${ shortBlockName }.design.filtered-block-attributes`, 'stackable.design-library.attributes--migrate-to-new-color-picker', attributes => {
- let newAttributes = { ...attributes }
- newAttributes = deprecateContainerBackgroundColorOpacity.migrate( newAttributes )
- newAttributes = deprecateBlockBackgroundColorOpacity.migrate( newAttributes )
- newAttributes = deprecateTypographyGradientColor.migrate( '%s' )( newAttributes )
- return newAttributes
- } )
-
- const blockAttributes = applyFilters( `stackable.${ shortBlockName }.design.filtered-block-attributes`, attributes )
+ const block = await cleanBlockAttributes( [ {
+ name: blockName, attributes, innerBlocks,
+ } ] )
- return createBlock( blockName, blockAttributes, createBlocksFromInnerBlocksTemplate( innerBlocks ) )
-}
+ blockName = block[ 0 ].name
+ attributes = block[ 0 ].attributes
+ innerBlocks = block[ 0 ].innerBlocks
-const createBlockWithContent = serializedBlock => {
- return parse( serializedBlock )
+ return createBlock( blockName, attributes, createBlocksFromInnerBlocksTemplate( innerBlocks ) )
}
const Edit = props => {
@@ -149,11 +172,76 @@ const Edit = props => {
} = props
const [ isLibraryOpen, setIsLibraryOpen ] = useState( false )
+ const [ isDialogOpen, setIsDialogOpen ] = useState( false )
+
+ const designsRef = useRef( [] )
+ const disabledBlocksRef = useRef( [] )
+ const callbackRef = useRef( null )
const blockProps = useBlockProps( {
className: 'ugb-design-library-block',
} )
+ const addDesigns = async substituteBlocks => {
+ if ( ! designsRef.current?.length ) {
+ console.error( 'Design library selection failed: No designs found' ) // eslint-disable-line no-console
+ }
+
+ const designs = designsRef.current
+ const blocks = []
+
+ for ( const designData of designs ) {
+ const {
+ name, attributes, innerBlocks,
+ } = designData
+ if ( name && attributes ) {
+ const block = await createBlockWithAttributes( name, applyFilters( 'stackable.design-library.attributes', attributes ), innerBlocks || [], substituteBlocks )
+ blocks.push( block )
+ } else {
+ console.error( 'Design library selection failed: No block data found' ) // eslint-disable-line no-console
+ }
+ }
+
+ if ( blocks.length ) {
+ dispatch( 'core/block-editor' ).replaceBlocks( clientId, blocks )
+ if ( callbackRef.current ) {
+ callbackRef.current()
+ }
+ }
+ }
+
+ const onClickTertiary = () => {
+ const disabledBlocks = disabledBlocksRef.current
+
+ const settingsPageUrl = `/wp-admin/options-general.php?page=stackable`
+ const newWindow = window.open( settingsPageUrl, '_blank' )
+
+ if ( newWindow ) {
+ newWindow.onload = () => { // Wait for the new page to fully load
+ setTimeout( () => {
+ try {
+ const blocksTab = newWindow.document.getElementById( 'stk-tab__blocks' )
+ if ( blocksTab ) {
+ blocksTab.click()
+
+ newWindow.postMessage( {
+ type: 'STK_ENABLE_BLOCKS', blocks: disabledBlocks, source: 'STK_DESIGN_LIBRARY',
+ }, window.location.origin )
+ }
+ } catch ( error ) {}
+ }, 5 )
+ }
+ newWindow.focus()
+ }
+ }
+
+ const onClickSecondary = async () => {
+ await addDesigns( false )
+ }
+ const onClickPrimary = async () => {
+ await addDesigns( true )
+ }
+
if ( attributes.previewMode ) {
const src = previewImage.match( /https?:/i ) ? previewImage
: srcUrl ? `${ srcUrl }/${ previewImage }`
@@ -187,35 +275,74 @@ const Edit = props => {
onClose={ () => {
setIsLibraryOpen( false )
} }
- onSelect={ ( _designData, _design, callback = null ) => {
- const designData = ! Array.isArray( _designData ) ? [ _designData ] : _designData
- const designs = ! Array.isArray( _design ) ? [ _design ] : _design
-
- const blocks = designData.reduce( ( blocks, designData, i ) => {
- const design = designs[ i ]
- const {
- name, attributes, innerBlocks, serialized,
- } = designData
- if ( name && attributes ) {
- const block = createBlockWithAttributes( name, applyFilters( 'stackable.design-library.attributes', attributes ), innerBlocks || [], design )
- blocks.push( block )
- } else if ( serialized ) {
- blocks.push( createBlockWithContent( serialized ) )
- } else {
- console.error( 'Design library selection failed: No block data found' ) // eslint-disable-line no-console
- }
- return blocks
- }, [] )
+ onSelect={ async ( _designs, callback ) => {
+ const designs = []
+ let disabledBlocks = new Set()
+
+ _designs.forEach( design => {
+ const { designData, blocksForSubstitution } = design
- if ( blocks.length ) {
- dispatch( 'core/block-editor' ).replaceBlocks( clientId, blocks )
- if ( callback ) {
- callback()
+ if ( blocksForSubstitution.size ) {
+ disabledBlocks = disabledBlocks.union( blocksForSubstitution )
}
+
+ designs.push( designData )
+ } )
+
+ designsRef.current = designs
+ disabledBlocksRef.current = disabledBlocks
+ callbackRef.current = callback
+
+ if ( disabledBlocks.size ) {
+ setIsDialogOpen( true )
+ return
}
+
+ await addDesigns( false )
} }
/>
}
+ { isDialogOpen &&
+ setIsDialogOpen( false ) }
+ >
+
+
+
{ __( 'The designs you have selected contain the following disabled blocks:', i18n ) }
+
+ { disabledBlocksRef.current && [ ...disabledBlocksRef.current ].map( ( block, i ) => { block } ) }
+
+
{ __( 'These blocks can be enabled in the Stackable settings page. Do you want to keep the disabled blocks or substitute them with other Stackable or core blocks?', i18n ) }
+
+
+ onClickTertiary() }
+ >
+ { __( 'Visit the settings page and enable the blocks', i18n ) }
+
+ onClickPrimary() }
+ >
+ { __( 'Add patterns and substitute missing blocks', i18n ) }
+
+ onClickSecondary() }
+ >
+ { __( 'Add patterns without substituting missing blocks', i18n ) }
+
+
+
+
+
+ }
)
}
diff --git a/src/components/color-scheme-preview/editor.scss b/src/components/color-scheme-preview/editor.scss
index 3960c92a55..6f7347181d 100644
--- a/src/components/color-scheme-preview/editor.scss
+++ b/src/components/color-scheme-preview/editor.scss
@@ -76,3 +76,15 @@
.stk-scheme--is-disabled {
opacity: 0.1;
}
+
+.stk-scheme--is-collapsed {
+ flex-direction: row;
+ gap: 4px;
+ align-items: center;
+ max-height: 30px;
+
+ .stk-global-color-scheme__preview__typography {
+ margin-bottom: 0;
+ font-size: 12px;
+ }
+}
diff --git a/src/components/color-scheme-preview/index.js b/src/components/color-scheme-preview/index.js
index 2389b92799..3dcff64a4b 100644
--- a/src/components/color-scheme-preview/index.js
+++ b/src/components/color-scheme-preview/index.js
@@ -14,13 +14,18 @@ export const DEFAULT_COLOR_SCHEME_COLORS = {
const NOOP = () => {}
const ColorSchemePreview = ( {
- colors, withWrapper = false, onClick = NOOP, isDisabled = false,
+ colors,
+ withWrapper = false,
+ onClick = NOOP,
+ isDisabled = false,
+ isCollapsed = false,
} ) => {
const TagName = onClick === NOOP ? 'div' : Button
const additionalProps = onClick === NOOP ? {} : { onClick }
const classNames = classnames( 'stk-global-color-scheme__preview__background', {
'stk-scheme--is-disabled': isDisabled,
+ 'stk-scheme--is-collapsed': isCollapsed,
} )
return (
diff --git a/src/components/color-schemes-help/index.js b/src/components/color-schemes-help/index.js
index caeef807a1..d390c8222b 100644
--- a/src/components/color-schemes-help/index.js
+++ b/src/components/color-schemes-help/index.js
@@ -4,8 +4,15 @@ import { Link } from '~stackable/components'
import { __ } from '@wordpress/i18n'
import { dispatch } from '@wordpress/data'
-export const ColorSchemesHelp = () => {
+export const ColorSchemesHelp = props => {
+ const {
+ customText, callback, renderComponent,
+ } = props
const onClick = () => {
+ if ( callback ) {
+ callback()
+ }
+
// Open the global settings sidebar.
dispatch( 'core/edit-post' )?.openGeneralSidebar( 'stackable-global-settings/sidebar' ) // For Block Editor
dispatch( 'core/edit-site' )?.openGeneralSidebar( 'stackable-global-settings/sidebar' ) // For Site Editor
@@ -30,8 +37,13 @@ export const ColorSchemesHelp = () => {
}, 10 )
}
+ if ( renderComponent ) {
+ return renderComponent( onClick )
+ }
+
return <>
- {
+ if ( ! isPro && plan !== 'free' ) {
+ return
+ }
+ const cardRect = ref.current.getBoundingClientRect()
+
+ const newPreviewSize = { ...previewSize }
+ const newCardHeight = { ...cardHeight }
+ newPreviewSize.heightSelected = enableBackground ? previewSize.heightBackground : previewSize.heightNoBackground
+ newCardHeight.selected = cardRect.height
+
+ setPreviewSize( newPreviewSize )
+ setCardHeight( newCardHeight )
+
+ onClick( designId, parsedBlocks, blocksForSubstitutionRef.current )
+ } }
>
{ isBusy &&
}
{ ! isPro && plan !== 'free' &&
}
-
{
- if ( ! isPro && plan !== 'free' ) {
- return
- }
- if ( isMultiSelectMode ) {
- onClick( designId )
- return
- }
- setIsBusy( true )
- getDesign( designId, apiVersion ).then( designData => {
- const cb = setIsBusy( false )
- onClick( designData, cb )
- } )
- } }
- >
+
{ ! isPro && plan !== 'free' && (
{
showHideNote={ false }
/>
) }
-
-
+
+
-
+
)
-}
+} )
DesignLibraryListItem.defaultProps = {
designId: '',
@@ -91,10 +301,26 @@ DesignLibraryListItem.defaultProps = {
label: '',
onClick: () => {},
plan: 'free',
- isPro,
premiumLabel: __( 'Go Premium', i18n ),
- apiVersion: '',
- // isFavorite: false,
}
export default DesignLibraryListItem
+
+const DesignPreview = ( {
+ blocks, adjustScale, prevEnableBackground, enableBackground,
+} ) => {
+ useEffect( () => {
+ if ( prevEnableBackground !== enableBackground ) {
+ // Adjust scale if the background was toggled
+ setTimeout( adjustScale, 50 )
+ }
+ }, [ blocks ] )
+
+ return (
+