frontblocks-edge-alignment-frontend.js
9 months ago
frontblocks-edge-alignment-option.jsx
2 months ago
frontblocks-edge-alignment-panel.css
1 week ago
frontblocks-edge-alignment.css
1 week ago
frontblocks-edge-alignment.js
2 months ago
frontblocks-edge-alignment-option.jsx
185 lines
| 1 | const { addFilter } = wp.hooks; |
| 2 | const { createHigherOrderComponent } = wp.compose; |
| 3 | const { Fragment } = wp.element; |
| 4 | const { InspectorControls } = wp.blockEditor; |
| 5 | const { PanelBody, SelectControl } = wp.components; |
| 6 | const { __ } = wp.i18n; |
| 7 | |
| 8 | const GB_BLOCKS = [ 'generateblocks/container', 'generateblocks/element' ]; |
| 9 | const NATIVE_BLOCKS = [ 'core/group', 'core/columns' ]; |
| 10 | const ALL_SUPPORTED_BLOCKS = [ ...GB_BLOCKS, ...NATIVE_BLOCKS ]; |
| 11 | |
| 12 | /** |
| 13 | * Add custom attributes to supported blocks. |
| 14 | */ |
| 15 | function addEdgeAlignmentAttributes( settings, name ) { |
| 16 | if ( ! ALL_SUPPORTED_BLOCKS.includes( name ) ) { |
| 17 | return settings; |
| 18 | } |
| 19 | |
| 20 | settings.attributes = Object.assign( settings.attributes, { |
| 21 | frblEdgeAlignment: { |
| 22 | type: 'string', |
| 23 | default: '', |
| 24 | }, |
| 25 | } ); |
| 26 | |
| 27 | return settings; |
| 28 | } |
| 29 | |
| 30 | addFilter( |
| 31 | 'blocks.registerBlockType', |
| 32 | 'frontblocks/edge-alignment-attributes', |
| 33 | addEdgeAlignmentAttributes |
| 34 | ); |
| 35 | |
| 36 | /** |
| 37 | * Check if a GenerateBlocks container uses the global container width. |
| 38 | * Only containers with var(--gb-container-width) should have edge alignment. |
| 39 | */ |
| 40 | function usesGlobalMaxWidth( attributes ) { |
| 41 | if ( ! attributes.styles || typeof attributes.styles !== 'object' ) { |
| 42 | return false; |
| 43 | } |
| 44 | |
| 45 | if ( |
| 46 | attributes.styles.maxWidth && |
| 47 | attributes.styles.maxWidth.includes( 'var(--gb-container-width)' ) |
| 48 | ) { |
| 49 | if ( |
| 50 | attributes.styles.marginLeft === 'auto' && |
| 51 | attributes.styles.marginRight === 'auto' |
| 52 | ) { |
| 53 | return true; |
| 54 | } |
| 55 | } |
| 56 | |
| 57 | return false; |
| 58 | } |
| 59 | |
| 60 | /** |
| 61 | * Check if a native block uses a constrained (centered, max-width) layout. |
| 62 | * Matches core/group and core/columns with constrained layout or inherited layout. |
| 63 | */ |
| 64 | function usesConstrainedLayout( attributes ) { |
| 65 | // No explicit layout — inherits from theme, which is typically constrained. |
| 66 | if ( ! attributes.layout ) { |
| 67 | return true; |
| 68 | } |
| 69 | return attributes.layout.type === 'constrained'; |
| 70 | } |
| 71 | |
| 72 | /** |
| 73 | * Add edge alignment controls to supported block inspector panels. |
| 74 | */ |
| 75 | const withEdgeAlignmentControls = createHigherOrderComponent( ( BlockEdit ) => { |
| 76 | return ( props ) => { |
| 77 | if ( ! ALL_SUPPORTED_BLOCKS.includes( props.name ) ) { |
| 78 | return <BlockEdit { ...props } />; |
| 79 | } |
| 80 | |
| 81 | const { attributes, setAttributes } = props; |
| 82 | const { frblEdgeAlignment } = attributes; |
| 83 | const isGBBlock = GB_BLOCKS.includes( props.name ); |
| 84 | |
| 85 | // Guard: only show panel when the block uses a centered/constrained layout. |
| 86 | const shouldShowPanel = isGBBlock |
| 87 | ? usesGlobalMaxWidth( attributes ) |
| 88 | : usesConstrainedLayout( attributes ); |
| 89 | |
| 90 | if ( ! shouldShowPanel ) { |
| 91 | return <BlockEdit { ...props } />; |
| 92 | } |
| 93 | |
| 94 | return ( |
| 95 | <Fragment> |
| 96 | <BlockEdit { ...props } /> |
| 97 | <InspectorControls> |
| 98 | <PanelBody |
| 99 | title={ __( 'FrontBlocks Edge Alignment', 'frontblocks' ) } |
| 100 | initialOpen={ false } |
| 101 | className="frbl-edge-alignment-panel" |
| 102 | > |
| 103 | <p className="frbl-edge-alignment-description"> |
| 104 | { __( |
| 105 | 'Remove padding from one side to create an edge-to-edge effect. Perfect for asymmetric layouts where content extends to the browser edge on one side.', |
| 106 | 'frontblocks' |
| 107 | ) } |
| 108 | </p> |
| 109 | <SelectControl |
| 110 | label={ __( 'Align to Edge', 'frontblocks' ) } |
| 111 | value={ frblEdgeAlignment } |
| 112 | options={ [ |
| 113 | { |
| 114 | label: __( 'None', 'frontblocks' ), |
| 115 | value: '', |
| 116 | }, |
| 117 | { |
| 118 | label: __( 'Remove Left Padding', 'frontblocks' ), |
| 119 | value: 'left', |
| 120 | }, |
| 121 | { |
| 122 | label: __( 'Remove Right Padding', 'frontblocks' ), |
| 123 | value: 'right', |
| 124 | }, |
| 125 | ] } |
| 126 | onChange={ ( value ) => |
| 127 | setAttributes( { frblEdgeAlignment: value } ) |
| 128 | } |
| 129 | help={ __( |
| 130 | 'Choose which side should extend to the browser edge.', |
| 131 | 'frontblocks' |
| 132 | ) } |
| 133 | /> |
| 134 | </PanelBody> |
| 135 | </InspectorControls> |
| 136 | </Fragment> |
| 137 | ); |
| 138 | }; |
| 139 | }, 'withEdgeAlignmentControls' ); |
| 140 | |
| 141 | addFilter( |
| 142 | 'editor.BlockEdit', |
| 143 | 'frontblocks/edge-alignment-controls', |
| 144 | withEdgeAlignmentControls |
| 145 | ); |
| 146 | |
| 147 | /** |
| 148 | * Add visual feedback classes in the editor. |
| 149 | */ |
| 150 | const addEdgeAlignmentClass = createHigherOrderComponent( ( BlockListBlock ) => { |
| 151 | return ( props ) => { |
| 152 | if ( ! ALL_SUPPORTED_BLOCKS.includes( props.name ) ) { |
| 153 | return <BlockListBlock { ...props } />; |
| 154 | } |
| 155 | |
| 156 | const { attributes } = props; |
| 157 | const { frblEdgeAlignment } = attributes; |
| 158 | |
| 159 | let additionalClasses = ''; |
| 160 | |
| 161 | if ( frblEdgeAlignment === 'left' ) { |
| 162 | additionalClasses = ' frbl-edge-left'; |
| 163 | } else if ( frblEdgeAlignment === 'right' ) { |
| 164 | additionalClasses = ' frbl-edge-right'; |
| 165 | } |
| 166 | |
| 167 | if ( additionalClasses ) { |
| 168 | return ( |
| 169 | <BlockListBlock |
| 170 | { ...props } |
| 171 | className={ props.className + additionalClasses } |
| 172 | /> |
| 173 | ); |
| 174 | } |
| 175 | |
| 176 | return <BlockListBlock { ...props } />; |
| 177 | }; |
| 178 | }, 'addEdgeAlignmentClass' ); |
| 179 | |
| 180 | addFilter( |
| 181 | 'editor.BlockListBlock', |
| 182 | 'frontblocks/edge-alignment-class', |
| 183 | addEdgeAlignmentClass |
| 184 | ); |
| 185 |