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