PluginProbe
Block Animations, Motion & Scroll Effects – Ghost Kit / 3.3.2
Block Animations, Motion & Scroll Effects – Ghost Kit v3.3.2
3.7.2 3.7.1 3.7.0 3.6.1 trunk 1.6.3 2.25.0 3.3.0 3.3.1 3.3.2 3.3.3 3.4.0 3.4.1 3.4.2 3.4.3 3.4.4 3.4.5 3.4.6 3.5.0 3.5.1 3.6.0
ghostkit / gutenberg / blocks / testimonial / edit.js

edit.js in Block Animations, Motion & Scroll Effects – Ghost Kit 3.3.2, at gutenberg/blocks/testimonial/edit.js

400 lines 9.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import classnames from 'classnames/dedupe';
2
3 import {
4 InnerBlocks,
5 InspectorControls,
6 MediaUpload,
7 RichText,
8 useBlockProps,
9 useInnerBlocksProps,
10 } from '@wordpress/block-editor';
11 import {
12 BaseControl,
13 Button,
14 ExternalLink,
15 PanelBody,
16 SelectControl,
17 TextareaControl,
18 } from '@wordpress/components';
19 import { useSelect } from '@wordpress/data';
20 import { applyFilters } from '@wordpress/hooks';
21 import { __ } from '@wordpress/i18n';
22
23 import IconPicker from '../../components/icon-picker';
24 import RangeControl from '../../components/range-control';
25 import URLPicker from '../../components/url-picker';
26
27 const DEFAULT_SIZE_SLUG = 'thumbnail';
28
29 /**
30 * Block Edit Class.
31 *
32 * @param props
33 */
34 export default function BlockEdit(props) {
35 const { attributes, setAttributes, isSelected, clientId } = props;
36 let { className = '' } = props;
37
38 const {
39 icon,
40 source,
41
42 photoId,
43 photoUrl,
44 photoAlt,
45 photoWidth,
46 photoHeight,
47 photoSizeSlug,
48
49 stars,
50 starsIcon,
51
52 url,
53 ariaLabel,
54 target,
55 rel,
56 } = attributes;
57
58 const { hasChildBlocks, editorSettings, photoImage } = useSelect(
59 (select) => {
60 const blockEditor = select('core/block-editor');
61 const { getMedia } = select('core');
62
63 return {
64 hasChildBlocks: blockEditor
65 ? blockEditor.getBlockOrder(clientId).length > 0
66 : false,
67 editorSettings: blockEditor.getSettings(),
68 photoImage:
69 attributes.photoId && isSelected
70 ? getMedia(attributes.photoId)
71 : null,
72 };
73 }
74 );
75
76 const onPhotoSelect = (imageData, imageSize = false) => {
77 imageSize = imageSize || attributes.photoSizeSlug || DEFAULT_SIZE_SLUG;
78
79 const result = {
80 photoId: imageData.id,
81 photoUrl: imageData.url || imageData.source_url,
82 photoAlt: imageData.alt || imageData.alt_text,
83 photoWidth:
84 imageData.width ||
85 (imageData.media_details && imageData.media_details.width
86 ? imageData.media_details.width
87 : undefined),
88 photoHeight:
89 imageData.height ||
90 (imageData.media_details && imageData.media_details.height
91 ? imageData.media_details.height
92 : undefined),
93 photoSizeSlug: imageSize,
94 };
95
96 let sizes = imageData.sizes && imageData.sizes[imageSize];
97
98 if (
99 !sizes &&
100 imageData.media_details &&
101 imageData.media_details.sizes &&
102 imageData.media_details.sizes[imageSize]
103 ) {
104 sizes = imageData.media_details.sizes[imageSize];
105 }
106
107 // Prepare image data for selected size.
108 if (sizes) {
109 if (sizes.url) {
110 result.photoUrl = sizes.url;
111 }
112 if (sizes.source_url) {
113 result.photoUrl = sizes.source_url;
114 }
115 if (sizes.width) {
116 result.photoWidth = sizes.width;
117 }
118 if (sizes.height) {
119 result.photoHeight = sizes.height;
120 }
121 }
122
123 setAttributes(result);
124 };
125
126 className = classnames('ghostkit-testimonial', className);
127
128 className = applyFilters('ghostkit.editor.className', className, props);
129
130 const blockProps = useBlockProps({ className });
131 const innerBlockProps = useInnerBlocksProps(
132 {},
133 {
134 renderAppender: hasChildBlocks
135 ? undefined
136 : InnerBlocks.ButtonBlockAppender,
137 templateLock: false,
138 }
139 );
140
141 return (
142 <>
143 <InspectorControls>
144 <PanelBody>
145 <IconPicker
146 label={__('Icon', 'ghostkit')}
147 value={icon}
148 onChange={(value) => setAttributes({ icon: value })}
149 insideInspector
150 />
151 </PanelBody>
152 <PanelBody title={__('Photo', 'ghostkit')}>
153 {!photoId ? (
154 <MediaUpload
155 onSelect={(media) => {
156 onPhotoSelect(media);
157 }}
158 allowedTypes={['image']}
159 value={photoId}
160 render={({ open }) => (
161 <Button onClick={open} isPrimary>
162 {__('Select Image', 'ghostkit')}
163 </Button>
164 )}
165 />
166 ) : null}
167
168 {photoId ? (
169 <>
170 <MediaUpload
171 onSelect={(media) => {
172 onPhotoSelect(media);
173 }}
174 allowedTypes={['image']}
175 value={photoId}
176 render={({ open }) => (
177 <BaseControl
178 help={__(
179 'Click the image to edit or update',
180 'ghostkit'
181 )}
182 >
183 {/* eslint-disable-next-line jsx-a11y/control-has-associated-label, jsx-a11y/anchor-is-valid */}
184 <a
185 href="#"
186 onClick={open}
187 className="ghostkit-gutenberg-media-upload"
188 style={{ display: 'block' }}
189 >
190 <img
191 src={photoUrl}
192 alt={photoAlt}
193 width={photoWidth}
194 height={photoHeight}
195 />
196 </a>
197 </BaseControl>
198 )}
199 />
200 <div style={{ marginTop: -20 }} />
201 <Button
202 isLink
203 onClick={(e) => {
204 setAttributes({
205 photoId: '',
206 photoUrl: '',
207 photoAlt: '',
208 photoWidth: '',
209 photoHeight: '',
210 });
211 e.preventDefault();
212 }}
213 className="button button-secondary"
214 >
215 {__('Remove Image', 'ghostkit')}
216 </Button>
217 <div style={{ marginBottom: 13 }} />
218 {editorSettings && editorSettings.imageSizes ? (
219 <SelectControl
220 label={__('Resolution', 'ghostkit')}
221 help={__(
222 'Select the size of the source image.',
223 'ghostkit'
224 )}
225 value={photoSizeSlug || DEFAULT_SIZE_SLUG}
226 onChange={(val) => {
227 onPhotoSelect(photoImage, val);
228 }}
229 options={editorSettings.imageSizes.map(
230 (imgSize) => ({
231 value: imgSize.slug,
232 label: imgSize.name,
233 })
234 )}
235 />
236 ) : null}
237 <TextareaControl
238 label={__('Alt text (alternative text)')}
239 value={photoAlt}
240 onChange={(val) =>
241 setAttributes({ photoAlt: val })
242 }
243 help={
244 <>
245 <ExternalLink href="https://www.w3.org/WAI/tutorials/images/decision-tree">
246 {__(
247 'Describe the purpose of the image',
248 'ghostkit'
249 )}
250 </ExternalLink>
251 {__(
252 'Leave empty if the image is purely decorative.',
253 'ghostkit'
254 )}
255 </>
256 }
257 />
258 </>
259 ) : null}
260 </PanelBody>
261 <PanelBody title={__('Stars', 'ghostkit')}>
262 <RangeControl
263 value={stars}
264 min={0}
265 max={5}
266 step={0.5}
267 beforeIcon="star-filled"
268 allowReset
269 onChange={(value) => setAttributes({ stars: value })}
270 />
271 {typeof stars === 'number' ? (
272 <IconPicker
273 label={__('Icon', 'ghostkit')}
274 value={starsIcon}
275 onChange={(value) =>
276 setAttributes({ starsIcon: value })
277 }
278 insideInspector
279 />
280 ) : null}
281 </PanelBody>
282 </InspectorControls>
283 <URLPicker
284 url={url}
285 rel={rel}
286 ariaLabel={ariaLabel}
287 target={target}
288 onChange={(data) => {
289 setAttributes(data);
290 }}
291 isSelected={isSelected}
292 toolbarSettings
293 inspectorSettings
294 />
295 <div {...blockProps}>
296 {icon ? (
297 <div className="ghostkit-testimonial-icon">
298 <IconPicker.Dropdown
299 onChange={(value) => setAttributes({ icon: value })}
300 value={icon}
301 renderToggle={({ onToggle }) => (
302 <IconPicker.Preview
303 onClick={onToggle}
304 name={icon}
305 />
306 )}
307 />
308 </div>
309 ) : null}
310 <div className="ghostkit-testimonial-content">
311 <div {...innerBlockProps} />
312 </div>
313 <div className="ghostkit-testimonial-photo">
314 {!photoId ? (
315 <MediaUpload
316 onSelect={(media) => {
317 onPhotoSelect(media);
318 }}
319 allowedTypes={['image']}
320 value={photoId}
321 render={({ open }) => (
322 <Button onClick={open}>
323 <span className="dashicons dashicons-format-image" />
324 </Button>
325 )}
326 />
327 ) : null}
328
329 {photoId ? (
330 <MediaUpload
331 onSelect={(media) => {
332 onPhotoSelect(media);
333 }}
334 allowedTypes={['image']}
335 value={photoId}
336 render={({ open }) => (
337 // eslint-disable-next-line jsx-a11y/control-has-associated-label, jsx-a11y/anchor-is-valid
338 <a
339 href="#"
340 onClick={open}
341 className="ghostkit-gutenberg-media-upload"
342 style={{ display: 'block' }}
343 >
344 <img
345 src={photoUrl}
346 alt={photoAlt}
347 width={photoWidth}
348 height={photoHeight}
349 />
350 </a>
351 )}
352 />
353 ) : null}
354 </div>
355 <div className="ghostkit-testimonial-meta">
356 <RichText
357 inlineToolbar
358 tagName="div"
359 className="ghostkit-testimonial-name"
360 placeholder={__('Write name…', 'ghostkit')}
361 value={attributes.name}
362 onChange={(value) => setAttributes({ name: value })}
363 />
364 <RichText
365 inlineToolbar
366 tagName="div"
367 className="ghostkit-testimonial-source"
368 placeholder={__('Write source…', 'ghostkit')}
369 value={source}
370 onChange={(value) => setAttributes({ source: value })}
371 />
372 </div>
373 {typeof stars === 'number' && starsIcon ? (
374 <div className="ghostkit-testimonial-stars">
375 <div className="ghostkit-testimonial-stars-wrap">
376 <div
377 className="ghostkit-testimonial-stars-front"
378 style={{ width: `${(100 * stars) / 5}%` }}
379 >
380 <IconPicker.Preview name={starsIcon} />
381 <IconPicker.Preview name={starsIcon} />
382 <IconPicker.Preview name={starsIcon} />
383 <IconPicker.Preview name={starsIcon} />
384 <IconPicker.Preview name={starsIcon} />
385 </div>
386 <div className="ghostkit-testimonial-stars-back">
387 <IconPicker.Preview name={starsIcon} />
388 <IconPicker.Preview name={starsIcon} />
389 <IconPicker.Preview name={starsIcon} />
390 <IconPicker.Preview name={starsIcon} />
391 <IconPicker.Preview name={starsIcon} />
392 </div>
393 </div>
394 </div>
395 ) : null}
396 </div>
397 </>
398 );
399 }
400