css
6 years ago
attributes.js
6 years ago
block.js
6 years ago
edit.js
6 years ago
editor.scss
6 years ago
save.js
6 years ago
edit.js
410 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 DesktopCSS from './css/desktop.js'; |
| 10 | import PanelArea from '../../components/panel-area/'; |
| 11 | |
| 12 | const { __ } = wp.i18n; // Import __() from wp.i18n |
| 13 | const { |
| 14 | TextControl, |
| 15 | Tooltip, |
| 16 | Button, |
| 17 | ToggleControl, |
| 18 | Toolbar, |
| 19 | } = wp.components; |
| 20 | |
| 21 | const { |
| 22 | Fragment, |
| 23 | Component, |
| 24 | } = wp.element; |
| 25 | |
| 26 | const { |
| 27 | InspectorControls, |
| 28 | InnerBlocks, |
| 29 | AlignmentToolbar, |
| 30 | BlockControls, |
| 31 | } = wp.blockEditor; |
| 32 | |
| 33 | const { |
| 34 | createBlock, |
| 35 | cloneBlock, |
| 36 | } = wp.blocks; |
| 37 | |
| 38 | const { |
| 39 | applyFilters, |
| 40 | } = wp.hooks; |
| 41 | |
| 42 | const ELEMENT_ID_REGEX = /[\s#]/g; |
| 43 | const gbButtonContainerIds = []; |
| 44 | |
| 45 | const ALIGNMENT_CONTROLS = [ |
| 46 | { |
| 47 | icon: 'editor-alignleft', |
| 48 | title: __( 'Align Buttons Left', 'generateblocks' ), |
| 49 | align: 'left', |
| 50 | }, |
| 51 | { |
| 52 | icon: 'editor-aligncenter', |
| 53 | title: __( 'Align Buttons Center', 'generateblocks' ), |
| 54 | align: 'center', |
| 55 | }, |
| 56 | { |
| 57 | icon: 'editor-alignright', |
| 58 | title: __( 'Align Buttons Right', 'generateblocks' ), |
| 59 | align: 'right', |
| 60 | }, |
| 61 | ]; |
| 62 | |
| 63 | class GenerateButtonContainer extends Component { |
| 64 | constructor() { |
| 65 | super( ...arguments ); |
| 66 | |
| 67 | this.state = { |
| 68 | selectedDevice: 'desktop', |
| 69 | }; |
| 70 | } |
| 71 | |
| 72 | componentDidMount() { |
| 73 | const id = this.props.clientId.substr( 2, 9 ).replace( '-', '' ); |
| 74 | |
| 75 | if ( ! this.props.attributes.uniqueId ) { |
| 76 | this.props.setAttributes( { |
| 77 | uniqueId: id, |
| 78 | } ); |
| 79 | |
| 80 | gbButtonContainerIds.push( id ); |
| 81 | } else if ( gbButtonContainerIds.includes( this.props.attributes.uniqueId ) ) { |
| 82 | this.props.setAttributes( { |
| 83 | uniqueId: id, |
| 84 | } ); |
| 85 | |
| 86 | gbButtonContainerIds.push( id ); |
| 87 | } else { |
| 88 | gbButtonContainerIds.push( this.props.attributes.uniqueId ); |
| 89 | } |
| 90 | |
| 91 | const thisBlock = wp.data.select( 'core/block-editor' ).getBlocksByClientId( this.props.clientId )[ 0 ]; |
| 92 | |
| 93 | if ( thisBlock ) { |
| 94 | const childBlocks = thisBlock.innerBlocks; |
| 95 | |
| 96 | if ( 0 === childBlocks.length ) { |
| 97 | wp.data.dispatch( 'core/block-editor' ).insertBlocks( createBlock( 'generateblocks/button', generateBlocksStyling.button ), undefined, this.props.clientId ); |
| 98 | } |
| 99 | } |
| 100 | } |
| 101 | |
| 102 | render() { |
| 103 | const { |
| 104 | attributes, |
| 105 | setAttributes, |
| 106 | clientId, |
| 107 | } = this.props; |
| 108 | |
| 109 | const { |
| 110 | selectedDevice, |
| 111 | } = this.state; |
| 112 | |
| 113 | const { |
| 114 | uniqueId, |
| 115 | elementId, |
| 116 | cssClasses, |
| 117 | alignment, |
| 118 | alignmentTablet, |
| 119 | alignmentMobile, |
| 120 | stack, |
| 121 | stackTablet, |
| 122 | stackMobile, |
| 123 | fillHorizontalSpace, |
| 124 | fillHorizontalSpaceTablet, |
| 125 | fillHorizontalSpaceMobile, |
| 126 | } = attributes; |
| 127 | |
| 128 | return ( |
| 129 | <Fragment> |
| 130 | <BlockControls> |
| 131 | <Toolbar> |
| 132 | <Tooltip text={ __( 'Add Button', 'generateblocks' ) }> |
| 133 | <Button |
| 134 | className="gblocks-add-new-button" |
| 135 | icon={ 'insert' } |
| 136 | onClick={ () => { |
| 137 | const thisBlock = wp.data.select( 'core/block-editor' ).getBlocksByClientId( clientId )[ 0 ]; |
| 138 | |
| 139 | if ( thisBlock ) { |
| 140 | const childBlocks = thisBlock.innerBlocks; |
| 141 | const keys = Object.keys( childBlocks ); |
| 142 | const lastKey = keys[ keys.length - 1 ]; |
| 143 | |
| 144 | if ( typeof childBlocks[ lastKey ] !== 'undefined' ) { |
| 145 | const blockToCopyId = childBlocks[ lastKey ].clientId; |
| 146 | |
| 147 | if ( blockToCopyId ) { |
| 148 | const blockToCopy = wp.data.select( 'core/block-editor' ).getBlocksByClientId( blockToCopyId )[ 0 ]; |
| 149 | const clonedBlock = cloneBlock( blockToCopy ); |
| 150 | |
| 151 | wp.data.dispatch( 'core/block-editor' ).insertBlocks( clonedBlock, undefined, clientId ); |
| 152 | } |
| 153 | } else if ( 0 === childBlocks.length ) { |
| 154 | wp.data.dispatch( 'core/block-editor' ).insertBlocks( createBlock( 'generateblocks/button', generateBlocksStyling.button ), undefined, clientId ); |
| 155 | } |
| 156 | } |
| 157 | } } |
| 158 | /> |
| 159 | </Tooltip> |
| 160 | </Toolbar> |
| 161 | <AlignmentToolbar |
| 162 | isCollapsed={ false } |
| 163 | value={ alignment } |
| 164 | alignmentControls={ ALIGNMENT_CONTROLS } |
| 165 | onChange={ ( nextAlign ) => { |
| 166 | setAttributes( { alignment: nextAlign } ); |
| 167 | } } |
| 168 | /> |
| 169 | </BlockControls> |
| 170 | |
| 171 | <InspectorControls> |
| 172 | <ResponsiveTabs { ...this.props } |
| 173 | selectedDevice={ selectedDevice } |
| 174 | onClick={ ( device ) => { |
| 175 | this.setState( { |
| 176 | selectedDevice: device, |
| 177 | } ); |
| 178 | } } |
| 179 | /> |
| 180 | |
| 181 | <PanelArea { ...this.props } |
| 182 | title={ __( 'Spacing', 'generateblocks' ) } |
| 183 | initialOpen={ true } |
| 184 | icon={ getIcon( 'spacing' ) } |
| 185 | className={ 'gblocks-panel-label' } |
| 186 | id={ 'buttonContainerSpacing' } |
| 187 | state={ this.state } |
| 188 | > |
| 189 | { 'desktop' === selectedDevice && ( |
| 190 | <Fragment> |
| 191 | <AlignmentToolbar |
| 192 | isCollapsed={ false } |
| 193 | value={ alignment } |
| 194 | alignmentControls={ ALIGNMENT_CONTROLS } |
| 195 | onChange={ ( value ) => { |
| 196 | setAttributes( { alignment: value } ); |
| 197 | } } |
| 198 | /> |
| 199 | |
| 200 | <DimensionsControl { ...this.props } |
| 201 | device={ selectedDevice } |
| 202 | type={ 'margin' } |
| 203 | label={ __( 'Margin', 'generateblocks' ) } |
| 204 | attrTop={ 'marginTop' } |
| 205 | attrRight={ 'marginRight' } |
| 206 | attrBottom={ 'marginBottom' } |
| 207 | attrLeft={ 'marginLeft' } |
| 208 | attrUnit={ 'marginUnit' } |
| 209 | attrSyncUnits={ 'marginSyncUnits' } |
| 210 | defaults={ generateBlocksDefaults.buttonContainer } |
| 211 | /> |
| 212 | |
| 213 | <ToggleControl |
| 214 | label={ __( 'Stack Vertically', 'generateblocks' ) } |
| 215 | checked={ !! stack } |
| 216 | onChange={ ( value ) => { |
| 217 | setAttributes( { |
| 218 | stack: value, |
| 219 | } ); |
| 220 | } } |
| 221 | /> |
| 222 | |
| 223 | <ToggleControl |
| 224 | label={ __( 'Fill Horizontal Space', 'generateblocks' ) } |
| 225 | checked={ !! fillHorizontalSpace } |
| 226 | onChange={ ( value ) => { |
| 227 | setAttributes( { |
| 228 | fillHorizontalSpace: value, |
| 229 | } ); |
| 230 | } } |
| 231 | /> |
| 232 | </Fragment> |
| 233 | ) } |
| 234 | |
| 235 | { 'tablet' === selectedDevice && ( |
| 236 | <Fragment> |
| 237 | <AlignmentToolbar |
| 238 | isCollapsed={ false } |
| 239 | value={ alignmentTablet } |
| 240 | alignmentControls={ ALIGNMENT_CONTROLS } |
| 241 | onChange={ ( value ) => { |
| 242 | setAttributes( { alignmentTablet: value } ); |
| 243 | } } |
| 244 | /> |
| 245 | |
| 246 | <DimensionsControl { ...this.props } |
| 247 | device={ selectedDevice } |
| 248 | type={ 'margin' } |
| 249 | label={ __( 'Margin', 'generateblocks' ) } |
| 250 | attrTop={ 'marginTopTablet' } |
| 251 | attrRight={ 'marginRightTablet' } |
| 252 | attrBottom={ 'marginBottomTablet' } |
| 253 | attrLeft={ 'marginLeftTablet' } |
| 254 | attrUnit={ 'marginUnit' } |
| 255 | attrSyncUnits={ 'marginSyncUnits' } |
| 256 | defaults={ generateBlocksDefaults.buttonContainer } |
| 257 | /> |
| 258 | |
| 259 | <ToggleControl |
| 260 | label={ __( 'Stack Vertically', 'generateblocks' ) } |
| 261 | checked={ !! stackTablet } |
| 262 | onChange={ ( value ) => { |
| 263 | setAttributes( { |
| 264 | stackTablet: value, |
| 265 | } ); |
| 266 | } } |
| 267 | /> |
| 268 | |
| 269 | <ToggleControl |
| 270 | label={ __( 'Fill Horizontal Space', 'generateblocks' ) } |
| 271 | checked={ !! fillHorizontalSpaceTablet } |
| 272 | onChange={ ( value ) => { |
| 273 | setAttributes( { |
| 274 | fillHorizontalSpaceTablet: value, |
| 275 | } ); |
| 276 | } } |
| 277 | /> |
| 278 | </Fragment> |
| 279 | ) } |
| 280 | |
| 281 | { 'mobile' === selectedDevice && ( |
| 282 | <Fragment> |
| 283 | <AlignmentToolbar |
| 284 | isCollapsed={ false } |
| 285 | value={ alignmentMobile } |
| 286 | alignmentControls={ ALIGNMENT_CONTROLS } |
| 287 | onChange={ ( value ) => { |
| 288 | setAttributes( { alignmentMobile: value } ); |
| 289 | } } |
| 290 | /> |
| 291 | |
| 292 | <DimensionsControl { ...this.props } |
| 293 | device={ selectedDevice } |
| 294 | type={ 'margin' } |
| 295 | label={ __( 'Margin', 'generateblocks' ) } |
| 296 | attrTop={ 'marginTopMobile' } |
| 297 | attrRight={ 'marginRightMobile' } |
| 298 | attrBottom={ 'marginBottomMobile' } |
| 299 | attrLeft={ 'marginLeftMobile' } |
| 300 | attrUnit={ 'marginUnit' } |
| 301 | attrSyncUnits={ 'marginSyncUnits' } |
| 302 | defaults={ generateBlocksDefaults.buttonContainer } |
| 303 | /> |
| 304 | |
| 305 | <ToggleControl |
| 306 | label={ __( 'Stack Vertically', 'generateblocks' ) } |
| 307 | checked={ !! stackMobile } |
| 308 | onChange={ ( value ) => { |
| 309 | setAttributes( { |
| 310 | stackMobile: value, |
| 311 | } ); |
| 312 | } } |
| 313 | /> |
| 314 | |
| 315 | <ToggleControl |
| 316 | label={ __( 'Fill Horizontal Space', 'generateblocks' ) } |
| 317 | checked={ !! fillHorizontalSpaceMobile } |
| 318 | onChange={ ( value ) => { |
| 319 | setAttributes( { |
| 320 | fillHorizontalSpaceMobile: value, |
| 321 | } ); |
| 322 | } } |
| 323 | /> |
| 324 | </Fragment> |
| 325 | ) } |
| 326 | |
| 327 | { applyFilters( 'generateblocks.editor.controls', '', 'buttonContainerSpacing', this.props, this.state ) } |
| 328 | </PanelArea> |
| 329 | |
| 330 | <PanelArea { ...this.props } |
| 331 | title={ __( 'Advanced', 'generateblocks' ) } |
| 332 | initialOpen={ false } |
| 333 | icon={ getIcon( 'advanced' ) } |
| 334 | className={ 'gblocks-panel-label' } |
| 335 | id={ 'buttonContainerAdvanced' } |
| 336 | state={ this.state } |
| 337 | showPanel={ 'desktop' === selectedDevice || false } |
| 338 | > |
| 339 | <TextControl |
| 340 | label={ __( 'Element ID', 'generateblocks' ) } |
| 341 | value={ elementId } |
| 342 | onChange={ ( value ) => { |
| 343 | const newElementId = value.replace( ELEMENT_ID_REGEX, '-' ); |
| 344 | |
| 345 | setAttributes( { |
| 346 | elementId: newElementId, |
| 347 | } ); |
| 348 | } } |
| 349 | /> |
| 350 | |
| 351 | <TextControl |
| 352 | label={ __( 'CSS Classes', 'generateblocks' ) } |
| 353 | value={ cssClasses } |
| 354 | onChange={ ( value ) => { |
| 355 | setAttributes( { |
| 356 | cssClasses: value, |
| 357 | } ); |
| 358 | } } |
| 359 | /> |
| 360 | |
| 361 | { applyFilters( 'generateblocks.editor.controls', '', 'buttonContainerAdvanced', this.props, this.state ) } |
| 362 | </PanelArea> |
| 363 | |
| 364 | <PanelArea { ...this.props } |
| 365 | title={ __( 'Documentation', 'generateblocks' ) } |
| 366 | icon={ getIcon( 'documentation' ) } |
| 367 | initialOpen={ false } |
| 368 | className={ 'gblocks-panel-label' } |
| 369 | id={ 'buttonContainerDocumentation' } |
| 370 | state={ this.state } |
| 371 | > |
| 372 | <p>{ __( 'Need help with this block?', 'generateblocks' ) }</p> |
| 373 | <a href="https://docs.generateblocks.com/collection/buttons/" target="_blank" rel="noreferrer noopener">{ __( 'Visit our documentation', 'generateblocks' ) }</a> |
| 374 | |
| 375 | { applyFilters( 'generateblocks.editor.controls', '', 'buttonContainerDocumentation', this.props, this.state ) } |
| 376 | </PanelArea> |
| 377 | </InspectorControls> |
| 378 | |
| 379 | <DesktopCSS { ...this.props } /> |
| 380 | |
| 381 | <div |
| 382 | id={ !! elementId ? elementId : undefined } |
| 383 | className={ classnames( { |
| 384 | 'gb-button-wrapper': true, |
| 385 | [ `gb-button-wrapper-${ uniqueId }` ]: true, |
| 386 | [ `${ cssClasses }` ]: '' !== cssClasses, |
| 387 | } ) } |
| 388 | > |
| 389 | <InnerBlocks |
| 390 | allowedBlocks={ [ 'generateblocks/button' ] } |
| 391 | renderAppender={ () => ( |
| 392 | <Tooltip text={ __( 'Add Button', 'generateblocks' ) }> |
| 393 | <Button |
| 394 | className="gblocks-add-new-button gblocks-button-container-appender" |
| 395 | icon={ 'insert' } |
| 396 | onClick={ () => { |
| 397 | wp.data.dispatch( 'core/block-editor' ).insertBlocks( createBlock( 'generateblocks/button', generateBlocksStyling.button ), undefined, clientId ); |
| 398 | } } |
| 399 | /> |
| 400 | </Tooltip> |
| 401 | ) } |
| 402 | /> |
| 403 | </div> |
| 404 | </Fragment> |
| 405 | ); |
| 406 | } |
| 407 | } |
| 408 | |
| 409 | export default ( GenerateButtonContainer ); |
| 410 |