PluginProbe ʕ •ᴥ•ʔ
GenerateBlocks / 1.3.4
GenerateBlocks v1.3.4
trunk 1.0 1.0.1 1.0.2 1.1.0 1.1.1 1.1.2 1.2.0 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.6.0 1.7.0 1.7.1 1.7.2 1.7.3 1.8.0 1.8.1 1.8.2 1.8.3 1.9.0 1.9.1 2.0.0 2.0.1 2.0.2 2.1.0 2.1.1 2.1.2 2.2.0 2.2.1 2.3.0
generateblocks / src / blocks / button-container / edit.js
generateblocks / src / blocks / button-container 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
492 lines
1 /**
2 * Block: Button Container
3 */
4
5 import classnames from 'classnames';
6 import DimensionsControl from '../../components/dimensions/';
7 import ResponsiveTabs from '../../components/responsive-tabs';
8 import getIcon from '../../utils/get-icon';
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 Tooltip,
22 Button,
23 ToggleControl,
24 ToolbarGroup,
25 ToolbarButton,
26 TextControl,
27 } from '@wordpress/components';
28
29 import {
30 Fragment,
31 Component,
32 } from '@wordpress/element';
33
34 import {
35 InspectorControls,
36 InnerBlocks,
37 AlignmentToolbar,
38 BlockControls,
39 InspectorAdvancedControls,
40 } from '@wordpress/block-editor';
41
42 import {
43 createBlock,
44 cloneBlock,
45 } from '@wordpress/blocks';
46
47 import {
48 applyFilters,
49 } from '@wordpress/hooks';
50
51 import {
52 withSelect,
53 withDispatch,
54 } from '@wordpress/data';
55
56 import {
57 compose,
58 } from '@wordpress/compose';
59
60 /**
61 * Regular expression matching invalid anchor characters for replacement.
62 *
63 * @type {RegExp}
64 */
65 const ANCHOR_REGEX = /[\s#]/g;
66
67 const gbButtonContainerIds = [];
68
69 const ALIGNMENT_CONTROLS = [
70 {
71 icon: 'editor-alignleft',
72 title: __( 'Align Buttons Left', 'generateblocks' ),
73 align: 'left',
74 },
75 {
76 icon: 'editor-aligncenter',
77 title: __( 'Align Buttons Center', 'generateblocks' ),
78 align: 'center',
79 },
80 {
81 icon: 'editor-alignright',
82 title: __( 'Align Buttons Right', 'generateblocks' ),
83 align: 'right',
84 },
85 ];
86
87 class GenerateButtonContainer extends Component {
88 constructor() {
89 super( ...arguments );
90
91 this.state = {
92 selectedDevice: 'Desktop',
93 };
94
95 this.getDeviceType = this.getDeviceType.bind( this );
96 this.setDeviceType = this.setDeviceType.bind( this );
97 }
98
99 componentDidMount() {
100 const id = this.props.clientId.substr( 2, 9 ).replace( '-', '' );
101
102 // We don't want to ever regenerate unique IDs if they're a global style.
103 const isGlobalStyle = 'undefined' !== typeof this.props.attributes.isGlobalStyle && this.props.attributes.isGlobalStyle;
104
105 if ( ! this.props.attributes.uniqueId ) {
106 this.props.setAttributes( {
107 uniqueId: id,
108 } );
109
110 gbButtonContainerIds.push( id );
111 } else if ( gbButtonContainerIds.includes( this.props.attributes.uniqueId ) && ! isGlobalStyle ) {
112 this.props.setAttributes( {
113 uniqueId: id,
114 } );
115
116 gbButtonContainerIds.push( id );
117 } else {
118 gbButtonContainerIds.push( this.props.attributes.uniqueId );
119 }
120
121 const thisBlock = wp.data.select( 'core/block-editor' ).getBlocksByClientId( this.props.clientId )[ 0 ];
122
123 if ( thisBlock ) {
124 const childBlocks = thisBlock.innerBlocks;
125
126 if ( 0 === childBlocks.length ) {
127 wp.data.dispatch( 'core/block-editor' ).insertBlocks( createBlock( 'generateblocks/button', generateBlocksStyling.button ), undefined, this.props.clientId );
128 }
129 }
130
131 // This block used to be static. Set it to dynamic by default from now on.
132 if ( 'undefined' === typeof this.props.attributes.isDynamic || ! this.props.attributes.isDynamic ) {
133 this.props.setAttributes( {
134 isDynamic: true,
135 } );
136 }
137 }
138
139 getDeviceType() {
140 let deviceType = this.props.deviceType ? this.props.deviceType : this.state.selectedDevice;
141
142 if ( ! generateBlocksInfo.syncResponsivePreviews ) {
143 deviceType = this.state.selectedDevice;
144 }
145
146 return deviceType;
147 }
148
149 setDeviceType( deviceType ) {
150 if ( generateBlocksInfo.syncResponsivePreviews && this.props.deviceType ) {
151 this.props.setDeviceType( deviceType );
152 this.setState( { selectedDevice: deviceType } );
153 } else {
154 this.setState( { selectedDevice: deviceType } );
155 }
156 }
157
158 render() {
159 const {
160 attributes,
161 setAttributes,
162 clientId,
163 } = this.props;
164
165 const {
166 uniqueId,
167 className,
168 anchor,
169 alignment,
170 alignmentTablet,
171 alignmentMobile,
172 stack,
173 stackTablet,
174 stackMobile,
175 fillHorizontalSpace,
176 fillHorizontalSpaceTablet,
177 fillHorizontalSpaceMobile,
178 } = attributes;
179
180 let htmlAttributes = {
181 className: classnames( {
182 'gb-button-wrapper': true,
183 [ `gb-button-wrapper-${ uniqueId }` ]: true,
184 [ `${ className }` ]: undefined !== className,
185 } ),
186 id: anchor ? anchor : null,
187 };
188
189 htmlAttributes = applyFilters( 'generateblocks.frontend.htmlAttributes', htmlAttributes, 'generateblocks/button-container', attributes );
190
191 return (
192 <Fragment>
193 <BlockControls>
194 <ToolbarGroup>
195 <ToolbarButton
196 className="gblocks-add-new-button"
197 icon={ 'insert' }
198 label={ __( 'Add Button', 'generateblocks' ) }
199 onClick={ () => {
200 const thisBlock = wp.data.select( 'core/block-editor' ).getBlocksByClientId( clientId )[ 0 ];
201
202 if ( thisBlock ) {
203 const childBlocks = thisBlock.innerBlocks;
204 const keys = Object.keys( childBlocks );
205 const lastKey = keys[ keys.length - 1 ];
206
207 if ( typeof childBlocks[ lastKey ] !== 'undefined' ) {
208 const blockToCopyId = childBlocks[ lastKey ].clientId;
209
210 if ( blockToCopyId ) {
211 const blockToCopy = wp.data.select( 'core/block-editor' ).getBlocksByClientId( blockToCopyId )[ 0 ];
212 const clonedBlock = cloneBlock( blockToCopy );
213
214 wp.data.dispatch( 'core/block-editor' ).insertBlocks( clonedBlock, undefined, clientId );
215 }
216 } else if ( 0 === childBlocks.length ) {
217 wp.data.dispatch( 'core/block-editor' ).insertBlocks( createBlock( 'generateblocks/button', generateBlocksStyling.button ), undefined, clientId );
218 }
219 }
220 } }
221 showTooltip
222 />
223 </ToolbarGroup>
224
225 { 'Desktop' === this.getDeviceType() && (
226 <AlignmentToolbar
227 value={ alignment }
228 alignmentControls={ ALIGNMENT_CONTROLS }
229 onChange={ ( nextAlign ) => {
230 setAttributes( { alignment: nextAlign } );
231 } }
232 />
233 ) }
234
235 { 'Tablet' === this.getDeviceType() && (
236 <AlignmentToolbar
237 value={ alignmentTablet }
238 alignmentControls={ ALIGNMENT_CONTROLS }
239 onChange={ ( value ) => {
240 setAttributes( { alignmentTablet: value } );
241 } }
242 />
243 ) }
244
245 { 'Mobile' === this.getDeviceType() && (
246 <AlignmentToolbar
247 value={ alignmentMobile }
248 alignmentControls={ ALIGNMENT_CONTROLS }
249 onChange={ ( value ) => {
250 setAttributes( { alignmentMobile: value } );
251 } }
252 />
253 ) }
254 </BlockControls>
255
256 <InspectorControls>
257 <ResponsiveTabs { ...this.props }
258 selectedDevice={ this.getDeviceType() }
259 onClick={ ( device ) => {
260 this.setDeviceType( device );
261 } }
262 />
263
264 <PanelArea { ...this.props }
265 title={ __( 'Spacing', 'generateblocks' ) }
266 initialOpen={ true }
267 icon={ getIcon( 'spacing' ) }
268 className={ 'gblocks-panel-label' }
269 id={ 'buttonContainerSpacing' }
270 state={ this.state }
271 >
272 { 'Desktop' === this.getDeviceType() && (
273 <Fragment>
274 <DimensionsControl { ...this.props }
275 device={ this.getDeviceType() }
276 type={ 'margin' }
277 label={ __( 'Margin', 'generateblocks' ) }
278 attrTop={ 'marginTop' }
279 attrRight={ 'marginRight' }
280 attrBottom={ 'marginBottom' }
281 attrLeft={ 'marginLeft' }
282 attrUnit={ 'marginUnit' }
283 attrSyncUnits={ 'marginSyncUnits' }
284 defaults={ generateBlocksDefaults.buttonContainer }
285 units={ [ 'px', 'em', '%' ] }
286 />
287
288 <ToggleControl
289 label={ __( 'Stack Vertically', 'generateblocks' ) }
290 checked={ !! stack }
291 onChange={ ( value ) => {
292 setAttributes( {
293 stack: value,
294 } );
295 } }
296 />
297
298 <ToggleControl
299 label={ __( 'Fill Horizontal Space', 'generateblocks' ) }
300 checked={ !! fillHorizontalSpace }
301 onChange={ ( value ) => {
302 setAttributes( {
303 fillHorizontalSpace: value,
304 } );
305 } }
306 />
307 </Fragment>
308 ) }
309
310 { 'Tablet' === this.getDeviceType() && (
311 <Fragment>
312 <DimensionsControl { ...this.props }
313 device={ this.getDeviceType() }
314 type={ 'margin' }
315 label={ __( 'Margin', 'generateblocks' ) }
316 attrTop={ 'marginTopTablet' }
317 attrRight={ 'marginRightTablet' }
318 attrBottom={ 'marginBottomTablet' }
319 attrLeft={ 'marginLeftTablet' }
320 attrUnit={ 'marginUnit' }
321 attrSyncUnits={ 'marginSyncUnits' }
322 defaults={ generateBlocksDefaults.buttonContainer }
323 units={ [ 'px', 'em', '%' ] }
324 />
325
326 <ToggleControl
327 label={ __( 'Stack Vertically', 'generateblocks' ) }
328 checked={ !! stackTablet }
329 onChange={ ( value ) => {
330 setAttributes( {
331 stackTablet: value,
332 } );
333 } }
334 />
335
336 <ToggleControl
337 label={ __( 'Fill Horizontal Space', 'generateblocks' ) }
338 checked={ !! fillHorizontalSpaceTablet }
339 onChange={ ( value ) => {
340 setAttributes( {
341 fillHorizontalSpaceTablet: value,
342 } );
343 } }
344 />
345 </Fragment>
346 ) }
347
348 { 'Mobile' === this.getDeviceType() && (
349 <Fragment>
350 <DimensionsControl { ...this.props }
351 device={ this.getDeviceType() }
352 type={ 'margin' }
353 label={ __( 'Margin', 'generateblocks' ) }
354 attrTop={ 'marginTopMobile' }
355 attrRight={ 'marginRightMobile' }
356 attrBottom={ 'marginBottomMobile' }
357 attrLeft={ 'marginLeftMobile' }
358 attrUnit={ 'marginUnit' }
359 attrSyncUnits={ 'marginSyncUnits' }
360 defaults={ generateBlocksDefaults.buttonContainer }
361 units={ [ 'px', 'em', '%' ] }
362 />
363
364 <ToggleControl
365 label={ __( 'Stack Vertically', 'generateblocks' ) }
366 checked={ !! stackMobile }
367 onChange={ ( value ) => {
368 setAttributes( {
369 stackMobile: value,
370 } );
371 } }
372 />
373
374 <ToggleControl
375 label={ __( 'Fill Horizontal Space', 'generateblocks' ) }
376 checked={ !! fillHorizontalSpaceMobile }
377 onChange={ ( value ) => {
378 setAttributes( {
379 fillHorizontalSpaceMobile: value,
380 } );
381 } }
382 />
383 </Fragment>
384 ) }
385
386 { applyFilters( 'generateblocks.editor.controls', '', 'buttonContainerSpacing', this.props, this.state ) }
387 </PanelArea>
388
389 <PanelArea { ...this.props }
390 title={ __( 'Documentation', 'generateblocks' ) }
391 icon={ getIcon( 'documentation' ) }
392 initialOpen={ false }
393 className={ 'gblocks-panel-label' }
394 id={ 'buttonContainerDocumentation' }
395 state={ this.state }
396 >
397 <p>{ __( 'Need help with this block?', 'generateblocks' ) }</p>
398 <a href="https://docs.generateblocks.com/collection/buttons/" target="_blank" rel="noreferrer noopener">{ __( 'Visit our documentation', 'generateblocks' ) }</a>
399
400 { applyFilters( 'generateblocks.editor.controls', '', 'buttonContainerDocumentation', this.props, this.state ) }
401 </PanelArea>
402 </InspectorControls>
403
404 <InspectorAdvancedControls>
405 <TextControl
406 label={ __( 'HTML Anchor', 'generateblocks' ) }
407 help={ __( 'Anchors lets you link directly to a section on a page.', 'generateblocks' ) }
408 value={ anchor || '' }
409 onChange={ ( nextValue ) => {
410 nextValue = nextValue.replace( ANCHOR_REGEX, '-' );
411 setAttributes( {
412 anchor: nextValue,
413 } );
414 } } />
415 </InspectorAdvancedControls>
416
417 <MainCSS { ...this.props } />
418
419 { this.props.deviceType &&
420 <Fragment>
421 { 'Desktop' === this.props.deviceType &&
422 <DesktopCSS { ...this.props } />
423 }
424
425 { ( 'Tablet' === this.props.deviceType || 'Mobile' === this.props.deviceType ) &&
426 <TabletCSS { ...this.props } />
427 }
428
429 { 'Tablet' === this.props.deviceType &&
430 <TabletOnlyCSS { ...this.props } />
431 }
432
433 { 'Mobile' === this.props.deviceType &&
434 <MobileCSS { ...this.props } />
435 }
436 </Fragment>
437 }
438
439 <div
440 { ...htmlAttributes }
441 >
442 <InnerBlocks
443 allowedBlocks={ [ 'generateblocks/button' ] }
444 renderAppender={ () => (
445 <Tooltip text={ __( 'Add Button', 'generateblocks' ) }>
446 <Button
447 className="gblocks-add-new-button gblocks-button-container-appender"
448 icon={ 'insert' }
449 onClick={ () => {
450 wp.data.dispatch( 'core/block-editor' ).insertBlocks( createBlock( 'generateblocks/button', generateBlocksStyling.button ), undefined, clientId );
451 } }
452 />
453 </Tooltip>
454 ) }
455 />
456 </div>
457 </Fragment>
458 );
459 }
460 }
461
462 export default compose( [
463 withDispatch( ( dispatch ) => ( {
464 setDeviceType( type ) {
465 const {
466 __experimentalSetPreviewDeviceType: setPreviewDeviceType,
467 } = dispatch( 'core/edit-post' );
468
469 if ( ! setPreviewDeviceType ) {
470 return;
471 }
472
473 setPreviewDeviceType( type );
474 },
475 } ) ),
476 withSelect( ( select ) => {
477 const {
478 __experimentalGetPreviewDeviceType: getPreviewDeviceType,
479 } = select( 'core/edit-post' );
480
481 if ( ! getPreviewDeviceType ) {
482 return {
483 deviceType: null,
484 };
485 }
486
487 return {
488 deviceType: getPreviewDeviceType(),
489 };
490 } ),
491 ] )( GenerateButtonContainer );
492