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