PluginProbe ʕ •ᴥ•ʔ
GenerateBlocks / 1.3.2
GenerateBlocks v1.3.2
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 / dimensions / index.js
generateblocks / src / components / dimensions Last commit date
editor.scss 5 years ago index.js 5 years ago
index.js
399 lines
1 /**
2 * External dependencies
3 */
4 import classnames from 'classnames';
5 import './editor.scss';
6 import getIcon from '../../utils/get-icon';
7 import UnitPicker from '../unit-picker';
8
9 /**
10 * WordPress dependencies
11 */
12 import {
13 __,
14 sprintf,
15 } from '@wordpress/i18n';
16
17 import {
18 Component,
19 Fragment,
20 } from '@wordpress/element';
21
22 import {
23 Button,
24 Tooltip,
25 } from '@wordpress/components';
26
27 class DimensionsControl extends Component {
28 constructor() {
29 super( ...arguments );
30 this.onChangeTop = this.onChangeTop.bind( this );
31 this.onChangeRight = this.onChangeRight.bind( this );
32 this.onChangeBottom = this.onChangeBottom.bind( this );
33 this.onChangeLeft = this.onChangeLeft.bind( this );
34 this.onChangeAll = this.onChangeAll.bind( this );
35 this.syncUnits = this.syncUnits.bind( this );
36 this.onChangeUnits = this.onChangeUnits.bind( this );
37 }
38
39 onReset( type ) {
40 this.props.setAttributes( { [ this.props[ type ] ]: '' } );
41 }
42
43 onChangeTop( value ) {
44 this.props.setAttributes( { [ this.props[ 'attrTop' ] ]: value } ); // eslint-disable-line dot-notation
45 }
46
47 onChangeRight( value ) {
48 this.props.setAttributes( { [ this.props[ 'attrRight' ] ]: value } ); // eslint-disable-line dot-notation
49 }
50
51 onChangeBottom( value ) {
52 this.props.setAttributes( { [ this.props[ 'attrBottom' ] ]: value } ); // eslint-disable-line dot-notation
53 }
54
55 onChangeLeft( value ) {
56 this.props.setAttributes( { [ this.props[ 'attrLeft' ] ]: value } ); // eslint-disable-line dot-notation
57 }
58
59 onChangeAll( value ) {
60 this.props.setAttributes( { [ this.props[ 'attrTop' ] ]: value, [ this.props[ 'attrRight' ] ]: value, [ this.props[ 'attrBottom' ] ]: value, [ this.props[ 'attrLeft' ] ]: value } ); // eslint-disable-line dot-notation
61 }
62
63 syncUnits() {
64 const numbers = [ this.props.attributes[ this.props.attrTop ], this.props.attributes[ this.props.attrRight ], this.props.attributes[ this.props.attrBottom ], this.props.attributes[ this.props.attrLeft ] ];
65
66 const syncValue = Math.max.apply( null, numbers );
67
68 this.props.setAttributes( {
69 [ this.props[ 'attrSyncUnits' ] ]: ! this.props.attributes[ this.props.attrSyncUnits ], // eslint-disable-line dot-notation
70 [ this.props[ 'attrTop' ] ]: syncValue.toString(), [ this.props[ 'attrRight' ] ]: syncValue.toString(), [ this.props[ 'attrBottom' ] ]: syncValue.toString(), [ this.props[ 'attrLeft' ] ]: syncValue.toString(), // eslint-disable-line dot-notation
71 } );
72 }
73
74 onChangeUnits( value ) {
75 this.props.setAttributes( { [ this.props[ 'attrUnit' ] ]: value } ); // eslint-disable-line dot-notation
76 }
77
78 render() {
79 const {
80 attributes,
81 label = __( 'Margin', 'generateblocks' ),
82 type = 'margin',
83 attrTop,
84 attrRight,
85 attrBottom,
86 attrLeft,
87 attrSyncUnits,
88 attrUnit,
89 labelTop = __( 'Top', 'generateblocks' ),
90 labelRight = __( 'Right', 'generateblocks' ),
91 labelBottom = __( 'Bottom', 'generateblocks' ),
92 labelLeft = __( 'Left', 'generateblocks' ),
93 device,
94 block,
95 defaults,
96 units,
97 } = this.props;
98
99 const classes = classnames(
100 'components-base-control',
101 'components-gblocks-dimensions-control',
102 );
103
104 const onChangeTopValue = ( event ) => {
105 let newValue = event.target.value;
106
107 if ( 'padding' === type ) {
108 // No negative values allowed here.
109 newValue = newValue.toString().replace( /-/g, '' );
110 }
111
112 if ( '' === newValue ) {
113 this.onReset( 'attrTop' );
114 return;
115 }
116
117 if ( this.props.attributes[ this.props.attrSyncUnits ] ) {
118 this.onChangeAll( newValue );
119 } else {
120 this.onChangeTop( newValue );
121 }
122 };
123
124 const onChangeRightValue = ( event ) => {
125 let newValue = event.target.value;
126
127 if ( 'padding' === type ) {
128 // No negative values allowed here.
129 newValue = newValue.toString().replace( /-/g, '' );
130 }
131
132 if ( '' === newValue ) {
133 this.onReset( 'attrRight' );
134 return;
135 }
136
137 if ( this.props.attributes[ this.props.attrSyncUnits ] ) {
138 this.onChangeAll( newValue );
139 } else {
140 this.onChangeRight( newValue );
141 }
142 };
143
144 const onChangeBottomValue = ( event ) => {
145 let newValue = event.target.value;
146
147 if ( 'padding' === type ) {
148 // No negative values allowed here.
149 newValue = newValue.toString().replace( /-/g, '' );
150 }
151
152 if ( '' === newValue ) {
153 this.onReset( 'attrBottom' );
154 return;
155 }
156
157 if ( this.props.attributes[ this.props.attrSyncUnits ] ) {
158 this.onChangeAll( newValue );
159 } else {
160 this.onChangeBottom( newValue );
161 }
162 };
163
164 const onChangeLeftValue = ( event ) => {
165 let newValue = event.target.value;
166
167 if ( 'padding' === type ) {
168 // No negative values allowed here.
169 newValue = newValue.toString().replace( /-/g, '' );
170 }
171
172 if ( '' === newValue ) {
173 this.onReset( 'attrLeft' );
174 return;
175 }
176
177 if ( this.props.attributes[ this.props.attrSyncUnits ] ) {
178 this.onChangeAll( newValue );
179 } else {
180 this.onChangeLeft( newValue );
181 }
182 };
183
184 let topPlaceholder = '',
185 rightPlaceholder = '',
186 bottomPlaceholder = '',
187 leftPlaceholder = '';
188
189 if ( 'headline' === block && attrBottom.includes( 'marginBottom' ) ) {
190 if ( 'px' === this.props.attributes.marginUnit ) {
191 const headlineId = document.querySelector( '.gb-headline-' + this.props.attributes.uniqueId );
192
193 if ( headlineId ) {
194 bottomPlaceholder = parseFloat( window.getComputedStyle( headlineId ).marginBottom );
195 }
196 } else if ( 'em' === this.props.attributes.marginUnit && 'undefined' !== typeof generateBlocksStyling.headline ) {
197 if ( 'undefined' !== typeof generateBlocksStyling.headline[ attributes.element ] && 'undefined' !== typeof generateBlocksStyling.headline[ attributes.element ].marginBottom ) {
198 if ( generateBlocksStyling.headline[ attributes.element ].marginUnit === attributes.marginUnit ) {
199 bottomPlaceholder = generateBlocksStyling.headline[ attributes.element ].marginBottom;
200 }
201 }
202 }
203
204 if ( 'div' === this.props.attributes.element || 'span' === this.props.attributes.element ) {
205 bottomPlaceholder = '';
206 }
207 }
208
209 if ( 'Tablet' === device ) {
210 const topAttrName = attrTop.replace( 'Tablet', '' ),
211 rightAttrName = attrRight.replace( 'Tablet', '' ),
212 bottomAttrName = attrBottom.replace( 'Tablet', '' ),
213 leftAttrName = attrLeft.replace( 'Tablet', '' );
214
215 topPlaceholder = attributes[ topAttrName ] ? attributes[ topAttrName ] : topPlaceholder;
216 rightPlaceholder = attributes[ rightAttrName ] ? attributes[ rightAttrName ] : rightPlaceholder;
217 bottomPlaceholder = attributes[ bottomAttrName ] ? attributes[ bottomAttrName ] : bottomPlaceholder;
218 leftPlaceholder = attributes[ leftAttrName ] ? attributes[ leftAttrName ] : leftPlaceholder;
219 }
220
221 if ( 'Mobile' === device ) {
222 const topAttrName = attrTop.replace( 'Mobile', '' ),
223 rightAttrName = attrRight.replace( 'Mobile', '' ),
224 bottomAttrName = attrBottom.replace( 'Mobile', '' ),
225 leftAttrName = attrLeft.replace( 'Mobile', '' );
226
227 if ( attributes[ topAttrName + 'Tablet' ] ) {
228 topPlaceholder = attributes[ topAttrName + 'Tablet' ];
229 } else if ( attributes[ topAttrName ] ) {
230 topPlaceholder = attributes[ topAttrName ];
231 }
232
233 if ( attributes[ rightAttrName + 'Tablet' ] ) {
234 rightPlaceholder = attributes[ rightAttrName + 'Tablet' ];
235 } else if ( attributes[ rightAttrName ] ) {
236 rightPlaceholder = attributes[ rightAttrName ];
237 }
238
239 if ( attributes[ bottomAttrName + 'Tablet' ] ) {
240 bottomPlaceholder = attributes[ bottomAttrName + 'Tablet' ];
241 } else if ( attributes[ bottomAttrName ] ) {
242 bottomPlaceholder = attributes[ bottomAttrName ];
243 }
244
245 if ( attributes[ leftAttrName + 'Tablet' ] ) {
246 leftPlaceholder = attributes[ leftAttrName + 'Tablet' ];
247 } else if ( attributes[ leftAttrName ] ) {
248 leftPlaceholder = attributes[ leftAttrName ];
249 }
250 }
251
252 const usingGlobalStyle = 'undefined' !== typeof attributes.useGlobalStyle && attributes.useGlobalStyle;
253
254 return (
255 <Fragment>
256 <div className={ classes }>
257 <UnitPicker
258 label={ label }
259 value={ 'undefined' !== typeof attributes[ attrUnit ] ? attributes[ attrUnit ] : 'px' }
260 units={ units }
261 onClick={ ( value ) => {
262 if ( 'undefined' !== typeof attributes[ attrUnit ] ) {
263 this.onChangeUnits( value );
264 } else {
265 return false;
266 }
267 } }
268 />
269
270 <div className="components-gblocks-dimensions-control__inputs">
271 <input
272 className="components-gblocks-dimensions-control__number"
273 placeholder={ topPlaceholder }
274 type="number"
275 onChange={ onChangeTopValue }
276 onBlur={ () => {
277 if ( ! usingGlobalStyle && '' === attributes[ attrTop ] && '' !== defaults[ attrTop ] ) {
278 // If we have no value and a default exists, set to 0 to prevent default from coming back.
279 if ( this.props.attributes[ this.props.attrSyncUnits ] ) {
280 this.onChangeAll( '0' );
281 } else {
282 this.onChangeTop( '0' );
283 }
284 }
285 } }
286 onClick={ ( e ) => {
287 // Make sure onBlur fires in Firefox.
288 e.currentTarget.focus();
289 } }
290 /* translators: Dimension label (padding, margin, border) */
291 aria-label={ sprintf( __( '%s Top', 'generateblocks' ), label ) }
292 value={ attributes[ attrTop ] ? attributes[ attrTop ] : '' }
293 min={ type === 'padding' ? 0 : undefined }
294 data-attribute={ type }
295 />
296 <input
297 className="components-gblocks-dimensions-control__number"
298 placeholder={ rightPlaceholder }
299 type="number"
300 onChange={ onChangeRightValue }
301 onBlur={ () => {
302 if ( ! usingGlobalStyle && '' === attributes[ attrRight ] && '' !== defaults[ attrRight ] ) {
303 // If we have no value and a default exists, set to 0 to prevent default from coming back.
304 if ( this.props.attributes[ this.props.attrSyncUnits ] ) {
305 this.onChangeAll( '0' );
306 } else {
307 this.onChangeRight( '0' );
308 }
309 }
310 } }
311 onClick={ ( e ) => {
312 // Make sure onBlur fires in Firefox.
313 e.currentTarget.focus();
314 } }
315 /* translators: Dimension label (padding, margin, border) */
316 aria-label={ sprintf( __( '%s Right', 'generateblocks' ), label ) }
317 value={ attributes[ attrRight ] ? attributes[ attrRight ] : '' }
318 min={ type === 'padding' ? 0 : undefined }
319 data-attribute={ type }
320 />
321 <input
322 className="components-gblocks-dimensions-control__number"
323 placeholder={ bottomPlaceholder }
324 type="number"
325 onChange={ onChangeBottomValue }
326 onBlur={ () => {
327 if ( ! usingGlobalStyle && '' === attributes[ attrBottom ] && '' !== defaults[ attrBottom ] ) {
328 // If we have no value and a default exists, set to 0 to prevent default from coming back.
329 if ( this.props.attributes[ this.props.attrSyncUnits ] ) {
330 this.onChangeAll( '0' );
331 } else {
332 this.onChangeBottom( '0' );
333 }
334 }
335 } }
336 onClick={ ( e ) => {
337 // Make sure onBlur fires in Firefox.
338 e.currentTarget.focus();
339 } }
340 /* translators: Dimension label (padding, margin, border) */
341 aria-label={ sprintf( __( '%s Bottom', 'generateblocks' ), label ) }
342 value={ attributes[ attrBottom ] ? attributes[ attrBottom ] : '' }
343 min={ type === 'padding' ? 0 : undefined }
344 data-attribute={ type }
345 />
346 <input
347 className="components-gblocks-dimensions-control__number"
348 placeholder={ leftPlaceholder }
349 type="number"
350 onChange={ onChangeLeftValue }
351 onBlur={ () => {
352 if ( ! usingGlobalStyle && '' === attributes[ attrLeft ] && '' !== defaults[ attrLeft ] ) {
353 // If we have no value and a default exists, set to 0 to prevent default from coming back.
354 if ( this.props.attributes[ this.props.attrSyncUnits ] ) {
355 this.onChangeAll( '0' );
356 } else {
357 this.onChangeLeft( '0' );
358 }
359 }
360 } }
361 onClick={ ( e ) => {
362 // Make sure onBlur fires in Firefox.
363 e.currentTarget.focus();
364 } }
365 /* translators: Dimension label (padding, margin, border) */
366 aria-label={ sprintf( __( '%s Left', 'generateblocks' ), label ) }
367 value={ attributes[ attrLeft ] ? attributes[ attrLeft ] : '' }
368 min={ type === 'padding' ? 0 : undefined }
369 data-attribute={ type }
370 />
371 <Tooltip text={ !! attributes[ attrSyncUnits ] ? __( 'Unsync', 'generateblocks' ) : __( 'Sync', 'generateblocks' ) } >
372 <Button
373 className="components-gblocks-dimensions-control_sync"
374 aria-label={ __( 'Sync Units', 'generateblocks' ) }
375 isPrimary={ attributes[ attrSyncUnits ] ? attributes[ attrSyncUnits ] : false }
376 aria-pressed={ attributes[ attrSyncUnits ] ? attributes[ attrSyncUnits ] : false }
377 onClick={ ( value ) => this.syncUnits( value, '' ) }
378 isSmall
379 >
380 { !! attributes[ attrSyncUnits ] ? getIcon( 'sync' ) : getIcon( 'sync' ) }
381 </Button>
382 </Tooltip>
383 </div>
384
385 <div className="components-gblocks-dimensions-control__input-labels">
386 <span className="components-gblocks-dimensions-control__number-label">{ labelTop }</span>
387 <span className="components-gblocks-dimensions-control__number-label">{ labelRight }</span>
388 <span className="components-gblocks-dimensions-control__number-label">{ labelBottom }</span>
389 <span className="components-gblocks-dimensions-control__number-label">{ labelLeft }</span>
390 <span className="components-gblocks-dimensions-control__number-label"></span>
391 </div>
392 </div>
393 </Fragment>
394 );
395 }
396 }
397
398 export default DimensionsControl;
399