PluginProbe ʕ •ᴥ•ʔ
GenerateBlocks / 2.2.0
GenerateBlocks v2.2.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 / media / components / Image.jsx
generateblocks / src / blocks / media / components Last commit date
BlockSettings.jsx 10 months ago Image.jsx 10 months ago ImagePlaceholder.jsx 1 year ago
Image.jsx
140 lines
1 import { useState, useMemo, useRef } from '@wordpress/element';
2 import { ImagePlaceholder } from './ImagePlaceholder.jsx';
3 import { useDispatch } from '@wordpress/data';
4 import { store as blockEditorStore } from '@wordpress/block-editor';
5 import { isURL } from '@wordpress/url';
6
7 export function Image( {
8 elementAttributes,
9 temporaryURL,
10 onSelectImage,
11 onSelectURL,
12 onUploadError,
13 dynamicTagValue,
14 isSelected,
15 clientId,
16 linkHtmlAttributes,
17 attributes,
18 } ) {
19 const imageRef = useRef();
20 const [
21 { loadedNaturalWidth, loadedNaturalHeight },
22 setLoadedNaturalSize,
23 ] = useState( {} );
24 const { selectBlock } = useDispatch( blockEditorStore );
25
26 // Get naturalWidth and naturalHeight from image ref, and fall back to loaded natural
27 // width and height. This resolves an issue in Safari where the loaded natural
28 // witdth and height is otherwise lost when switching between alignments.
29 // See: https://github.com/WordPress/gutenberg/pull/37210.
30 const { naturalWidth, naturalHeight } = useMemo( () => {
31 return {
32 naturalWidth:
33 imageRef.current?.naturalWidth ||
34 loadedNaturalWidth ||
35 undefined,
36 naturalHeight:
37 imageRef.current?.naturalHeight ||
38 loadedNaturalHeight ||
39 undefined,
40 };
41 }, [
42 loadedNaturalWidth,
43 loadedNaturalHeight,
44 imageRef.current?.complete,
45 ] );
46
47 const imageSrc = useMemo( () => {
48 if ( dynamicTagValue?.[ 0 ]?.replacement && isURL( dynamicTagValue?.[ 0 ]?.replacement ) ) {
49 return dynamicTagValue?.[ 0 ]?.replacement;
50 }
51
52 if ( temporaryURL ) {
53 return temporaryURL;
54 }
55
56 if ( elementAttributes?.src ) {
57 if ( elementAttributes?.src.startsWith( '{{' ) ) {
58 return generateblocksBlockMedia.squarePlaceholder;
59 }
60
61 return elementAttributes.src;
62 }
63 }, [ dynamicTagValue, temporaryURL, elementAttributes?.src ] );
64
65 /* eslint-disable jsx-a11y/alt-text */
66 // The alt tag below is added via elementAttributes.
67
68 /* eslint-disable jsx-a11y/no-noninteractive-element-interactions */
69 // The img element below is interactive if it's not selected.
70 // This allows us to not render the surrounding `<div>` with the `blockProps`
71 // unless the image is selected.
72
73 /* eslint-disable jsx-a11y/anchor-is-valid */
74 // We disable the anchor in the editor only.
75
76 const image = (
77 <>
78 <img
79 width={ naturalWidth }
80 height={ naturalHeight }
81 { ...elementAttributes }
82 src={ imageSrc }
83 ref={ imageRef }
84 onLoad={ ( event ) => {
85 setLoadedNaturalSize( {
86 loadedNaturalWidth: event.target?.naturalWidth,
87 loadedNaturalHeight: event.target?.naturalHeight,
88 } );
89 } }
90 onClick={ () => {
91 if ( isSelected ) {
92 return;
93 }
94
95 selectBlock( clientId );
96 } }
97 onKeyDown={ () => {
98 if ( isSelected ) {
99 return;
100 }
101
102 selectBlock( clientId );
103 } }
104 role={ ! isSelected ? 'button' : undefined }
105 tabIndex={ ! isSelected ? 0 : undefined }
106 />
107 </>
108 );
109
110 return (
111 <>
112 { ( !! temporaryURL || !! elementAttributes?.src ) ? (
113 <>
114 { linkHtmlAttributes.href ? (
115 <a
116 { ...linkHtmlAttributes }
117 href={ undefined }
118 >
119 { image }
120 </a>
121 ) : (
122 image
123 ) }
124 </>
125 ) : (
126 <ImagePlaceholder
127 onSelectImage={ onSelectImage }
128 onSelectURL={ onSelectURL }
129 onUploadError={ onUploadError }
130 uniqueId={ attributes?.uniqueId ?? '' }
131 />
132 ) }
133 </>
134 );
135
136 /* eslint-enable jsx-a11y/alt-text */
137 /* eslint-enable jsx-a11y/no-noninteractive-element-interactions */
138 /* eslint-enable jsx-a11y/anchor-is-valid */
139 }
140