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 / 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
489 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 if ( ! this.props.attributes.uniqueId ) {
103 this.props.setAttributes( {
104 uniqueId: id,
105 } );
106
107 gbButtonContainerIds.push( id );
108 } else if ( gbButtonContainerIds.includes( this.props.attributes.uniqueId ) ) {
109 this.props.setAttributes( {
110 uniqueId: id,
111 } );
112
113 gbButtonContainerIds.push( id );
114 } else {
115 gbButtonContainerIds.push( this.props.attributes.uniqueId );
116 }
117
118 const thisBlock = wp.data.select( 'core/block-editor' ).getBlocksByClientId( this.props.clientId )[ 0 ];
119
120 if ( thisBlock ) {
121 const childBlocks = thisBlock.innerBlocks;
122
123 if ( 0 === childBlocks.length ) {
124 wp.data.dispatch( 'core/block-editor' ).insertBlocks( createBlock( 'generateblocks/button', generateBlocksStyling.button ), undefined, this.props.clientId );
125 }
126 }
127
128 // This block used to be static. Set it to dynamic by default from now on.
129 if ( 'undefined' === typeof this.props.attributes.isDynamic || ! this.props.attributes.isDynamic ) {
130 this.props.setAttributes( {
131 isDynamic: true,
132 } );
133 }
134 }
135
136 getDeviceType() {
137 let deviceType = this.props.deviceType ? this.props.deviceType : this.state.selectedDevice;
138
139 if ( ! generateBlocksInfo.syncResponsivePreviews ) {
140 deviceType = this.state.selectedDevice;
141 }
142
143 return deviceType;
144 }
145
146 setDeviceType( deviceType ) {
147 if ( generateBlocksInfo.syncResponsivePreviews && this.props.deviceType ) {
148 this.props.setDeviceType( deviceType );
149 this.setState( { selectedDevice: deviceType } );
150 } else {
151 this.setState( { selectedDevice: deviceType } );
152 }
153 }
154
155 render() {
156 const {
157 attributes,
158 setAttributes,
159 clientId,
160 } = this.props;
161
162 const {
163 uniqueId,
164 className,
165 anchor,
166 alignment,
167 alignmentTablet,
168 alignmentMobile,
169 stack,
170 stackTablet,
171 stackMobile,
172 fillHorizontalSpace,
173 fillHorizontalSpaceTablet,
174 fillHorizontalSpaceMobile,
175 } = attributes;
176
177 let htmlAttributes = {
178 className: classnames( {
179 'gb-button-wrapper': true,
180 [ `gb-button-wrapper-${ uniqueId }` ]: true,
181 [ `${ className }` ]: undefined !== className,
182 } ),
183 id: anchor ? anchor : null,
184 };
185
186 htmlAttributes = applyFilters( 'generateblocks.frontend.htmlAttributes', htmlAttributes, 'generateblocks/button-container', attributes );
187
188 return (
189 <Fragment>
190 <BlockControls>
191 <ToolbarGroup>
192 <ToolbarButton
193 className="gblocks-add-new-button"
194 icon={ 'insert' }
195 label={ __( 'Add Button', 'generateblocks' ) }
196 onClick={ () => {
197 const thisBlock = wp.data.select( 'core/block-editor' ).getBlocksByClientId( clientId )[ 0 ];
198
199 if ( thisBlock ) {
200 const childBlocks = thisBlock.innerBlocks;
201 const keys = Object.keys( childBlocks );
202 const lastKey = keys[ keys.length - 1 ];
203
204 if ( typeof childBlocks[ lastKey ] !== 'undefined' ) {
205 const blockToCopyId = childBlocks[ lastKey ].clientId;
206
207 if ( blockToCopyId ) {
208 const blockToCopy = wp.data.select( 'core/block-editor' ).getBlocksByClientId( blockToCopyId )[ 0 ];
209 const clonedBlock = cloneBlock( blockToCopy );
210
211 wp.data.dispatch( 'core/block-editor' ).insertBlocks( clonedBlock, undefined, clientId );
212 }
213 } else if ( 0 === childBlocks.length ) {
214 wp.data.dispatch( 'core/block-editor' ).insertBlocks( createBlock( 'generateblocks/button', generateBlocksStyling.button ), undefined, clientId );
215 }
216 }
217 } }
218 showTooltip
219 />
220 </ToolbarGroup>
221
222 { 'Desktop' === this.getDeviceType() && (
223 <AlignmentToolbar
224 value={ alignment }
225 alignmentControls={ ALIGNMENT_CONTROLS }
226 onChange={ ( nextAlign ) => {
227 setAttributes( { alignment: nextAlign } );
228 } }
229 />
230 ) }
231
232 { 'Tablet' === this.getDeviceType() && (
233 <AlignmentToolbar
234 value={ alignmentTablet }
235 alignmentControls={ ALIGNMENT_CONTROLS }
236 onChange={ ( value ) => {
237 setAttributes( { alignmentTablet: value } );
238 } }
239 />
240 ) }
241
242 { 'Mobile' === this.getDeviceType() && (
243 <AlignmentToolbar
244 value={ alignmentMobile }
245 alignmentControls={ ALIGNMENT_CONTROLS }
246 onChange={ ( value ) => {
247 setAttributes( { alignmentMobile: value } );
248 } }
249 />
250 ) }
251 </BlockControls>
252
253 <InspectorControls>
254 <ResponsiveTabs { ...this.props }
255 selectedDevice={ this.getDeviceType() }
256 onClick={ ( device ) => {
257 this.setDeviceType( device );
258 } }
259 />
260
261 <PanelArea { ...this.props }
262 title={ __( 'Spacing', 'generateblocks' ) }
263 initialOpen={ true }
264 icon={ getIcon( 'spacing' ) }
265 className={ 'gblocks-panel-label' }
266 id={ 'buttonContainerSpacing' }
267 state={ this.state }
268 >
269 { 'Desktop' === this.getDeviceType() && (
270 <Fragment>
271 <DimensionsControl { ...this.props }
272 device={ this.getDeviceType() }
273 type={ 'margin' }
274 label={ __( 'Margin', 'generateblocks' ) }
275 attrTop={ 'marginTop' }
276 attrRight={ 'marginRight' }
277 attrBottom={ 'marginBottom' }
278 attrLeft={ 'marginLeft' }
279 attrUnit={ 'marginUnit' }
280 attrSyncUnits={ 'marginSyncUnits' }
281 defaults={ generateBlocksDefaults.buttonContainer }
282 units={ [ 'px', 'em', '%' ] }
283 />
284
285 <ToggleControl
286 label={ __( 'Stack Vertically', 'generateblocks' ) }
287 checked={ !! stack }
288 onChange={ ( value ) => {
289 setAttributes( {
290 stack: value,
291 } );
292 } }
293 />
294
295 <ToggleControl
296 label={ __( 'Fill Horizontal Space', 'generateblocks' ) }
297 checked={ !! fillHorizontalSpace }
298 onChange={ ( value ) => {
299 setAttributes( {
300 fillHorizontalSpace: value,
301 } );
302 } }
303 />
304 </Fragment>
305 ) }
306
307 { 'Tablet' === this.getDeviceType() && (
308 <Fragment>
309 <DimensionsControl { ...this.props }
310 device={ this.getDeviceType() }
311 type={ 'margin' }
312 label={ __( 'Margin', 'generateblocks' ) }
313 attrTop={ 'marginTopTablet' }
314 attrRight={ 'marginRightTablet' }
315 attrBottom={ 'marginBottomTablet' }
316 attrLeft={ 'marginLeftTablet' }
317 attrUnit={ 'marginUnit' }
318 attrSyncUnits={ 'marginSyncUnits' }
319 defaults={ generateBlocksDefaults.buttonContainer }
320 units={ [ 'px', 'em', '%' ] }
321 />
322
323 <ToggleControl
324 label={ __( 'Stack Vertically', 'generateblocks' ) }
325 checked={ !! stackTablet }
326 onChange={ ( value ) => {
327 setAttributes( {
328 stackTablet: value,
329 } );
330 } }
331 />
332
333 <ToggleControl
334 label={ __( 'Fill Horizontal Space', 'generateblocks' ) }
335 checked={ !! fillHorizontalSpaceTablet }
336 onChange={ ( value ) => {
337 setAttributes( {
338 fillHorizontalSpaceTablet: value,
339 } );
340 } }
341 />
342 </Fragment>
343 ) }
344
345 { 'Mobile' === this.getDeviceType() && (
346 <Fragment>
347 <DimensionsControl { ...this.props }
348 device={ this.getDeviceType() }
349 type={ 'margin' }
350 label={ __( 'Margin', 'generateblocks' ) }
351 attrTop={ 'marginTopMobile' }
352 attrRight={ 'marginRightMobile' }
353 attrBottom={ 'marginBottomMobile' }
354 attrLeft={ 'marginLeftMobile' }
355 attrUnit={ 'marginUnit' }
356 attrSyncUnits={ 'marginSyncUnits' }
357 defaults={ generateBlocksDefaults.buttonContainer }
358 units={ [ 'px', 'em', '%' ] }
359 />
360
361 <ToggleControl
362 label={ __( 'Stack Vertically', 'generateblocks' ) }
363 checked={ !! stackMobile }
364 onChange={ ( value ) => {
365 setAttributes( {
366 stackMobile: value,
367 } );
368 } }
369 />
370
371 <ToggleControl
372 label={ __( 'Fill Horizontal Space', 'generateblocks' ) }
373 checked={ !! fillHorizontalSpaceMobile }
374 onChange={ ( value ) => {
375 setAttributes( {
376 fillHorizontalSpaceMobile: value,
377 } );
378 } }
379 />
380 </Fragment>
381 ) }
382
383 { applyFilters( 'generateblocks.editor.controls', '', 'buttonContainerSpacing', this.props, this.state ) }
384 </PanelArea>
385
386 <PanelArea { ...this.props }
387 title={ __( 'Documentation', 'generateblocks' ) }
388 icon={ getIcon( 'documentation' ) }
389 initialOpen={ false }
390 className={ 'gblocks-panel-label' }
391 id={ 'buttonContainerDocumentation' }
392 state={ this.state }
393 >
394 <p>{ __( 'Need help with this block?', 'generateblocks' ) }</p>
395 <a href="https://docs.generateblocks.com/collection/buttons/" target="_blank" rel="noreferrer noopener">{ __( 'Visit our documentation', 'generateblocks' ) }</a>
396
397 { applyFilters( 'generateblocks.editor.controls', '', 'buttonContainerDocumentation', this.props, this.state ) }
398 </PanelArea>
399 </InspectorControls>
400
401 <InspectorAdvancedControls>
402 <TextControl
403 label={ __( 'HTML Anchor' ) }
404 help={ __( 'Anchors lets you link directly to a section on a page.', 'generateblocks' ) }
405 value={ anchor || '' }
406 onChange={ ( nextValue ) => {
407 nextValue = nextValue.replace( ANCHOR_REGEX, '-' );
408 setAttributes( {
409 anchor: nextValue,
410 } );
411 } } />
412 </InspectorAdvancedControls>
413
414 <MainCSS { ...this.props } />
415
416 { this.props.deviceType &&
417 <Fragment>
418 { 'Desktop' === this.props.deviceType &&
419 <DesktopCSS { ...this.props } />
420 }
421
422 { ( 'Tablet' === this.props.deviceType || 'Mobile' === this.props.deviceType ) &&
423 <TabletCSS { ...this.props } />
424 }
425
426 { 'Tablet' === this.props.deviceType &&
427 <TabletOnlyCSS { ...this.props } />
428 }
429
430 { 'Mobile' === this.props.deviceType &&
431 <MobileCSS { ...this.props } />
432 }
433 </Fragment>
434 }
435
436 <div
437 { ...htmlAttributes }
438 >
439 <InnerBlocks
440 allowedBlocks={ [ 'generateblocks/button' ] }
441 renderAppender={ () => (
442 <Tooltip text={ __( 'Add Button', 'generateblocks' ) }>
443 <Button
444 className="gblocks-add-new-button gblocks-button-container-appender"
445 icon={ 'insert' }
446 onClick={ () => {
447 wp.data.dispatch( 'core/block-editor' ).insertBlocks( createBlock( 'generateblocks/button', generateBlocksStyling.button ), undefined, clientId );
448 } }
449 />
450 </Tooltip>
451 ) }
452 />
453 </div>
454 </Fragment>
455 );
456 }
457 }
458
459 export default compose( [
460 withDispatch( ( dispatch ) => ( {
461 setDeviceType( type ) {
462 const {
463 __experimentalSetPreviewDeviceType: setPreviewDeviceType,
464 } = dispatch( 'core/edit-post' );
465
466 if ( ! setPreviewDeviceType ) {
467 return;
468 }
469
470 setPreviewDeviceType( type );
471 },
472 } ) ),
473 withSelect( ( select ) => {
474 const {
475 __experimentalGetPreviewDeviceType: getPreviewDeviceType,
476 } = select( 'core/edit-post' );
477
478 if ( ! getPreviewDeviceType ) {
479 return {
480 deviceType: null,
481 };
482 }
483
484 return {
485 deviceType: getPreviewDeviceType(),
486 };
487 } ),
488 ] )( GenerateButtonContainer );
489