summaryrefslogtreecommitdiff
blob: e4d77349531abf2965f2cc7647e8c5ada8aae97c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/**
 * External Dependencies
 */
import classnames from 'classnames';
import { __ } from '@wordpress/i18n';
import { BACKSPACE, DELETE } from '@wordpress/keycodes';
import { Component, createRef, Fragment } from '@wordpress/element';
import { IconButton, Spinner } from '@wordpress/components';
import { isBlobURL } from '@wordpress/blob';
import { withSelect } from '@wordpress/data';

class GalleryImageEdit extends Component {
	img = createRef();

	onImageClick = () => {
		if ( ! this.props.isSelected ) {
			this.props.onSelect();
		}
	};

	onImageKeyDown = event => {
		if (
			this.img.current === document.activeElement &&
			this.props.isSelected &&
			[ BACKSPACE, DELETE ].includes( event.keyCode )
		) {
			this.props.onRemove();
		}
	};

	componentDidUpdate() {
		const { alt, height, image, link, url, width } = this.props;

		if ( image ) {
			const nextAtts = {};

			if ( ! alt && image.alt_text ) {
				nextAtts.alt = image.alt_text;
			}
			if ( ! height && image.media_details && image.media_details.height ) {
				nextAtts.height = +image.media_details.height;
			}
			if ( ! link && image.link ) {
				nextAtts.link = image.link;
			}
			if ( ! url && image.source_url ) {
				nextAtts.url = image.source_url;
			}
			if ( ! width && image.media_details && image.media_details.width ) {
				nextAtts.width = +image.media_details.width;
			}

			if ( Object.keys( nextAtts ).length ) {
				this.props.setAttributes( nextAtts );
			}
		}
	}

	render() {
		const {
			'aria-label': ariaLabel,
			alt,
			height,
			id,
			imageFilter,
			isSelected,
			link,
			linkTo,
			onRemove,
			origUrl,
			url,
			width,
		} = this.props;

		let href;

		switch ( linkTo ) {
			case 'media':
				href = url;
				break;
			case 'attachment':
				href = link;
				break;
		}

		const isTransient = isBlobURL( origUrl );

		const img = (
			// Disable reason: Image itself is not meant to be interactive, but should
			// direct image selection and unfocus caption fields.
			/* eslint-disable jsx-a11y/no-noninteractive-element-interactions, jsx-a11y/no-noninteractive-tabindex */
			<Fragment>
				<img
					alt={ alt }
					aria-label={ ariaLabel }
					data-height={ height }
					data-id={ id }
					data-link={ link }
					data-url={ origUrl }
					data-width={ width }
					onClick={ this.onImageClick }
					onKeyDown={ this.onImageKeyDown }
					ref={ this.img }
					src={ isTransient ? undefined : url }
					tabIndex="0"
					style={ isTransient ? { backgroundImage: `url(${ url })` } : undefined }
				/>
				{ isTransient && <Spinner /> }
			</Fragment>
			/* eslint-enable jsx-a11y/no-noninteractive-element-interactions, jsx-a11y/no-noninteractive-tabindex */
		);

		// Disable reason: Each block can be selected by clicking on it and we should keep the same saved markup
		return (
			<figure
				className={ classnames( 'tiled-gallery__item', {
					'is-selected': isSelected,
					'is-transient': isTransient,
					[ `filter__${ imageFilter }` ]: !! imageFilter,
				} ) }
			>
				{ isSelected && (
					<div className="tiled-gallery__item__inline-menu">
						<IconButton
							icon="no-alt"
							onClick={ onRemove }
							className="tiled-gallery__item__remove"
							label={ __( 'Remove Image', 'jetpack' ) }
						/>
					</div>
				) }
				{ /* Keep the <a> HTML structure, but ensure there is no navigation from edit */
				/* eslint-disable-next-line jsx-a11y/anchor-is-valid */ }
				{ href ? <a>{ img }</a> : img }
			</figure>
		);
	}
}

export default withSelect( ( select, ownProps ) => {
	const { getMedia } = select( 'core' );
	const { id } = ownProps;

	return {
		image: id ? getMedia( id ) : null,
	};
} )( GalleryImageEdit );