-
Notifications
You must be signed in to change notification settings - Fork 4.3k
/
gallery-image.js
154 lines (133 loc) · 3.98 KB
/
gallery-image.js
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
148
149
150
151
152
153
154
/**
* External Dependencies
*/
import classnames from 'classnames';
/**
* WordPress Dependencies
*/
import { Component } from '@wordpress/element';
import { IconButton, Spinner } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import { keycodes } from '@wordpress/utils';
import { withSelect } from '@wordpress/data';
import { RichText } from '@wordpress/editor';
/**
* Module constants
*/
const { BACKSPACE, DELETE } = keycodes;
class GalleryImage extends Component {
constructor() {
super( ...arguments );
this.onImageClick = this.onImageClick.bind( this );
this.onSelectCaption = this.onSelectCaption.bind( this );
this.onKeyDown = this.onKeyDown.bind( this );
this.bindContainer = this.bindContainer.bind( this );
this.state = {
captionSelected: false,
};
}
bindContainer( ref ) {
this.container = ref;
}
onSelectCaption() {
if ( ! this.state.captionSelected ) {
this.setState( {
captionSelected: true,
} );
}
if ( ! this.props.isSelected ) {
this.props.onSelect();
}
}
onImageClick() {
if ( ! this.props.isSelected ) {
this.props.onSelect();
}
if ( this.state.captionSelected ) {
this.setState( {
captionSelected: false,
} );
}
}
onKeyDown( event ) {
if (
this.container === document.activeElement &&
this.props.isSelected && [ BACKSPACE, DELETE ].indexOf( event.keyCode ) !== -1
) {
event.stopPropagation();
event.preventDefault();
this.props.onRemove();
}
}
componentWillReceiveProps( { isSelected, image, url } ) {
if ( image && ! url ) {
this.props.setAttributes( {
url: image.source_url,
alt: image.alt_text,
} );
}
// unselect the caption so when the user selects other image and comeback
// the caption is not immediately selected
if ( this.state.captionSelected && ! isSelected && this.props.isSelected ) {
this.setState( {
captionSelected: false,
} );
}
}
render() {
const { url, alt, id, linkTo, link, isSelected, caption, onRemove, setAttributes } = this.props;
let href;
switch ( linkTo ) {
case 'media':
href = url;
break;
case 'attachment':
href = link;
break;
}
// Disable reason: Image itself is not meant to be
// interactive, but should direct image selection and unfocus caption fields
// eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions, jsx-a11y/click-events-have-key-events
const img = url ? <img src={ url } alt={ alt } data-id={ id } onClick={ this.onImageClick } /> : <Spinner />;
const className = classnames( {
'is-selected': isSelected,
'is-transient': url && 0 === url.indexOf( 'blob:' ),
} );
// Disable reason: Each block can be selected by clicking on it and we should keep the same saved markup
/* eslint-disable jsx-a11y/no-noninteractive-element-interactions, jsx-a11y/onclick-has-role, jsx-a11y/click-events-have-key-events */
return (
<figure className={ className } tabIndex="-1" onKeyDown={ this.onKeyDown } ref={ this.bindContainer }>
{ isSelected &&
<div className="core-blocks-gallery-item__inline-menu">
<IconButton
icon="no-alt"
onClick={ onRemove }
className="blocks-gallery-item__remove"
label={ __( 'Remove Image' ) }
/>
</div>
}
{ href ? <a href={ href }>{ img }</a> : img }
{ ( caption && caption.length > 0 ) || isSelected ? (
<RichText
tagName="figcaption"
placeholder={ __( 'Write caption…' ) }
value={ caption }
isSelected={ this.state.captionSelected }
onChange={ ( newCaption ) => setAttributes( { caption: newCaption } ) }
onFocus={ this.onSelectCaption }
inlineToolbar
/>
) : null }
</figure>
);
/* eslint-enable jsx-a11y/no-noninteractive-element-interactions, jsx-a11y/onclick-has-role, jsx-a11y/click-events-have-key-events */
}
}
export default withSelect( ( select, ownProps ) => {
const { getMedia } = select( 'core' );
const { id } = ownProps;
return {
image: id ? getMedia( id ) : null,
};
} )( GalleryImage );