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 / grid / edit.js
generateblocks / src / blocks / grid 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
edit.js
914 lines
1 /**
2 * Block: Grid
3 */
4
5 import classnames from 'classnames';
6 import getIcon from '../../utils/get-icon';
7 import ResponsiveTabs from '../../components/responsive-tabs';
8 import UnitPicker from '../../components/unit-picker';
9 import MainCSS from './css/main.js';
10 import DesktopCSS from './css/desktop.js';
11 import TabletCSS from './css/tablet.js';
12 import TabletOnlyCSS from './css/tablet-only.js';
13 import MobileCSS from './css/mobile.js';
14 import PanelArea from '../../components/panel-area/';
15
16 import {
17 __,
18 } from '@wordpress/i18n';
19
20 import {
21 TextControl,
22 SelectControl,
23 Placeholder,
24 Button,
25 ToolbarGroup,
26 ToolbarButton,
27 } from '@wordpress/components';
28
29 import {
30 Fragment,
31 Component,
32 } from '@wordpress/element';
33
34 import {
35 InspectorControls,
36 InnerBlocks,
37 BlockControls,
38 InspectorAdvancedControls,
39 } from '@wordpress/block-editor';
40
41 import {
42 createBlock,
43 } from '@wordpress/blocks';
44
45 import {
46 applyFilters,
47 } from '@wordpress/hooks';
48
49 import {
50 withSelect,
51 withDispatch,
52 } from '@wordpress/data';
53
54 import {
55 compose,
56 } from '@wordpress/compose';
57
58 /**
59 * Regular expression matching invalid anchor characters for replacement.
60 *
61 * @type {RegExp}
62 */
63 const ANCHOR_REGEX = /[\s#]/g;
64
65 const gbGridIds = [];
66
67 class GenerateBlockGridContainer extends Component {
68 constructor() {
69 super( ...arguments );
70
71 this.state = {
72 selectedLayout: false,
73 selectedDevice: 'Desktop',
74 };
75
76 this.onLayoutSelect = this.onLayoutSelect.bind( this );
77 this.getColumnsFromLayout = this.getColumnsFromLayout.bind( this );
78 this.getLayoutsSelector = this.getLayoutsSelector.bind( this );
79 this.getDeviceType = this.getDeviceType.bind( this );
80 this.setDeviceType = this.setDeviceType.bind( this );
81 }
82
83 componentDidMount() {
84 const id = this.props.clientId.substr( 2, 9 ).replace( '-', '' );
85
86 // We don't want to ever regenerate unique IDs if they're a global style.
87 const isGlobalStyle = 'undefined' !== typeof this.props.attributes.isGlobalStyle && this.props.attributes.isGlobalStyle;
88
89 if ( ! this.props.attributes.uniqueId ) {
90 this.props.setAttributes( {
91 uniqueId: id,
92 } );
93
94 gbGridIds.push( id );
95 } else if ( gbGridIds.includes( this.props.attributes.uniqueId ) && ! isGlobalStyle ) {
96 this.props.setAttributes( {
97 uniqueId: id,
98 } );
99
100 gbGridIds.push( id );
101 } else {
102 gbGridIds.push( this.props.attributes.uniqueId );
103 }
104
105 // This block used to be static. Set it to dynamic by default from now on.
106 if ( 'undefined' === typeof this.props.attributes.isDynamic || ! this.props.attributes.isDynamic ) {
107 this.props.setAttributes( {
108 isDynamic: true,
109 } );
110 }
111 }
112
113 componentDidUpdate() {
114 const {
115 attributes,
116 setAttributes,
117 clientId,
118 } = this.props;
119
120 let {
121 columns,
122 } = attributes;
123
124 if ( this.state.selectedLayout ) {
125 const columnsData = this.getColumnsFromLayout( this.state.selectedLayout );
126
127 columnsData.forEach( ( colAttrs ) => {
128 wp.data.dispatch( 'core/block-editor' ).insertBlocks( createBlock( 'generateblocks/container', colAttrs ), undefined, clientId, false );
129 } );
130
131 columns = columnsData.length;
132
133 setAttributes( {
134 columns,
135 } );
136
137 this.setState( {
138 selectedLayout: false,
139 } );
140 } else {
141 const parentBlock = wp.data.select( 'core/block-editor' ).getBlocksByClientId( clientId )[ 0 ];
142
143 if ( parentBlock ) {
144 const childBlocks = parentBlock.innerBlocks;
145 columns = childBlocks.length;
146
147 setAttributes( {
148 columns,
149 } );
150 }
151 }
152 }
153
154 /**
155 * Get columns sizes array from layout string
156 *
157 * @param {string} layout - layout data. Example: `3-6-3`
158 *
159 * @return {Array}.
160 */
161 getColumnsFromLayout( layout ) {
162 const result = [];
163 const columnsData = layout.split( '-' );
164
165 let i = 0;
166 columnsData.forEach( () => {
167 const colAttrs = {
168 isGrid: true,
169 gridId: this.props.attributes.uniqueId,
170 paddingTop: generateBlocksStyling.container.gridItemPaddingTop || '0',
171 paddingRight: generateBlocksStyling.container.gridItemPaddingRight || '0',
172 paddingBottom: generateBlocksStyling.container.gridItemPaddingBottom || '0',
173 paddingLeft: generateBlocksStyling.container.gridItemPaddingLeft || '0',
174 };
175
176 colAttrs.width = Number( columnsData[ i ] );
177 i++;
178
179 result.push( colAttrs );
180 } );
181
182 return result;
183 }
184
185 /**
186 * Layouts selector when no columns selected.
187 *
188 * @return {JSX}.
189 */
190 getLayoutsSelector() {
191 const layouts = [
192 '100',
193 '50-50',
194 '33.33-33.33-33.33',
195 '25-25-25-25',
196
197 '25-75',
198 '75-25',
199 '25-25-50',
200 '25-50-25',
201
202 '50-25-25',
203 '20-60-20',
204 '20-20-20-20-20',
205 '16-16-16-16-16-16',
206 ];
207
208 return (
209 <Placeholder
210 label={ __( 'Grid', 'generateblocks' ) }
211 instructions={ __( 'Select one layout to get started.', 'generateblocks' ) }
212 className="gb-select-layout"
213 >
214 <div className="gb-grid-wrapper-layout-preview">
215 { layouts.map( ( layout ) => {
216 const columnsData = this.getColumnsFromLayout( layout );
217
218 return (
219 <button
220 key={ `layout-${ layout }` }
221 className="gb-grid-wrapper-layout-preview-btn"
222 onClick={ () => this.onLayoutSelect( layout ) }
223 >
224 { columnsData.map( ( colAttrs, i ) => {
225 return (
226 <div
227 key={ `layout-${ layout }-col-${ i }` }
228 className={ classnames( 'gb-col', `gb-col-${ colAttrs.width }` ) }
229 />
230 );
231 } ) }
232 </button>
233 );
234 } ) }
235 </div>
236 </Placeholder>
237 );
238 }
239
240 /**
241 * Select predefined layout.
242 *
243 * @param {string} layout layout string.
244 */
245 onLayoutSelect( layout ) {
246 this.setState( {
247 selectedLayout: layout,
248 } );
249 }
250
251 getDeviceType() {
252 let deviceType = this.props.deviceType ? this.props.deviceType : this.state.selectedDevice;
253
254 if ( ! generateBlocksInfo.syncResponsivePreviews ) {
255 deviceType = this.state.selectedDevice;
256 }
257
258 return deviceType;
259 }
260
261 setDeviceType( deviceType ) {
262 if ( generateBlocksInfo.syncResponsivePreviews && this.props.deviceType ) {
263 this.props.setDeviceType( deviceType );
264 this.setState( { selectedDevice: deviceType } );
265 } else {
266 this.setState( { selectedDevice: deviceType } );
267 }
268 }
269
270 render() {
271 const {
272 attributes,
273 setAttributes,
274 clientId,
275 } = this.props;
276
277 const {
278 uniqueId,
279 className,
280 anchor,
281 columns,
282 horizontalGap,
283 verticalGap,
284 verticalAlignment,
285 horizontalGapTablet,
286 verticalGapTablet,
287 verticalAlignmentTablet,
288 horizontalGapMobile,
289 verticalGapMobile,
290 verticalAlignmentMobile,
291 horizontalAlignment,
292 horizontalAlignmentTablet,
293 horizontalAlignmentMobile,
294 } = attributes;
295
296 const usingGlobalStyle = 'undefined' !== typeof attributes.useGlobalStyle && attributes.useGlobalStyle && 'undefined' !== typeof attributes.globalStyleId && attributes.globalStyleId;
297 let horizontalGapValue = horizontalGap || 0 === horizontalGap ? horizontalGap : '';
298
299 if ( usingGlobalStyle ) {
300 if ( generateBlocksDefaults.gridContainer.horizontalGap === horizontalGapValue ) {
301 horizontalGapValue = '';
302 }
303 }
304
305 const horizontalGapPlaceholderTablet = horizontalGapValue,
306 verticalGapPlaceholderTablet = verticalGap || 0 === verticalGap ? verticalGap : '';
307
308 let horizontalGapPlaceholderMobile = horizontalGapValue,
309 verticalGapPlaceholderMobile = verticalGap || 0 === verticalGap ? verticalGap : '';
310
311 if ( horizontalGapTablet ) {
312 horizontalGapPlaceholderMobile = horizontalGapTablet;
313 }
314
315 if ( verticalGapTablet ) {
316 verticalGapPlaceholderMobile = verticalGapTablet;
317 }
318
319 let htmlAttributes = {
320 className: classnames( {
321 'gb-grid-wrapper': true,
322 [ `gb-grid-wrapper-${ uniqueId }` ]: true,
323 [ `${ className }` ]: undefined !== className,
324 } ),
325 id: anchor ? anchor : null,
326 };
327
328 htmlAttributes = applyFilters( 'generateblocks.frontend.htmlAttributes', htmlAttributes, 'generateblocks/grid', attributes );
329
330 return (
331 <Fragment>
332 { ( columns > 0 || this.state.selectedLayout ) &&
333 <BlockControls>
334 <ToolbarGroup>
335 <ToolbarButton
336 className="gblocks-block-control-icon gblocks-add-grid-item"
337 icon={ getIcon( 'addContainer' ) }
338 label={ __( 'Add Grid Item', 'generateblocks' ) }
339 onClick={ () => {
340 wp.data.dispatch( 'core/block-editor' ).insertBlocks(
341 createBlock( 'generateblocks/container', {
342 isGrid: true,
343 gridId: uniqueId,
344 paddingTop: generateBlocksStyling.container.gridItemPaddingTop || '0',
345 paddingRight: generateBlocksStyling.container.gridItemPaddingRight || '0',
346 paddingBottom: generateBlocksStyling.container.gridItemPaddingBottom || '0',
347 paddingLeft: generateBlocksStyling.container.gridItemPaddingLeft || '0',
348 } ),
349 undefined,
350 clientId
351 );
352 } }
353 showTooltip
354 />
355 </ToolbarGroup>
356 </BlockControls>
357 }
358
359 <InspectorControls>
360 <ResponsiveTabs { ...this.props }
361 selectedDevice={ this.getDeviceType() }
362 onClick={ ( device ) => {
363 this.setDeviceType( device );
364 } }
365 />
366
367 <PanelArea { ...this.props }
368 id={ 'gridLayout' }
369 state={ this.state }
370 >
371 { 'Desktop' === this.getDeviceType() && (
372 <Fragment>
373 <UnitPicker
374 label={ __( 'Horizontal Gap', 'generateblocks' ) }
375 value={ 'px' }
376 units={ [ 'px' ] }
377 onClick={ () => {
378 return false;
379 } }
380 />
381
382 <div className="components-base-control components-gblocks-typography-control__inputs">
383 <TextControl
384 type={ 'number' }
385 value={ horizontalGapValue }
386 min="0"
387 onChange={ ( value ) => {
388 // No hyphens allowed here.
389 value = value.toString().replace( /-/g, '' );
390
391 setAttributes( {
392 horizontalGap: value,
393 } );
394 } }
395 onBlur={ () => {
396 if ( ! usingGlobalStyle && ! horizontalGap && generateBlocksDefaults.gridContainer.horizontalGap ) {
397 // If we have no value and a default exists, set to 0 to prevent default from coming back.
398 setAttributes( {
399 horizontalGap: 0,
400 } );
401 } else if ( '' !== horizontalGap ) {
402 setAttributes( {
403 horizontalGap: parseFloat( horizontalGap ),
404 } );
405 }
406 } }
407 onClick={ ( e ) => {
408 // Make sure onBlur fires in Firefox.
409 e.currentTarget.focus();
410 } }
411 />
412
413 <Button
414 isSmall
415 isSecondary
416 className="components-gblocks-default-number"
417 onClick={ () => {
418 setAttributes( {
419 horizontalGap: generateBlocksDefaults.gridContainer.horizontalGap,
420 } );
421 } }
422 >
423 { __( 'Reset', 'generateblocks' ) }
424 </Button>
425 </div>
426
427 <UnitPicker
428 label={ __( 'Vertical Gap', 'generateblocks' ) }
429 value={ 'px' }
430 units={ [ 'px' ] }
431 onClick={ () => {
432 return false;
433 } }
434 />
435
436 <div className="components-base-control components-gblocks-typography-control__inputs">
437 <TextControl
438 type={ 'number' }
439 value={ verticalGap || 0 === verticalGap ? verticalGap : '' }
440 min="0"
441 onChange={ ( value ) => {
442 // No negative values allowed here.
443 value = value.toString().replace( /-/g, '' );
444
445 setAttributes( {
446 verticalGap: value,
447 } );
448 } }
449 onBlur={ () => {
450 if ( ! usingGlobalStyle && ! verticalGap && generateBlocksDefaults.gridContainer.verticalGap ) {
451 // If we have no value and a default exists, set to 0 to prevent default from coming back.
452 setAttributes( {
453 verticalGap: 0,
454 } );
455 } else if ( '' !== verticalGap ) {
456 setAttributes( {
457 verticalGap: parseFloat( verticalGap ),
458 } );
459 }
460 } }
461 onClick={ ( e ) => {
462 // Make sure onBlur fires in Firefox.
463 e.currentTarget.focus();
464 } }
465 />
466
467 <Button
468 isSmall
469 isSecondary
470 className="components-gblocks-default-number"
471 onClick={ () => {
472 setAttributes( {
473 verticalGap: generateBlocksDefaults.gridContainer.verticalGap,
474 } );
475 } }
476 >
477 { __( 'Reset', 'generateblocks' ) }
478 </Button>
479 </div>
480
481 <SelectControl
482 label={ __( 'Vertical Alignment', 'generateblocks' ) }
483 value={ verticalAlignment }
484 help={ __( 'Align grid items. Removes same height columns and overrides grid item content alignment.', 'generateblocks' ) }
485 options={ [
486 { label: __( 'Default', 'generateblocks' ), value: '' },
487 { label: __( 'Top', 'generateblocks' ), value: 'flex-start' },
488 { label: __( 'Center', 'generateblocks' ), value: 'center' },
489 { label: __( 'Bottom', 'generateblocks' ), value: 'flex-end' },
490 ] }
491 onChange={ ( value ) => {
492 setAttributes( {
493 verticalAlignment: value,
494 } );
495 } }
496 />
497
498 <SelectControl
499 label={ __( 'Horizontal Alignment', 'generateblocks' ) }
500 value={ horizontalAlignment }
501 options={ [
502 { label: __( 'Default', 'generateblocks' ), value: '' },
503 { label: __( 'Left', 'generateblocks' ), value: 'flex-start' },
504 { label: __( 'Center', 'generateblocks' ), value: 'center' },
505 { label: __( 'Right', 'generateblocks' ), value: 'flex-end' },
506 ] }
507 onChange={ ( value ) => {
508 setAttributes( {
509 horizontalAlignment: value,
510 } );
511 } }
512 />
513 </Fragment>
514 ) }
515
516 { 'Tablet' === this.getDeviceType() && (
517 <Fragment>
518 <UnitPicker
519 label={ __( 'Horizontal Gap', 'generateblocks' ) }
520 value={ 'px' }
521 units={ [ 'px' ] }
522 onClick={ () => {
523 return false;
524 } }
525 />
526
527 <div className="components-base-control components-gblocks-typography-control__inputs">
528 <TextControl
529 type={ 'number' }
530 value={ horizontalGapTablet || 0 === horizontalGapTablet ? horizontalGapTablet : '' }
531 min="0"
532 placeholder={ horizontalGapPlaceholderTablet }
533 onChange={ ( value ) => {
534 // No negative values allowed here.
535 value = value.toString().replace( /-/g, '' );
536
537 setAttributes( {
538 horizontalGapTablet: value,
539 } );
540 } }
541 onBlur={ () => {
542 if ( ! usingGlobalStyle && ! horizontalGapTablet && generateBlocksDefaults.gridContainer.horizontalGapTablet ) {
543 // If we have no value and a default exists, set to 0 to prevent default from coming back.
544 setAttributes( {
545 horizontalGapTablet: 0,
546 } );
547 } else if ( '' !== horizontalGapTablet ) {
548 setAttributes( {
549 horizontalGapTablet: parseFloat( horizontalGapTablet ),
550 } );
551 }
552 } }
553 onClick={ ( e ) => {
554 // Make sure onBlur fires in Firefox.
555 e.currentTarget.focus();
556 } }
557 />
558
559 <Button
560 isSmall
561 isSecondary
562 className="components-gblocks-default-number"
563 onClick={ () => {
564 setAttributes( {
565 horizontalGapTablet: generateBlocksDefaults.gridContainer.horizontalGapTablet,
566 } );
567 } }
568 >
569 { __( 'Reset', 'generateblocks' ) }
570 </Button>
571 </div>
572
573 <UnitPicker
574 label={ __( 'Vertical Gap', 'generateblocks' ) }
575 value={ 'px' }
576 units={ [ 'px' ] }
577 onClick={ () => {
578 return false;
579 } }
580 />
581
582 <div className="components-base-control components-gblocks-typography-control__inputs">
583 <TextControl
584 type={ 'number' }
585 value={ verticalGapTablet || 0 === verticalGapTablet ? verticalGapTablet : '' }
586 min="0"
587 placeholder={ verticalGapPlaceholderTablet }
588 onChange={ ( value ) => {
589 // No negative values allowed here.
590 value = value.toString().replace( /-/g, '' );
591
592 setAttributes( {
593 verticalGapTablet: value,
594 } );
595 } }
596 onBlur={ () => {
597 if ( ! usingGlobalStyle && ! verticalGapTablet && generateBlocksDefaults.gridContainer.verticalGapTablet ) {
598 // If we have no value and a default exists, set to 0 to prevent default from coming back.
599 setAttributes( {
600 verticalGapTablet: 0,
601 } );
602 } else if ( '' !== verticalGapTablet ) {
603 setAttributes( {
604 verticalGapTablet: parseFloat( verticalGapTablet ),
605 } );
606 }
607 } }
608 onClick={ ( e ) => {
609 // Make sure onBlur fires in Firefox.
610 e.currentTarget.focus();
611 } }
612 />
613
614 <Button
615 isSmall
616 isSecondary
617 className="components-gblocks-default-number"
618 onClick={ () => {
619 setAttributes( {
620 verticalGapTablet: generateBlocksDefaults.gridContainer.verticalGapTablet,
621 } );
622 } }
623 >
624 { __( 'Reset', 'generateblocks' ) }
625 </Button>
626 </div>
627
628 <SelectControl
629 label={ __( 'Vertical Alignment', 'generateblocks' ) }
630 help={ __( 'Align grid items. Removes same height columns and overrides grid item content alignment.', 'generateblocks' ) }
631 value={ verticalAlignmentTablet }
632 options={ [
633 { label: __( 'Inherit', 'generateblocks' ), value: 'inherit' },
634 { label: __( 'Default', 'generateblocks' ), value: '' },
635 { label: __( 'Top', 'generateblocks' ), value: 'flex-start' },
636 { label: __( 'Center', 'generateblocks' ), value: 'center' },
637 { label: __( 'Bottom', 'generateblocks' ), value: 'flex-end' },
638 ] }
639 onChange={ ( value ) => {
640 setAttributes( {
641 verticalAlignmentTablet: value,
642 } );
643 } }
644 />
645
646 <SelectControl
647 label={ __( 'Horizontal Alignment', 'generateblocks' ) }
648 value={ horizontalAlignmentTablet }
649 options={ [
650 { label: __( 'Inherit', 'generateblocks' ), value: 'inherit' },
651 { label: __( 'Default', 'generateblocks' ), value: '' },
652 { label: __( 'Left', 'generateblocks' ), value: 'flex-start' },
653 { label: __( 'Center', 'generateblocks' ), value: 'center' },
654 { label: __( 'Right', 'generateblocks' ), value: 'flex-end' },
655 ] }
656 onChange={ ( value ) => {
657 setAttributes( {
658 horizontalAlignmentTablet: value,
659 } );
660 } }
661 />
662 </Fragment>
663 ) }
664
665 { 'Mobile' === this.getDeviceType() && (
666 <Fragment>
667 <UnitPicker
668 label={ __( 'Horizontal Gap', 'generateblocks' ) }
669 value={ 'px' }
670 units={ [ 'px' ] }
671 onClick={ () => {
672 return false;
673 } }
674 />
675
676 <div className="components-base-control components-gblocks-typography-control__inputs">
677 <TextControl
678 type={ 'number' }
679 value={ horizontalGapMobile || 0 === horizontalGapMobile ? horizontalGapMobile : '' }
680 min="0"
681 placeholder={ horizontalGapPlaceholderMobile }
682 onChange={ ( value ) => {
683 // No negative values allowed here.
684 value = value.toString().replace( /-/g, '' );
685
686 setAttributes( {
687 horizontalGapMobile: value,
688 } );
689 } }
690 onBlur={ () => {
691 if ( ! usingGlobalStyle && ! horizontalGapMobile && generateBlocksDefaults.gridContainer.horizontalGapMobile ) {
692 // If we have no value and a default exists, set to 0 to prevent default from coming back.
693 setAttributes( {
694 horizontalGapMobile: 0,
695 } );
696 } else if ( '' !== horizontalGapMobile ) {
697 setAttributes( {
698 horizontalGapMobile: parseFloat( horizontalGapMobile ),
699 } );
700 }
701 } }
702 onClick={ ( e ) => {
703 // Make sure onBlur fires in Firefox.
704 e.currentTarget.focus();
705 } }
706 />
707
708 <Button
709 isSmall
710 isSecondary
711 className="components-gblocks-default-number"
712 onClick={ () => {
713 setAttributes( {
714 horizontalGapMobile: generateBlocksDefaults.gridContainer.horizontalGapMobile,
715 } );
716 } }
717 >
718 { __( 'Reset', 'generateblocks' ) }
719 </Button>
720 </div>
721
722 <UnitPicker
723 label={ __( 'Vertical Gap', 'generateblocks' ) }
724 value={ 'px' }
725 units={ [ 'px' ] }
726 onClick={ () => {
727 return false;
728 } }
729 />
730
731 <div className="components-base-control components-gblocks-typography-control__inputs">
732 <TextControl
733 type={ 'number' }
734 value={ verticalGapMobile || 0 === verticalGapMobile ? verticalGapMobile : '' }
735 min="0"
736 placeholder={ verticalGapPlaceholderMobile }
737 onChange={ ( value ) => {
738 // No negative values allowed here.
739 value = value.toString().replace( /-/g, '' );
740
741 setAttributes( {
742 verticalGapMobile: value,
743 } );
744 } }
745 onBlur={ () => {
746 if ( ! usingGlobalStyle && ! verticalGapMobile && generateBlocksDefaults.gridContainer.verticalGapMobile ) {
747 // If we have no value and a default exists, set to 0 to prevent default from coming back.
748 setAttributes( {
749 verticalGapMobile: 0,
750 } );
751 } else if ( '' !== verticalGapMobile ) {
752 setAttributes( {
753 verticalGapMobile: parseFloat( verticalGapMobile ),
754 } );
755 }
756 } }
757 onClick={ ( e ) => {
758 // Make sure onBlur fires in Firefox.
759 e.currentTarget.focus();
760 } }
761 />
762
763 <Button
764 isSmall
765 isSecondary
766 className="components-gblocks-default-number"
767 onClick={ () => {
768 setAttributes( {
769 verticalGapMobile: generateBlocksDefaults.gridContainer.verticalGapMobile,
770 } );
771 } }
772 >
773 { __( 'Reset', 'generateblocks' ) }
774 </Button>
775 </div>
776
777 <SelectControl
778 label={ __( 'Vertical Alignment', 'generateblocks' ) }
779 help={ __( 'Align grid items. Removes same height columns and overrides grid item content alignment.', 'generateblocks' ) }
780 value={ verticalAlignmentMobile }
781 options={ [
782 { label: __( 'Inherit', 'generateblocks' ), value: 'inherit' },
783 { label: __( 'Default', 'generateblocks' ), value: '' },
784 { label: __( 'Top', 'generateblocks' ), value: 'flex-start' },
785 { label: __( 'Center', 'generateblocks' ), value: 'center' },
786 { label: __( 'Bottom', 'generateblocks' ), value: 'flex-end' },
787 ] }
788 onChange={ ( value ) => {
789 setAttributes( {
790 verticalAlignmentMobile: value,
791 } );
792 } }
793 />
794
795 <SelectControl
796 label={ __( 'Horizontal Alignment', 'generateblocks' ) }
797 value={ horizontalAlignmentMobile }
798 options={ [
799 { label: __( 'Inherit', 'generateblocks' ), value: 'inherit' },
800 { label: __( 'Default', 'generateblocks' ), value: '' },
801 { label: __( 'Left', 'generateblocks' ), value: 'flex-start' },
802 { label: __( 'Center', 'generateblocks' ), value: 'center' },
803 { label: __( 'Right', 'generateblocks' ), value: 'flex-end' },
804 ] }
805 onChange={ ( value ) => {
806 setAttributes( {
807 horizontalAlignmentMobile: value,
808 } );
809 } }
810 />
811 </Fragment>
812 ) }
813
814 { applyFilters( 'generateblocks.editor.controls', '', 'gridLayout', this.props, this.state ) }
815 </PanelArea>
816
817 <PanelArea { ...this.props }
818 title={ __( 'Documentation', 'generateblocks' ) }
819 icon={ getIcon( 'documentation' ) }
820 initialOpen={ false }
821 className={ 'gblocks-panel-label' }
822 id={ 'gridDocumentation' }
823 state={ this.state }
824 >
825 <p>{ __( 'Need help with this block?', 'generateblocks' ) }</p>
826 <a href="https://docs.generateblocks.com/collection/grid/" target="_blank" rel="noreferrer noopener">{ __( 'Visit our documentation', 'generateblocks' ) }</a>
827
828 { applyFilters( 'generateblocks.editor.controls', '', 'gridDocumentation', this.props, this.state ) }
829 </PanelArea>
830 </InspectorControls>
831
832 <InspectorAdvancedControls>
833 <TextControl
834 label={ __( 'HTML Anchor', 'generateblocks' ) }
835 help={ __( 'Anchors lets you link directly to a section on a page.', 'generateblocks' ) }
836 value={ anchor || '' }
837 onChange={ ( nextValue ) => {
838 nextValue = nextValue.replace( ANCHOR_REGEX, '-' );
839 setAttributes( {
840 anchor: nextValue,
841 } );
842 } } />
843 </InspectorAdvancedControls>
844
845 <MainCSS { ...this.props } />
846
847 { this.props.deviceType &&
848 <Fragment>
849 { 'Desktop' === this.props.deviceType &&
850 <DesktopCSS { ...this.props } />
851 }
852
853 { ( 'Tablet' === this.props.deviceType || 'Mobile' === this.props.deviceType ) &&
854 <TabletCSS { ...this.props } />
855 }
856
857 { 'Tablet' === this.props.deviceType &&
858 <TabletOnlyCSS { ...this.props } />
859 }
860
861 { 'Mobile' === this.props.deviceType &&
862 <MobileCSS { ...this.props } />
863 }
864 </Fragment>
865 }
866
867 <div
868 { ...htmlAttributes }
869 >
870 { columns > 0 || this.state.selectedLayout ? (
871 <Fragment>
872 <InnerBlocks
873 allowedBlocks={ [ 'generateblocks/container' ] }
874 renderAppender={ false }
875 />
876 </Fragment>
877 ) : this.getLayoutsSelector() }
878 </div>
879 </Fragment>
880 );
881 }
882 }
883
884 export default compose( [
885 withDispatch( ( dispatch ) => ( {
886 setDeviceType( type ) {
887 const {
888 __experimentalSetPreviewDeviceType: setPreviewDeviceType,
889 } = dispatch( 'core/edit-post' );
890
891 if ( ! setPreviewDeviceType ) {
892 return;
893 }
894
895 setPreviewDeviceType( type );
896 },
897 } ) ),
898 withSelect( ( select ) => {
899 const {
900 __experimentalGetPreviewDeviceType: getPreviewDeviceType,
901 } = select( 'core/edit-post' );
902
903 if ( ! getPreviewDeviceType ) {
904 return {
905 deviceType: null,
906 };
907 }
908
909 return {
910 deviceType: getPreviewDeviceType(),
911 };
912 } ),
913 ] )( GenerateBlockGridContainer );
914