PluginProbe ʕ •ᴥ•ʔ
GenerateBlocks / 1.8.0
GenerateBlocks v1.8.0
trunk 1.0 1.0.1 1.0.2 1.1.0 1.1.1 1.1.2 1.2.0 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.6.0 1.7.0 1.7.1 1.7.2 1.7.3 1.8.0 1.8.1 1.8.2 1.8.3 1.9.0 1.9.1 2.0.0 2.0.1 2.0.2 2.1.0 2.1.1 2.1.2 2.2.0 2.2.1 2.3.0
generateblocks / src / components / unit-control / index.js
generateblocks / src / components / unit-control Last commit date
editor.scss 2 years ago index.js 2 years ago unit-dropdown.js 2 years ago unit-list.js 2 years ago
index.js
173 lines
1 /**
2 * External dependencies
3 */
4 import { useEffect, useState, useRef } from '@wordpress/element';
5 import { TextControl, BaseControl } from '@wordpress/components';
6 import classnames from 'classnames';
7
8 /**
9 * Internal dependencies
10 */
11
12 import './editor.scss';
13 import UnitDropdown from './unit-dropdown';
14 import unitList from './unit-list';
15
16 export default function UnitControl( props ) {
17 const {
18 label,
19 units = [],
20 defaultUnit = '',
21 unitCount = 7,
22 min = 0,
23 max,
24 step,
25 id,
26 disabled = false,
27 overrideValue = null,
28 overrideAction = () => null,
29 onChange,
30 value,
31 placeholder,
32 help = '',
33 focusOnMount = false,
34 onFocus = () => null,
35 } = props;
36
37 const visibleUnits = units.concat( unitList ).slice( 0, unitCount );
38 const [ unitValue, setUnitValue ] = useState( '' );
39 const [ numericValue, setNumericValue ] = useState( '' );
40 const [ placeholderValue, setPlaceholderValue ] = useState( '' );
41 const isMounted = useRef( false );
42 const wrapperRef = useRef( false );
43 const inputRef = useRef( false );
44
45 const splitValues = ( values ) => {
46 const unitRegex = unitList.join( '|' );
47 const splitRegex = new RegExp( `(${ unitRegex })` );
48
49 return values
50 ? values.toString().toLowerCase().split( splitRegex ).filter( ( singleValue ) => '' !== singleValue )
51 : [];
52 };
53
54 const getNumericValue = ( values ) => values.length > 0 ? values[ 0 ].trim() : '';
55 const defaultUnitValue = defaultUnit ? defaultUnit : visibleUnits[ 0 ];
56 const getUnitValue = ( values ) => values.length > 1 ? values[ 1 ] : defaultUnitValue;
57
58 // Test if the value starts with a number, decimal or a single dash.
59 const startsWithNumber = ( number ) => /^([-]?\d|[-]?\.)/.test( number );
60
61 const setPlaceholders = () => {
62 if ( ! value ) {
63 const placeholderValues = overrideValue
64 ? splitValues( overrideValue )
65 : splitValues( placeholder );
66
67 setPlaceholderValue( getNumericValue( placeholderValues ) );
68 setUnitValue( getUnitValue( placeholderValues ) );
69 }
70 };
71
72 // Split the number and unit into two values.
73 useEffect( () => {
74 const newValue = overrideValue && disabled ? overrideValue : value;
75
76 // Split our values if we're starting with a number.
77 if ( startsWithNumber( newValue ) ) {
78 const values = splitValues( newValue );
79
80 setNumericValue( getNumericValue( values ) );
81 setUnitValue( getUnitValue( values ) );
82 } else {
83 setNumericValue( newValue );
84 setUnitValue( '' );
85 }
86
87 setPlaceholders();
88 }, [ value, overrideValue ] );
89
90 useEffect( () => {
91 // Don't run this on first render.
92 if ( ! isMounted.current ) {
93 isMounted.current = true;
94 return;
95 }
96
97 const hasOverride = !! overrideValue && !! disabled;
98
99 const fullValue = startsWithNumber( numericValue )
100 ? numericValue + unitValue
101 : numericValue;
102
103 // Clear the placeholder if the units don't match.
104 if ( ! fullValue ) {
105 if ( unitValue !== getUnitValue( splitValues( placeholder ) ) ) {
106 setPlaceholderValue( '' );
107 } else {
108 setPlaceholders();
109 }
110 }
111
112 if ( ! hasOverride && fullValue !== value ) {
113 onChange( fullValue );
114 }
115 }, [ numericValue, unitValue ] );
116
117 useEffect( () => {
118 if ( focusOnMount && inputRef?.current ) {
119 inputRef.current.focus();
120 }
121 }, [ label ] );
122
123 return (
124 <BaseControl
125 label={ label }
126 help={ help }
127 id={ id }
128 className={ classnames( {
129 'gblocks-unit-control': true,
130 'gblocks-unit-control__disabled': !! disabled,
131 } ) }
132 >
133 <div className="gblocks-unit-control__input" ref={ wrapperRef }>
134 <TextControl
135 type="text"
136 value={ numericValue }
137 placeholder={ placeholderValue }
138 id={ id }
139 min={ min }
140 max={ max }
141 step={ step }
142 autoComplete="off"
143 disabled={ disabled }
144 onChange={ ( newValue ) => setNumericValue( newValue ) }
145 onFocus={ () => {
146 onFocus();
147 } }
148 ref={ inputRef }
149 />
150
151 <div className="gblocks-unit-control__input--action">
152 { !! overrideAction && <div className="gblocks-unit-control__override-action">{ overrideAction() } </div> }
153
154 { (
155 startsWithNumber( numericValue ) ||
156 (
157 ! numericValue &&
158 ( ! placeholderValue || startsWithNumber( placeholderValue ) )
159 )
160 ) &&
161 <UnitDropdown
162 value={ unitValue }
163 disabled={ disabled || 1 === visibleUnits.length }
164 units={ visibleUnits }
165 onChange={ ( newValue ) => setUnitValue( newValue ) }
166 />
167 }
168 </div>
169 </div>
170 </BaseControl>
171 );
172 }
173