PluginProbe ʕ •ᴥ•ʔ
GenerateBlocks / 1.3.4
GenerateBlocks v1.3.4
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 / button / edit.js
generateblocks / src / blocks / button Last commit date
css 5 years ago attributes.js 5 years ago block.js 5 years ago deprecated.js 5 years ago edit.js 5 years ago editor.scss 5 years ago save.js 5 years ago
edit.js
1142 lines
1 /**
2 * Block: Buttons
3 */
4
5 import classnames from 'classnames';
6 import ColorPicker from '../../components/color-picker';
7 import UnitPicker from '../../components/unit-picker';
8 import IconPicker from '../../components/icon-picker';
9 import URLInput from '../../components/url-input';
10 import DimensionsControl from '../../components/dimensions/';
11 import TypographyControls from '../../components/typography';
12 import GradientControl from '../../components/gradient/';
13 import ResponsiveTabs from '../../components/responsive-tabs';
14 import PanelArea from '../../components/panel-area/';
15 import getIcon from '../../utils/get-icon';
16 import MainCSS from './css/main.js';
17 import DesktopCSS from './css/desktop.js';
18 import TabletCSS from './css/tablet.js';
19 import TabletOnlyCSS from './css/tablet-only.js';
20 import MobileCSS from './css/mobile.js';
21 import Element from '../../components/element';
22
23 import {
24 __,
25 } from '@wordpress/i18n';
26
27 import {
28 TabPanel,
29 TextControl,
30 ToolbarGroup,
31 ToolbarButton,
32 Button,
33 } from '@wordpress/components';
34
35 import {
36 Fragment,
37 Component,
38 } from '@wordpress/element';
39
40 import {
41 InspectorControls,
42 InspectorAdvancedControls,
43 RichText,
44 BlockControls,
45 } from '@wordpress/block-editor';
46
47 import {
48 cloneBlock,
49 } from '@wordpress/blocks';
50
51 import {
52 applyFilters,
53 } from '@wordpress/hooks';
54
55 import {
56 withSelect,
57 withDispatch,
58 } from '@wordpress/data';
59
60 import {
61 compose,
62 } from '@wordpress/compose';
63
64 /**
65 * Regular expression matching invalid anchor characters for replacement.
66 *
67 * @type {RegExp}
68 */
69 const ANCHOR_REGEX = /[\s#]/g;
70
71 const gbButtonIds = [];
72
73 class GenerateBlockButton extends Component {
74 constructor() {
75 super( ...arguments );
76
77 this.state = {
78 selectedDevice: 'Desktop',
79 fontSizePlaceholder: '17',
80 };
81
82 this.getFontSizePlaceholder = this.getFontSizePlaceholder.bind( this );
83 this.getDeviceType = this.getDeviceType.bind( this );
84 this.setDeviceType = this.setDeviceType.bind( this );
85 }
86
87 componentDidMount() {
88 const id = this.props.clientId.substr( 2, 9 ).replace( '-', '' );
89
90 // We don't want to ever regenerate unique IDs if they're a global style.
91 const isGlobalStyle = 'undefined' !== typeof this.props.attributes.isGlobalStyle && this.props.attributes.isGlobalStyle;
92
93 if ( ! this.props.attributes.uniqueId ) {
94 this.props.setAttributes( {
95 uniqueId: id,
96 } );
97
98 gbButtonIds.push( id );
99 } else if ( gbButtonIds.includes( this.props.attributes.uniqueId ) && ! isGlobalStyle ) {
100 this.props.setAttributes( {
101 uniqueId: id,
102 } );
103
104 gbButtonIds.push( id );
105 } else {
106 gbButtonIds.push( this.props.attributes.uniqueId );
107 }
108
109 const tempFontSizePlaceholder = this.getFontSizePlaceholder();
110
111 if ( tempFontSizePlaceholder !== this.state.fontSizePlaceholder ) {
112 this.setState( {
113 fontSizePlaceholder: tempFontSizePlaceholder,
114 } );
115 }
116
117 // hasIcon came late, so let's set it on mount if we have an icon.
118 if ( ! this.props.attributes.hasIcon && this.props.attributes.icon ) {
119 this.props.setAttributes( {
120 hasIcon: true,
121 } );
122 }
123
124 // hasUrl came late, so let's set it if it doesn't exist.
125 if ( 'undefined' === typeof this.props.attributes.hasUrl ) {
126 if ( ! this.props.attributes.url ) {
127 this.props.setAttributes( {
128 hasUrl: false,
129 } );
130 } else {
131 this.props.setAttributes( {
132 hasUrl: true,
133 } );
134 }
135 }
136 }
137
138 componentDidUpdate() {
139 const tempFontSizePlaceholder = this.getFontSizePlaceholder();
140
141 if ( tempFontSizePlaceholder !== this.state.fontSizePlaceholder ) {
142 this.setState( {
143 fontSizePlaceholder: tempFontSizePlaceholder,
144 } );
145 }
146 }
147
148 getFontSizePlaceholder() {
149 let placeholder = '17';
150 const buttonId = document.querySelector( '.gb-button-' + this.props.attributes.uniqueId );
151
152 if ( buttonId ) {
153 placeholder = parseFloat( window.getComputedStyle( buttonId ).fontSize );
154 }
155
156 return placeholder;
157 }
158
159 getDeviceType() {
160 let deviceType = this.props.deviceType ? this.props.deviceType : this.state.selectedDevice;
161
162 if ( ! generateBlocksInfo.syncResponsivePreviews ) {
163 deviceType = this.state.selectedDevice;
164 }
165
166 return deviceType;
167 }
168
169 setDeviceType( deviceType ) {
170 if ( generateBlocksInfo.syncResponsivePreviews && this.props.deviceType ) {
171 this.props.setDeviceType( deviceType );
172 this.setState( { selectedDevice: deviceType } );
173 } else {
174 this.setState( { selectedDevice: deviceType } );
175 }
176 }
177
178 render() {
179 const {
180 attributes,
181 setAttributes,
182 isSelected,
183 clientId,
184 } = this.props;
185
186 const {
187 fontSizePlaceholder,
188 } = this.state;
189
190 const {
191 uniqueId,
192 className,
193 anchor,
194 text,
195 url,
196 target,
197 relNoFollow,
198 relSponsored,
199 icon,
200 iconLocation,
201 removeText,
202 ariaLabel,
203 backgroundColor,
204 backgroundColorOpacity,
205 textColor,
206 backgroundColorHover,
207 backgroundColorHoverOpacity,
208 textColorHover,
209 fontFamily,
210 googleFont,
211 googleFontVariants,
212 borderColor,
213 borderColorOpacity,
214 borderColorHover,
215 borderColorHoverOpacity,
216 iconSize,
217 iconSizeTablet,
218 iconSizeMobile,
219 iconSizeUnit,
220 } = attributes;
221
222 // Stop the buttons from doing anything in the editor.
223 const links = document.querySelectorAll( 'a.gb-button' );
224
225 for ( let i = 0; i < links.length; i++ ) {
226 links[ i ].addEventListener( 'click', function( e ) {
227 if ( links[ i ].getAttribute( 'href' ) ) {
228 links[ i ].removeAttribute( 'href' );
229 e.preventDefault();
230 }
231 }, false );
232 }
233
234 const relAttributes = [];
235
236 if ( relNoFollow ) {
237 relAttributes.push( 'nofollow' );
238 }
239
240 if ( target ) {
241 relAttributes.push( 'noopener', 'noreferrer' );
242 }
243
244 if ( relSponsored ) {
245 relAttributes.push( 'sponsored' );
246 }
247
248 let googleFontsAttr = '';
249
250 if ( googleFontVariants ) {
251 googleFontsAttr = ':' + googleFontVariants;
252 }
253
254 let htmlAttributes = {
255 className: classnames( {
256 'gb-button': true,
257 [ `gb-button-${ uniqueId }` ]: true,
258 'gb-button-text': ! icon,
259 [ `${ className }` ]: undefined !== className,
260 } ),
261 href: !! url ? url : null,
262 target: !! target ? '_blank' : null,
263 rel: relAttributes && relAttributes.length > 0 ? relAttributes.join( ' ' ) : null,
264 'aria-label': !! ariaLabel ? ariaLabel : null,
265 id: anchor ? anchor : null,
266 };
267
268 htmlAttributes = applyFilters( 'generateblocks.frontend.htmlAttributes', htmlAttributes, 'generateblocks/button', attributes );
269
270 return (
271 <Fragment>
272 <BlockControls>
273 <ToolbarGroup>
274 <ToolbarButton
275 className="gblocks-add-new-button"
276 icon={ 'insert' }
277 label={ __( 'Add Button', 'generateblocks' ) }
278 onClick={ () => {
279 let parentBlockId = false;
280
281 if ( typeof wp.data.select( 'core/block-editor' ).getBlockParentsByBlockName === 'function' ) {
282 parentBlockId = wp.data.select( 'core/block-editor' ).getBlockParentsByBlockName( clientId, 'generateblocks/button-container', true )[ 0 ];
283 } else {
284 parentBlockId = wp.data.select( 'core/block-editor' ).getBlockRootClientId( clientId );
285 }
286
287 const thisBlock = wp.data.select( 'core/block-editor' ).getBlocksByClientId( clientId )[ 0 ];
288 const clonedBlock = cloneBlock( thisBlock );
289
290 wp.data.dispatch( 'core/block-editor' ).insertBlocks( clonedBlock, undefined, parentBlockId );
291 } }
292 showTooltip
293 />
294 </ToolbarGroup>
295 </BlockControls>
296
297 <InspectorControls>
298 <ResponsiveTabs { ...this.props }
299 selectedDevice={ this.getDeviceType() }
300 onClick={ ( device ) => {
301 this.setDeviceType( device );
302 } }
303 />
304
305 <PanelArea { ...this.props }
306 title={ __( 'Typography', 'generateblocks' ) }
307 initialOpen={ false }
308 icon={ getIcon( 'typography' ) }
309 className={ 'gblocks-panel-label' }
310 id={ 'buttonTypography' }
311 state={ this.state }
312 showPanel={ ! removeText || false }
313 >
314
315 { 'Desktop' === this.getDeviceType() && (
316 <Fragment>
317 <TypographyControls { ...this.props }
318 showFontFamily={ true }
319 showFontWeight={ true }
320 showTextTransform={ true }
321 showFontSize={ true }
322 showLetterSpacing={ true }
323 fontSizePlaceholder={ fontSizePlaceholder }
324 defaultFontSize={ generateBlocksDefaults.button.fontSize }
325 defaultFontSizeUnit={ generateBlocksDefaults.button.fontSizeUnit }
326 defaultLetterSpacing={ generateBlocksDefaults.button.letterSpacing }
327 />
328 </Fragment>
329 ) }
330
331 { 'Tablet' === this.getDeviceType() && (
332 <Fragment>
333 <TypographyControls { ...this.props }
334 device={ 'Tablet' }
335 showFontSize={ true }
336 showLetterSpacing={ true }
337 disableAdvancedToggle={ true }
338 defaultFontSize={ generateBlocksDefaults.button.fontSizeTablet }
339 defaultFontSizeUnit={ generateBlocksDefaults.button.fontSizeUnit }
340 defaultLetterSpacing={ generateBlocksDefaults.button.letterSpacingTablet }
341 />
342 </Fragment>
343 ) }
344
345 { 'Mobile' === this.getDeviceType() && (
346 <Fragment>
347 <TypographyControls { ...this.props }
348 device={ 'Mobile' }
349 showFontSize={ true }
350 showLetterSpacing={ true }
351 disableAdvancedToggle={ true }
352 defaultFontSize={ generateBlocksDefaults.button.fontSizeMobile }
353 defaultFontSizeUnit={ generateBlocksDefaults.button.fontSizeUnit }
354 defaultLetterSpacing={ generateBlocksDefaults.button.letterSpacingMobile }
355 />
356 </Fragment>
357 ) }
358
359 { applyFilters( 'generateblocks.editor.controls', '', 'buttonTypography', this.props, this.state ) }
360 </PanelArea>
361
362 <PanelArea { ...this.props }
363 title={ __( 'Spacing', 'generateblocks' ) }
364 initialOpen={ false }
365 icon={ getIcon( 'spacing' ) }
366 className={ 'gblocks-panel-label' }
367 id={ 'buttonSpacing' }
368 state={ this.state }
369 >
370
371 { 'Desktop' === this.getDeviceType() && (
372 <Fragment>
373 <DimensionsControl { ...this.props }
374 device={ this.getDeviceType() }
375 type={ 'padding' }
376 label={ __( 'Padding', 'generateblocks' ) }
377 attrTop={ 'paddingTop' }
378 attrRight={ 'paddingRight' }
379 attrBottom={ 'paddingBottom' }
380 attrLeft={ 'paddingLeft' }
381 attrUnit={ 'paddingUnit' }
382 attrSyncUnits={ 'paddingSyncUnits' }
383 defaults={ generateBlocksDefaults.button }
384 units={ [ 'px', 'em', '%' ] }
385 />
386
387 <DimensionsControl { ...this.props }
388 device={ this.getDeviceType() }
389 type={ 'margin' }
390 label={ __( 'Margin', 'generateblocks' ) }
391 attrTop={ 'marginTop' }
392 attrRight={ 'marginRight' }
393 attrBottom={ 'marginBottom' }
394 attrLeft={ 'marginLeft' }
395 attrUnit={ 'marginUnit' }
396 attrSyncUnits={ 'marginSyncUnits' }
397 defaults={ generateBlocksDefaults.button }
398 units={ [ 'px', 'em', '%' ] }
399 />
400
401 <DimensionsControl { ...this.props }
402 device={ this.getDeviceType() }
403 type={ 'padding' }
404 label={ __( 'Border Size', 'generateblocks' ) }
405 attrTop={ 'borderSizeTop' }
406 attrRight={ 'borderSizeRight' }
407 attrBottom={ 'borderSizeBottom' }
408 attrLeft={ 'borderSizeLeft' }
409 attrSyncUnits={ 'borderSizeSyncUnits' }
410 defaults={ generateBlocksDefaults.button }
411 units={ [ 'px' ] }
412 />
413
414 <DimensionsControl { ...this.props }
415 device={ this.getDeviceType() }
416 type={ 'padding' }
417 label={ __( 'Border Radius', 'generateblocks' ) }
418 attrTop={ 'borderRadiusTopLeft' }
419 attrRight={ 'borderRadiusTopRight' }
420 attrBottom={ 'borderRadiusBottomRight' }
421 attrLeft={ 'borderRadiusBottomLeft' }
422 attrUnit={ 'borderRadiusUnit' }
423 attrSyncUnits={ 'borderRadiusSyncUnits' }
424 labelTop={ __( 'T-Left', 'generateblocks' ) }
425 labelRight={ __( 'T-Right', 'generateblocks' ) }
426 labelBottom={ __( 'B-Right', 'generateblocks' ) }
427 labelLeft={ __( 'B-Left', 'generateblocks' ) }
428 defaults={ generateBlocksDefaults.button }
429 units={ [ 'px', 'em', '%' ] }
430 />
431 </Fragment>
432 ) }
433
434 { 'Tablet' === this.getDeviceType() && (
435 <Fragment>
436 <DimensionsControl { ...this.props }
437 device={ this.getDeviceType() }
438 type={ 'padding' }
439 label={ __( 'Padding', 'generateblocks' ) }
440 attrTop={ 'paddingTopTablet' }
441 attrRight={ 'paddingRightTablet' }
442 attrBottom={ 'paddingBottomTablet' }
443 attrLeft={ 'paddingLeftTablet' }
444 attrUnit={ 'paddingUnit' }
445 attrSyncUnits={ 'paddingSyncUnits' }
446 defaults={ generateBlocksDefaults.button }
447 units={ [ 'px', 'em', '%' ] }
448 />
449
450 <DimensionsControl { ...this.props }
451 device={ this.getDeviceType() }
452 type={ 'margin' }
453 label={ __( 'Margin', 'generateblocks' ) }
454 attrTop={ 'marginTopTablet' }
455 attrRight={ 'marginRightTablet' }
456 attrBottom={ 'marginBottomTablet' }
457 attrLeft={ 'marginLeftTablet' }
458 attrUnit={ 'marginUnit' }
459 attrSyncUnits={ 'marginSyncUnits' }
460 defaults={ generateBlocksDefaults.button }
461 units={ [ 'px', 'em', '%' ] }
462 />
463
464 <DimensionsControl { ...this.props }
465 device={ this.getDeviceType() }
466 type={ 'padding' }
467 label={ __( 'Border Size', 'generateblocks' ) }
468 attrTop={ 'borderSizeTopTablet' }
469 attrRight={ 'borderSizeRightTablet' }
470 attrBottom={ 'borderSizeBottomTablet' }
471 attrLeft={ 'borderSizeLeftTablet' }
472 attrSyncUnits={ 'borderSizeSyncUnits' }
473 defaults={ generateBlocksDefaults.button }
474 units={ [ 'px' ] }
475 />
476
477 <DimensionsControl { ...this.props }
478 device={ this.getDeviceType() }
479 type={ 'padding' }
480 label={ __( 'Border Radius', 'generateblocks' ) }
481 attrTop={ 'borderRadiusTopLeftTablet' }
482 attrRight={ 'borderRadiusTopRightTablet' }
483 attrBottom={ 'borderRadiusBottomRightTablet' }
484 attrLeft={ 'borderRadiusBottomLeftTablet' }
485 attrUnit={ 'borderRadiusUnit' }
486 attrSyncUnits={ 'borderRadiusSyncUnits' }
487 labelTop={ __( 'T-Left', 'generateblocks' ) }
488 labelRight={ __( 'T-Right', 'generateblocks' ) }
489 labelBottom={ __( 'B-Right', 'generateblocks' ) }
490 labelLeft={ __( 'B-Left', 'generateblocks' ) }
491 defaults={ generateBlocksDefaults.button }
492 units={ [ 'px', 'em', '%' ] }
493 />
494 </Fragment>
495 ) }
496
497 { 'Mobile' === this.getDeviceType() && (
498 <Fragment>
499 <DimensionsControl { ...this.props }
500 device={ this.getDeviceType() }
501 type={ 'padding' }
502 label={ __( 'Padding', 'generateblocks' ) }
503 attrTop={ 'paddingTopMobile' }
504 attrRight={ 'paddingRightMobile' }
505 attrBottom={ 'paddingBottomMobile' }
506 attrLeft={ 'paddingLeftMobile' }
507 attrUnit={ 'paddingUnit' }
508 attrSyncUnits={ 'paddingSyncUnits' }
509 defaults={ generateBlocksDefaults.button }
510 units={ [ 'px', 'em', '%' ] }
511 />
512
513 <DimensionsControl { ...this.props }
514 device={ this.getDeviceType() }
515 type={ 'padding' }
516 label={ __( 'Margin', 'generateblocks' ) }
517 attrTop={ 'marginTopMobile' }
518 attrRight={ 'marginRightMobile' }
519 attrBottom={ 'marginBottomMobile' }
520 attrLeft={ 'marginLeftMobile' }
521 attrUnit={ 'marginUnit' }
522 attrSyncUnits={ 'marginSyncUnits' }
523 defaults={ generateBlocksDefaults.button }
524 units={ [ 'px', 'em', '%' ] }
525 />
526
527 <DimensionsControl { ...this.props }
528 device={ this.getDeviceType() }
529 type={ 'padding' }
530 label={ __( 'Border Size', 'generateblocks' ) }
531 attrTop={ 'borderSizeTopMobile' }
532 attrRight={ 'borderSizeRightMobile' }
533 attrBottom={ 'borderSizeBottomMobile' }
534 attrLeft={ 'borderSizeLeftMobile' }
535 attrSyncUnits={ 'borderSizeSyncUnits' }
536 defaults={ generateBlocksDefaults.button }
537 units={ [ 'px' ] }
538 />
539
540 <DimensionsControl { ...this.props }
541 device={ this.getDeviceType() }
542 type={ 'padding' }
543 label={ __( 'Border Radius', 'generateblocks' ) }
544 attrTop={ 'borderRadiusTopLeftMobile' }
545 attrRight={ 'borderRadiusTopRightMobile' }
546 attrBottom={ 'borderRadiusBottomRightMobile' }
547 attrLeft={ 'borderRadiusBottomLeftMobile' }
548 attrUnit={ 'borderRadiusUnit' }
549 attrSyncUnits={ 'borderRadiusSyncUnits' }
550 labelTop={ __( 'T-Left', 'generateblocks' ) }
551 labelRight={ __( 'T-Right', 'generateblocks' ) }
552 labelBottom={ __( 'B-Right', 'generateblocks' ) }
553 labelLeft={ __( 'B-Left', 'generateblocks' ) }
554 defaults={ generateBlocksDefaults.button }
555 units={ [ 'px', 'em', '%' ] }
556 />
557 </Fragment>
558 ) }
559
560 { applyFilters( 'generateblocks.editor.controls', '', 'buttonSpacing', this.props, this.state ) }
561 </PanelArea>
562
563 <PanelArea { ...this.props }
564 title={ __( 'Colors', 'generateblocks' ) }
565 initialOpen={ false }
566 icon={ getIcon( 'colors' ) }
567 className={ 'gblocks-panel-label' }
568 id={ 'buttonColors' }
569 state={ this.state }
570 >
571 { 'Desktop' === this.getDeviceType() &&
572 <TabPanel className="layout-tab-panel gblocks-control-tabs"
573 activeClass="active-tab"
574 tabs={ [
575 {
576 name: 'button-colors',
577 title: __( 'Normal', 'generateblocks' ),
578 className: 'button-colors',
579 },
580 {
581 name: 'button-colors-hover',
582 title: __( 'Hover', 'generateblocks' ),
583 className: 'button-colors-hover',
584 },
585 ] }>
586 {
587 ( tab ) => {
588 const isNormal = tab.name === 'button-colors';
589
590 return (
591 <div>
592 { isNormal ? (
593 <Fragment>
594 <ColorPicker
595 label={ __( 'Background Color', 'generateblocks' ) }
596 value={ backgroundColor }
597 alpha={ true }
598 valueOpacity={ backgroundColorOpacity }
599 attrOpacity={ 'backgroundColorOpacity' }
600 key={ 'buttonBackgroundColor' }
601 onChange={ ( nextBackgroundColor ) =>
602 setAttributes( {
603 backgroundColor: nextBackgroundColor,
604 } )
605 }
606 onOpacityChange={ ( value ) =>
607 setAttributes( {
608 backgroundColorOpacity: value,
609 } )
610 }
611 />
612
613 <ColorPicker
614 label={ __( 'Text Color', 'generateblocks' ) }
615 value={ textColor }
616 alpha={ false }
617 key={ 'buttonTextColor' }
618 onChange={ ( nextTextColor ) =>
619 setAttributes( {
620 textColor: nextTextColor,
621 } )
622 }
623 />
624
625 <ColorPicker
626 label={ __( 'Border Color', 'generateblocks' ) }
627 value={ borderColor }
628 alpha={ true }
629 valueOpacity={ borderColorOpacity }
630 attrOpacity={ 'borderColorOpacity' }
631 key={ 'buttonBorderColor' }
632 onChange={ ( value ) =>
633 setAttributes( {
634 borderColor: value,
635 } )
636 }
637 onOpacityChange={ ( value ) =>
638 setAttributes( {
639 borderColorOpacity: value,
640 } )
641 }
642 />
643
644 { applyFilters( 'generateblocks.editor.controls', '', 'buttonColorsNormal', this.props, this.state ) }
645 </Fragment>
646
647 ) : (
648
649 <Fragment>
650 <ColorPicker
651 label={ __( 'Background Color', 'generateblocks' ) }
652 value={ backgroundColorHover }
653 alpha={ true }
654 valueOpacity={ backgroundColorHoverOpacity }
655 attrOpacity={ 'backgroundColorHoverOpacity' }
656 key={ 'buttonBackgroundColorHover' }
657 onChange={ ( nextBackgroundColorHover ) =>
658 setAttributes( {
659 backgroundColorHover: nextBackgroundColorHover,
660 } )
661 }
662 onOpacityChange={ ( value ) =>
663 setAttributes( {
664 backgroundColorHoverOpacity: value,
665 } )
666 }
667 />
668
669 <ColorPicker
670 label={ __( 'Text Color', 'generateblocks' ) }
671 value={ textColorHover }
672 alpha={ false }
673 key={ 'buttonTextColorHover' }
674 onChange={ ( nextTextColorHover ) =>
675 setAttributes( {
676 textColorHover: nextTextColorHover,
677 } )
678 }
679 />
680
681 <ColorPicker
682 label={ __( 'Border Color', 'generateblocks' ) }
683 value={ borderColorHover }
684 alpha={ true }
685 valueOpacity={ borderColorHoverOpacity }
686 attrOpacity={ 'borderColorHoverOpacity' }
687 key={ 'buttonBorderColorHover' }
688 onChange={ ( value ) =>
689 setAttributes( {
690 borderColorHover: value,
691 } )
692 }
693 onOpacityChange={ ( value ) =>
694 setAttributes( {
695 borderColorHoverOpacity: value,
696 } )
697 }
698 />
699
700 { applyFilters( 'generateblocks.editor.controls', '', 'buttonColorsHover', this.props, this.state ) }
701 </Fragment>
702 ) }
703 </div>
704 );
705 }
706 }
707 </TabPanel>
708 }
709
710 { applyFilters( 'generateblocks.editor.controls', '', 'buttonColors', this.props, this.state ) }
711 </PanelArea>
712
713 <PanelArea { ...this.props }
714 title={ __( 'Background Gradient', 'generateblocks' ) }
715 initialOpen={ false }
716 icon={ getIcon( 'gradients' ) }
717 className={ 'gblocks-panel-label' }
718 id={ 'buttonBackgroundGradient' }
719 state={ this.state }
720 >
721 { 'Desktop' === this.getDeviceType() &&
722 <GradientControl { ...this.props }
723 attrGradient={ 'gradient' }
724 attrGradientDirection={ 'gradientDirection' }
725 attrGradientColorOne={ 'gradientColorOne' }
726 attrGradientColorOneOpacity={ 'gradientColorOneOpacity' }
727 attrGradientColorStopOne={ 'gradientColorStopOne' }
728 attrGradientColorTwo={ 'gradientColorTwo' }
729 attrGradientColorTwoOpacity={ 'gradientColorTwoOpacity' }
730 attrGradientColorStopTwo={ 'gradientColorStopTwo' }
731 defaultColorOne={ generateBlocksDefaults.button.gradientColorOne }
732 defaultColorTwo={ generateBlocksDefaults.button.gradientColorTwo }
733 />
734 }
735
736 { applyFilters( 'generateblocks.editor.controls', '', 'buttonBackgroundGradient', this.props, this.state ) }
737 </PanelArea>
738
739 <PanelArea { ...this.props }
740 title={ __( 'Icon', 'generateblocks' ) }
741 initialOpen={ false }
742 icon={ getIcon( 'icons' ) }
743 className={ 'gblocks-panel-label' }
744 id={ 'buttonIcon' }
745 state={ this.state }
746 showPanel={ 'Desktop' === this.getDeviceType() || !! icon ? true : false }
747 >
748
749 { 'Desktop' === this.getDeviceType() &&
750 <IconPicker { ...this.props }
751 attrIcon={ 'icon' }
752 attrIconLocation={ 'iconLocation' }
753 attrRemoveText={ 'removeText' }
754 locationOptions={ [
755 { label: __( 'Left', 'generateblocks' ), value: 'left' },
756 { label: __( 'Right', 'generateblocks' ), value: 'right' },
757 ] }
758 />
759 }
760
761 { 'Desktop' === this.getDeviceType() && !! icon && (
762 <Fragment>
763 { ! removeText &&
764 <Fragment>
765 <DimensionsControl { ...this.props }
766 device={ this.getDeviceType() }
767 type={ 'padding' }
768 label={ __( 'Padding', 'generateblocks' ) }
769 attrTop={ 'iconPaddingTop' }
770 attrRight={ 'iconPaddingRight' }
771 attrBottom={ 'iconPaddingBottom' }
772 attrLeft={ 'iconPaddingLeft' }
773 attrUnit={ 'iconPaddingUnit' }
774 attrSyncUnits={ 'iconPaddingSyncUnits' }
775 defaults={ generateBlocksDefaults.button }
776 units={ [ 'px', 'em', '%' ] }
777 />
778 </Fragment>
779 }
780
781 <UnitPicker
782 label={ __( 'Icon Size', 'generateblocks' ) }
783 value={ iconSizeUnit }
784 units={ [ 'px', 'em' ] }
785 onClick={ ( value ) => {
786 setAttributes( {
787 iconSizeUnit: value,
788 } );
789 } }
790 />
791
792 <div className="components-base-control components-gblocks-typography-control__inputs">
793 <TextControl
794 type={ 'number' }
795 value={ iconSize || '' }
796 step={ 'em' === iconSizeUnit ? .1 : 1 }
797 onChange={ ( value ) => {
798 setAttributes( {
799 iconSize: value,
800 } );
801 } }
802 onBlur={ () => {
803 setAttributes( {
804 iconSize: parseFloat( iconSize ),
805 } );
806 } }
807 onClick={ ( e ) => {
808 // Make sure onBlur fires in Firefox.
809 e.currentTarget.focus();
810 } }
811 />
812
813 <Button
814 isSmall
815 isSecondary
816 className="components-gblocks-default-number"
817 onClick={ () => {
818 setAttributes( {
819 iconSize: generateBlocksDefaults.button.iconSize,
820 } );
821 } }
822 >
823 { __( 'Reset', 'generateblocks' ) }
824 </Button>
825 </div>
826 </Fragment>
827 ) }
828
829 { 'Tablet' === this.getDeviceType() && !! icon &&
830 <Fragment>
831 { ! removeText &&
832 <Fragment>
833 <DimensionsControl { ...this.props }
834 device={ this.getDeviceType() }
835 type={ 'padding' }
836 label={ __( 'Padding', 'generateblocks' ) }
837 attrTop={ 'iconPaddingTopTablet' }
838 attrRight={ 'iconPaddingRightTablet' }
839 attrBottom={ 'iconPaddingBottomTablet' }
840 attrLeft={ 'iconPaddingLeftTablet' }
841 attrUnit={ 'iconPaddingUnit' }
842 attrSyncUnits={ 'iconPaddingSyncUnits' }
843 defaults={ generateBlocksDefaults.button }
844 units={ [ 'px', 'em', '%' ] }
845 />
846 </Fragment>
847 }
848
849 <UnitPicker
850 label={ __( 'Icon Size', 'generateblocks' ) }
851 value={ iconSizeUnit }
852 units={ [ 'px', 'em' ] }
853 onClick={ ( value ) => {
854 setAttributes( {
855 iconSizeUnit: value,
856 } );
857 } }
858 />
859
860 <div className="components-base-control components-gblocks-typography-control__inputs">
861 <TextControl
862 type={ 'number' }
863 value={ iconSizeTablet || '' }
864 step={ 'em' === iconSizeUnit ? .1 : 1 }
865 placeholder="1"
866 onChange={ ( value ) => {
867 setAttributes( {
868 iconSizeTablet: value,
869 } );
870 } }
871 onBlur={ () => {
872 setAttributes( {
873 iconSizeTablet: parseFloat( iconSizeTablet ),
874 } );
875 } }
876 onClick={ ( e ) => {
877 // Make sure onBlur fires in Firefox.
878 e.currentTarget.focus();
879 } }
880 />
881
882 <Button
883 isSmall
884 isSecondary
885 className="components-gblocks-default-number"
886 onClick={ () => {
887 setAttributes( {
888 iconSizeTablet: generateBlocksDefaults.button.iconSizeTablet,
889 } );
890 } }
891 >
892 { __( 'Reset', 'generateblocks' ) }
893 </Button>
894 </div>
895 </Fragment>
896 }
897
898 { 'Mobile' === this.getDeviceType() && !! icon && (
899 <Fragment>
900 { ! removeText &&
901 <Fragment>
902 <DimensionsControl { ...this.props }
903 device={ this.getDeviceType() }
904 type={ 'padding' }
905 label={ __( 'Padding', 'generateblocks' ) }
906 attrTop={ 'iconPaddingTopMobile' }
907 attrRight={ 'iconPaddingRightMobile' }
908 attrBottom={ 'iconPaddingBottomMobile' }
909 attrLeft={ 'iconPaddingLeftMobile' }
910 attrUnit={ 'iconPaddingUnit' }
911 attrSyncUnits={ 'iconPaddingSyncUnits' }
912 defaults={ generateBlocksDefaults.button }
913 units={ [ 'px', 'em', '%' ] }
914 />
915 </Fragment>
916 }
917
918 <UnitPicker
919 label={ __( 'Icon Size', 'generateblocks' ) }
920 value={ iconSizeUnit }
921 units={ [ 'px', 'em' ] }
922 onClick={ ( value ) => {
923 setAttributes( {
924 iconSizeUnit: value,
925 } );
926 } }
927 />
928
929 <div className="components-base-control components-gblocks-typography-control__inputs">
930 <TextControl
931 type={ 'number' }
932 value={ iconSizeMobile || '' }
933 step={ 'em' === iconSizeUnit ? .1 : 1 }
934 placeholder="1"
935 onChange={ ( value ) => {
936 setAttributes( {
937 iconSizeMobile: value,
938 } );
939 } }
940 onBlur={ () => {
941 setAttributes( {
942 iconSizeMobile: parseFloat( iconSizeMobile ),
943 } );
944 } }
945 onClick={ ( e ) => {
946 // Make sure onBlur fires in Firefox.
947 e.currentTarget.focus();
948 } }
949 />
950
951 <Button
952 isSmall
953 isSecondary
954 className="components-gblocks-default-number"
955 onClick={ () => {
956 setAttributes( {
957 iconSizeMobile: generateBlocksDefaults.button.iconSizeMobile,
958 } );
959 } }
960 >
961 { __( 'Reset', 'generateblocks' ) }
962 </Button>
963 </div>
964 </Fragment>
965 ) }
966
967 { applyFilters( 'generateblocks.editor.controls', '', 'buttonIcon', this.props, this.state ) }
968 </PanelArea>
969
970 <PanelArea { ...this.props }
971 title={ __( 'Documentation', 'generateblocks' ) }
972 icon={ getIcon( 'documentation' ) }
973 initialOpen={ false }
974 className={ 'gblocks-panel-label' }
975 id={ 'buttonDocumentation' }
976 state={ this.state }
977 >
978 <p>{ __( 'Need help with this block?', 'generateblocks' ) }</p>
979 <a href="https://docs.generateblocks.com/collection/buttons/" target="_blank" rel="noreferrer noopener">{ __( 'Visit our documentation', 'generateblocks' ) }</a>
980
981 { applyFilters( 'generateblocks.editor.controls', '', 'buttonDocumentation', this.props, this.state ) }
982 </PanelArea>
983 </InspectorControls>
984
985 <InspectorAdvancedControls>
986 <TextControl
987 label={ __( 'HTML Anchor', 'generateblocks' ) }
988 help={ __( 'Anchors lets you link directly to a section on a page.', 'generateblocks' ) }
989 value={ anchor || '' }
990 onChange={ ( nextValue ) => {
991 nextValue = nextValue.replace( ANCHOR_REGEX, '-' );
992 setAttributes( {
993 anchor: nextValue,
994 } );
995 } } />
996
997 <TextControl
998 label={ __( 'ARIA Label', 'generateblocks' ) }
999 help={ __( 'Helpful to people using screen readers.', 'generateblocks' ) }
1000 value={ ariaLabel }
1001 onChange={ ( value ) => {
1002 setAttributes( {
1003 ariaLabel: value,
1004 } );
1005 } }
1006 />
1007 </InspectorAdvancedControls>
1008
1009 <MainCSS { ...this.props } />
1010
1011 { this.props.deviceType &&
1012 <Fragment>
1013 { 'Desktop' === this.props.deviceType &&
1014 <DesktopCSS { ...this.props } />
1015 }
1016
1017 { ( 'Tablet' === this.props.deviceType || 'Mobile' === this.props.deviceType ) &&
1018 <TabletCSS { ...this.props } />
1019 }
1020
1021 { 'Tablet' === this.props.deviceType &&
1022 <TabletOnlyCSS { ...this.props } />
1023 }
1024
1025 { 'Mobile' === this.props.deviceType &&
1026 <MobileCSS { ...this.props } />
1027 }
1028 </Fragment>
1029 }
1030
1031 { fontFamily && googleFont &&
1032 <link
1033 rel="stylesheet"
1034 href={ 'https://fonts.googleapis.com/css?family=' + fontFamily.replace( / /g, '+' ) + googleFontsAttr }
1035 />
1036 }
1037
1038 <Element
1039 tagName={ url ? 'a' : 'span' }
1040 htmlAttrs={ htmlAttributes }
1041 >
1042 { !! icon &&
1043 <Fragment>
1044 { 'left' === iconLocation &&
1045 <span
1046 className="gb-icon"
1047 dangerouslySetInnerHTML={ { __html: icon } }
1048 />
1049 }
1050
1051 { ! removeText &&
1052 <span className={ 'gb-button-text' }>
1053 <RichText
1054 placeholder={ __( 'Add text…', 'generateblocks' ) }
1055 value={ text }
1056 onChange={ ( value ) => setAttributes( { text: value } ) }
1057 allowedFormats={ applyFilters( 'generateblocks.editor.buttonDisableFormatting', false, this.props ) ? [] : [ 'core/bold', 'core/italic', 'core/strikethrough' ] }
1058 isSelected={ isSelected }
1059 keepPlaceholderOnFocus
1060 />
1061 </span>
1062 }
1063
1064 { 'right' === iconLocation &&
1065 <span
1066 className="gb-icon"
1067 dangerouslySetInnerHTML={ { __html: icon } }
1068 />
1069 }
1070 </Fragment>
1071 }
1072
1073 { ! icon && ! removeText &&
1074 <RichText
1075 placeholder={ __( 'Add text…', 'generateblocks' ) }
1076 value={ text }
1077 onChange={ ( value ) => setAttributes( { text: value } ) }
1078 allowedFormats={ applyFilters( 'generateblocks.editor.buttonDisableFormatting', false, this.props ) ? [] : [ 'core/bold', 'core/italic', 'core/strikethrough' ] }
1079 isSelected={ isSelected }
1080 keepPlaceholderOnFocus
1081 />
1082 }
1083 </Element>
1084 { isSelected &&
1085 <URLInput
1086 url={ url }
1087 target={ target }
1088 relNoFollow={ relNoFollow }
1089 relSponsored={ relSponsored }
1090 onChange={ ( data ) => {
1091 setAttributes( data );
1092
1093 if ( '' !== data.url ) {
1094 setAttributes( {
1095 hasUrl: true,
1096 } );
1097 } else {
1098 setAttributes( {
1099 hasUrl: false,
1100 } );
1101 }
1102 } }
1103 autoFocus={ false } // eslint-disable-line jsx-a11y/no-autofocus
1104 className="gblocks-component-url-input-float"
1105 />
1106 }
1107 </Fragment>
1108 );
1109 }
1110 }
1111
1112 export default compose( [
1113 withDispatch( ( dispatch ) => ( {
1114 setDeviceType( type ) {
1115 const {
1116 __experimentalSetPreviewDeviceType: setPreviewDeviceType,
1117 } = dispatch( 'core/edit-post' );
1118
1119 if ( ! setPreviewDeviceType ) {
1120 return;
1121 }
1122
1123 setPreviewDeviceType( type );
1124 },
1125 } ) ),
1126 withSelect( ( select ) => {
1127 const {
1128 __experimentalGetPreviewDeviceType: getPreviewDeviceType,
1129 } = select( 'core/edit-post' );
1130
1131 if ( ! getPreviewDeviceType ) {
1132 return {
1133 deviceType: null,
1134 };
1135 }
1136
1137 return {
1138 deviceType: getPreviewDeviceType(),
1139 };
1140 } ),
1141 ] )( GenerateBlockButton );
1142