PluginProbe ʕ •ᴥ•ʔ
GenerateBlocks / 1.1.0
GenerateBlocks v1.1.0
2.4.1 2.4.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 / blocks / headline / edit.js
generateblocks / src / blocks / headline Last commit date
css 6 years ago attributes.js 6 years ago block.js 6 years ago deprecated.js 6 years ago edit.js 6 years ago editor.scss 6 years ago markformat.js 6 years ago save.js 6 years ago transforms.js 6 years ago
edit.js
1194 lines
1 /**
2 * Block: Headline
3 */
4
5 import classnames from 'classnames';
6 import ColorPicker from '../../components/color-picker';
7 import IconPicker from '../../components/icon-picker';
8 import TypographyControls from '../../components/typography';
9 import DimensionsControl from '../../components/dimensions/';
10 import ResponsiveTabs from '../../components/responsive-tabs';
11 import getIcon from '../../utils/get-icon';
12 import getSelectedDevice from '../../utils/get-selected-device';
13 import sanitizeSVG from '../../utils/sanitize-svg';
14 import DesktopCSS from './css/desktop.js';
15 import PanelArea from '../../components/panel-area/';
16 import './markformat';
17
18 const {
19 __,
20 _x,
21 sprintf,
22 } = wp.i18n; // Import __() from wp.i18n
23 const {
24 TextControl,
25 Toolbar,
26 SelectControl,
27 DropdownMenu,
28 ToggleControl,
29 Tooltip,
30 Button,
31 ButtonGroup,
32 } = wp.components;
33
34 const {
35 Fragment,
36 Component,
37 } = wp.element;
38
39 const {
40 InspectorControls,
41 RichText,
42 BlockControls,
43 AlignmentToolbar,
44 } = wp.blockEditor;
45
46 const {
47 applyFilters,
48 } = wp.hooks;
49
50 const ELEMENT_ID_REGEX = /[\s#]/g;
51 const gbHeadlineIds = [];
52
53 class GenerateBlockHeadline extends Component {
54 constructor() {
55 super( ...arguments );
56
57 this.getFontSizePlaceholder = this.getFontSizePlaceholder.bind( this );
58
59 this.state = {
60 selectedDevice: 'desktop',
61 fontSizePlaceholder: '17',
62 };
63 }
64
65 componentDidMount() {
66 const id = this.props.clientId.substr( 2, 9 ).replace( '-', '' );
67
68 if ( ! this.props.attributes.uniqueId ) {
69 this.props.setAttributes( {
70 uniqueId: id,
71 } );
72
73 gbHeadlineIds.push( id );
74 } else if ( gbHeadlineIds.includes( this.props.attributes.uniqueId ) ) {
75 this.props.setAttributes( {
76 uniqueId: id,
77 } );
78
79 gbHeadlineIds.push( id );
80 } else {
81 gbHeadlineIds.push( this.props.attributes.uniqueId );
82 }
83
84 const tempFontSizePlaceholder = this.getFontSizePlaceholder();
85
86 if ( tempFontSizePlaceholder !== this.state.fontSizePlaceholder ) {
87 this.setState( {
88 fontSizePlaceholder: tempFontSizePlaceholder,
89 } );
90 }
91
92 // hasIcon came late, so let's set it on mount if we have an icon.
93 if ( ! this.props.attributes.hasIcon && this.props.attributes.icon ) {
94 this.props.setAttributes( {
95 hasIcon: true,
96 } );
97 }
98 }
99
100 componentDidUpdate() {
101 const tempFontSizePlaceholder = this.getFontSizePlaceholder();
102
103 if ( tempFontSizePlaceholder !== this.state.fontSizePlaceholder ) {
104 this.setState( {
105 fontSizePlaceholder: tempFontSizePlaceholder,
106 } );
107 }
108 }
109
110 getFontSizePlaceholder() {
111 let placeholder = '25';
112
113 if ( 'em' === this.props.attributes.fontSizeUnit ) {
114 placeholder = '1';
115 } else if ( '%' === this.props.attributes.fontSizeUnit ) {
116 placeholder = '100';
117 } else {
118 const headlineId = document.querySelector( '.gb-headline-' + this.props.attributes.uniqueId );
119
120 if ( headlineId ) {
121 placeholder = parseFloat( window.getComputedStyle( headlineId ).fontSize );
122 }
123 }
124
125 return placeholder;
126 }
127
128 render() {
129 const {
130 attributes,
131 setAttributes,
132 } = this.props;
133
134 const {
135 selectedDevice,
136 fontSizePlaceholder,
137 } = this.state;
138
139 const {
140 uniqueId,
141 elementId,
142 cssClasses,
143 content,
144 element,
145 alignment,
146 alignmentTablet,
147 alignmentMobile,
148 backgroundColor,
149 backgroundColorOpacity,
150 textColor,
151 linkColor,
152 linkColorHover,
153 borderColor,
154 borderColorOpacity,
155 highlightTextColor,
156 fontFamily,
157 googleFont,
158 googleFontVariants,
159 marginTop,
160 marginRight,
161 marginBottom,
162 marginLeft,
163 icon,
164 iconColor,
165 iconColorOpacity,
166 iconLocation,
167 iconLocationTablet,
168 iconLocationMobile,
169 iconVerticalAlignment,
170 iconVerticalAlignmentTablet,
171 iconVerticalAlignmentMobile,
172 iconSize,
173 iconSizeTablet,
174 iconSizeMobile,
175 iconSizeUnit,
176 inlineWidth,
177 inlineWidthTablet,
178 inlineWidthMobile,
179 removeText,
180 ariaLabel,
181 } = attributes;
182
183 let googleFontsAttr = '';
184
185 if ( googleFontVariants ) {
186 googleFontsAttr = ':' + googleFontVariants;
187 }
188
189 const unitSizes = [
190 {
191 name: _x( 'Pixel', 'A size unit for CSS markup', 'generateblocks' ),
192 unitValue: 'px',
193 },
194 {
195 name: _x( 'Em', 'A size unit for CSS markup', 'generateblocks' ),
196 unitValue: 'em',
197 },
198 ];
199
200 let iconSizePlaceholderMobile = '';
201
202 if ( iconSizeTablet || 0 === iconSizeTablet ) {
203 iconSizePlaceholderMobile = iconSizeTablet;
204 } else if ( iconSize || 0 === iconSize ) {
205 iconSizePlaceholderMobile = iconSize;
206 } else {
207 iconSizePlaceholderMobile = '';
208 }
209
210 let htmlAttributes = {
211 id: !! elementId ? elementId : undefined,
212 className: classnames( {
213 'gb-headline': true,
214 [ `gb-headline-${ uniqueId }` ]: true,
215 [ `${ cssClasses }` ]: '' !== cssClasses,
216 } ),
217 };
218
219 htmlAttributes = applyFilters( 'generateblocks.frontend.htmlAttributes', htmlAttributes, 'generateblocks/headline', attributes );
220
221 return (
222 <Fragment>
223
224 <BlockControls>
225 <Toolbar>
226 <DropdownMenu
227 icon={ getIcon( 'paragraph' ) }
228 label={ __( 'Element', 'generateblocks' ) }
229 controls={ [
230 {
231 title: 'paragraph',
232 onClick: () => {
233 setAttributes( { element: 'p' } );
234
235 if ( ! marginTop && ! marginRight && ! marginBottom && ! marginLeft ) {
236 setAttributes( { marginUnit: 'em' } );
237 }
238 },
239 },
240 {
241 title: 'h1',
242 onClick: () => {
243 setAttributes( { element: 'h1' } );
244
245 if ( ! marginTop && ! marginRight && ! marginBottom && ! marginLeft ) {
246 setAttributes( { marginUnit: generateBlocksDefaults.headline.marginUnit } );
247 }
248 },
249 },
250 {
251 title: 'h2',
252 onClick: () => {
253 setAttributes( { element: 'h2' } );
254
255 if ( ! marginTop && ! marginRight && ! marginBottom && ! marginLeft ) {
256 setAttributes( { marginUnit: generateBlocksDefaults.headline.marginUnit } );
257 }
258 },
259 },
260 {
261 title: 'h3',
262 onClick: () => {
263 setAttributes( { element: 'h3' } );
264
265 if ( ! marginTop && ! marginRight && ! marginBottom && ! marginLeft ) {
266 setAttributes( { marginUnit: generateBlocksDefaults.headline.marginUnit } );
267 }
268 },
269 },
270 {
271 title: 'h4',
272 onClick: () => {
273 setAttributes( { element: 'h4' } );
274
275 if ( ! marginTop && ! marginRight && ! marginBottom && ! marginLeft ) {
276 setAttributes( { marginUnit: generateBlocksDefaults.headline.marginUnit } );
277 }
278 },
279 },
280 ] }
281 />
282 </Toolbar>
283
284 { ! inlineWidth &&
285 <AlignmentToolbar
286 isCollapsed={ false }
287 value={ alignment }
288 onChange={ ( nextAlign ) => {
289 setAttributes( { alignment: nextAlign } );
290 } }
291 />
292 }
293 </BlockControls>
294
295 <InspectorControls>
296 <ResponsiveTabs { ...this.props }
297 selectedDevice={ getSelectedDevice( selectedDevice ) }
298 onClick={ ( device ) => {
299 window.localStorage.setItem( 'generateblocksSelectedDevice', device );
300
301 this.setState( {
302 selectedDevice: device,
303 } );
304 } }
305 />
306
307 <PanelArea { ...this.props }
308 id={ 'headlineElement' }
309 state={ this.state }
310 showPanel={ 'desktop' === getSelectedDevice( selectedDevice ) && ! removeText ? true : false }
311 >
312 <SelectControl
313 label={ __( 'Element', 'generateblocks' ) }
314 value={ element }
315 options={ [
316 { label: 'paragraph', value: 'p' },
317 { label: 'h1', value: 'h1' },
318 { label: 'h2', value: 'h2' },
319 { label: 'h3', value: 'h3' },
320 { label: 'h4', value: 'h4' },
321 { label: 'h5', value: 'h5' },
322 { label: 'h6', value: 'h6' },
323 ] }
324 onChange={ ( value ) => {
325 setAttributes( {
326 element: value,
327 } );
328
329 if ( ! marginTop && ! marginRight && ! marginBottom && ! marginLeft ) {
330 if ( 'p' === element ) {
331 setAttributes( { marginUnit: 'em' } );
332 } else {
333 setAttributes( { marginUnit: generateBlocksDefaults.headline.marginUnit } );
334 }
335 }
336 } }
337 />
338
339 { applyFilters( 'generateblocks.editor.controls', '', 'headlineElement', this.props, this.state ) }
340 </PanelArea>
341
342 <PanelArea { ...this.props }
343 title={ __( 'Typography', 'generateblocks' ) }
344 initialOpen={ false }
345 icon={ getIcon( 'typography' ) }
346 className={ 'gblocks-panel-label' }
347 id={ 'headlineTypography' }
348 state={ this.state }
349 showPanel={ ! removeText || false }
350 >
351 { 'desktop' === getSelectedDevice( selectedDevice ) && (
352 <Fragment>
353 { ! inlineWidth &&
354 <AlignmentToolbar
355 isCollapsed={ false }
356 value={ alignment }
357 onChange={ ( value ) => {
358 setAttributes( { alignment: value } );
359 } }
360 />
361 }
362
363 <TypographyControls { ...this.props }
364 showFontFamily={ true }
365 showFontWeight={ true }
366 showTextTransform={ true }
367 showFontSize={ true }
368 showLineHeight={ true }
369 showLetterSpacing={ true }
370 fontSizePlaceholder={ fontSizePlaceholder }
371 defaultFontSize={ generateBlocksDefaults.headline.fontSize }
372 defaultFontSizeUnit={ generateBlocksDefaults.headline.fontSizeUnit }
373 defaultLineHeight={ generateBlocksDefaults.headline.lineHeight }
374 defaultLineHeightUnit={ generateBlocksDefaults.headline.lineHeightUnit }
375 defaultLetterSpacing={ generateBlocksDefaults.headline.letterSpacing }
376 />
377 </Fragment>
378 ) }
379
380 { 'tablet' === getSelectedDevice( selectedDevice ) && (
381 <Fragment>
382 { ! inlineWidthTablet &&
383 <AlignmentToolbar
384 isCollapsed={ false }
385 value={ alignmentTablet }
386 onChange={ ( value ) => {
387 setAttributes( { alignmentTablet: value } );
388 } }
389 />
390 }
391
392 <TypographyControls { ...this.props }
393 device={ 'Tablet' }
394 showFontSize={ true }
395 showLineHeight={ true }
396 showLetterSpacing={ true }
397 defaultFontSize={ generateBlocksDefaults.headline.fontSizeTablet }
398 defaultFontSizeUnit={ generateBlocksDefaults.headline.fontSizeUnit }
399 defaultLineHeight={ generateBlocksDefaults.headline.lineHeightTablet }
400 defaultLineHeightUnit={ generateBlocksDefaults.headline.lineHeightUnit }
401 defaultLetterSpacing={ generateBlocksDefaults.headline.letterSpacingTablet }
402 />
403 </Fragment>
404 ) }
405
406 { 'mobile' === getSelectedDevice( selectedDevice ) && (
407 <Fragment>
408 { ! inlineWidthMobile &&
409 <AlignmentToolbar
410 isCollapsed={ false }
411 value={ alignmentMobile }
412 onChange={ ( value ) => {
413 setAttributes( { alignmentMobile: value } );
414 } }
415 />
416 }
417
418 <TypographyControls { ...this.props }
419 device={ 'Mobile' }
420 showFontSize={ true }
421 showLineHeight={ true }
422 showLetterSpacing={ true }
423 defaultFontSize={ generateBlocksDefaults.headline.fontSizeMobile }
424 defaultFontSizeUnit={ generateBlocksDefaults.headline.fontSizeUnit }
425 defaultLineHeight={ generateBlocksDefaults.headline.lineHeightMobile }
426 defaultLineHeightUnit={ generateBlocksDefaults.headline.lineHeightUnit }
427 defaultLetterSpacing={ generateBlocksDefaults.headline.letterSpacingMobile }
428 />
429 </Fragment>
430 ) }
431
432 { applyFilters( 'generateblocks.editor.controls', '', 'headlineTypography', this.props, this.state ) }
433 </PanelArea>
434
435 <PanelArea { ...this.props }
436 title={ __( 'Spacing', 'generateblocks' ) }
437 initialOpen={ false }
438 icon={ getIcon( 'spacing' ) }
439 className={ 'gblocks-panel-label' }
440 id={ 'headlineSpacing' }
441 state={ this.state }
442 >
443 { 'desktop' === getSelectedDevice( selectedDevice ) && (
444 <Fragment>
445 <ToggleControl
446 label={ __( 'Inline Width', 'generateblocks' ) }
447 checked={ !! inlineWidth }
448 onChange={ ( value ) => {
449 setAttributes( {
450 inlineWidth: value,
451 } );
452 } }
453 />
454
455 <DimensionsControl { ...this.props }
456 device={ getSelectedDevice( selectedDevice ) }
457 type={ 'padding' }
458 label={ __( 'Padding', 'generateblocks' ) }
459 attrTop={ 'paddingTop' }
460 attrRight={ 'paddingRight' }
461 attrBottom={ 'paddingBottom' }
462 attrLeft={ 'paddingLeft' }
463 attrUnit={ 'paddingUnit' }
464 attrSyncUnits={ 'paddingSyncUnits' }
465 defaults={ generateBlocksDefaults.headline }
466 />
467
468 <DimensionsControl { ...this.props }
469 device={ getSelectedDevice( selectedDevice ) }
470 type={ 'margin' }
471 block={ 'headline' }
472 label={ __( 'Margin', 'generateblocks' ) }
473 attrTop={ 'marginTop' }
474 attrRight={ 'marginRight' }
475 attrBottom={ 'marginBottom' }
476 attrLeft={ 'marginLeft' }
477 attrUnit={ 'marginUnit' }
478 attrSyncUnits={ 'marginSyncUnits' }
479 defaults={ generateBlocksDefaults.headline }
480 />
481
482 <DimensionsControl { ...this.props }
483 device={ getSelectedDevice( selectedDevice ) }
484 type={ 'padding' }
485 label={ __( 'Border Size', 'generateblocks' ) }
486 attrTop={ 'borderSizeTop' }
487 attrRight={ 'borderSizeRight' }
488 attrBottom={ 'borderSizeBottom' }
489 attrLeft={ 'borderSizeLeft' }
490 attrSyncUnits={ 'borderSizeSyncUnits' }
491 displayUnit={ 'px' }
492 defaults={ generateBlocksDefaults.headline }
493 />
494 </Fragment>
495 ) }
496
497 { 'tablet' === getSelectedDevice( selectedDevice ) && (
498 <Fragment>
499 <ToggleControl
500 label={ __( 'Inline Width', 'generateblocks' ) }
501 checked={ !! inlineWidthTablet }
502 onChange={ ( value ) => {
503 setAttributes( {
504 inlineWidthTablet: value,
505 } );
506 } }
507 />
508
509 <DimensionsControl { ...this.props }
510 device={ getSelectedDevice( selectedDevice ) }
511 type={ 'padding' }
512 label={ __( 'Padding', 'generateblocks' ) }
513 attrTop={ 'paddingTopTablet' }
514 attrRight={ 'paddingRightTablet' }
515 attrBottom={ 'paddingBottomTablet' }
516 attrLeft={ 'paddingLeftTablet' }
517 attrUnit={ 'paddingUnit' }
518 attrSyncUnits={ 'paddingSyncUnits' }
519 defaults={ generateBlocksDefaults.headline }
520 />
521
522 <DimensionsControl { ...this.props }
523 device={ getSelectedDevice( selectedDevice ) }
524 type={ 'margin' }
525 block={ 'headline' }
526 label={ __( 'Margin', 'generateblocks' ) }
527 attrTop={ 'marginTopTablet' }
528 attrRight={ 'marginRightTablet' }
529 attrBottom={ 'marginBottomTablet' }
530 attrLeft={ 'marginLeftTablet' }
531 attrUnit={ 'marginUnit' }
532 attrSyncUnits={ 'marginSyncUnits' }
533 defaults={ generateBlocksDefaults.headline }
534 />
535
536 <DimensionsControl { ...this.props }
537 device={ getSelectedDevice( selectedDevice ) }
538 type={ 'padding' }
539 label={ __( 'Border Size', 'generateblocks' ) }
540 attrTop={ 'borderSizeTopTablet' }
541 attrRight={ 'borderSizeRightTablet' }
542 attrBottom={ 'borderSizeBottomTablet' }
543 attrLeft={ 'borderSizeLeftTablet' }
544 attrSyncUnits={ 'borderSizeSyncUnits' }
545 displayUnit={ 'px' }
546 defaults={ generateBlocksDefaults.headline }
547 />
548 </Fragment>
549 ) }
550
551 { 'mobile' === getSelectedDevice( selectedDevice ) && (
552 <Fragment>
553 <ToggleControl
554 label={ __( 'Inline Width', 'generateblocks' ) }
555 checked={ !! inlineWidthMobile }
556 onChange={ ( value ) => {
557 setAttributes( {
558 inlineWidthMobile: value,
559 } );
560 } }
561 />
562
563 <DimensionsControl { ...this.props }
564 device={ getSelectedDevice( selectedDevice ) }
565 type={ 'padding' }
566 label={ __( 'Padding', 'generateblocks' ) }
567 attrTop={ 'paddingTopMobile' }
568 attrRight={ 'paddingRightMobile' }
569 attrBottom={ 'paddingBottomMobile' }
570 attrLeft={ 'paddingLeftMobile' }
571 attrUnit={ 'paddingUnit' }
572 attrSyncUnits={ 'paddingSyncUnits' }
573 defaults={ generateBlocksDefaults.headline }
574 />
575
576 <DimensionsControl { ...this.props }
577 device={ getSelectedDevice( selectedDevice ) }
578 type={ 'margin' }
579 block={ 'headline' }
580 label={ __( 'Margin', 'generateblocks' ) }
581 attrTop={ 'marginTopMobile' }
582 attrRight={ 'marginRightMobile' }
583 attrBottom={ 'marginBottomMobile' }
584 attrLeft={ 'marginLeftMobile' }
585 attrUnit={ 'marginUnit' }
586 attrSyncUnits={ 'marginSyncUnits' }
587 defaults={ generateBlocksDefaults.headline }
588 />
589
590 <DimensionsControl { ...this.props }
591 device={ getSelectedDevice( selectedDevice ) }
592 type={ 'padding' }
593 label={ __( 'Border Size', 'generateblocks' ) }
594 attrTop={ 'borderSizeTopMobile' }
595 attrRight={ 'borderSizeRightMobile' }
596 attrBottom={ 'borderSizeBottomMobile' }
597 attrLeft={ 'borderSizeLeftMobile' }
598 attrSyncUnits={ 'borderSizeSyncUnits' }
599 displayUnit={ 'px' }
600 defaults={ generateBlocksDefaults.headline }
601 />
602 </Fragment>
603 ) }
604
605 { applyFilters( 'generateblocks.editor.controls', '', 'headlineSpacing', this.props, this.state ) }
606 </PanelArea>
607
608 <PanelArea { ...this.props }
609 title={ __( 'Colors', 'generateblocks' ) }
610 initialOpen={ false }
611 icon={ getIcon( 'colors' ) }
612 className={ 'gblocks-panel-label' }
613 id={ 'headlineColors' }
614 state={ this.state }
615 showPanel={ 'desktop' === getSelectedDevice( selectedDevice ) || false }
616 >
617 <ColorPicker
618 label={ __( 'Background Color', 'generateblocks' ) }
619 value={ backgroundColor }
620 alpha={ true }
621 valueOpacity={ backgroundColorOpacity }
622 attrOpacity={ 'backgroundColorOpacity' }
623 onChange={ ( value ) =>
624 setAttributes( {
625 backgroundColor: value,
626 } )
627 }
628 onOpacityChange={ ( value ) =>
629 setAttributes( {
630 backgroundColorOpacity: value,
631 } )
632 }
633 />
634
635 <ColorPicker
636 label={ __( 'Text Color', 'generateblocks' ) }
637 value={ textColor }
638 alpha={ false }
639 onChange={ ( value ) =>
640 setAttributes( {
641 textColor: value,
642 } )
643 }
644 />
645
646 <ColorPicker
647 label={ __( 'Link Color', 'generateblocks' ) }
648 value={ linkColor }
649 alpha={ false }
650 onChange={ ( value ) =>
651 setAttributes( {
652 linkColor: value,
653 } )
654 }
655 />
656
657 <ColorPicker
658 label={ __( 'Link Color Hover', 'generateblocks' ) }
659 value={ linkColorHover }
660 alpha={ false }
661 onChange={ ( value ) =>
662 setAttributes( {
663 linkColorHover: value,
664 } )
665 }
666 />
667
668 <ColorPicker
669 label={ __( 'Border Color', 'generateblocks' ) }
670 value={ borderColor }
671 alpha={ true }
672 valueOpacity={ borderColorOpacity }
673 attrOpacity={ 'borderColorOpacity' }
674 onChange={ ( value ) =>
675 setAttributes( {
676 borderColor: value,
677 } )
678 }
679 onOpacityChange={ ( value ) =>
680 setAttributes( {
681 borderColorOpacity: value,
682 } )
683 }
684 />
685
686 { icon &&
687 <ColorPicker
688 label={ __( 'Icon Color', 'generateblocks' ) }
689 value={ iconColor }
690 alpha={ true }
691 valueOpacity={ iconColorOpacity }
692 attrOpacity={ 'iconColorOpacity' }
693 onChange={ ( value ) =>
694 setAttributes( {
695 iconColor: value,
696 } )
697 }
698 onOpacityChange={ ( value ) =>
699 setAttributes( {
700 iconColorOpacity: value,
701 } )
702 }
703 />
704 }
705
706 <ColorPicker
707 label={ __( 'Highlight Text', 'generateblocks' ) }
708 value={ highlightTextColor }
709 alpha={ false }
710 onChange={ ( value ) =>
711 setAttributes( {
712 highlightTextColor: value,
713 } )
714 }
715 />
716 </PanelArea>
717
718 <PanelArea { ...this.props }
719 title={ __( 'Icon', 'generateblocks' ) }
720 initialOpen={ false }
721 icon={ getIcon( 'icons' ) }
722 className={ 'gblocks-panel-label' }
723 id={ 'headlineIcon' }
724 state={ this.state }
725 showPanel={ 'desktop' === getSelectedDevice( selectedDevice ) || !! icon ? true : false }
726 >
727
728 { 'desktop' === getSelectedDevice( selectedDevice ) &&
729 <IconPicker { ...this.props }
730 attrIcon={ 'icon' }
731 attrRemoveText={ 'removeText' }
732 attrAriaLabel={ 'ariaLabel' }
733 />
734 }
735
736 { 'desktop' === getSelectedDevice( selectedDevice ) && !! icon &&
737 <Fragment>
738 { ! removeText &&
739 <Fragment>
740 <SelectControl
741 label={ __( 'Icon Location', 'generateblocks' ) }
742 value={ iconLocation }
743 options={ [
744 { label: __( 'Inline', 'generateblocks' ), value: 'inline' },
745 { label: __( 'Above', 'generateblocks' ), value: 'above' },
746 ] }
747 onChange={ ( value ) => {
748 setAttributes( {
749 iconLocation: value,
750 iconPaddingRight: 'inline' === value ? '0.5' : '',
751 iconPaddingBottom: 'above' === value ? '0.5' : '',
752 } );
753 } }
754 />
755
756 { 'inline' === iconLocation &&
757 <SelectControl
758 label={ __( 'Icon Alignment', 'generateblocks' ) }
759 value={ iconVerticalAlignment }
760 options={ [
761 { label: __( 'Top', 'generateblocks' ), value: 'top' },
762 { label: __( 'Center', 'generateblocks' ), value: 'center' },
763 { label: __( 'Bottom', 'generateblocks' ), value: 'bottom' },
764 ] }
765 onChange={ ( value ) => {
766 setAttributes( {
767 iconVerticalAlignment: value,
768 } );
769 } }
770 />
771 }
772
773 <DimensionsControl { ...this.props }
774 device={ getSelectedDevice( selectedDevice ) }
775 type={ 'padding' }
776 label={ __( 'Padding', 'generateblocks' ) }
777 attrTop={ 'iconPaddingTop' }
778 attrRight={ 'iconPaddingRight' }
779 attrBottom={ 'iconPaddingBottom' }
780 attrLeft={ 'iconPaddingLeft' }
781 attrUnit={ 'iconPaddingUnit' }
782 attrSyncUnits={ 'iconPaddingSyncUnits' }
783 defaults={ generateBlocksDefaults.headline }
784 />
785 </Fragment>
786 }
787
788 <div className="components-gblocks-typography-control__header">
789 <div className="components-gblocks-typography-control__label components-base-control__label">
790 { __( 'Icon Size', 'generateblocks' ) }
791 </div>
792
793 <div className="components-gblocks-control__units">
794 <ButtonGroup className="components-gblocks-typography-control__units" aria-label={ __( 'Select Units', 'generateblocks' ) }>
795 { unitSizes.map( ( unit ) =>
796 /* translators: %s: values associated with CSS syntax, 'Pixel', 'Em', 'Percentage' */
797 <Tooltip text={ sprintf( __( '%s Units', 'generateblocks' ), unit.name ) } key={ unit.unitValue }>
798 <Button
799 key={ unit.unitValue }
800 className={ 'components-gblocks-typography-control__units--' + unit.name }
801 isSmall
802 isPrimary={ iconSizeUnit === unit.unitValue }
803 aria-pressed={ iconSizeUnit === unit.unitValue }
804 /* translators: %s: values associated with CSS syntax, 'Pixel', 'Em', 'Percentage' */
805 aria-label={ sprintf( __( '%s Units', 'generateblocks' ), unit.name ) }
806 onClick={ () => setAttributes( { iconSizeUnit: unit.unitValue } ) }
807 >
808 { unit.unitValue }
809 </Button>
810 </Tooltip>
811 ) }
812 </ButtonGroup>
813 </div>
814 </div>
815
816 <div className="components-base-control components-gblocks-typography-control__inputs">
817 <TextControl
818 type={ 'number' }
819 value={ iconSize || 0 === iconSize ? iconSize : '' }
820 step={ 'em' === iconSizeUnit ? .1 : 1 }
821 onChange={ ( value ) => {
822 setAttributes( {
823 iconSize: value,
824 } );
825 } }
826 onBlur={ () => {
827 setAttributes( {
828 iconSize: parseFloat( iconSize ),
829 } );
830 } }
831 onClick={ ( e ) => {
832 // Make sure onBlur fires in Firefox.
833 e.currentTarget.focus();
834 } }
835 />
836
837 <Button
838 isSmall
839 isSecondary
840 className="components-gblocks-default-number"
841 onClick={ () => {
842 setAttributes( {
843 iconSize: generateBlocksDefaults.headline.iconSize,
844 } );
845 } }
846 >
847 { __( 'Reset', 'generateblocks' ) }
848 </Button>
849 </div>
850 </Fragment>
851 }
852
853 { 'tablet' === getSelectedDevice( selectedDevice ) && !! icon &&
854 <Fragment>
855 { ! removeText &&
856 <Fragment>
857 <SelectControl
858 label={ __( 'Icon Location', 'generateblocks' ) }
859 value={ iconLocationTablet }
860 options={ [
861 { label: __( 'Inherit', 'generateblocks' ), value: '' },
862 { label: __( 'Inline', 'generateblocks' ), value: 'inline' },
863 { label: __( 'Above', 'generateblocks' ), value: 'above' },
864 ] }
865 onChange={ ( value ) => {
866 setAttributes( {
867 iconLocationTablet: value,
868 iconPaddingRightTablet: 'inline' === value ? '0.5' : '',
869 iconPaddingBottomTablet: 'above' === value ? '0.5' : '',
870 } );
871 } }
872 />
873
874 { 'inline' === iconLocationTablet &&
875 <SelectControl
876 label={ __( 'Icon Alignment', 'generateblocks' ) }
877 value={ iconVerticalAlignmentTablet }
878 options={ [
879 { label: __( 'Top', 'generateblocks' ), value: 'top' },
880 { label: __( 'Center', 'generateblocks' ), value: 'center' },
881 { label: __( 'Bottom', 'generateblocks' ), value: 'bottom' },
882 ] }
883 onChange={ ( value ) => {
884 setAttributes( {
885 iconVerticalAlignmentTablet: value,
886 } );
887 } }
888 />
889 }
890
891 <DimensionsControl { ...this.props }
892 device={ getSelectedDevice( selectedDevice ) }
893 type={ 'padding' }
894 label={ __( 'Padding', 'generateblocks' ) }
895 attrTop={ 'iconPaddingTopTablet' }
896 attrRight={ 'iconPaddingRightTablet' }
897 attrBottom={ 'iconPaddingBottomTablet' }
898 attrLeft={ 'iconPaddingLeftTablet' }
899 attrUnit={ 'iconPaddingUnit' }
900 attrSyncUnits={ 'iconPaddingSyncUnits' }
901 defaults={ generateBlocksDefaults.headline }
902 />
903 </Fragment>
904 }
905
906 <div className="components-gblocks-typography-control__header">
907 <div className="components-gblocks-typography-control__label components-base-control__label">
908 { __( 'Icon Size', 'generateblocks' ) }
909 </div>
910
911 <div className="components-gblocks-control__units">
912 <ButtonGroup className="components-gblocks-typography-control__units" aria-label={ __( 'Select Units', 'generateblocks' ) }>
913 { unitSizes.map( ( unit ) =>
914 /* translators: %s: values associated with CSS syntax, 'Pixel', 'Em', 'Percentage' */
915 <Tooltip text={ sprintf( __( '%s Units', 'generateblocks' ), unit.name ) } key={ unit.unitValue }>
916 <Button
917 key={ unit.unitValue }
918 className={ 'components-gblocks-typography-control__units--' + unit.name }
919 isSmall
920 isPrimary={ iconSizeUnit === unit.unitValue }
921 aria-pressed={ iconSizeUnit === unit.unitValue }
922 /* translators: %s: values associated with CSS syntax, 'Pixel', 'Em', 'Percentage' */
923 aria-label={ sprintf( __( '%s Units', 'generateblocks' ), unit.name ) }
924 onClick={ () => setAttributes( { iconSizeUnit: unit.unitValue } ) }
925 >
926 { unit.unitValue }
927 </Button>
928 </Tooltip>
929 ) }
930 </ButtonGroup>
931 </div>
932 </div>
933
934 <div className="components-base-control components-gblocks-typography-control__inputs">
935 <TextControl
936 type={ 'number' }
937 value={ iconSizeTablet || 0 === iconSizeTablet ? iconSizeTablet : '' }
938 step={ 'em' === iconSizeUnit ? .1 : 1 }
939 placeholder={ iconSize || 0 === iconSize ? iconSize : '' }
940 onChange={ ( value ) => {
941 setAttributes( {
942 iconSizeTablet: value,
943 } );
944 } }
945 onBlur={ () => {
946 setAttributes( {
947 iconSizeTablet: parseFloat( iconSizeTablet ),
948 } );
949 } }
950 onClick={ ( e ) => {
951 // Make sure onBlur fires in Firefox.
952 e.currentTarget.focus();
953 } }
954 />
955
956 <Button
957 isSmall
958 isSecondary
959 className="components-gblocks-default-number"
960 onClick={ () => {
961 setAttributes( {
962 iconSizeTablet: generateBlocksDefaults.headline.iconSizeTablet,
963 } );
964 } }
965 >
966 { __( 'Reset', 'generateblocks' ) }
967 </Button>
968 </div>
969 </Fragment>
970 }
971
972 { 'mobile' === getSelectedDevice( selectedDevice ) && !! icon &&
973 <Fragment>
974 { ! removeText &&
975 <Fragment>
976 <SelectControl
977 label={ __( 'Icon Location', 'generateblocks' ) }
978 value={ iconLocationMobile }
979 options={ [
980 { label: __( 'Inherit', 'generateblocks' ), value: '' },
981 { label: __( 'Inline', 'generateblocks' ), value: 'inline' },
982 { label: __( 'Above', 'generateblocks' ), value: 'above' },
983 ] }
984 onChange={ ( value ) => {
985 setAttributes( {
986 iconLocationMobile: value,
987 iconPaddingRightMobile: 'inline' === value ? '0.5' : '',
988 iconPaddingBottomMobile: 'above' === value ? '0.5' : '',
989 } );
990 } }
991 />
992
993 { 'inline' === iconLocationMobile &&
994 <SelectControl
995 label={ __( 'Icon Alignment', 'generateblocks' ) }
996 value={ iconVerticalAlignmentMobile }
997 options={ [
998 { label: __( 'Top', 'generateblocks' ), value: 'top' },
999 { label: __( 'Center', 'generateblocks' ), value: 'center' },
1000 { label: __( 'Bottom', 'generateblocks' ), value: 'bottom' },
1001 ] }
1002 onChange={ ( value ) => {
1003 setAttributes( {
1004 iconVerticalAlignmentMobile: value,
1005 } );
1006 } }
1007 />
1008 }
1009
1010 <DimensionsControl { ...this.props }
1011 device={ getSelectedDevice( selectedDevice ) }
1012 type={ 'padding' }
1013 label={ __( 'Padding', 'generateblocks' ) }
1014 attrTop={ 'iconPaddingTopMobile' }
1015 attrRight={ 'iconPaddingRightMobile' }
1016 attrBottom={ 'iconPaddingBottomMobile' }
1017 attrLeft={ 'iconPaddingLeftMobile' }
1018 attrUnit={ 'iconPaddingUnit' }
1019 attrSyncUnits={ 'iconPaddingSyncUnits' }
1020 defaults={ generateBlocksDefaults.headline }
1021 />
1022 </Fragment>
1023 }
1024
1025 <div className="components-gblocks-typography-control__header">
1026 <div className="components-gblocks-typography-control__label components-base-control__label">
1027 { __( 'Icon Size', 'generateblocks' ) }
1028 </div>
1029
1030 <div className="components-gblocks-control__units">
1031 <ButtonGroup className="components-gblocks-typography-control__units" aria-label={ __( 'Select Units', 'generateblocks' ) }>
1032 { unitSizes.map( ( unit ) =>
1033 /* translators: %s: values associated with CSS syntax, 'Pixel', 'Em', 'Percentage' */
1034 <Tooltip text={ sprintf( __( '%s Units', 'generateblocks' ), unit.name ) } key={ unit.unitValue }>
1035 <Button
1036 key={ unit.unitValue }
1037 className={ 'components-gblocks-typography-control__units--' + unit.name }
1038 isSmall
1039 isPrimary={ iconSizeUnit === unit.unitValue }
1040 aria-pressed={ iconSizeUnit === unit.unitValue }
1041 /* translators: %s: values associated with CSS syntax, 'Pixel', 'Em', 'Percentage' */
1042 aria-label={ sprintf( __( '%s Units', 'generateblocks' ), unit.name ) }
1043 onClick={ () => setAttributes( { iconSizeUnit: unit.unitValue } ) }
1044 >
1045 { unit.unitValue }
1046 </Button>
1047 </Tooltip>
1048 ) }
1049 </ButtonGroup>
1050 </div>
1051 </div>
1052
1053 <div className="components-base-control components-gblocks-typography-control__inputs">
1054 <TextControl
1055 type={ 'number' }
1056 value={ iconSizeMobile || 0 === iconSizeMobile ? iconSizeMobile : '' }
1057 step={ 'em' === iconSizeUnit ? .1 : 1 }
1058 placeholder={ iconSizePlaceholderMobile }
1059 onChange={ ( value ) => {
1060 setAttributes( {
1061 iconSizeMobile: value,
1062 } );
1063 } }
1064 onBlur={ () => {
1065 setAttributes( {
1066 iconSizeMobile: parseFloat( iconSizeMobile ),
1067 } );
1068 } }
1069 onClick={ ( e ) => {
1070 // Make sure onBlur fires in Firefox.
1071 e.currentTarget.focus();
1072 } }
1073 />
1074
1075 <Button
1076 isSmall
1077 isSecondary
1078 className="components-gblocks-default-number"
1079 onClick={ () => {
1080 setAttributes( {
1081 iconSizeMobile: generateBlocksDefaults.headline.iconSizeMobile,
1082 } );
1083 } }
1084 >
1085 { __( 'Reset', 'generateblocks' ) }
1086 </Button>
1087 </div>
1088 </Fragment>
1089 }
1090
1091 { applyFilters( 'generateblocks.editor.controls', '', 'headlineIcon', this.props, this.state ) }
1092 </PanelArea>
1093
1094 <PanelArea { ...this.props }
1095 title={ __( 'Advanced', 'generateblocks' ) }
1096 initialOpen={ false }
1097 icon={ getIcon( 'advanced' ) }
1098 className={ 'gblocks-panel-label' }
1099 id={ 'headlineAdvanced' }
1100 state={ this.state }
1101 showPanel={ 'desktop' === getSelectedDevice( selectedDevice ) || false }
1102 >
1103 <TextControl
1104 label={ __( 'Element ID', 'generateblocks' ) }
1105 value={ elementId }
1106 onChange={ ( value ) => {
1107 const newElementId = value.replace( ELEMENT_ID_REGEX, '-' );
1108
1109 setAttributes( {
1110 elementId: newElementId,
1111 } );
1112 } }
1113 />
1114
1115 <TextControl
1116 label={ __( 'CSS Classes', 'generateblocks' ) }
1117 value={ cssClasses }
1118 onChange={ ( value ) => {
1119 setAttributes( {
1120 cssClasses: value,
1121 } );
1122 } }
1123 />
1124
1125 { applyFilters( 'generateblocks.editor.controls', '', 'headlineAdvanced', this.props, this.state ) }
1126 </PanelArea>
1127
1128 <PanelArea { ...this.props }
1129 title={ __( 'Documentation', 'generateblocks' ) }
1130 icon={ getIcon( 'documentation' ) }
1131 initialOpen={ false }
1132 className={ 'gblocks-panel-label' }
1133 id={ 'headlineDocumentation' }
1134 state={ this.state }
1135 >
1136 <p>{ __( 'Need help with this block?', 'generateblocks' ) }</p>
1137 <a href="https://docs.generateblocks.com/collection/headline/" target="_blank" rel="noreferrer noopener">{ __( 'Visit our documentation', 'generateblocks' ) }</a>
1138
1139 { applyFilters( 'generateblocks.editor.controls', '', 'headlineDocumentation', this.props, this.state ) }
1140 </PanelArea>
1141 </InspectorControls>
1142
1143 <DesktopCSS { ...this.props } />
1144
1145 { fontFamily && googleFont &&
1146 <link
1147 rel="stylesheet"
1148 href={ 'https://fonts.googleapis.com/css?family=' + fontFamily.replace( / /g, '+' ) + googleFontsAttr }
1149 />
1150 }
1151
1152 { icon ? (
1153 <div
1154 className={ classnames( {
1155 'gb-headline-wrapper': true,
1156 [ `gb-headline-wrapper-${ uniqueId }` ]: true,
1157 } ) }
1158 >
1159 { icon &&
1160 <span
1161 className="gb-icon"
1162 aria-label={ !! removeText && !! ariaLabel ? ariaLabel : undefined }
1163 dangerouslySetInnerHTML={ { __html: sanitizeSVG( icon ) } }
1164 />
1165 }
1166
1167 { ! removeText &&
1168 <RichText
1169 tagName={ element }
1170 value={ content }
1171 onChange={ ( value ) => setAttributes( { content: value } ) }
1172 placeholder={ __( 'Write headline…', 'generateblocks' ) }
1173 keepPlaceholderOnFocus={ true }
1174 { ...htmlAttributes }
1175 />
1176 }
1177 </div>
1178 ) : (
1179 <RichText
1180 tagName={ element }
1181 value={ content }
1182 onChange={ ( value ) => setAttributes( { content: value } ) }
1183 placeholder={ __( 'Write headline…', 'generateblocks' ) }
1184 keepPlaceholderOnFocus={ true }
1185 { ...htmlAttributes }
1186 />
1187 ) }
1188 </Fragment>
1189 );
1190 }
1191 }
1192
1193 export default ( GenerateBlockHeadline );
1194