PluginProbe ʕ •ᴥ•ʔ
GenerateBlocks / 1.6.0
GenerateBlocks v1.6.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 / container / components / InspectorControls.js
generateblocks / src / blocks / container / components Last commit date
BlockControls.js 4 years ago ComponentCSS.js 4 years ago ContainerContentRenderer.js 3 years ago GridItem.js 4 years ago InspectorControls.js 4 years ago ShapeDividers.js 4 years ago
InspectorControls.js
1938 lines
1 import { InspectorControls, MediaUpload } from '@wordpress/block-editor';
2 import PanelArea from '../../../components/panel-area';
3 import { __, sprintf } from '@wordpress/i18n';
4 import getIcon from '../../../utils/get-icon';
5 import { Fragment, useEffect } from '@wordpress/element';
6 import {
7 BaseControl,
8 Button,
9 ButtonGroup, Dropdown, Notice, PanelBody, PanelRow, RangeControl,
10 SelectControl,
11 TextControl,
12 ToggleControl,
13 Tooltip,
14 } from '@wordpress/components';
15 import UnitPicker from '../../../components/unit-picker';
16 import { applyFilters } from '@wordpress/hooks';
17 import RangeControlInput from '../../../components/range-control';
18 import hasNumericValue from '../../../utils/has-numeric-value';
19 import getResponsivePlaceholder from '../../../utils/get-responsive-placeholder';
20 import TypographyControls from '../../../components/typography';
21 import DimensionsGroup from '../../../components/dimensions-group';
22 import ColorPicker from '../../../components/color-picker';
23 import ColorGroup from '../../../components/color-group';
24 import GradientControl from '../../../components/gradient';
25 import classnames from 'classnames';
26 import sanitizeSVG from '../../../utils/sanitize-svg';
27 import { useSelect } from '@wordpress/data';
28
29 const hasFlexBasis = ( attribute ) => {
30 return hasNumericValue( attribute ) && 'auto' !== attribute;
31 };
32
33 export default ( props ) => {
34 const {
35 clientId,
36 attributes,
37 setAttributes,
38 deviceType,
39 state,
40 blockDefaults,
41 tagNames,
42 filterTagName,
43 allShapes,
44 context,
45 } = props;
46
47 const {
48 tagName,
49 isGrid,
50 isQueryLoopItem,
51 gridId,
52 width,
53 widthTablet,
54 widthMobile,
55 autoWidthTablet,
56 autoWidthMobile,
57 flexGrow,
58 flexGrowTablet,
59 flexGrowMobile,
60 flexShrink,
61 flexShrinkTablet,
62 flexShrinkMobile,
63 flexBasis,
64 flexBasisTablet,
65 flexBasisMobile,
66 flexBasisUnit,
67 outerContainer,
68 innerContainer,
69 containerWidth,
70 minHeight,
71 minHeightUnit,
72 minHeightTablet,
73 minHeightUnitTablet,
74 minHeightMobile,
75 minHeightUnitMobile,
76 backgroundColor,
77 bgImage,
78 bgOptions,
79 bgImageSize,
80 bgImageInline,
81 verticalAlignment,
82 verticalAlignmentTablet,
83 verticalAlignmentMobile,
84 zindex,
85 innerZindex,
86 removeVerticalGap,
87 removeVerticalGapTablet,
88 removeVerticalGapMobile,
89 orderTablet,
90 orderMobile,
91 align,
92 shapeDividers,
93 useDynamicData,
94 dynamicContentType,
95 } = attributes;
96
97 const {
98 getBlockParents,
99 getBlocksByClientId,
100 } = useSelect( ( select ) => select( 'core/block-editor' ), [] );
101
102 useEffect( () => {
103 const parentBlockId = getBlockParents( clientId, true );
104
105 if ( parentBlockId.length > 0 ) {
106 const parentBlocks = getBlocksByClientId( parentBlockId );
107
108 if ( parentBlocks.length > 0 ) {
109 if ( 'generateblocks/grid' === parentBlocks[ 0 ].name ) {
110 const parentGridId = parentBlocks[ 0 ].attributes.uniqueId;
111
112 if ( parentGridId !== gridId ) {
113 setAttributes( {
114 isGrid: true,
115 gridId: parentGridId,
116 } );
117 }
118 } else if ( isGrid && ! isQueryLoopItem ) {
119 // Grid block isn't the parent, can't be a grid item.
120 setAttributes( {
121 isGrid: false,
122 gridId: '',
123 } );
124 }
125 }
126 } else if ( isGrid && ! isQueryLoopItem ) {
127 // No parent exists, can't be a grid item.
128 setAttributes( {
129 isGrid: false,
130 gridId: '',
131 } );
132 }
133 } );
134
135 const isInQueryLoop = 'undefined' !== typeof context[ 'generateblocks/queryId' ];
136 const hideWidthDesktop = hasFlexBasis( flexBasis );
137 const hideWidthTablet = 'auto' !== flexBasisTablet &&
138 ( hasFlexBasis( flexBasis ) || hasFlexBasis( flexBasisTablet ) );
139 const hideWidthMobile = 'auto' !== flexBasisMobile &&
140 ( hasFlexBasis( flexBasis ) || hasFlexBasis( flexBasisTablet ) || hasFlexBasis( flexBasisMobile ) );
141
142 const handleAddShape = () => {
143 const shapeDividersValues = [ ...shapeDividers ];
144
145 shapeDividersValues.push( {
146 shape: generateBlocksStyling.container.shapeDividers.shape,
147 color: generateBlocksStyling.container.shapeDividers.color,
148 colorOpacity: generateBlocksStyling.container.shapeDividers.colorOpacity,
149 location: generateBlocksStyling.container.shapeDividers.location,
150 height: generateBlocksStyling.container.shapeDividers.height,
151 heightTablet: generateBlocksStyling.container.shapeDividers.heightTablet,
152 heightMobile: generateBlocksStyling.container.shapeDividers.heightMobile,
153 width: generateBlocksStyling.container.shapeDividers.width,
154 widthTablet: generateBlocksStyling.container.shapeDividers.widthTablet,
155 widthMobile: generateBlocksStyling.container.shapeDividers.widthMobile,
156 flipHorizontally: generateBlocksStyling.container.shapeDividers.flipHorizontally,
157 zindex: generateBlocksStyling.container.shapeDividers.zindex,
158 } );
159
160 setAttributes( { shapeDividers: shapeDividersValues } );
161 };
162
163 const handleRemoveShape = ( index ) => {
164 const shapeDividersValues = [ ...shapeDividers ];
165
166 shapeDividersValues.splice( index, 1 );
167 setAttributes( { shapeDividers: shapeDividersValues } );
168 };
169
170 const bgImageSizes = [];
171
172 Object.keys( generateBlocksInfo.imageSizes ).forEach( ( size ) => {
173 bgImageSizes.push( {
174 label: generateBlocksInfo.imageSizes[ size ],
175 value: generateBlocksInfo.imageSizes[ size ],
176 } );
177 } );
178
179 return (
180 <InspectorControls>
181 { ! isGrid && (
182 <PanelArea
183 { ...props }
184 title={ __( 'Layout', 'generateblocks' ) }
185 initialOpen={ true }
186 icon={ getIcon( 'layout' ) }
187 className={ 'gblocks-panel-label' }
188 id={ 'containerLayout' }
189 state={ state }
190 >
191 { 'Desktop' === deviceType &&
192 <Fragment>
193 <SelectControl
194 label={ __( 'Container', 'generateblocks' ) }
195 value={ outerContainer }
196 options={ [
197 { label: __( 'Full width', 'generateblocks' ), value: 'full' },
198 { label: __( 'Contained width', 'generateblocks' ), value: 'contained' },
199 ] }
200 onChange={ ( value ) => {
201 setAttributes( {
202 outerContainer: value,
203 } );
204
205 if ( 'contained' === value && 'full' === align ) {
206 setAttributes( {
207 align: '',
208 } );
209 }
210 } }
211 />
212
213 { 'full' === outerContainer &&
214 <SelectControl
215 label={ __( 'Inner Container', 'generateblocks' ) }
216 value={ innerContainer }
217 options={ [
218 { label: __( 'Full width', 'generateblocks' ), value: 'full' },
219 { label: __( 'Contained width', 'generateblocks' ), value: 'contained' },
220 ] }
221 onChange={ ( value ) => {
222 setAttributes( {
223 innerContainer: value,
224 } );
225 } }
226 />
227 }
228
229 { ( 'contained' === outerContainer || 'contained' === innerContainer ) &&
230 <Fragment>
231 <UnitPicker
232 label={
233 'full' === outerContainer &&
234 'contained' === innerContainer
235 ? __( 'Inner Container Width', 'generateblocks' )
236 : __( 'Container Width', 'generateblocks' )
237 }
238 value={ 'px' }
239 units={ [ 'px' ] }
240 onClick={ () => {
241 return false;
242 } }
243 />
244
245 <TextControl
246 type={ 'number' }
247 className="gblocks-container-width"
248 value={ parseFloat( containerWidth ) || '' }
249 placeholder={ blockDefaults.containerWidth }
250 onChange={ ( value ) => {
251 setAttributes( {
252 containerWidth: '' !== value ? parseFloat( value ) : undefined,
253 } );
254 } }
255 />
256 </Fragment>
257 }
258
259 <SelectControl
260 label={ __( 'Tag Name', 'generateblocks' ) }
261 value={ tagName }
262 options={ tagNames }
263 onChange={ ( value ) => {
264 setAttributes( {
265 tagName: filterTagName( value ),
266 } );
267 } }
268 />
269
270 { applyFilters( 'generateblocks.editor.controls', '', 'containerAfterElementTag', props, state ) }
271 </Fragment>
272 }
273
274 { applyFilters( 'generateblocks.editor.controls', '', 'containerLayout', props, state ) }
275 </PanelArea>
276 ) }
277
278 { isGrid && (
279 <PanelArea
280 { ...props }
281 title={ __( 'Layout', 'generateblocks' ) }
282 initialOpen={ true }
283 icon={ getIcon( 'layout' ) }
284 className={ 'gblocks-panel-label' }
285 id={ 'containerGridLayout' }
286 state={ state }
287 >
288 { 'Desktop' === deviceType && (
289 <Fragment>
290 <BaseControl>
291 <UnitPicker
292 label={ __( 'Container Width', 'generateblocks' ) }
293 value={ '%' }
294 units={ [ '%' ] }
295 onClick={ () => {
296 return false;
297 } }
298 />
299
300 { !! hideWidthDesktop &&
301 <div className="gblocks-small-notice-description">
302 { __( 'Width disabled as Flex Basis is not "auto".', 'generateblocks' ) }
303 </div>
304 }
305
306 <ButtonGroup className={ 'widthButtons' }>
307 <Button isPrimary={ width === 25 } onClick={ () => setAttributes( { width: 25 } ) } disabled={ hideWidthDesktop }>25</Button>
308 <Button isPrimary={ width === 33.33 } onClick={ () => setAttributes( { width: 33.33 } ) } disabled={ hideWidthDesktop }>33</Button>
309 <Button isPrimary={ width === 50 } onClick={ () => setAttributes( { width: 50 } ) } disabled={ hideWidthDesktop }>50</Button>
310 <Button isPrimary={ width === 66.66 } onClick={ () => setAttributes( { width: 66.66 } ) } disabled={ hideWidthDesktop }>66</Button>
311 <Button isPrimary={ width === 75 } onClick={ () => setAttributes( { width: 75 } ) } disabled={ hideWidthDesktop }>75</Button>
312 <Button isPrimary={ width === 100 } onClick={ () => setAttributes( { width: 100 } ) } disabled={ hideWidthDesktop }>100</Button>
313 </ButtonGroup>
314
315 <RangeControlInput
316 value={ hasNumericValue( width ) ? width : '' }
317 onChange={ ( value ) => {
318 // No zero value or values that start with zero.
319 if ( String( value ).startsWith( 0 ) ) {
320 value = '';
321 }
322
323 setAttributes( {
324 width: value,
325 } );
326 } }
327 rangeMin={ 10 }
328 rangeMax={ 100 }
329 step={ 5 }
330 initialPosition={ blockDefaults.width }
331 disabled={ hideWidthDesktop }
332 />
333 </BaseControl>
334
335 <BaseControl
336 className="gblocks-flex-controls"
337 >
338 <div className="gblocks-utility-label">
339 <label
340 htmlFor="gblocks-flex-grow-desktop"
341 className="components-base-control__label"
342 >
343 { __( 'Flex', 'generateblocks' ) }
344 </label>
345
346 <Tooltip text={ __( 'Reset', 'generateblocks' ) } position="top">
347 <Button
348 className="gblocks-reset-button"
349 icon={ getIcon( 'reset' ) }
350 onClick={ () => {
351 setAttributes( {
352 flexGrow: '',
353 flexShrink: '',
354 flexBasis: '',
355 } );
356 } }
357 />
358 </Tooltip>
359 </div>
360
361 <div className="gblocks-flex-controls-inner">
362 <TextControl
363 help={ __( 'Grow', 'generateblocks' ) }
364 id="gblocks-flex-grow-desktop"
365 type={ 'number' }
366 value={ flexGrow }
367 min="0"
368 step="1"
369 placeholder="0"
370 onChange={ ( value ) => {
371 setAttributes( {
372 flexGrow: value,
373 } );
374 } }
375 onBlur={ () => {
376 if ( '' !== flexGrow ) {
377 setAttributes( {
378 flexGrow: parseFloat( flexGrow ),
379 } );
380 }
381 } }
382 onClick={ ( e ) => {
383 // Make sure onBlur fires in Firefox.
384 e.currentTarget.focus();
385 } }
386 />
387
388 <TextControl
389 help={ __( 'Shrink', 'generateblocks' ) }
390 type={ 'number' }
391 value={ flexShrink }
392 min="0"
393 step="1"
394 placeholder="1"
395 onChange={ ( value ) => {
396 setAttributes( {
397 flexShrink: value,
398 } );
399 } }
400 onBlur={ () => {
401 if ( '' !== flexShrink ) {
402 setAttributes( {
403 flexShrink: parseFloat( flexShrink ),
404 } );
405 }
406 } }
407 onClick={ ( e ) => {
408 // Make sure onBlur fires in Firefox.
409 e.currentTarget.focus();
410 } }
411 />
412
413 <div className="gblocks-flex-basis-wrapper">
414 { ! isNaN( flexBasis ) &&
415 <UnitPicker
416 value={ flexBasisUnit }
417 units={ [ 'px', '%' ] }
418 onClick={ ( value ) => {
419 setAttributes( {
420 flexBasisUnit: value,
421 } );
422 } }
423 />
424 }
425
426 <TextControl
427 help={ __( 'Basis', 'generateblocks' ) }
428 type={ 'text' }
429 placeholder="auto"
430 value={ flexBasis }
431 onChange={ ( value ) => {
432 setAttributes( {
433 flexBasis: value,
434 } );
435 } }
436 onBlur={ () => {
437 if ( ! flexBasis.match( /(auto|fill|max-content|min-content|fit-content|content|inherit|initial|revert|unset|[0-9.]+)/g ) ) {
438 setAttributes( {
439 flexBasis: '',
440 } );
441 }
442 } }
443 />
444 </div>
445 </div>
446 </BaseControl>
447
448 <SelectControl
449 label={ __( 'Vertical Alignment', 'generateblocks' ) }
450 help={ __( 'Align grid item content. Does not apply if vertical alignment is set in the grid.', 'generateblocks' ) }
451 value={ verticalAlignment }
452 options={ [
453 { label: __( 'Default', 'generateblocks' ), value: '' },
454 { label: __( 'Top', 'generateblocks' ), value: 'flex-start' },
455 { label: __( 'Center', 'generateblocks' ), value: 'center' },
456 { label: __( 'Bottom', 'generateblocks' ), value: 'flex-end' },
457 ] }
458 onChange={ ( value ) => {
459 setAttributes( {
460 verticalAlignment: value,
461 } );
462 } }
463 />
464
465 { ! isQueryLoopItem &&
466 <ToggleControl
467 label={ __( 'Remove Vertical Gap', 'generateblocks' ) }
468 checked={ !! removeVerticalGap }
469 onChange={ ( value ) => {
470 setAttributes( {
471 removeVerticalGap: value,
472 } );
473 } }
474 />
475 }
476
477 <SelectControl
478 label={ __( 'Tag Name', 'generateblocks' ) }
479 value={ tagName }
480 options={ tagNames }
481 onChange={ ( value ) => {
482 setAttributes( {
483 tagName: filterTagName( value ),
484 } );
485 } }
486 />
487
488 { applyFilters( 'generateblocks.editor.controls', '', 'containerAfterElementTag', props, state ) }
489 </Fragment>
490 ) }
491
492 { 'Tablet' === deviceType && (
493 <Fragment>
494 <BaseControl>
495 <UnitPicker
496 label={ __( 'Container Width', 'generateblocks' ) }
497 value={ '%' }
498 units={ [ '%' ] }
499 onClick={ () => {
500 return false;
501 } }
502 />
503
504 { !! hideWidthTablet &&
505 <div className="gblocks-small-notice-description">
506 { __( 'Width disabled as Flex Basis is not "auto".', 'generateblocks' ) }
507 </div>
508 }
509
510 <ButtonGroup className={ 'widthButtons' }>
511 <Button isPrimary={ !! autoWidthTablet } disabled={ hideWidthTablet } onClick={ () => {
512 if ( autoWidthTablet ) {
513 setAttributes( { autoWidthTablet: false } );
514 } else {
515 setAttributes( { autoWidthTablet: true } );
516 }
517 } }>
518 { __( 'Auto', 'generateblocks' ) }
519 </Button>
520
521 <Button isPrimary={ widthTablet === 25 && ! autoWidthTablet } onClick={ () => setAttributes( { widthTablet: 25, autoWidthTablet: false } ) } disabled={ hideWidthTablet }>25</Button>
522 <Button isPrimary={ widthTablet === 33.33 && ! autoWidthTablet } onClick={ () => setAttributes( { widthTablet: 33.33, autoWidthTablet: false } ) } disabled={ hideWidthTablet }>33</Button>
523 <Button isPrimary={ widthTablet === 50 && ! autoWidthTablet } onClick={ () => setAttributes( { widthTablet: 50, autoWidthTablet: false } ) } disabled={ hideWidthTablet }>50</Button>
524 <Button isPrimary={ widthTablet === 66.66 && ! autoWidthTablet } onClick={ () => setAttributes( { widthTablet: 66.66, autoWidthTablet: false } ) } disabled={ hideWidthTablet }>66</Button>
525 <Button isPrimary={ widthTablet === 75 && ! autoWidthTablet } onClick={ () => setAttributes( { widthTablet: 75, autoWidthTablet: false } ) } disabled={ hideWidthTablet }>75</Button>
526 <Button isPrimary={ widthTablet === 100 && ! autoWidthTablet } onClick={ () => setAttributes( { widthTablet: 100, autoWidthTablet: false } ) } disabled={ hideWidthTablet }>100</Button>
527 </ButtonGroup>
528
529 { ! autoWidthTablet &&
530 <RangeControlInput
531 value={ hasNumericValue( widthTablet ) ? widthTablet : '' }
532 onChange={ ( value ) => {
533 // No zero value or values that start with zero.
534 if ( String( value ).startsWith( 0 ) ) {
535 value = '';
536 }
537
538 setAttributes( {
539 widthTablet: value,
540 autoWidthTablet: false,
541 } );
542 } }
543 rangeMin={ 10 }
544 rangeMax={ 100 }
545 step={ 5 }
546 initialPosition={ blockDefaults.widthTablet }
547 disabled={ hideWidthTablet }
548 />
549 }
550 </BaseControl>
551
552 <BaseControl
553 className="gblocks-flex-controls"
554 >
555 <div className="gblocks-utility-label">
556 <label
557 htmlFor="gblocks-flex-grow-tablet"
558 className="components-base-control__label"
559 >
560 { __( 'Flex', 'generateblocks' ) }
561 </label>
562
563 <Tooltip text={ __( 'Reset', 'generateblocks' ) } position="top">
564 <Button
565 className="gblocks-reset-button"
566 icon={ getIcon( 'reset' ) }
567 onClick={ () => {
568 setAttributes( {
569 flexGrowTablet: '',
570 flexShrinkTablet: '',
571 flexBasisTablet: '',
572 } );
573 } }
574 />
575 </Tooltip>
576 </div>
577
578 <div className="gblocks-flex-controls-inner">
579 <TextControl
580 help={ __( 'Grow', 'generateblocks' ) }
581 id="gblocks-flex-grow-tablet"
582 type={ 'number' }
583 value={ flexGrowTablet }
584 min="0"
585 step="1"
586 placeholder={ getResponsivePlaceholder( 'flexGrow', attributes, 'Tablet', '0' ) }
587 onChange={ ( value ) => {
588 setAttributes( {
589 flexGrowTablet: value,
590 } );
591 } }
592 onBlur={ () => {
593 if ( '' !== flexGrowTablet ) {
594 setAttributes( {
595 flexGrowTablet: parseFloat( flexGrowTablet ),
596 } );
597 }
598 } }
599 onClick={ ( e ) => {
600 // Make sure onBlur fires in Firefox.
601 e.currentTarget.focus();
602 } }
603 />
604
605 <TextControl
606 help={ __( 'Shrink', 'generateblocks' ) }
607 type={ 'number' }
608 value={ flexShrinkTablet }
609 min="0"
610 step="1"
611 placeholder={ getResponsivePlaceholder( 'flexShrink', attributes, 'Tablet', '1' ) }
612 onChange={ ( value ) => {
613 setAttributes( {
614 flexShrinkTablet: value,
615 } );
616 } }
617 onBlur={ () => {
618 if ( '' !== flexShrinkTablet ) {
619 setAttributes( {
620 flexShrinkTablet: parseFloat( flexShrinkTablet ),
621 } );
622 }
623 } }
624 onClick={ ( e ) => {
625 // Make sure onBlur fires in Firefox.
626 e.currentTarget.focus();
627 } }
628 />
629
630 <div className="gblocks-flex-basis-wrapper">
631 { ! isNaN( flexBasisTablet ) &&
632 <UnitPicker
633 value={ flexBasisUnit }
634 units={ [ 'px', '%' ] }
635 onClick={ ( value ) => {
636 setAttributes( {
637 flexBasisUnit: value,
638 } );
639 } }
640 />
641 }
642
643 <TextControl
644 help={ __( 'Basis', 'generateblocks' ) }
645 type={ 'text' }
646 value={ flexBasisTablet }
647 placeholder={ getResponsivePlaceholder( 'flexBasis', attributes, 'Tablet', 'auto' ) }
648 onChange={ ( value ) => {
649 setAttributes( {
650 flexBasisTablet: value,
651 } );
652 } }
653 onBlur={ () => {
654 if ( ! flexBasisTablet.match( /(auto|fill|max-content|min-content|fit-content|content|inherit|initial|revert|unset|[0-9.]+)/g ) ) {
655 setAttributes( {
656 flexBasisTablet: '',
657 } );
658 }
659 } }
660 />
661 </div>
662 </div>
663 </BaseControl>
664
665 <SelectControl
666 label={ __( 'Vertical Alignment', 'generateblocks' ) }
667 help={ __( 'Align grid item content. Does not apply if vertical alignment is set in the grid.', 'generateblocks' ) }
668 value={ verticalAlignmentTablet }
669 options={ [
670 { label: __( 'Inherit', 'generateblocks' ), value: 'inherit' },
671 { label: __( 'Default', 'generateblocks' ), value: '' },
672 { label: __( 'Top', 'generateblocks' ), value: 'flex-start' },
673 { label: __( 'Center', 'generateblocks' ), value: 'center' },
674 { label: __( 'Bottom', 'generateblocks' ), value: 'flex-end' },
675 ] }
676 onChange={ ( value ) => {
677 setAttributes( {
678 verticalAlignmentTablet: value,
679 } );
680 } }
681 />
682
683 { ! isQueryLoopItem &&
684 <ToggleControl
685 label={ __( 'Remove Vertical Gap', 'generateblocks' ) }
686 checked={ !! removeVerticalGapTablet }
687 onChange={ ( value ) => {
688 setAttributes( {
689 removeVerticalGapTablet: value,
690 } );
691 } }
692 />
693 }
694
695 <TextControl
696 type={ 'number' }
697 label={ __( 'Order', 'generateblocks' ) }
698 value={ orderTablet || 0 === orderTablet ? orderTablet : '' }
699 onChange={ ( value ) => {
700 setAttributes( {
701 orderTablet: parseFloat( value ),
702 } );
703 } }
704 />
705 </Fragment>
706 ) }
707
708 { 'Mobile' === deviceType && (
709 <Fragment>
710 <BaseControl>
711 <UnitPicker
712 label={ __( 'Container Width', 'generateblocks' ) }
713 value={ '%' }
714 units={ [ '%' ] }
715 onClick={ () => {
716 return false;
717 } }
718 />
719
720 { !! hideWidthMobile &&
721 <div className="gblocks-small-notice-description">
722 { __( 'Width disabled as Flex Basis is not "auto".', 'generateblocks' ) }
723 </div>
724 }
725
726 <ButtonGroup className={ 'widthButtons' }>
727 <Button isPrimary={ !! autoWidthMobile } disabled={ hideWidthMobile } onClick={ () => {
728 if ( autoWidthMobile ) {
729 setAttributes( { autoWidthMobile: false } );
730 } else {
731 setAttributes( { autoWidthMobile: true } );
732 }
733 } }>
734 { __( 'Auto', 'generateblocks' ) }
735 </Button>
736
737 <Button isPrimary={ widthMobile === 25 && ! autoWidthMobile } onClick={ () => setAttributes( { widthMobile: 25, autoWidthMobile: false } ) } disabled={ hideWidthMobile }>25</Button>
738 <Button isPrimary={ widthMobile === 33.33 && ! autoWidthMobile } onClick={ () => setAttributes( { widthMobile: 33.33, autoWidthMobile: false } ) } disabled={ hideWidthMobile }>33</Button>
739 <Button isPrimary={ widthMobile === 50 && ! autoWidthMobile } onClick={ () => setAttributes( { widthMobile: 50, autoWidthMobile: false } ) } disabled={ hideWidthMobile }>50</Button>
740 <Button isPrimary={ widthMobile === 66.66 && ! autoWidthMobile } onClick={ () => setAttributes( { widthMobile: 66.66, autoWidthMobile: false } ) } disabled={ hideWidthMobile }>66</Button>
741 <Button isPrimary={ widthMobile === 75 && ! autoWidthMobile } onClick={ () => setAttributes( { widthMobile: 75, autoWidthMobile: false } ) } disabled={ hideWidthMobile }>75</Button>
742 <Button isPrimary={ widthMobile === 100 && ! autoWidthMobile } onClick={ () => setAttributes( { widthMobile: 100, autoWidthMobile: false } ) } disabled={ hideWidthMobile }>100</Button>
743 </ButtonGroup>
744
745 { ! autoWidthMobile &&
746 <RangeControlInput
747 value={ hasNumericValue( widthMobile ) ? widthMobile : '' }
748 onChange={ ( value ) => {
749 // No zero value or values that start with zero.
750 if ( String( value ).startsWith( 0 ) ) {
751 value = '';
752 }
753
754 setAttributes( {
755 widthMobile: value,
756 autoWidthMobile: false,
757 } );
758 } }
759 rangeMin={ 10 }
760 rangeMax={ 100 }
761 step={ 5 }
762 initialPosition={ blockDefaults.widthMobile }
763 disabled={ hideWidthMobile }
764 />
765 }
766 </BaseControl>
767
768 <BaseControl
769 className="gblocks-flex-controls"
770 >
771 <div className="gblocks-utility-label">
772 <label
773 htmlFor="gblocks-flex-grow-mobile"
774 className="components-base-control__label"
775 >
776 { __( 'Flex', 'generateblocks' ) }
777 </label>
778
779 <Tooltip text={ __( 'Reset', 'generateblocks' ) } position="top">
780 <Button
781 className="gblocks-reset-button"
782 icon={ getIcon( 'reset' ) }
783 onClick={ () => {
784 setAttributes( {
785 flexGrowMobile: '',
786 flexShrinkMobile: '',
787 flexBasisMobile: '',
788 } );
789 } }
790 />
791 </Tooltip>
792 </div>
793
794 <div className="gblocks-flex-controls-inner">
795 <TextControl
796 help={ __( 'Grow', 'generateblocks' ) }
797 id="gblocks-flex-grow-mobile"
798 type={ 'number' }
799 value={ flexGrowMobile }
800 min="0"
801 step="1"
802 placeholder={ getResponsivePlaceholder( 'flexGrow', attributes, 'Mobile', '0' ) }
803 onChange={ ( value ) => {
804 setAttributes( {
805 flexGrowMobile: value,
806 } );
807 } }
808 onBlur={ () => {
809 if ( '' !== flexGrowMobile ) {
810 setAttributes( {
811 flexGrowMobile: parseFloat( flexGrowMobile ),
812 } );
813 }
814 } }
815 onClick={ ( e ) => {
816 // Make sure onBlur fires in Firefox.
817 e.currentTarget.focus();
818 } }
819 />
820
821 <TextControl
822 help={ __( 'Shrink', 'generateblocks' ) }
823 type={ 'number' }
824 value={ flexShrinkMobile }
825 min="0"
826 step="1"
827 placeholder={ getResponsivePlaceholder( 'flexShrink', attributes, 'Mobile', '1' ) }
828 onChange={ ( value ) => {
829 setAttributes( {
830 flexShrinkMobile: value,
831 } );
832 } }
833 onBlur={ () => {
834 if ( '' !== flexShrinkMobile ) {
835 setAttributes( {
836 flexShrinkMobile: parseFloat( flexShrinkMobile ),
837 } );
838 }
839 } }
840 onClick={ ( e ) => {
841 // Make sure onBlur fires in Firefox.
842 e.currentTarget.focus();
843 } }
844 />
845
846 <div className="gblocks-flex-basis-wrapper">
847 { ! isNaN( flexBasisMobile ) &&
848 <UnitPicker
849 value={ flexBasisUnit }
850 units={ [ 'px', '%' ] }
851 onClick={ ( value ) => {
852 setAttributes( {
853 flexBasisUnit: value,
854 } );
855 } }
856 />
857 }
858
859 <TextControl
860 help={ __( 'Basis', 'generateblocks' ) }
861 type={ 'text' }
862 value={ flexBasisMobile }
863 placeholder={ getResponsivePlaceholder( 'flexBasis', attributes, 'Mobile', 'auto' ) }
864 onChange={ ( value ) => {
865 setAttributes( {
866 flexBasisMobile: value,
867 } );
868 } }
869 onBlur={ () => {
870 if ( ! flexBasisMobile.match( /(auto|fill|max-content|min-content|fit-content|content|inherit|initial|revert|unset|[0-9.]+)/g ) ) {
871 setAttributes( {
872 flexBasisMobile: '',
873 } );
874 }
875 } }
876 />
877 </div>
878 </div>
879 </BaseControl>
880
881 <SelectControl
882 label={ __( 'Vertical Alignment', 'generateblocks' ) }
883 help={ __( 'Align grid item content. Does not apply if vertical alignment is set in the grid.', 'generateblocks' ) }
884 value={ verticalAlignmentMobile }
885 options={ [
886 { label: __( 'Inherit', 'generateblocks' ), value: 'inherit' },
887 { label: __( 'Default', 'generateblocks' ), value: '' },
888 { label: __( 'Top', 'generateblocks' ), value: 'flex-start' },
889 { label: __( 'Center', 'generateblocks' ), value: 'center' },
890 { label: __( 'Bottom', 'generateblocks' ), value: 'flex-end' },
891 ] }
892 onChange={ ( value ) => {
893 setAttributes( {
894 verticalAlignmentMobile: value,
895 } );
896 } }
897 />
898
899 { ! isQueryLoopItem &&
900 <ToggleControl
901 label={ __( 'Remove Vertical Gap', 'generateblocks' ) }
902 checked={ !! removeVerticalGapMobile }
903 onChange={ ( value ) => {
904 setAttributes( {
905 removeVerticalGapMobile: value,
906 } );
907 } }
908 />
909 }
910
911 <TextControl
912 type={ 'number' }
913 label={ __( 'Order', 'generateblocks' ) }
914 value={ orderMobile || 0 === orderMobile ? orderMobile : '' }
915 onChange={ ( value ) => {
916 setAttributes( {
917 orderMobile: parseFloat( value ),
918 } );
919 } }
920 />
921 </Fragment>
922 ) }
923
924 { applyFilters( 'generateblocks.editor.controls', '', 'containerGridLayout', props, state ) }
925 </PanelArea>
926 ) }
927
928 <PanelArea
929 { ...props }
930 title={ __( 'Typography', 'generateblocks' ) }
931 initialOpen={ false }
932 icon={ getIcon( 'typography' ) }
933 className={ 'gblocks-panel-label' }
934 id={ 'containerTypography' }
935 state={ state }
936 >
937 <TypographyControls
938 { ...props }
939 deviceType={ deviceType }
940 options={ [ 'fontWeight', 'textTransform', 'fontSize', 'fontFamily' ] }
941 />
942
943 { applyFilters( 'generateblocks.editor.controls', '', 'containerTypography', props, state ) }
944 </PanelArea>
945
946 <PanelArea
947 { ...props }
948 title={ __( 'Spacing', 'generateblocks' ) }
949 initialOpen={ false }
950 icon={ getIcon( 'spacing' ) }
951 className={ 'gblocks-panel-label' }
952 id={ 'containerSpacing' }
953 state={ state }
954 >
955 <DimensionsGroup
956 { ...props }
957 deviceType={ deviceType }
958 dimensions={
959 [
960 {
961 type: 'padding',
962 label: __( 'Padding', 'generateblocks' ),
963 units: [ 'px', 'em', '%' ],
964 },
965 {
966 type: 'margin',
967 label: __( 'Margin', 'generateblocks' ),
968 units: [ 'px', 'em', '%' ],
969 },
970 {
971 type: 'borderSize',
972 label: __( 'Border Size', 'generateblocks' ),
973 units: [ 'px' ],
974 },
975 {
976 type: 'borderRadius',
977 label: __( 'Border Radius', 'generateblocks' ),
978 units: [ 'px', 'em', '%' ],
979 },
980 ]
981 }
982 />
983 { 'Desktop' === deviceType && (
984 <Fragment>
985 <UnitPicker
986 label={ __( 'Minimum Height', 'generateblocks' ) }
987 value={ minHeightUnit }
988 units={ [ 'px', 'vh', 'vw' ] }
989 onClick={ ( value ) => {
990 setAttributes( {
991 minHeightUnit: value,
992 } );
993 } }
994 />
995
996 <TextControl
997 type={ 'number' }
998 value={ minHeight ? minHeight : '' }
999 onChange={ ( value ) => {
1000 setAttributes( {
1001 minHeight: parseFloat( value ),
1002 } );
1003 } }
1004 />
1005
1006 { !! minHeight && ! isGrid &&
1007 <SelectControl
1008 label={ __( 'Vertical Alignment', 'generateblocks' ) }
1009 value={ verticalAlignment }
1010 options={ [
1011 { label: __( 'Default', 'generateblocks' ), value: '' },
1012 { label: __( 'Top', 'generateblocks' ), value: 'flex-start' },
1013 { label: __( 'Center', 'generateblocks' ), value: 'center' },
1014 { label: __( 'Bottom', 'generateblocks' ), value: 'flex-end' },
1015 ] }
1016 onChange={ ( value ) => {
1017 setAttributes( {
1018 verticalAlignment: value,
1019 } );
1020 } }
1021 />
1022 }
1023
1024 <TextControl
1025 label={ __( 'Outer z-index', 'generateblocks' ) }
1026 type={ 'number' }
1027 value={ zindex || 0 === zindex ? zindex : '' }
1028 onChange={ ( value ) => {
1029 setAttributes( {
1030 zindex: value,
1031 } );
1032 } }
1033 onBlur={ () => {
1034 setAttributes( {
1035 zindex: parseFloat( zindex ),
1036 } );
1037 } }
1038 onClick={ ( e ) => {
1039 // Make sure onBlur fires in Firefox.
1040 e.currentTarget.focus();
1041 } }
1042 />
1043
1044 <TextControl
1045 label={ __( 'Inner z-index', 'generateblocks' ) }
1046 type={ 'number' }
1047 value={ innerZindex || 0 === innerZindex ? innerZindex : '' }
1048 onChange={ ( value ) => {
1049 setAttributes( {
1050 innerZindex: value,
1051 } );
1052 } }
1053 onBlur={ () => {
1054 setAttributes( {
1055 innerZindex: parseFloat( innerZindex ),
1056 } );
1057 } }
1058 onClick={ ( e ) => {
1059 // Make sure onBlur fires in Firefox.
1060 e.currentTarget.focus();
1061 } }
1062 />
1063 </Fragment>
1064 ) }
1065
1066 { 'Tablet' === deviceType && (
1067 <Fragment>
1068 <UnitPicker
1069 label={ __( 'Minimum Height', 'generateblocks' ) }
1070 value={ minHeightUnitTablet }
1071 units={ [ 'px', 'vh', 'vw' ] }
1072 onClick={ ( value ) => {
1073 setAttributes( {
1074 minHeightUnitTablet: value,
1075 } );
1076 } }
1077 />
1078
1079 <TextControl
1080 type={ 'number' }
1081 value={ minHeightTablet || 0 === minHeightTablet ? minHeightTablet : '' }
1082 onChange={ ( value ) => {
1083 setAttributes( {
1084 minHeightTablet: parseFloat( value ),
1085 } );
1086 } }
1087 />
1088
1089 { ( !! minHeight || !! minHeightTablet ) && ! isGrid &&
1090 <SelectControl
1091 label={ __( 'Vertical Alignment', 'generateblocks' ) }
1092 value={ verticalAlignmentTablet }
1093 options={ [
1094 { label: __( 'Inherit', 'generateblocks' ), value: 'inherit' },
1095 { label: __( 'Default', 'generateblocks' ), value: '' },
1096 { label: __( 'Top', 'generateblocks' ), value: 'flex-start' },
1097 { label: __( 'Center', 'generateblocks' ), value: 'center' },
1098 { label: __( 'Bottom', 'generateblocks' ), value: 'flex-end' },
1099 ] }
1100 onChange={ ( value ) => {
1101 setAttributes( {
1102 verticalAlignmentTablet: value,
1103 } );
1104 } }
1105 />
1106 }
1107 </Fragment>
1108 ) }
1109
1110 { 'Mobile' === deviceType && (
1111 <Fragment>
1112 <UnitPicker
1113 label={ __( 'Minimum Height', 'generateblocks' ) }
1114 value={ minHeightUnitMobile }
1115 units={ [ 'px', 'vh', 'vw' ] }
1116 onClick={ ( value ) => {
1117 setAttributes( {
1118 minHeightUnitMobile: value,
1119 } );
1120 } }
1121 />
1122
1123 <TextControl
1124 type={ 'number' }
1125 value={ minHeightMobile || 0 === minHeightMobile ? minHeightMobile : '' }
1126 onChange={ ( value ) => {
1127 setAttributes( {
1128 minHeightMobile: parseFloat( value ),
1129 } );
1130 } }
1131 />
1132
1133 { ( !! minHeight || !! minHeightTablet || !! minHeightMobile ) && ! isGrid &&
1134 <SelectControl
1135 label={ __( 'Vertical Alignment', 'generateblocks' ) }
1136 value={ verticalAlignmentMobile }
1137 options={ [
1138 { label: __( 'Inherit', 'generateblocks' ), value: 'inherit' },
1139 { label: __( 'Default', 'generateblocks' ), value: '' },
1140 { label: __( 'Top', 'generateblocks' ), value: 'flex-start' },
1141 { label: __( 'Center', 'generateblocks' ), value: 'center' },
1142 { label: __( 'Bottom', 'generateblocks' ), value: 'flex-end' },
1143 ] }
1144 onChange={ ( value ) => {
1145 setAttributes( {
1146 verticalAlignmentMobile: value,
1147 } );
1148 } }
1149 />
1150 }
1151 </Fragment>
1152 ) }
1153
1154 { applyFilters( 'generateblocks.editor.controls', '', 'containerSpacing', props, state ) }
1155 </PanelArea>
1156
1157 <PanelArea
1158 { ...props }
1159 title={ __( 'Colors', 'generateblocks' ) }
1160 initialOpen={ false }
1161 icon={ getIcon( 'colors' ) }
1162 className={ 'gblocks-panel-label' }
1163 id={ 'containerColors' }
1164 state={ state }
1165 >
1166 { 'Desktop' === deviceType &&
1167 <ColorGroup
1168 { ...props }
1169 colors={
1170 [
1171 {
1172 group: 'background',
1173 label: __( 'Background', 'generateblocks' ),
1174 items: [
1175 {
1176 attribute: 'backgroundColor',
1177 alpha: true,
1178 },
1179 ],
1180 },
1181 {
1182 group: 'text',
1183 label: __( 'Text', 'generateblocks' ),
1184 items: [
1185 {
1186 attribute: 'textColor',
1187 },
1188 ],
1189 },
1190 {
1191 group: 'link',
1192 label: __( 'Link', 'generateblocks' ),
1193 items: [
1194 {
1195 attribute: 'linkColor',
1196 },
1197 {
1198 tooltip: __( 'Hover', 'generateblocks' ),
1199 attribute: 'linkColorHover',
1200 },
1201 ],
1202 },
1203 {
1204 group: 'border',
1205 label: __( 'Border', 'generateblocks' ),
1206 items: [
1207 {
1208 attribute: 'borderColor',
1209 alpha: true,
1210 },
1211 ],
1212 },
1213 ]
1214 }
1215 />
1216 }
1217
1218 { applyFilters( 'generateblocks.editor.controls', '', 'containerColors', props, state ) }
1219 </PanelArea>
1220
1221 <PanelArea
1222 { ...props }
1223 title={ __( 'Backgrounds', 'generateblocks' ) }
1224 initialOpen={ false }
1225 icon={ getIcon( 'gradients' ) }
1226 className={ 'gblocks-panel-label' }
1227 id={ 'containerBackground' }
1228 state={ state }
1229 >
1230 <Fragment>
1231 <BaseControl
1232 id="gblocks-background-image-upload"
1233 label={ __( 'Image URL', 'generateblocks' ) }
1234 >
1235 <div className="gblocks-bg-image-wrapper">
1236 <TextControl
1237 type={ 'text' }
1238 value={ !! bgImage ? bgImage.image.url : '' }
1239 onChange={ ( value ) => {
1240 if ( ! value ) {
1241 setAttributes( {
1242 bgImage: null,
1243 } );
1244 } else {
1245 setAttributes( {
1246 bgImage: {
1247 id: '',
1248 image: {
1249 url: value,
1250 },
1251 },
1252 } );
1253 }
1254 } }
1255 />
1256
1257 <div className="gblocks-background-image-action-buttons">
1258 <MediaUpload
1259 title={ __( 'Set background image', 'generateblocks' ) }
1260 onSelect={ ( media ) => {
1261 let size = blockDefaults.bgImageSize;
1262
1263 if ( 'undefined' === typeof media.sizes[ size ] ) {
1264 size = 'full';
1265 }
1266
1267 setAttributes( {
1268 bgImage: {
1269 id: media.id,
1270 image: media.sizes[ size ],
1271 },
1272 } );
1273 } }
1274 onClose={ () => {
1275 document.querySelector( '.gblocks-bg-image-wrapper input' ).focus();
1276 } }
1277 allowedTypes={ [ 'image' ] }
1278 value={ !! bgImage ? bgImage.id : '' }
1279 modalClass="editor-gb-container-background__media-modal"
1280 render={ ( { open } ) => (
1281 <Tooltip text={ __( 'Open the Media Library', 'generateblocks' ) }>
1282 <Button
1283 onClick={ open }
1284 className="is-secondary is-small"
1285 >
1286 { __( 'Browse', 'generateblocks' ) }
1287 </Button>
1288 </Tooltip>
1289 ) }
1290 />
1291
1292 { applyFilters( 'generateblocks.editor.backgroundImageActions', '', props, state ) }
1293 </div>
1294 </div>
1295 </BaseControl>
1296
1297 { useDynamicData && '' !== dynamicContentType &&
1298 <Notice
1299 className="gblocks-option-notice"
1300 status="info"
1301 isDismissible={ false }
1302 >
1303 { __( 'Using featured image as dynamic background.', 'generateblocks' ) }
1304 </Notice>
1305 }
1306
1307 { ( !! bgImage || ( useDynamicData && '' !== dynamicContentType ) ) && (
1308 <Fragment>
1309 <ToggleControl
1310 label={ __( 'Use inline style', 'generateblocks' ) }
1311 disabled={ useDynamicData && '' !== dynamicContentType && ( isQueryLoopItem || isInQueryLoop ) }
1312 checked={ !! bgImageInline }
1313 onChange={ ( nextImageInline ) => {
1314 setAttributes( {
1315 bgImageInline: nextImageInline,
1316 } );
1317 } }
1318 />
1319
1320 { !! bgOptions.overlay ? ( // This option is deprecated, so only show it if it's in use.
1321 <Fragment>
1322 <ToggleControl
1323 label={ __( 'Background Color Overlay', 'generateblocks' ) }
1324 checked={ !! bgOptions.overlay }
1325 onChange={ ( nextOverlay ) => {
1326 setAttributes( {
1327 bgOptions: {
1328 ...bgOptions,
1329 overlay: nextOverlay,
1330 },
1331 } );
1332 } }
1333 />
1334
1335 <Notice
1336 className="gblocks-option-notice"
1337 status="info"
1338 isDismissible={ false }
1339 >
1340 { __( 'The background color overlay option is deprecated. Toggle this option to use the new method.', 'generateblocks' ) }
1341 </Notice>
1342 </Fragment>
1343 ) : ( // These options is only for people not using the deprecated overlay option.
1344 <Fragment>
1345 { (
1346 ( bgImage && bgImage.id ) ||
1347 ( useDynamicData && '' !== dynamicContentType ) ) &&
1348 <SelectControl
1349 label={ __( 'Image Size', 'generateblocks' ) }
1350 value={ bgImageSize }
1351 options={ bgImageSizes }
1352 onChange={ ( value ) => {
1353 setAttributes( {
1354 bgImageSize: value,
1355 } );
1356 } }
1357 />
1358 }
1359
1360 <SelectControl
1361 label={ __( 'Selector', 'generateblocks' ) }
1362 value={ bgOptions.selector }
1363 options={ [
1364 { label: __( 'Element', 'generateblocks' ), value: 'element' },
1365 { label: __( 'Pseudo Element', 'generateblocks' ), value: 'pseudo-element' },
1366 ] }
1367 onChange={ ( value ) => {
1368 setAttributes( {
1369 bgOptions: {
1370 ...bgOptions,
1371 selector: value,
1372 },
1373 } );
1374
1375 if ( 'pseudo-element' === value && ! innerZindex && 0 !== innerZindex ) {
1376 setAttributes( {
1377 innerZindex: 1,
1378 } );
1379 }
1380 } }
1381 />
1382
1383 <RangeControl
1384 label={ __( 'Image Opacity', 'generateblocks' ) }
1385 value={ bgOptions.opacity }
1386 onChange={ ( value ) => {
1387 setAttributes( {
1388 bgOptions: {
1389 ...bgOptions,
1390 opacity: value,
1391 selector: 'pseudo-element',
1392 },
1393 } );
1394
1395 if ( ! innerZindex && 0 !== innerZindex ) {
1396 setAttributes( {
1397 innerZindex: 1,
1398 } );
1399 }
1400 } }
1401 min={ 0 }
1402 max={ 1 }
1403 step={ 0.01 }
1404 initialPosition={ blockDefaults.bgOptions.opacity }
1405 />
1406
1407 { 1 !== bgOptions.opacity && 'pseudo-element' !== bgOptions.selector &&
1408 <Notice
1409 className="gblocks-option-notice"
1410 status="info"
1411 isDismissible={ false }
1412 >
1413 { __( 'Your selector must be set to Pseudo Element to use opacity.', 'generateblocks' ) }
1414 </Notice>
1415 }
1416 </Fragment>
1417 ) }
1418
1419 <TextControl
1420 label={ __( 'Size', 'generateblocks' ) }
1421 value={ bgOptions.size }
1422 onChange={ ( nextSize ) => {
1423 setAttributes( {
1424 bgOptions: {
1425 ...bgOptions,
1426 size: nextSize,
1427 },
1428 } );
1429 } }
1430 />
1431
1432 <TextControl
1433 label={ __( 'Position', 'generateblocks' ) }
1434 value={ bgOptions.position }
1435 onChange={ ( nextPosition ) => {
1436 setAttributes( {
1437 bgOptions: {
1438 ...bgOptions,
1439 position: nextPosition,
1440 },
1441 } );
1442 } }
1443 />
1444
1445 <SelectControl
1446 label={ __( 'Repeat', 'generateblocks' ) }
1447 value={ bgOptions.repeat }
1448 options={ [
1449 { label: 'no-repeat', value: 'no-repeat' },
1450 { label: 'repeat', value: 'repeat' },
1451 { label: 'repeat-x', value: 'repeat-x' },
1452 { label: 'repeat-y', value: 'repeat-y' },
1453 ] }
1454 onChange={ ( nextRepeat ) => {
1455 setAttributes( {
1456 bgOptions: {
1457 ...bgOptions,
1458 repeat: nextRepeat,
1459 },
1460 } );
1461 } }
1462 />
1463
1464 <SelectControl
1465 label={ __( 'Attachment', 'generateblocks' ) }
1466 value={ bgOptions.attachment }
1467 options={ [
1468 { label: 'scroll', value: '' },
1469 { label: 'fixed', value: 'fixed' },
1470 { label: 'local', value: 'local' },
1471 ] }
1472 onChange={ ( nextAttachment ) => {
1473 setAttributes( {
1474 bgOptions: {
1475 ...bgOptions,
1476 attachment: nextAttachment,
1477 },
1478 } );
1479 } }
1480 />
1481 </Fragment>
1482 ) }
1483
1484 <GradientControl
1485 { ...props }
1486 attrGradient={ 'gradient' }
1487 attrGradientDirection={ 'gradientDirection' }
1488 attrGradientColorOne={ 'gradientColorOne' }
1489 attrGradientColorStopOne={ 'gradientColorStopOne' }
1490 attrGradientColorTwo={ 'gradientColorTwo' }
1491 attrGradientColorStopTwo={ 'gradientColorStopTwo' }
1492 attrGradientColorOneOpacity={ 'gradientColorOneOpacity' }
1493 attrGradientColorTwoOpacity={ 'gradientColorTwoOpacity' }
1494 defaultColorOne={ blockDefaults.gradientColorOne }
1495 defaultColorTwo={ blockDefaults.gradientColorTwo }
1496 />
1497
1498 { applyFilters( 'generateblocks.editor.controls', '', 'containerBackground', props, state ) }
1499 </Fragment>
1500 </PanelArea>
1501
1502 <PanelArea
1503 { ...props }
1504 title={ __( 'Shapes', 'generateblocks' ) }
1505 initialOpen={ false }
1506 icon={ getIcon( 'shapes' ) }
1507 className={ 'gblocks-panel-label' }
1508 id={ 'containerShapes' }
1509 state={ state }
1510 showPanel={ 'Desktop' === deviceType || attributes.shapeDividers.length ? true : false }
1511 >
1512 <BaseControl className="gb-icon-chooser gb-shape-chooser">
1513 {
1514 shapeDividers.map( ( location, index ) => {
1515 const shapeNumber = index + 1;
1516
1517 return <Fragment key={ index }>
1518 <div className="gblocks-shape-container">
1519 <div
1520 className={ classnames( {
1521 'gblocks-shape-toggle-preview': true,
1522 [ `gblocks-shape-toggle-preview-${ shapeNumber }` ]: true,
1523 } ) }
1524 style={ { backgroundColor } }
1525 >
1526 { 'undefined' !== typeof allShapes[ shapeDividers[ index ].shape ] &&
1527 <div
1528 className="gblocks-shape-divider-preview"
1529 style={ { color: shapeDividers[ index ].color } }
1530 dangerouslySetInnerHTML={ { __html: sanitizeSVG( allShapes[ shapeDividers[ index ].shape ].icon ) } }
1531 />
1532 }
1533 </div>
1534
1535 {
1536 /* translators: Shape number */
1537 sprintf( __( 'Shape %s', 'generateblocks' ), shapeNumber )
1538 }
1539
1540 <Fragment>
1541 <Dropdown
1542 contentClassName="gblocks-shapes-dropdown"
1543 renderToggle={ ( { isOpen, onToggle } ) => (
1544 <Tooltip text={ __( 'Edit Shape', 'generateblocks' ) }>
1545 <Button
1546 className="gblocks-shape-dropdown"
1547 isSecondary={ isOpen ? undefined : true }
1548 isPrimary={ isOpen ? true : undefined }
1549 icon={ getIcon( 'wrench' ) }
1550 onClick={ onToggle }
1551 aria-expanded={ isOpen }
1552 />
1553 </Tooltip>
1554 ) }
1555 renderContent={ () => (
1556 <div className="gblocks-shape-controls">
1557 { 'Desktop' === deviceType &&
1558 <Fragment>
1559 <BaseControl className="gb-icon-chooser">
1560 {
1561 Object.keys( generateBlocksInfo.svgShapes ).map( ( svg, i ) => {
1562 const svgItems = generateBlocksInfo.svgShapes[ svg ].svgs;
1563
1564 return (
1565 <PanelBody
1566 title={ generateBlocksInfo.svgShapes[ svg ].group }
1567 initialOpen={ svgItems.hasOwnProperty( shapeDividers[ index ].shape ) }
1568 key={ i }
1569 >
1570 <PanelRow>
1571 <BaseControl>
1572 <ul className="gblocks-icon-chooser gblocks-shape-chooser">
1573 {
1574 Object.keys( svgItems ).map( ( svgItem, iconIndex ) => {
1575 return (
1576 <li key={ `editor-pblock-types-list-item-${ iconIndex }` }>
1577 <Tooltip text={ ( svgItems[ svgItem ].label ) }>
1578 <Button
1579 className={ classnames( {
1580 'editor-block-list-item-button': true,
1581 'gblocks-shape-is-active': shapeDividers[ index ].shape === svgItem,
1582 } ) }
1583 onClick={ () => {
1584 const shapes = [ ...shapeDividers ];
1585
1586 shapes[ index ] = {
1587 ...shapes[ index ],
1588 shape: svgItem,
1589 };
1590
1591 setAttributes( {
1592 shapeDividers: shapes,
1593 } );
1594 } }
1595 >
1596 { 'string' === typeof svgItems[ svgItem ].icon ? (
1597 <Fragment>
1598 <span
1599 className="editor-block-types-list__item-icon"
1600 dangerouslySetInnerHTML={ { __html: sanitizeSVG( svgItems[ svgItem ].icon ) } }
1601 />
1602 </Fragment>
1603 ) : (
1604 <Fragment>
1605 <span className="editor-block-types-list__item-icon">
1606 { svgItems[ svgItem ].icon }
1607 </span>
1608 </Fragment>
1609 ) }
1610 </Button>
1611 </Tooltip>
1612 </li>
1613 );
1614 } )
1615 }
1616 </ul>
1617 </BaseControl>
1618 </PanelRow>
1619 </PanelBody>
1620 );
1621 } )
1622 }
1623 </BaseControl>
1624
1625 <BaseControl>
1626 <ColorPicker
1627 label={ __( 'Color', 'generateblocks' ) }
1628 value={ shapeDividers[ index ].color }
1629 alpha={ true }
1630 valueOpacity={ shapeDividers[ index ].colorOpacity }
1631 onChange={ ( value ) => {
1632 const shapes = [ ...shapeDividers ];
1633
1634 shapes[ index ] = {
1635 ...shapes[ index ],
1636 color: value,
1637 };
1638
1639 setAttributes( {
1640 shapeDividers: shapes,
1641 } );
1642 } }
1643 onOpacityChange={ ( value ) => {
1644 const shapes = [ ...shapeDividers ];
1645
1646 shapes[ index ] = {
1647 ...shapes[ index ],
1648 colorOpacity: value,
1649 };
1650
1651 setAttributes( {
1652 shapeDividers: shapes,
1653 } );
1654 } }
1655 />
1656 </BaseControl>
1657
1658 <SelectControl
1659 label={ __( 'Location', 'generateblocks' ) }
1660 value={ shapeDividers[ index ].location }
1661 options={ [
1662 { label: __( 'Top', 'generateblocks' ), value: 'top' },
1663 { label: __( 'Bottom', 'generateblocks' ), value: 'bottom' },
1664 ] }
1665 onChange={ ( value ) => {
1666 const shapes = [ ...shapeDividers ];
1667
1668 shapes[ index ] = {
1669 ...shapes[ index ],
1670 location: value,
1671 };
1672
1673 setAttributes( {
1674 shapeDividers: shapes,
1675 } );
1676 } }
1677 />
1678
1679 <UnitPicker
1680 label={ __( 'Height', 'generateblocks' ) }
1681 value={ 'px' }
1682 units={ [ 'px' ] }
1683 onClick={ () => {
1684 return false;
1685 } }
1686 />
1687
1688 <TextControl
1689 type={ 'number' }
1690 value={ shapeDividers[ index ].height ? shapeDividers[ index ].height : '' }
1691 onChange={ ( value ) => {
1692 const shapes = [ ...shapeDividers ];
1693
1694 shapes[ index ] = {
1695 ...shapes[ index ],
1696 height: parseFloat( value ),
1697 };
1698
1699 setAttributes( {
1700 shapeDividers: shapes,
1701 } );
1702 } }
1703 />
1704
1705 <UnitPicker
1706 label={ __( 'Width', 'generateblocks' ) }
1707 value={ '%' }
1708 units={ [ '%' ] }
1709 onClick={ () => {
1710 return false;
1711 } }
1712 />
1713
1714 <TextControl
1715 type={ 'number' }
1716 value={ shapeDividers[ index ].width ? shapeDividers[ index ].width : '' }
1717 min="100"
1718 onChange={ ( value ) => {
1719 const shapes = [ ...shapeDividers ];
1720
1721 shapes[ index ] = {
1722 ...shapes[ index ],
1723 width: parseFloat( value ),
1724 };
1725
1726 setAttributes( {
1727 shapeDividers: shapes,
1728 } );
1729 } }
1730 />
1731
1732 <ToggleControl
1733 label={ __( 'Flip Horizontally', 'generateblocks' ) }
1734 checked={ !! shapeDividers[ index ].flipHorizontally }
1735 onChange={ ( value ) => {
1736 const shapes = [ ...shapeDividers ];
1737
1738 shapes[ index ] = {
1739 ...shapes[ index ],
1740 flipHorizontally: value,
1741 };
1742
1743 setAttributes( {
1744 shapeDividers: shapes,
1745 } );
1746 } }
1747 />
1748
1749 <TextControl
1750 label={ __( 'z-index', 'generateblocks' ) }
1751 type={ 'number' }
1752 min="0"
1753 value={ shapeDividers[ index ].zindex || 0 === shapeDividers[ index ].zindex ? shapeDividers[ index ].zindex : '' }
1754 onChange={ ( value ) => {
1755 const shapes = [ ...shapeDividers ];
1756
1757 shapes[ index ] = {
1758 ...shapes[ index ],
1759 zindex: value,
1760 };
1761
1762 setAttributes( {
1763 shapeDividers: shapes,
1764 } );
1765 } }
1766 onBlur={ () => {
1767 const shapes = [ ...shapeDividers ];
1768
1769 shapes[ index ] = {
1770 ...shapes[ index ],
1771 zindex: parseFloat( shapeDividers[ index ].zindex ),
1772 };
1773
1774 setAttributes( {
1775 shapeDividers: shapes,
1776 } );
1777 } }
1778 onClick={ ( e ) => {
1779 // Make sure onBlur fires in Firefox.
1780 e.currentTarget.focus();
1781 } }
1782 />
1783 </Fragment>
1784 }
1785
1786 { 'Tablet' === deviceType &&
1787 <Fragment>
1788 <UnitPicker
1789 label={ __( 'Height', 'generateblocks' ) }
1790 value={ 'px' }
1791 units={ [ 'px' ] }
1792 onClick={ () => {
1793 return false;
1794 } }
1795 />
1796
1797 <TextControl
1798 type={ 'number' }
1799 value={ shapeDividers[ index ].heightTablet ? shapeDividers[ index ].heightTablet : '' }
1800 onChange={ ( value ) => {
1801 const shapes = [ ...shapeDividers ];
1802
1803 shapes[ index ] = {
1804 ...shapes[ index ],
1805 heightTablet: parseFloat( value ),
1806 };
1807
1808 setAttributes( {
1809 shapeDividers: shapes,
1810 } );
1811 } }
1812 />
1813
1814 <UnitPicker
1815 label={ __( 'Width', 'generateblocks' ) }
1816 value={ '%' }
1817 units={ [ '%' ] }
1818 onClick={ () => {
1819 return false;
1820 } }
1821 />
1822
1823 <TextControl
1824 type={ 'number' }
1825 value={ shapeDividers[ index ].widthTablet ? shapeDividers[ index ].widthTablet : '' }
1826 min="100"
1827 onChange={ ( value ) => {
1828 const shapes = [ ...shapeDividers ];
1829
1830 shapes[ index ] = {
1831 ...shapes[ index ],
1832 widthTablet: parseFloat( value ),
1833 };
1834
1835 setAttributes( {
1836 shapeDividers: shapes,
1837 } );
1838 } }
1839 />
1840 </Fragment>
1841 }
1842
1843 { 'Mobile' === deviceType &&
1844 <Fragment>
1845 <UnitPicker
1846 label={ __( 'Height', 'generateblocks' ) }
1847 value={ 'px' }
1848 units={ [ 'px' ] }
1849 onClick={ () => {
1850 return false;
1851 } }
1852 />
1853
1854 <TextControl
1855 type={ 'number' }
1856 value={ shapeDividers[ index ].heightMobile ? shapeDividers[ index ].heightMobile : '' }
1857 onChange={ ( value ) => {
1858 const shapes = [ ...shapeDividers ];
1859
1860 shapes[ index ] = {
1861 ...shapes[ index ],
1862 heightMobile: parseFloat( value ),
1863 };
1864
1865 setAttributes( {
1866 shapeDividers: shapes,
1867 } );
1868 } }
1869 />
1870
1871 <UnitPicker
1872 label={ __( 'Width', 'generateblocks' ) }
1873 value={ '%' }
1874 units={ [ '%' ] }
1875 onClick={ () => {
1876 return false;
1877 } }
1878 />
1879
1880 <TextControl
1881 type={ 'number' }
1882 value={ shapeDividers[ index ].widthMobile ? shapeDividers[ index ].widthMobile : '' }
1883 min="100"
1884 onChange={ ( value ) => {
1885 const shapes = [ ...shapeDividers ];
1886
1887 shapes[ index ] = {
1888 ...shapes[ index ],
1889 widthMobile: parseFloat( value ),
1890 };
1891
1892 setAttributes( {
1893 shapeDividers: shapes,
1894 } );
1895 } }
1896 />
1897 </Fragment>
1898 }
1899 </div>
1900 ) }
1901 />
1902 </Fragment>
1903
1904 { 'Desktop' === deviceType &&
1905 <Tooltip text={ __( 'Delete Shape', 'generateblocks' ) }>
1906 <Button
1907 className="gblocks-remove-shape"
1908 onClick={ () => {
1909 // eslint-disable-next-line
1910 if ( window.confirm( __( 'This will permanently delete this shape.', 'generateblocks' ) ) ) {
1911 handleRemoveShape( index );
1912 }
1913 } }
1914 icon={ getIcon( 'x' ) }
1915 />
1916 </Tooltip>
1917 }
1918 </div>
1919 </Fragment>;
1920 } )
1921 }
1922
1923 <div className="gblocks-add-new-shape">
1924 <Button
1925 isSecondary
1926 onClick={ handleAddShape.bind( this ) }
1927 >
1928 { __( 'Add Shape', 'generateblocks' ) }
1929 </Button>
1930 </div>
1931 </BaseControl>
1932
1933 { applyFilters( 'generateblocks.editor.controls', '', 'containerShapeDivider', props, state ) }
1934 </PanelArea>
1935 </InspectorControls>
1936 );
1937 };
1938