PluginProbe ʕ •ᴥ•ʔ
GenerateBlocks / 1.6.0
GenerateBlocks v1.6.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 4 years ago index.js 4 years ago
index.js
160 lines
1 /**
2 * External dependencies
3 */
4 import { useEffect, useState, useRef } from '@wordpress/element';
5 import { TextControl, BaseControl } from '@wordpress/components';
6
7 /**
8 * Internal dependencies
9 */
10 import hasNumericValue from '../../utils/has-numeric-value';
11 import './editor.scss';
12
13 export default function UnitControl( props ) {
14 const {
15 label,
16 attributeName,
17 attributes,
18 setAttributes,
19 units = [ 'px', 'em', '%', 'rem' ],
20 device,
21 min = 0,
22 max,
23 step,
24 id = attributeName,
25 } = props;
26
27 const [ unitValue, setUnitValue ] = useState( '' );
28 const [ numericValue, setNumericValue ] = useState( '' );
29 const [ placeholderValue, setPlaceholderValue ] = useState( '' );
30 const isMounted = useRef( false );
31
32 const attribute = device && 'Desktop' !== device
33 ? attributeName + device
34 : attributeName;
35
36 const splitValues = ( value ) => {
37 return value
38 ? value.split( /(\d+)/ ).filter( ( singleValue ) => '' !== singleValue )
39 : [];
40 };
41
42 const getNumericValue = ( values ) => values.length > 0 ? values[ 0 ] : '';
43 const getUnitValue = ( values ) => values.length > 1 ? values[ 1 ] : 'px';
44 const desktopValues = splitValues( attributes[ attributeName ] );
45 const tabletValues = splitValues( attributes[ attributeName + 'Tablet' ] );
46
47 const setPlaceholders = () => {
48 if ( ! attributes[ attribute ] ) {
49 // Set desktop value as placeholder.
50 if ( ! attributes[ attributeName + 'Tablet' ] ) {
51 if (
52 'Tablet' === device ||
53 (
54 'Mobile' === device &&
55 attributes[ attributeName ]
56 )
57 ) {
58 setPlaceholderValue( getNumericValue( desktopValues ) );
59 setUnitValue( getUnitValue( desktopValues ) );
60 }
61 }
62
63 // Set tablet value as placeholder.
64 if (
65 'Mobile' === device &&
66 attributes[ attributeName + 'Tablet' ]
67 ) {
68 setPlaceholderValue( getNumericValue( tabletValues ) );
69 setUnitValue( getUnitValue( tabletValues ) );
70 }
71 }
72 };
73
74 // Split the number and unit into two values.
75 useEffect( () => {
76 const values = splitValues( attributes[ attribute ] );
77
78 setNumericValue( getNumericValue( values ) );
79 setUnitValue( getUnitValue( values ) );
80
81 // Set the device placeholders and switch the units to match
82 // their parent device value if no device-specific value exists.
83 setPlaceholders();
84 }, [ device, attributes[ attribute ] ] );
85
86 useEffect( () => {
87 // Don't run this on first render.
88 if ( ! isMounted.current ) {
89 isMounted.current = true;
90 return;
91 }
92
93 const fullValue = hasNumericValue( numericValue )
94 ? numericValue + unitValue
95 : '';
96
97 const deviceValues = {
98 Tablet: desktopValues,
99 Mobile: tabletValues,
100 };
101
102 // Clear the placeholder if the units don't match.
103 if ( ! fullValue ) {
104 if ( device in deviceValues ) {
105 if ( unitValue !== getUnitValue( deviceValues[ device ] ) ) {
106 setPlaceholderValue( '' );
107 } else {
108 setPlaceholders();
109 }
110 }
111 }
112
113 if ( fullValue !== attributes[ attribute ] ) {
114 setAttributes( {
115 [ attribute ]: fullValue,
116 } );
117 }
118 }, [ numericValue, unitValue ] );
119
120 return (
121 <BaseControl
122 label={ label }
123 id={ id }
124 className="gblocks-unit-control"
125 >
126 <div className="gblocks-unit-control__input">
127 <TextControl
128 type="number"
129 value={ numericValue }
130 placeholder={ placeholderValue }
131 id={ id }
132 min={ min }
133 max={ max }
134 step={ step }
135 autoComplete="off"
136 onChange={ ( value ) => {
137 if ( min >= 0 ) {
138 // No hyphens allowed here.
139 value = value.toString().replace( /-/g, '' );
140 }
141
142 setNumericValue( value );
143 } }
144 />
145
146 <span className="gblocks-unit-control__unit-select">
147 <select
148 value={ unitValue }
149 onChange={ ( e ) => {
150 setUnitValue( e.target.value );
151 } }
152 >
153 { units.map( ( unitOption ) => <option key={ unitOption } value={ unitOption }>{ unitOption }</option> ) }
154 </select>
155 </span>
156 </div>
157 </BaseControl>
158 );
159 }
160