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