PluginProbe ʕ •ᴥ•ʔ
GenerateBlocks / 2.0.2
GenerateBlocks v2.0.2
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 / media / components / BlockSettings.jsx
generateblocks / src / blocks / media / components Last commit date
BlockSettings.jsx 1 year ago Image.jsx 1 year ago ImagePlaceholder.jsx 1 year ago
BlockSettings.jsx
267 lines
1 import { __ } from '@wordpress/i18n';
2 import { SelectControl, TextControl, Flex, FlexBlock } from '@wordpress/components';
3 import { useEffect, useState, useMemo, useCallback } from '@wordpress/element';
4 import apiFetch from '@wordpress/api-fetch';
5 import { addQueryArgs, isURL } from '@wordpress/url';
6 import { applyFilters } from '@wordpress/hooks';
7 import { debounce } from '@wordpress/compose';
8
9 import { OpenPanel } from '@edge22/components';
10 import { UnitControl } from '@edge22/styles-builder';
11
12 import {
13 ApplyFilters,
14 ImageUpload,
15 URLControls,
16 DynamicTagsOnboarder,
17 } from '@components/index.js';
18 import { useBlockStyles } from '@hooks/useBlockStyles';
19
20 async function getImageByUrl( url ) {
21 const image = await apiFetch( {
22 path: addQueryArgs( `/generateblocks/v1/get-attachment-by-url`, {
23 url,
24 } ),
25 method: 'GET',
26 } );
27
28 if ( image.success ) {
29 return image.response;
30 }
31
32 return null;
33 }
34
35 export function BlockSettings( {
36 getStyleValue,
37 onStyleChange,
38 name,
39 attributes,
40 setAttributes,
41 onSelectImage,
42 htmlAttributes,
43 context,
44 } ) {
45 const {
46 linkHtmlAttributes,
47 mediaId,
48 tagName,
49 } = attributes;
50
51 const {
52 currentAtRule,
53 } = useBlockStyles();
54 const [ imageData, setImageData ] = useState( null );
55 const [ hasResolved, setHasResolved ] = useState( false );
56
57 const debouncedOnStyleChange = useCallback(
58 debounce( ( property, value, atRule ) => {
59 onStyleChange( property, value, atRule );
60 }, 250 ),
61 [ onStyleChange ]
62 );
63
64 useEffect( () => {
65 if ( ! isURL( htmlAttributes?.src ) ) {
66 return;
67 }
68
69 ( async function() {
70 try {
71 const image = await getImageByUrl( htmlAttributes?.src );
72
73 if ( image ) {
74 setImageData( image );
75 }
76
77 setHasResolved( true );
78 } catch ( error ) {
79 console.info( 'Error fetching image:', error ); // eslint-disable-line no-console
80 setHasResolved( true );
81 }
82 }() );
83 }, [ htmlAttributes?.src ] );
84
85 useEffect( () => {
86 const id = imageData?.id;
87
88 if ( hasResolved && id !== mediaId ) {
89 setAttributes( {
90 mediaId: id ?? 0,
91 } );
92 }
93 }, [ imageData?.id ] );
94
95 const sizes = useMemo( () => {
96 const imageSizes = imageData?.sizes
97 ? Object.keys( imageData?.sizes )
98 : [];
99
100 if ( ! imageSizes.length ) {
101 return [];
102 }
103
104 const options = imageSizes.map( ( imageSize ) => {
105 return {
106 label: imageSize.charAt( 0 ).toUpperCase() + imageSize.slice( 1 ),
107 value: imageSize,
108 };
109 } );
110
111 options.unshift( { label: __( 'Full', 'generateblocks-pro' ), value: '' } );
112
113 return options;
114 }, [ imageData?.sizes ] );
115
116 const imageSizeValue = useMemo( () => {
117 const imageSizes = imageData?.sizes
118 ? Object.keys( imageData?.sizes )
119 : [];
120
121 if ( ! imageSizes.length ) {
122 return '';
123 }
124
125 // Get the key by using the value (htmlAttributes?.src) in the imageData?.sizes array
126 const key = imageSizes.find( ( sizeKey ) => imageData?.sizes[ sizeKey ]?.url === htmlAttributes?.src );
127
128 if ( ! key ) {
129 return '';
130 }
131
132 return key;
133 }, [ htmlAttributes?.src, imageData?.sizes ] );
134
135 const panelProps = {
136 name,
137 attributes,
138 setAttributes,
139 };
140
141 return (
142 <ApplyFilters
143 name="generateblocks.editor.blockControls"
144 blockName={ name }
145 getStyleValue={ getStyleValue }
146 onStyleChange={ onStyleChange }
147 currentAtRule={ currentAtRule }
148 attributes={ attributes }
149 setAttributes={ setAttributes }
150 >
151 <OpenPanel
152 { ...panelProps }
153 shouldRender={ '' === currentAtRule }
154 panelId="settings"
155 >
156 <ImageUpload
157 context={ context }
158 value={ htmlAttributes?.src ?? '' }
159 onInsert={ ( value ) => {
160 const newHtmlAttributes = {
161 ...htmlAttributes,
162 src: value,
163 };
164
165 setAttributes( {
166 htmlAttributes: newHtmlAttributes,
167 } );
168 } }
169 onSelectImage={ onSelectImage }
170 allowDynamicTags={ true }
171 onInsertDynamicTag={ ( value ) => {
172 const newHtmlAttributes = {
173 ...htmlAttributes,
174 src: value,
175 };
176
177 setAttributes( {
178 htmlAttributes: newHtmlAttributes,
179 mediaId: 0,
180 } );
181 } }
182 />
183
184 <URLControls
185 setAttributes={ setAttributes }
186 htmlAttributes={ linkHtmlAttributes }
187 attributesName="linkHtmlAttributes"
188 context={ context }
189 tagName={ tagName }
190 />
191
192 { applyFilters(
193 'generateblocks.blockSettings.afterImageUrlControls',
194 null,
195 panelProps
196 ) }
197
198 { !! sizes?.length && (
199 <SelectControl
200 label={ __( 'Size', 'generateblocks' ) }
201 options={ sizes }
202 value={ imageSizeValue }
203 onChange={ ( value ) => {
204 if ( '' === value ) {
205 setAttributes( {
206 htmlAttributes: {
207 ...htmlAttributes,
208 src: imageData?.full_url ?? '',
209 width: imageData?.width ?? '',
210 height: imageData?.height ?? '',
211 },
212 } );
213
214 return;
215 }
216
217 setAttributes( {
218 htmlAttributes: {
219 ...htmlAttributes,
220 src: imageData?.sizes[ value ]?.url ?? '',
221 width: imageData?.sizes[ value ]?.width ?? '',
222 height: imageData?.sizes[ value ]?.height ?? '',
223 },
224 } );
225 } }
226 />
227 ) }
228
229 <Flex>
230 <FlexBlock>
231 <UnitControl
232 id="width"
233 label={ __( 'Width', 'generateblocks' ) }
234 value={ getStyleValue( 'width', currentAtRule ) }
235 onChange={ ( value ) => debouncedOnStyleChange( 'width', value, currentAtRule ) }
236 />
237 </FlexBlock>
238
239 <FlexBlock>
240 <UnitControl
241 id="height"
242 label={ __( 'Height', 'generateblocks' ) }
243 value={ getStyleValue( 'height', currentAtRule ) }
244 onChange={ ( value ) => debouncedOnStyleChange( 'height', value, currentAtRule ) }
245 />
246 </FlexBlock>
247 </Flex>
248
249 <TextControl
250 label={ __( 'Alt text', 'generateblocks' ) }
251 value={ htmlAttributes?.alt ?? '' }
252 onChange={ ( value ) => {
253 setAttributes( {
254 htmlAttributes: {
255 ...htmlAttributes,
256 alt: value,
257 },
258 } );
259 } }
260 />
261 </OpenPanel>
262
263 <DynamicTagsOnboarder />
264 </ApplyFilters>
265 );
266 }
267