PluginProbe ʕ •ᴥ•ʔ
GenerateBlocks / 1.0
GenerateBlocks v1.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 / dimensions / index.js
generateblocks / src / components / dimensions Last commit date
editor.scss 6 years ago index.js 6 years ago
index.js
432 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' ) } key={ 'px-unit' }>
293 <Button
294 key={ 'px-unit' }
295 isSmall
296 isPrimary={ true }
297 /* translators: %s: values associated with CSS syntax, 'Pixel', 'Em', 'Percentage' */
298 aria-label={ __( 'Pixel Units' ) }
299 >
300 { displayUnit }
301 </Button>
302 </Tooltip>
303 </div>
304 }
305 </div>
306
307 <div className="components-gblocks-dimensions-control__inputs">
308 <input
309 className="components-gblocks-dimensions-control__number"
310 placeholder={ topPlaceholder }
311 type="number"
312 onChange={ onChangeTopValue }
313 onBlur={ () => {
314 if ( '' === attributes[ attrTop ] && '' !== defaults[ attrTop ] ) {
315 // If we have no value and a default exists, set to 0 to prevent default from coming back.
316 if ( this.props.attributes[ this.props.attrSyncUnits ] ) {
317 this.onChangeAll( '0' );
318 } else {
319 this.onChangeTop( '0' );
320 }
321 }
322 } }
323 onClick={ ( e ) => {
324 // Make sure onBlur fires in Firefox.
325 e.currentTarget.focus();
326 } }
327 aria-label={ sprintf( __( '%s Top', 'generateblocks' ), label ) }
328 value={ attributes[ attrTop ] ? attributes[ attrTop ] : '' }
329 min={ type === 'padding' ? 0 : undefined }
330 data-attribute={ type }
331 />
332 <input
333 className="components-gblocks-dimensions-control__number"
334 placeholder={ rightPlaceholder }
335 type="number"
336 onChange={ onChangeRightValue }
337 onBlur={ () => {
338 if ( '' === attributes[ attrRight ] && '' !== defaults[ attrRight ] ) {
339 // If we have no value and a default exists, set to 0 to prevent default from coming back.
340 if ( this.props.attributes[ this.props.attrSyncUnits ] ) {
341 this.onChangeAll( '0' );
342 } else {
343 this.onChangeRight( '0' );
344 }
345 }
346 } }
347 onClick={ ( e ) => {
348 // Make sure onBlur fires in Firefox.
349 e.currentTarget.focus();
350 } }
351 aria-label={ sprintf( __( '%s Right', 'generateblocks' ), label ) }
352 value={ attributes[ attrRight ] ? attributes[ attrRight ] : '' }
353 min={ type === 'padding' ? 0 : undefined }
354 data-attribute={ type }
355 />
356 <input
357 className="components-gblocks-dimensions-control__number"
358 placeholder={ bottomPlaceholder }
359 type="number"
360 onChange={ onChangeBottomValue }
361 onBlur={ () => {
362 if ( '' === attributes[ attrBottom ] && '' !== defaults[ attrBottom ] ) {
363 // If we have no value and a default exists, set to 0 to prevent default from coming back.
364 if ( this.props.attributes[ this.props.attrSyncUnits ] ) {
365 this.onChangeAll( '0' );
366 } else {
367 this.onChangeBottom( '0' );
368 }
369 }
370 } }
371 onClick={ ( e ) => {
372 // Make sure onBlur fires in Firefox.
373 e.currentTarget.focus();
374 } }
375 aria-label={ sprintf( __( '%s Bottom', 'generateblocks' ), label ) }
376 value={ attributes[ attrBottom ] ? attributes[ attrBottom ] : '' }
377 min={ type === 'padding' ? 0 : undefined }
378 data-attribute={ type }
379 />
380 <input
381 className="components-gblocks-dimensions-control__number"
382 placeholder={ leftPlaceholder }
383 type="number"
384 onChange={ onChangeLeftValue }
385 onBlur={ () => {
386 if ( '' === attributes[ attrLeft ] && '' !== defaults[ attrLeft ] ) {
387 // If we have no value and a default exists, set to 0 to prevent default from coming back.
388 if ( this.props.attributes[ this.props.attrSyncUnits ] ) {
389 this.onChangeAll( '0' );
390 } else {
391 this.onChangeLeft( '0' );
392 }
393 }
394 } }
395 onClick={ ( e ) => {
396 // Make sure onBlur fires in Firefox.
397 e.currentTarget.focus();
398 } }
399 aria-label={ sprintf( __( '%s Left', 'generateblocks' ), label ) }
400 value={ attributes[ attrLeft ] ? attributes[ attrLeft ] : '' }
401 min={ type === 'padding' ? 0 : undefined }
402 data-attribute={ type }
403 />
404 <Tooltip text={ !! attributes[ attrSyncUnits ] ? __( 'Unsync', 'generateblocks' ) : __( 'Sync', 'generateblocks' ) } >
405 <Button
406 className="components-gblocks-dimensions-control_sync"
407 aria-label={ __( 'Sync Units', 'generateblocks' ) }
408 isPrimary={ attributes[ attrSyncUnits ] ? attributes[ attrSyncUnits ] : false }
409 aria-pressed={ attributes[ attrSyncUnits ] ? attributes[ attrSyncUnits ] : false }
410 onClick={ ( value ) => this.syncUnits( value, '' ) }
411 isSmall
412 >
413 { !! attributes[ attrSyncUnits ] ? getIcon( 'sync' ) : getIcon( 'sync' ) }
414 </Button>
415 </Tooltip>
416 </div>
417
418 <div className="components-gblocks-dimensions-control__input-labels">
419 <span className="components-gblocks-dimensions-control__number-label">{ labelTop }</span>
420 <span className="components-gblocks-dimensions-control__number-label">{ labelRight }</span>
421 <span className="components-gblocks-dimensions-control__number-label">{ labelBottom }</span>
422 <span className="components-gblocks-dimensions-control__number-label">{ labelLeft }</span>
423 <span className="components-gblocks-dimensions-control__number-label"></span>
424 </div>
425 </div>
426 </Fragment>
427 );
428 }
429 }
430
431 export default DimensionsControl;
432