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 / typography / index.js
generateblocks / src / components / typography Last commit date
editor.scss 6 years ago google-fonts.js 6 years ago index.js 6 years ago
index.js
522 lines
1 /**
2 * Internal dependencies
3 */
4 import './editor.scss';
5 import googleFonts from './google-fonts';
6
7 /**
8 * WordPress dependencies
9 */
10 const {
11 __,
12 _x,
13 sprintf,
14 } = wp.i18n;
15 const { Component, Fragment } = wp.element;
16
17 const {
18 BaseControl,
19 SelectControl,
20 ToggleControl,
21 TextControl,
22 ButtonGroup,
23 Tooltip,
24 Button,
25 } = wp.components;
26
27 /**
28 * Typography Component
29 */
30 class TypographyControls extends Component {
31 render() {
32 const {
33 setAttributes,
34 attributes,
35 device = '',
36 showFontSize = false,
37 showFontFamily = false,
38 showFontWeight = false,
39 showTextTransform = false,
40 showLineHeight = false,
41 showLetterSpacing = false,
42 disableAdvancedToggle = false,
43 fontSizePlaceholder = '17',
44 } = this.props;
45
46 const fonts = [
47 { value: '', label: __( 'Select font...', 'generateblocks' ) },
48 { value: 'Arial', label: 'Arial' },
49 { value: 'Helvetica', label: 'Helvetica' },
50 { value: 'Times New Roman', label: 'Times New Roman' },
51 { value: 'Georgia', label: 'Georgia' },
52 ];
53
54 Object.keys( googleFonts ).slice( 0, 20 ).map( ( k ) => {
55 fonts.push(
56 { value: k, label: k }
57 );
58 } );
59
60 fonts.push(
61 { value: 'other', label: __( 'Other', 'generateblocks' ) }
62 );
63
64 let weight = [
65 { value: '', label: __( 'Default', 'generateblocks' ) },
66 { value: 'normal', label: __( 'Normal', 'generateblocks' ) },
67 { value: 'bold', label: __( 'Bold', 'generateblocks' ) },
68 { value: '100', label: '100' },
69 { value: '200', label: '200' },
70 { value: '300', label: '300' },
71 { value: '400', label: '400' },
72 { value: '500', label: '500' },
73 { value: '600', label: '600' },
74 { value: '700', label: '700' },
75 { value: '800', label: '800' },
76 { value: '900', label: '900' },
77 ];
78
79 const transform = [
80 { value: '', label: __( 'Default', 'generateblocks' ) },
81 { value: 'uppercase', label: __( 'Uppercase', 'generateblocks' ) },
82 { value: 'lowercase', label: __( 'Lowercase', 'generateblocks' ) },
83 { value: 'capitalize', label: __( 'Capitalize', 'generateblocks' ) },
84 { value: 'initial', label: __( 'Normal', 'generateblocks' ) },
85 ];
86
87 if ( typeof googleFonts[ attributes.fontFamily ] !== 'undefined' && typeof googleFonts[ attributes.fontFamily ].weight !== 'undefined' ) {
88 weight = [
89 { value: '', label: __( 'Default', 'generateblocks' ) },
90 { value: 'normal', label: __( 'Normal', 'generateblocks' ) },
91 { value: 'bold', label: __( 'Bold', 'generateblocks' ) },
92 ];
93
94 googleFonts[ attributes.fontFamily ].weight.filter( function( k ) {
95 const hasLetters = k.match( /[a-z]/g );
96 const hasNumbers = k.match( /[0-9]/g );
97
98 if ( ( hasLetters && hasNumbers ) || 'italic' === k ) {
99 return false;
100 }
101
102 return true;
103 } ).map( ( k ) => {
104 weight.push(
105 { value: k, label: k }
106 );
107 } );
108 }
109
110 const onFontChange = ( value ) => {
111 if ( 'other' === value ) {
112 value = '';
113 }
114
115 let fontWeight = attributes.fontWeight; // eslint-disable-line no-unused-vars
116
117 setAttributes( { fontFamily: value } );
118
119 if ( attributes.fontWeight && Object.values( weight ).indexOf( attributes.fontWeight ) < 0 ) {
120 fontWeight = '';
121 }
122
123 if ( typeof googleFonts[ value ] !== 'undefined' ) {
124 setAttributes( {
125 'googleFont': true, // eslint-disable-line quote-props
126 'fontFamilyFallback': googleFonts[ value ].fallback, // eslint-disable-line quote-props
127 'googleFontVariants': googleFonts[ value ].weight.join( ', ' ), // eslint-disable-line quote-props
128 } );
129 } else {
130 setAttributes( {
131 'googleFont': false, // eslint-disable-line quote-props
132 'fontFamilyFallback': '', // eslint-disable-line quote-props
133 'googleFontVariants': '', // eslint-disable-line quote-props
134 } );
135 }
136 };
137
138 const onFontShortcut = ( event ) => {
139 setAttributes( { 'fontFamily': event.target.value } ); // eslint-disable-line quote-props
140 onFontChange( event.target.value );
141 };
142
143 const unitSizes = [
144 {
145 name: _x( 'Pixel', 'A size unit for CSS markup', 'generateblocks' ),
146 unitValue: 'px',
147 },
148 {
149 name: _x( 'Em', 'A size unit for CSS markup', 'generateblocks' ),
150 unitValue: 'em',
151 },
152 {
153 name: _x( 'Percentage', 'A size unit for CSS markup', 'generateblocks' ),
154 unitValue: '%',
155 },
156 ];
157
158 const getValue = ( value, setDevice ) => {
159 const valueName = value + setDevice;
160
161 return attributes[ valueName ];
162 };
163
164 const getAttributeName = ( name, setDevice ) => {
165 const attributeName = name + setDevice;
166
167 return attributeName;
168 };
169
170 let showAdvancedToggle = attributes.showAdvancedTypography;
171
172 if ( disableAdvancedToggle ) {
173 showAdvancedToggle = true;
174 }
175
176 let responsiveFontSizePlaceholder = fontSizePlaceholder;
177
178 if ( 'Tablet' === device && attributes.fontSize ) {
179 responsiveFontSizePlaceholder = attributes.fontSize;
180 }
181
182 if ( 'Mobile' === device ) {
183 if ( attributes.fontSizeTablet ) {
184 responsiveFontSizePlaceholder = attributes.fontSizeTablet;
185 } else if ( attributes.fontSize ) {
186 responsiveFontSizePlaceholder = attributes.fontSize;
187 }
188 }
189
190 return (
191 <Fragment>
192 <div className={ 'components-gblocks-typography-weight-transform' }>
193 { showFontWeight &&
194 <SelectControl
195 label={ __( 'Weight', 'generateblocks' ) }
196 value={ attributes.fontWeight }
197 options={ weight }
198 onChange={ ( value ) => {
199 setAttributes( {
200 'fontWeight': value, // eslint-disable-line quote-props
201 } );
202 } }
203 className="components-base-control"
204 />
205 }
206
207 { showTextTransform &&
208 <SelectControl
209 label={ __( 'Transform', 'generateblocks' ) }
210 value={ attributes.textTransform }
211 options={ transform }
212 onChange={ ( value ) => {
213 setAttributes( {
214 'textTransform': value, // eslint-disable-line quote-props
215 } );
216 } }
217 className="components-base-control"
218 />
219 }
220 </div>
221
222 { ! disableAdvancedToggle &&
223 <ToggleControl
224 label={ __( 'Show Advanced Typography', 'generateblocks' ) }
225 checked={ !! attributes.showAdvancedTypography }
226 onChange={ ( value ) => {
227 setAttributes( {
228 'showAdvancedTypography': value, // eslint-disable-line quote-props
229 } );
230 } }
231 />
232 }
233
234 { showFontFamily && showAdvancedToggle &&
235 <BaseControl className={ 'gblocks-font-family-shortcuts' } label={ __( 'Font Family', 'generateblocks' ) }>
236 <select
237 className="components-select-control__input components-select-control__input--gblocks-fontfamily"
238 onChange={ onFontShortcut }
239 onBlur={ onFontShortcut }
240 >
241 { fonts.map( ( option, index ) =>
242 <option
243 key={ `${ option.label }-${ option.value }-${ index }` }
244 value={ option.value }
245 >
246 { option.label }
247 </option>
248 ) }
249 </select>
250 </BaseControl>
251 }
252
253 { showFontFamily && showAdvancedToggle &&
254 <TextControl
255 value={ attributes.fontFamily }
256 placeholder={ __( 'Enter font name...', 'generateblocks' ) }
257 onChange={ ( nextFontFamily ) => onFontChange( nextFontFamily ) }
258 />
259 }
260
261 { showFontFamily && '' !== attributes.fontFamily && showAdvancedToggle &&
262 <Fragment>
263 <ToggleControl
264 label={ __( 'Google Font', 'generateblocks' ) }
265 checked={ !! attributes.googleFont }
266 onChange={ ( value ) => {
267 setAttributes( {
268 'googleFont': value, // eslint-disable-line quote-props
269 } );
270
271 if ( value ) {
272 if ( typeof googleFonts[ attributes.fontFamily ] !== 'undefined' ) {
273 setAttributes( {
274 'fontFamilyFallback': googleFonts[ attributes.fontFamily ].fallback, // eslint-disable-line quote-props
275 'googleFontVariants': googleFonts[ attributes.fontFamily ].weight.join( ', ' ), // eslint-disable-line quote-props
276 } );
277 }
278 }
279 } }
280 />
281
282 { !! attributes.googleFont &&
283 <TextControl
284 label={ __( 'Variants', 'generateblocks' ) }
285 value={ attributes.googleFontVariants }
286 placeholder={ __( '300, 400, 400i', 'generateblocks' ) }
287 onChange={ ( value ) => {
288 setAttributes( {
289 'googleFontVariants': value, // eslint-disable-line quote-props
290 } );
291 } }
292 />
293 }
294 </Fragment>
295 }
296
297 { showFontFamily && showAdvancedToggle &&
298 <TextControl
299 label={ __( 'Font Family Fallback', 'generateblocks' ) }
300 value={ attributes.fontFamilyFallback }
301 placeholder={ __( 'sans-serif', 'generateblocks' ) }
302 onChange={ ( value ) => {
303 setAttributes( {
304 'fontFamilyFallback': value, // eslint-disable-line quote-props
305 } );
306 } }
307 />
308 }
309
310 { showFontSize && showAdvancedToggle &&
311 <Fragment>
312 <div className="components-gblocks-typography-control__header">
313 <div className="components-gblocks-typography-control__label components-base-control__label">
314 { __( 'Font Size', 'generateblocks' ) }
315 </div>
316
317 <div className="components-gblocks-control__units">
318 <ButtonGroup className="components-gblocks-typography-control__units" aria-label={ __( 'Select Units', 'generateblocks' ) }>
319 { unitSizes.map( ( unit ) =>
320 /* translators: %s: values associated with CSS syntax, 'Pixel', 'Em', 'Percentage' */
321 <Tooltip text={ sprintf( __( '%s Units', 'generateblocks' ), unit.name ) } key={ unit.unitValue }>
322 <Button
323 key={ unit.unitValue }
324 className={ 'components-gblocks-typography-control__units--' + unit.name }
325 isSmall
326 isPrimary={ attributes.fontSizeUnit === unit.unitValue }
327 aria-pressed={ attributes.fontSizeUnit === unit.unitValue }
328 /* translators: %s: values associated with CSS syntax, 'Pixel', 'Em', 'Percentage' */
329 aria-label={ sprintf( __( '%s Units', 'generateblocks' ), unit.name ) }
330 onClick={ () => setAttributes( { fontSizeUnit: unit.unitValue } ) }
331 >
332 { unit.unitValue }
333 </Button>
334 </Tooltip>
335 ) }
336 </ButtonGroup>
337 </div>
338 </div>
339
340 <div className="components-gblocks-typography-control__inputs">
341 <TextControl
342 type={ 'number' }
343 value={ getValue( 'fontSize', device ) || '' }
344 placeholder={ responsiveFontSizePlaceholder }
345 onChange={ ( value ) => {
346 const name = getAttributeName( 'fontSize', device );
347
348 setAttributes( {
349 [ name ]: parseFloat( value ),
350 } );
351 } }
352 min={ 1 }
353 autoComplete="off"
354 />
355
356 <Button
357 isSmall
358 isSecondary
359 className="components-gblocks-default-number"
360 onClick={ () => {
361 const name = getAttributeName( 'fontSize', device );
362
363 setAttributes( {
364 [ name ]: this.props.defaultFontSize,
365 } );
366 } }
367 >
368 { __( 'Reset', 'generateblocks' ) }
369 </Button>
370 </div>
371 </Fragment>
372 }
373
374 { showLineHeight && showAdvancedToggle &&
375 <Fragment>
376 <div className="components-gblocks-typography-control__header">
377 <div className="components-gblocks-typography-control__label components-base-control__label">
378 { __( 'Line Height', 'generateblocks' ) }
379 </div>
380
381 <div className="components-gblocks-control__units">
382 <ButtonGroup className="components-gblocks-typography-control__units" aria-label={ __( 'Select Units', 'generateblocks' ) }>
383 { unitSizes.map( ( unit ) =>
384 /* translators: %s: values associated with CSS syntax, 'Pixel', 'Em', 'Percentage' */
385 <Tooltip text={ sprintf( __( '%s Units', 'generateblocks' ), unit.name ) } key={ unit.unitValue }>
386 <Button
387 key={ unit.unitValue }
388 className={ 'components-gblocks-typography-control__units--' + unit.name }
389 isSmall
390 isPrimary={ attributes.lineHeightUnit === unit.unitValue }
391 aria-pressed={ attributes.lineHeightUnit === unit.unitValue }
392 /* translators: %s: values associated with CSS syntax, 'Pixel', 'Em', 'Percentage' */
393 aria-label={ sprintf( __( '%s Units', 'generateblocks' ), unit.name ) }
394 onClick={ () => setAttributes( { lineHeightUnit: unit.unitValue } ) }
395 >
396 { unit.unitValue }
397 </Button>
398 </Tooltip>
399 ) }
400 </ButtonGroup>
401 </div>
402 </div>
403
404 <div className="components-gblocks-typography-control__inputs">
405 <TextControl
406 type={ 'number' }
407 value={ getValue( 'lineHeight', device ) || 0 === getValue( 'lineHeight', device ) ? getValue( 'lineHeight', device ) : '' }
408 placeholder="1.5"
409 onChange={ ( value ) => {
410 const name = getAttributeName( 'lineHeight', device );
411
412 setAttributes( {
413 [ name ]: value,
414 } );
415 } }
416 onBlur={ () => {
417 const name = getAttributeName( 'lineHeight', device );
418
419 setAttributes( {
420 [ name ]: parseFloat( getValue( 'lineHeight', device ) ),
421 } );
422 } }
423 onClick={ ( e ) => {
424 // Make sure onBlur fires in Firefox.
425 e.currentTarget.focus();
426 } }
427 min={ 0 }
428 step={ .1 }
429 autoComplete="off"
430 />
431
432 <Button
433 isSmall
434 isSecondary
435 className="components-gblocks-default-number"
436 onClick={ () => {
437 const name = getAttributeName( 'lineHeight', device );
438
439 setAttributes( {
440 [ name ]: this.props.defaultLineHeight,
441 } );
442 } }
443 >
444 { __( 'Reset', 'generateblocks' ) }
445 </Button>
446 </div>
447 </Fragment>
448 }
449
450 { showLetterSpacing && showAdvancedToggle &&
451 <Fragment>
452 <div className="components-gblocks-typography-control__header">
453 <div className="components-gblocks-control__label">
454 { __( 'Letter Spacing', 'generateblocks' ) }
455 </div>
456
457 <div className="components-gblocks-control__units">
458 <Tooltip text={ __( 'Em Units', 'generateblocks' ) } key={ 'letter-spacing-unit' }>
459 <Button
460 key={ 'letter-spacing-unit' }
461 isSmall
462 isPrimary={ true }
463 aria-label={ __( 'Em Units', 'generateblocks' ) }
464 >
465 em
466 </Button>
467 </Tooltip>
468 </div>
469 </div>
470
471 <div className="components-gblocks-typography-control__inputs">
472 <TextControl
473 type={ 'number' }
474 value={ getValue( 'letterSpacing', device ) || '' }
475 placeholder="0.01"
476 onChange={ ( value ) => {
477 const name = getAttributeName( 'letterSpacing', device );
478
479 setAttributes( {
480 [ name ]: value,
481 } );
482 } }
483 onBlur={ () => {
484 const name = getAttributeName( 'letterSpacing', device );
485
486 setAttributes( {
487 [ name ]: parseFloat( getValue( 'letterSpacing', device ) ),
488 } );
489 } }
490 onClick={ ( e ) => {
491 // Make sure onBlur fires in Firefox.
492 e.currentTarget.focus();
493 } }
494 min={ -1 }
495 step={ .01 }
496 autoComplete="off"
497 />
498
499 <Button
500 isSmall
501 isSecondary
502 className="components-gblocks-default-number"
503 onClick={ () => {
504 const name = getAttributeName( 'letterSpacing', device );
505
506 setAttributes( {
507 [ name ]: this.props.defaultLetterSpacing,
508 } );
509 } }
510 >
511 { __( 'Reset', 'generateblocks' ) }
512 </Button>
513 </div>
514 </Fragment>
515 }
516 </Fragment>
517 );
518 }
519 }
520
521 export default TypographyControls;
522