PluginProbe
Block Animations, Motion & Scroll Effects – Ghost Kit / 3.4.1
Block Animations, Motion & Scroll Effects – Ghost Kit v3.4.1
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 / gif / edit.js

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

308 lines 8.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { GiphyFetch } from '@giphy/js-fetch-api';
2 import classnames from 'classnames/dedupe';
3
4 import {
5 InspectorControls,
6 RichText,
7 useBlockProps,
8 } from '@wordpress/block-editor';
9 import {
10 Button,
11 ExternalLink,
12 PanelBody,
13 Placeholder,
14 Spinner,
15 TextareaControl,
16 TextControl,
17 } from '@wordpress/components';
18 import { useState } from '@wordpress/element';
19 import { __ } from '@wordpress/i18n';
20
21 import getIcon from '../../utils/get-icon';
22
23 const GIPHY_API_KEY = 'Qm6AupESs2abqy7fSeHNQ892EWSS28r8';
24
25 // use @giphy/js-fetch-api to fetch gifs, instantiate with your api key
26 const gf = new GiphyFetch(GIPHY_API_KEY);
27
28 function splitAndLast(array, delimiter) {
29 const split = array.split(delimiter);
30 return split[split.length - 1];
31 }
32
33 /**
34 * Block Edit Class.
35 *
36 * @param props
37 */
38 export default function BlockEdit(props) {
39 const { attributes, isSelected, setAttributes } = props;
40
41 let { className } = props;
42
43 const { caption, url, srcset, alt, width, height, searchText } = attributes;
44
45 const [results, setResults] = useState(null);
46 const [loading, setLoading] = useState(false);
47
48 function parseSearch() {
49 let giphyID = null;
50
51 // If search is hardcoded Giphy URL following this pattern: https://giphy.com/embed/4ZFekt94LMhNK
52 if (searchText.indexOf('//giphy.com/gifs') !== -1) {
53 giphyID = splitAndLast(splitAndLast(searchText, '/'), '-');
54 }
55
56 // If search is hardcoded Giphy URL following this pattern: http://i.giphy.com/4ZFekt94LMhNK.gif
57 if (searchText.indexOf('//i.giphy.com') !== -1) {
58 giphyID = splitAndLast(searchText, '/').replace('.gif', '');
59 }
60
61 // https://media.giphy.com/media/gt0hYzKlMpfOg/giphy.gif
62 const match = searchText.match(
63 /http[s]?:\/\/media.giphy.com\/media\/([A-Za-z0-9\-.]+)\/giphy.gif/
64 );
65
66 if (match) {
67 // eslint-disable-next-line prefer-destructuring
68 giphyID = match[1];
69 }
70
71 if (giphyID) {
72 return {
73 id: giphyID,
74 };
75 }
76
77 return {
78 search: searchText,
79 };
80 }
81
82 function fetch() {
83 setLoading(true);
84
85 const searchData = parseSearch();
86 let request = false;
87
88 if (searchData.id) {
89 request = gf.gifs([searchData.id]);
90 } else {
91 request = gf.search(searchData.search || '', {
92 sort: 'relevant',
93 limit: 10,
94 });
95 }
96
97 request.then((result) => {
98 setLoading(false);
99
100 if (
101 result.meta &&
102 result.meta.status &&
103 result.meta.status === 200
104 ) {
105 // If there is only one result, Giphy's API does not return an array.
106 // The following statement normalizes the data into an array with one member in this case.
107 const newResults =
108 typeof result.data.images !== 'undefined'
109 ? [result.data]
110 : result.data;
111 const giphyData = newResults[0];
112
113 // No results
114 if (!giphyData.images) {
115 return;
116 }
117
118 setResults(newResults);
119 } else {
120 // Error
121 }
122 });
123 }
124
125 function onSubmit() {
126 fetch();
127 }
128
129 function onFormSubmit(event) {
130 event.preventDefault();
131 onSubmit();
132 }
133
134 function selectGiphy(giphy) {
135 const { images } = giphy;
136
137 const sizes = [
138 'preview_gif',
139 'downsized_small',
140 'downsized_medium',
141 'downsized_large',
142 'downsized',
143 ];
144
145 let newSrcset = '';
146
147 sizes.forEach((sizeName) => {
148 if (
149 images[sizeName] &&
150 images[sizeName].url &&
151 !new RegExp(` ${images[sizeName].width}w`).test(newSrcset)
152 ) {
153 newSrcset += `${newSrcset ? ', ' : ''}${images[sizeName].url} ${
154 images[sizeName].width
155 }w`;
156 }
157 });
158
159 setAttributes({
160 url: images.original.url,
161 srcset: newSrcset,
162 caption: giphy.title,
163 alt: giphy.title,
164 width: parseInt(images.original.width, 10),
165 height: parseInt(images.original.height, 10),
166 });
167 }
168
169 const inputFields = (
170 <>
171 <form
172 className="ghostkit-gif-input-container"
173 onSubmit={onFormSubmit}
174 >
175 <TextControl
176 className="ghostkit-gif-input"
177 placeholder={__(
178 'Enter search terms, e.g. cat…',
179 'ghostkit'
180 )}
181 onChange={(val) => setAttributes({ searchText: val })}
182 value={searchText}
183 __next40pxDefaultSize
184 __nextHasNoMarginBottom
185 />
186 <Button
187 variant="secondary"
188 onClick={(e) => {
189 onFormSubmit(e);
190 }}
191 >
192 {__('Search', 'ghostkit')}
193 </Button>
194 </form>
195 {loading && <Spinner />}
196 {!loading && results && results.length > 1 && (
197 <div className="ghostkit-gif-thumbnails-container">
198 {results.map((thumbnail) => {
199 const thumbnailStyle = {
200 backgroundImage: `url(${thumbnail.images.downsized_still.url})`,
201 };
202
203 return (
204 // eslint-disable-next-line react/button-has-type
205 <button
206 className="ghostkit-gif-thumbnail-container"
207 key={thumbnail.id}
208 onClick={() => {
209 selectGiphy(thumbnail);
210 }}
211 style={thumbnailStyle}
212 >
213 {' '}
214 </button>
215 );
216 })}
217 </div>
218 )}
219 </>
220 );
221
222 className = classnames('ghostkit-gif', className);
223
224 const blockProps = useBlockProps({ className });
225
226 return (
227 <>
228 <InspectorControls>
229 <PanelBody className="components-panel__body-gif-branding">
230 <svg
231 xmlns="http://www.w3.org/2000/svg"
232 viewBox="0 0 202 22"
233 >
234 <path d="M4.6 5.9H0v10h1.6v-3.1h3c4.8 0 4.8-6.9 0-6.9zm0 5.4h-3v-4h3c2.6.1 2.6 4 0 4zM51.2 12.3c2-.3 2.7-1.7 2.7-3.1 0-1.7-1.2-3.3-3.5-3.3h-4.6v10h1.6v-3.4h2.1l3 3.4h1.9l-.2-.3-3-3.3zM47.4 11V7.4h3c1.3 0 1.9.9 1.9 1.8s-.6 1.8-1.9 1.8h-3zM30.6 13.6L28 5.9h-1.1l-2.5 7.7-2.6-7.7H20l3.7 10H25l1.4-3.5L27.5 9l1.1 3.4 1.3 3.5h1.4l3.5-10h-1.7z" />
235 <path d="M14.4 5.7c-3 0-5.1 2.2-5.1 5.2 0 2.6 1.6 5.1 5.1 5.1 3.5 0 5.1-2.5 5.1-5.2-.1-2.6-1.7-5.1-5.1-5.1zm-.1 8.9c-2.5 0-3.5-1.9-3.5-3.7 0-2.2 1.2-3.8 3.5-3.8 2.4 0 3.5 2 3.5 3.8.1 2-1 3.7-3.5 3.7zM57.7 11.6h5.5v-1.5h-5.5V7.4h5.7V5.9h-7.3v10h7.3v-1.6h-5.7zM38 14.3v-2.7h5.5v-1.5H38V7.4h5.7V5.9h-7.3v10h7.3v-1.6zM93 10.3l-2.7-4.4h-1.9V6l3.8 5.8v4.1h1.6v-4.1l4-5.8v-.1h-2zM69.3 5.9h-3.8v10h3.8c3.5 0 5.1-2.5 5-5.1-.1-2.5-1.6-4.9-5-4.9zm0 8.4h-2.2V7.4h2.2c2.3 0 3.4 1.7 3.4 3.4s-1 3.5-3.4 3.5zM86.3 10.7c.9-.4 1.4-1.1 1.4-2 0-2-1.5-2.8-3.4-2.8h-4.6v10h4.6c2 0 3.7-.7 3.7-2.8 0-.8-.5-2-1.7-2.4zm-5-3.4h3c1.2 0 1.8.7 1.8 1.4 0 .8-.6 1.3-1.8 1.3h-3V7.3zm3 7.1h-3v-2.9h3c.9 0 2.1.5 2.1 1.6 0 1-1.2 1.3-2.1 1.3zM113.9 13.3h5.3V16c-1.2.9-2.9 1.1-4 1.1-4.2 0-5.6-3.3-5.6-6 0-4.1 2.2-6.1 5.6-6.1 1.4 0 3.2.4 4.8 1.8l3.4-3.4C120.7.6 118.1 0 115.2 0c-7.8 0-11.4 5.6-11.4 11s3.1 10.9 11.4 10.9c4 0 7.6-1.4 8.9-4.1V8.6h-10.2v4.7zM171.9 8.5h-7.4V.6h-5.9v20.8h5.9v-7.8h7.4v7.8h5.9V.6h-5.9zM195.1.6l-4.5 7.1-4.3-7.1h-6.6v.2l7.9 12.3v8.3h5.9v-8.3L201.8.9V.6zM127.4.6h5.9v20.8h-5.9zM147.6.6h-10.1v20.8h5.9v-5.6h4.2c5.6-.1 8.3-3.4 8.3-7.6.1-4.1-2.7-7.6-8.3-7.6zm0 10.2h-4.2V5.6h4.2c1.6 0 2.5 1.2 2.5 2.6 0 1.4-.9 2.6-2.5 2.6z" />
236 </svg>
237 </PanelBody>
238 {url ? (
239 <PanelBody title={__('Image settings', 'ghostkit')}>
240 {inputFields}
241 <TextareaControl
242 label={__('Alt text (alternative text)')}
243 value={alt}
244 onChange={(val) => setAttributes({ alt: val })}
245 help={
246 <>
247 <ExternalLink href="https://www.w3.org/WAI/tutorials/images/decision-tree">
248 {__(
249 'Describe the purpose of the image',
250 'ghostkit'
251 )}
252 </ExternalLink>
253 {__(
254 'Leave empty if the image is purely decorative.',
255 'ghostkit'
256 )}
257 </>
258 }
259 __nextHasNoMarginBottom
260 />
261 </PanelBody>
262 ) : null}
263 </InspectorControls>
264 <figure {...blockProps}>
265 {!url ? (
266 <Placeholder
267 className="ghostkit-gif-placeholder"
268 icon={getIcon('block-gif')}
269 label={__('GIF', 'ghostkit')}
270 instructions={__(
271 'Search for a term or paste a Giphy URL',
272 'ghostkit'
273 )}
274 >
275 {inputFields}
276 </Placeholder>
277 ) : (
278 <>
279 <img
280 src={url}
281 srcSet={srcset}
282 alt={alt}
283 width={width}
284 height={height}
285 />
286 {(!RichText.isEmpty(caption) || isSelected) &&
287 !!url && (
288 <RichText
289 inlineToolbar
290 className="ghostkit-gif-caption"
291 onChange={(value) =>
292 setAttributes({ caption: value })
293 }
294 placeholder={__(
295 'Write caption…',
296 'jetpack'
297 )}
298 tagName="figcaption"
299 value={caption}
300 />
301 )}
302 </>
303 )}
304 </figure>
305 </>
306 );
307 }
308