Skip to content

Commit 888ad9b

Browse files
committed
fix: use extractNumbersAndUnits that can process clamp, min, etc.
1 parent f86d210 commit 888ad9b

File tree

3 files changed

+84
-39
lines changed

3 files changed

+84
-39
lines changed

src/components/advanced-range-control/index.js

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
useBlockSetAttributesContext,
1414
useDeviceType,
1515
} from '~stackable/hooks'
16+
import { extractNumbersAndUnits } from '~stackable/util'
1617

1718
/**
1819
* External dependencies
@@ -186,7 +187,7 @@ const AdvancedRangeControl = props => {
186187
let rangeOnChange = _onChange
187188
if ( isMarkMode ) {
188189
rangeValue = props.marks.findIndex( mark => {
189-
const [ _value, _unit ] = extractNumberAndUnit( mark.value )
190+
const [ _value, _unit ] = extractNumbersAndUnits( mark.value )[ 0 ]
190191
return _value === derivedValue
191192
} )
192193
rangeOnChange = ( value, property = 'value' ) => {
@@ -195,7 +196,7 @@ const AdvancedRangeControl = props => {
195196
}
196197
// Extract the unit and value.
197198
const markValue = props.marks[ value ]?.[ property ] || '0'
198-
const [ _newValue, unit ] = extractNumberAndUnit( markValue )
199+
const [ _newValue, unit ] = extractNumbersAndUnits( markValue )[ 0 ]
199200
const newValue = _newValue
200201

201202
// Update the unit.
@@ -277,14 +278,3 @@ AdvancedRangeControl.defaultProps = {
277278
}
278279

279280
export default memo( AdvancedRangeControl, isEqual )
280-
281-
// The value can be in the format '10px' or '10.0em' or '10rem'.
282-
// Return an array with the number and the unit.
283-
const extractNumberAndUnit = value => {
284-
// Match the last characters that are not numbers.
285-
const matches = value.match( /([\d.]+)(\D*)$/ )
286-
if ( ! matches || value.startsWith( 'var' ) ) {
287-
return [ value, '' ]
288-
}
289-
return [ matches[ 1 ], matches[ 2 ] ]
290-
}

src/components/four-range-control/index.js

Lines changed: 52 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import RangeControl from '../advanced-range-control/range-control'
1818
import { ResetButton } from '../base-control2/reset-button'
1919
import AdvancedControl, { extractControlProps } from '../base-control2'
2020
import { useControlHandlers } from '../base-control2/hooks'
21+
import { extractNumbersAndUnits } from '~stackable/util'
2122

2223
/**
2324
* WordPress dependencies
@@ -54,17 +55,6 @@ const isEqualInitial = ( props, value, firstValue ) => {
5455
return isEqual
5556
}
5657

57-
// The value can be in the format '10px' or '10.0em' or '10rem'.
58-
// Return an array with the number and the unit.
59-
const extractNumberAndUnit = value => {
60-
// Match the last characters that are not numbers.
61-
const matches = value.match( /([\d.]+)(\D*)$/ )
62-
if ( ! matches || value.startsWith( 'var' ) ) {
63-
return [ value, '' ]
64-
}
65-
return [ matches[ 1 ], matches[ 2 ] ]
66-
}
67-
6858
const FourRangeControl = memo( props => {
6959
const [ _value, _onChange ] = useControlHandlers( props.attribute, props.responsive, props.hover, props.valueCallback, props.changeCallback )
7060
const [ propsToPass, controlProps ] = extractControlProps( props )
@@ -294,8 +284,8 @@ const FourRangeControl = memo( props => {
294284
} )
295285
setIsFourMarkMode( prev => ( {
296286
...prev,
297-
right: prev.right,
298-
left: prev.right,
287+
right: prev.left,
288+
left: prev.left,
299289
} ) )
300290
}
301291
// Support for steps. Modify the props to make the range control show steps.
@@ -341,17 +331,17 @@ const FourRangeControl = memo( props => {
341331
let rangeOnChange = initialOnChange
342332
if ( props.marks && isMarkMode ) {
343333
rangeValue = props.marks.findIndex( mark => {
344-
const [ _value, _unit ] = extractNumberAndUnit( mark.value )
334+
const [ _value, _unit ] = extractNumbersAndUnits( mark.value )[ 0 ]
345335
return _value === initialValue
346336
} )
347-
rangeOnChange = value => {
337+
rangeOnChange = ( value, property = 'value' ) => {
348338
if ( value === '' ) {
349339
return initialOnChange( value )
350340
}
351341

352342
// Extract the unit and value.
353-
const markValue = props.marks[ value ]?.value || '0'
354-
const [ _newValue, unit ] = extractNumberAndUnit( markValue )
343+
const markValue = props.marks[ value ]?.[ property ] || '0'
344+
const [ _newValue, unit ] = extractNumbersAndUnits( markValue )[ 0 ]
355345
const newValue = _newValue
356346

357347
// Update the unit.
@@ -417,8 +407,8 @@ const FourRangeControl = memo( props => {
417407
)
418408

419409
const [ propsToPassHorizontal, rangeValueHorizontal, rangeOnChangeHorizontal ] = stepSupport(
420-
isFourMarkMode.right,
421-
value.right,
410+
isFourMarkMode.left,
411+
value.left,
422412
onChangeHorizontal,
423413
)
424414

@@ -464,7 +454,13 @@ const FourRangeControl = memo( props => {
464454
className="stk-range-control__custom-button"
465455
size="small"
466456
variant="tertiary"
467-
onClick={ () => setIsFourMarkMode( prev => ( { ...prev, first: ! prev.first } ) ) }
457+
onClick={ () => {
458+
// Set the value when changing from mark mode to custom
459+
if ( isFourMarkMode.first && rangeValueFirst !== -1 ) {
460+
rangeOnChangeFirst( rangeValueFirst, 'size' )
461+
}
462+
setIsFourMarkMode( prev => ( { ...prev, first: ! prev.first } ) )
463+
} }
468464
icon={ settings }
469465
>
470466
</Button>
@@ -522,7 +518,12 @@ const FourRangeControl = memo( props => {
522518
className="stk-range-control__custom-button"
523519
size="small"
524520
variant="tertiary"
525-
onClick={ () => setIsFourMarkMode( prev => ( { ...prev, top: ! prev.top } ) ) }
521+
onClick={ () => {
522+
if ( isFourMarkMode.top && rangeValueTop !== -1 ) {
523+
rangeOnChangeTop( rangeValueTop, 'size' )
524+
}
525+
setIsFourMarkMode( prev => ( { ...prev, top: ! prev.top } ) )
526+
} }
526527
icon={ settings }
527528
>
528529
</Button>
@@ -576,7 +577,12 @@ const FourRangeControl = memo( props => {
576577
className="stk-range-control__custom-button"
577578
size="small"
578579
variant="tertiary"
579-
onClick={ () => setIsFourMarkMode( prev => ( { ...prev, left: ! prev.left } ) ) }
580+
onClick={ () => {
581+
if ( isFourMarkMode.left && rangeValueLeft !== -1 ) {
582+
rangeOnChangeLeft( rangeValueLeft, 'size' )
583+
}
584+
setIsFourMarkMode( prev => ( { ...prev, left: ! prev.left } ) )
585+
} }
580586
icon={ settings }
581587
>
582588
</Button>
@@ -636,7 +642,12 @@ const FourRangeControl = memo( props => {
636642
className="stk-range-control__custom-button"
637643
size="small"
638644
variant="tertiary"
639-
onClick={ () => setIsFourMarkMode( prev => ( { ...prev, top: ! prev.top } ) ) }
645+
onClick={ () => {
646+
if ( isFourMarkMode.top && rangeValueTop !== -1 ) {
647+
rangeOnChangeTop( rangeValueTop, 'size' )
648+
}
649+
setIsFourMarkMode( prev => ( { ...prev, top: ! prev.top } ) )
650+
} }
640651
icon={ settings }
641652
>
642653
</Button>
@@ -693,7 +704,12 @@ const FourRangeControl = memo( props => {
693704
className="stk-range-control__custom-button"
694705
size="small"
695706
variant="tertiary"
696-
onClick={ () => setIsFourMarkMode( prev => ( { ...prev, right: ! prev.right } ) ) }
707+
onClick={ () => {
708+
if ( isFourMarkMode.right && rangeValueRight !== -1 ) {
709+
rangeOnChangeRight( rangeValueRight, 'size' )
710+
}
711+
setIsFourMarkMode( prev => ( { ...prev, right: ! prev.right } ) )
712+
} }
697713
icon={ settings }
698714
>
699715
</Button>
@@ -750,7 +766,12 @@ const FourRangeControl = memo( props => {
750766
className="stk-range-control__custom-button"
751767
size="small"
752768
variant="tertiary"
753-
onClick={ () => setIsFourMarkMode( prev => ( { ...prev, bottom: ! prev.bottom } ) ) }
769+
onClick={ () => {
770+
if ( isFourMarkMode.bottom && rangeValueBottom !== -1 ) {
771+
rangeOnChangeBottom( rangeValueBottom, 'size' )
772+
}
773+
setIsFourMarkMode( prev => ( { ...prev, bottom: ! prev.bottom } ) )
774+
} }
754775
icon={ settings }
755776
>
756777
</Button>
@@ -807,7 +828,12 @@ const FourRangeControl = memo( props => {
807828
className="stk-range-control__custom-button"
808829
size="small"
809830
variant="tertiary"
810-
onClick={ () => setIsFourMarkMode( prev => ( { ...prev, left: ! prev.left } ) ) }
831+
onClick={ () => {
832+
if ( isFourMarkMode.left && rangeValueLeft !== -1 ) {
833+
rangeOnChangeLeft( rangeValueLeft, 'size' )
834+
}
835+
setIsFourMarkMode( prev => ( { ...prev, left: ! prev.left } ) )
836+
} }
811837
icon={ settings }
812838
>
813839
</Button>

src/util/index.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,3 +388,32 @@ export const createUniqueClass = uid => `${ uid.substring( 0, 7 ) }`
388388
export const semverCompare = ( version1, operator, version2 ) => {
389389
return compare( version1, version2, operator )
390390
}
391+
392+
/**
393+
* Extracts all number-unit pairs from a CSS value.
394+
*
395+
* @param { string } value - The CSS value to extract from.
396+
* @return { Array } An array of tuples, each containing a number and its corresponding unit.
397+
*
398+
* @example
399+
* extractNumbersAndUnits( "min(1.5rem, 2vw)" )
400+
* // Returns: [["1.5", "rem"], ["2", "vw"]]
401+
*/
402+
export const extractNumbersAndUnits = value => {
403+
if ( value.startsWith( 'var' ) ) {
404+
return [ [ value, '' ] ]
405+
}
406+
// Match numbers followed by a unit, including decimals and negative values.
407+
const regex = /(-?\d*\.?\d+)([a-zA-Z%]*)/g
408+
const matches = [ ...value.matchAll( regex ) ]
409+
410+
if ( matches.length ) {
411+
return matches.map( match => [ match[ 1 ], match[ 2 ] || 'px' ] )
412+
}
413+
414+
// If the input is purely numeric (e.g., "10"), assume "px"
415+
if ( /^-?\d*\.?\d+$/.test( value ) ) {
416+
return [ [ value, 'px' ] ]
417+
}
418+
return [ [ '0', 'px' ] ]
419+
}

0 commit comments

Comments
 (0)