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