PluginProbe ʕ •ᴥ•ʔ
GenerateBlocks / 2.0.0
GenerateBlocks v2.0.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 / element / components / BlockSettings.jsx
generateblocks / src / blocks / element / components Last commit date
BlockSettings.jsx 1 year ago InlineBackgroundImage.jsx 1 year ago
BlockSettings.jsx
267 lines
1 import { __ } from '@wordpress/i18n';
2 import { Button, BaseControl, Notice } from '@wordpress/components';
3 import { useState } from '@wordpress/element';
4 import { createBlock, cloneBlock } from '@wordpress/blocks';
5 import { useDispatch, useSelect } from '@wordpress/data';
6 import { store as blockEditorStore } from '@wordpress/block-editor';
7
8 import { OpenPanel, IconModal } from '@edge22/components';
9
10 import {
11 ApplyFilters,
12 URLControls,
13 TagNameControl,
14 GridColumnSelector,
15 gridColumnLayouts as layouts,
16 DynamicTagsOnboarder,
17 } from '@components/index.js';
18 import { useBlockStyles } from '@hooks/useBlockStyles';
19 import { getElementType } from '../utils/getElementType';
20 import { InlineBackgroundImage } from './InlineBackgroundImage';
21
22 export function BlockSettings( {
23 getStyleValue,
24 onStyleChange,
25 name,
26 attributes,
27 setAttributes,
28 clientId,
29 htmlAttributes,
30 styles,
31 context,
32 } ) {
33 const {
34 tagName,
35 } = attributes;
36
37 const [ openShapeLibrary, setOpenShapeLibrary ] = useState( false );
38 const {
39 insertBlocks,
40 removeBlock,
41 } = useDispatch( blockEditorStore );
42 const { getBlock } = useSelect( ( select ) => select( blockEditorStore ), [] );
43 const {
44 currentAtRule,
45 } = useBlockStyles();
46
47 const panelProps = {
48 name,
49 attributes,
50 setAttributes,
51 clientId,
52 };
53
54 return (
55 <ApplyFilters
56 name="generateblocks.editor.blockControls"
57 blockName={ name }
58 getStyleValue={ getStyleValue }
59 onStyleChange={ onStyleChange }
60 currentAtRule={ currentAtRule }
61 attributes={ attributes }
62 setAttributes={ setAttributes }
63 >
64 <OpenPanel
65 { ...panelProps }
66 shouldRender={ 'a' === tagName && '' === currentAtRule }
67 panelId="link-destination"
68 >
69 <URLControls
70 label={ __( 'Link Destination', 'generateblocks' ) }
71 setAttributes={ setAttributes }
72 htmlAttributes={ htmlAttributes }
73 context={ context }
74 tagName={ tagName }
75 />
76 </OpenPanel>
77
78 <OpenPanel
79 { ...panelProps }
80 shouldRender={
81 'grid' === getStyleValue( 'display' ) &&
82 (
83 'grid' === getStyleValue( 'display', currentAtRule ) ||
84 '' === getStyleValue( 'display', currentAtRule )
85 )
86 }
87 panelId="grid"
88 >
89 <BaseControl
90 label={ __( 'Layout', 'generateblocks' ) }
91 id="grid-template-columns"
92 >
93 <GridColumnSelector
94 value={ getStyleValue( 'gridTemplateColumns', currentAtRule ) }
95 onClick={ ( value ) => {
96 if ( value === getStyleValue( 'gridTemplateColumns', currentAtRule ) ) {
97 // If the same layout is clicked, remove the layout.
98 onStyleChange( 'gridTemplateColumns', '', currentAtRule );
99 return;
100 }
101
102 onStyleChange( 'gridTemplateColumns', value, currentAtRule );
103
104 if ( '' !== currentAtRule ) {
105 // Don't add/remove blocks for at rules.
106 return;
107 }
108
109 const selectedLayout = layouts.find( ( { layout } ) => layout === value );
110 const selectedLayoutDivCount = selectedLayout?.divs || 0;
111 const innerBlocksCount = getBlock( clientId ).innerBlocks.length;
112
113 if ( selectedLayoutDivCount > innerBlocksCount ) {
114 const lastInnerBlock = getBlock( clientId ).innerBlocks[ innerBlocksCount - 1 ];
115
116 if ( lastInnerBlock ) {
117 const newBlockCount = selectedLayoutDivCount - innerBlocksCount;
118 const newBlocksToInsert = [];
119
120 for ( let i = 0; i < newBlockCount; i++ ) {
121 const clonedBlock = cloneBlock(
122 lastInnerBlock,
123 {
124 uniqueId: '',
125 }
126 );
127 newBlocksToInsert.push( clonedBlock );
128 }
129
130 insertBlocks( newBlocksToInsert, innerBlocksCount, clientId, false );
131 }
132 } else if ( selectedLayoutDivCount < innerBlocksCount ) {
133 const blocksToRemove = getBlock( clientId )?.innerBlocks
134 .slice( selectedLayoutDivCount )
135 .filter( ( block ) => (
136 'generateblocks/element' === block.name &&
137 0 === block.innerBlocks.length
138 ) );
139
140 if ( blocksToRemove.length ) {
141 blocksToRemove.forEach( ( block ) => {
142 removeBlock( block.clientId, false );
143 } );
144 }
145 }
146 } }
147 />
148 </BaseControl>
149 </OpenPanel>
150
151 <OpenPanel
152 { ...panelProps }
153 shouldRender={ '' === currentAtRule }
154 panelId="settings"
155 >
156 <TagNameControl
157 blockName="generateblocks/element"
158 value={ tagName }
159 onChange={ ( value ) => {
160 setAttributes( { tagName: value } );
161
162 if ( 'a' === value && ! styles?.display ) {
163 onStyleChange( 'display', 'block' );
164 }
165 } }
166 />
167
168 { 'a' === tagName && (
169 <BaseControl>
170 <Notice
171 status="warning"
172 isDismissible={ false }
173 >
174 { __( 'This container is now a link element. Be sure not to add any interactive elements inside of it, like buttons or other links.', 'generateblocks' ) }
175 </Notice>
176 </BaseControl>
177 ) }
178 </OpenPanel>
179
180 <OpenPanel
181 { ...panelProps }
182 shouldRender={ '' === currentAtRule }
183 panelId="shapes"
184 >
185 <BaseControl
186 label={ __( 'Shape', 'generateblocks' ) }
187 id="shape"
188 >
189 <Button
190 variant="secondary"
191 size="compact"
192 onClick={ () => setOpenShapeLibrary( true ) }
193 style={ { display: 'block' } }
194 >
195 { __( 'Open Shape Library', 'generateblocks' ) }
196 </Button>
197 </BaseControl>
198
199 { !! openShapeLibrary && (
200 <IconModal
201 title={ __( 'Shape Library', 'generateblocks' ) }
202 iconType="divider"
203 setIsOpen={ setOpenShapeLibrary }
204 icons={ generateBlocksInfo.svgShapes }
205 onChange={ ( value ) => {
206 setAttributes( {
207 styles: {
208 ...styles,
209 position: 'relative',
210 },
211 } );
212
213 const newShapeBlock = createBlock(
214 'generateblocks/shape',
215 {
216 html: value,
217 className: 'gb-shape--divider',
218 styles: {
219 position: 'absolute',
220 bottom: '0',
221 left: '0',
222 right: '0',
223 overflowX: 'hidden',
224 overflowY: 'hidden',
225 pointerEvents: 'none',
226 color: '#000000',
227 svg: {
228 fill: 'currentColor',
229 width: '100%',
230 },
231 },
232 },
233 );
234
235 insertBlocks(
236 newShapeBlock,
237 0,
238 clientId,
239 true
240 );
241
242 setOpenShapeLibrary( false );
243 } }
244 />
245 ) }
246 </OpenPanel>
247
248 <OpenPanel
249 { ...panelProps }
250 shouldRender={ 'container' === getElementType( tagName ) && '' === currentAtRule }
251 panelId="inline-background-image"
252 >
253 <InlineBackgroundImage
254 label={ __( 'Inline Background Image', 'generateblocks' ) }
255 htmlAttributes={ htmlAttributes }
256 setAttributes={ setAttributes }
257 styles={ styles }
258 onStyleChange={ onStyleChange }
259 context={ context }
260 />
261 </OpenPanel>
262
263 <DynamicTagsOnboarder />
264 </ApplyFilters>
265 );
266 }
267