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 / 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
523 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...' ) },
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' ) } key={ 'letter-spacing-unit' }>
459 <Button
460 key={ 'letter-spacing-unit' }
461 isSmall
462 isPrimary={ true }
463 /* translators: %s: values associated with CSS syntax, 'Pixel', 'Em', 'Percentage' */
464 aria-label={ __( 'Em Units' ) }
465 >
466 em
467 </Button>
468 </Tooltip>
469 </div>
470 </div>
471
472 <div className="components-gblocks-typography-control__inputs">
473 <TextControl
474 type={ 'number' }
475 value={ getValue( 'letterSpacing', device ) || '' }
476 placeholder="0.01"
477 onChange={ ( value ) => {
478 const name = getAttributeName( 'letterSpacing', device );
479
480 setAttributes( {
481 [ name ]: value,
482 } );
483 } }
484 onBlur={ () => {
485 const name = getAttributeName( 'letterSpacing', device );
486
487 setAttributes( {
488 [ name ]: parseFloat( getValue( 'letterSpacing', device ) ),
489 } );
490 } }
491 onClick={ ( e ) => {
492 // Make sure onBlur fires in Firefox.
493 e.currentTarget.focus();
494 } }
495 min={ -1 }
496 step={ .01 }
497 autoComplete="off"
498 />
499
500 <Button
501 isSmall
502 isSecondary
503 className="components-gblocks-default-number"
504 onClick={ () => {
505 const name = getAttributeName( 'letterSpacing', device );
506
507 setAttributes( {
508 [ name ]: this.props.defaultLetterSpacing,
509 } );
510 } }
511 >
512 { __( 'Reset', 'generateblocks' ) }
513 </Button>
514 </div>
515 </Fragment>
516 }
517 </Fragment>
518 );
519 }
520 }
521
522 export default TypographyControls;
523