@performant-software/semantic-components 0.5.16-beta.1 → 0.5.16-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/index.js +1 -1
- package/build/index.js.map +1 -1
- package/package.json +3 -3
- package/src/components/DownloadButton.js +63 -12
- package/src/components/IIIFModal.js +26 -0
- package/src/components/LazyAudio.js +10 -0
- package/src/components/LazyDocument.js +0 -3
- package/src/components/LazyIIIF.js +44 -0
- package/src/components/LazyImage.js +10 -0
- package/src/components/LazyMedia.js +243 -0
- package/src/components/LazyVideo.js +10 -0
- package/src/i18n/en.json +9 -6
- package/src/index.js +3 -0
- package/types/components/DownloadButton.js.flow +63 -12
- package/types/components/IIIFModal.js.flow +26 -0
- package/types/components/LazyAudio.js.flow +10 -0
- package/types/components/LazyDocument.js.flow +0 -3
- package/types/components/LazyIIIF.js.flow +44 -0
- package/types/components/LazyImage.js.flow +10 -0
- package/types/components/LazyMedia.js.flow +243 -0
- package/types/components/LazyVideo.js.flow +10 -0
- package/types/index.js.flow +3 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { Modal } from 'semantic-ui-react';
|
|
5
|
+
import { IIIFViewer } from '@performant-software/shared-components';
|
|
6
|
+
|
|
7
|
+
type Props = {
|
|
8
|
+
onClose: () => void
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const IIIFModal = ({ onClose, ...props }: Props) => (
|
|
12
|
+
<Modal
|
|
13
|
+
centered={false}
|
|
14
|
+
closeIcon
|
|
15
|
+
onClose={onClose}
|
|
16
|
+
open
|
|
17
|
+
>
|
|
18
|
+
<Modal.Content>
|
|
19
|
+
<IIIFViewer
|
|
20
|
+
{...props}
|
|
21
|
+
/>
|
|
22
|
+
</Modal.Content>
|
|
23
|
+
</Modal>
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
export default IIIFModal;
|
|
@@ -13,14 +13,17 @@ import {
|
|
|
13
13
|
} from 'semantic-ui-react';
|
|
14
14
|
import i18n from '../i18n/i18n';
|
|
15
15
|
import AudioPlayer from './AudioPlayer';
|
|
16
|
+
import DownloadButton from './DownloadButton';
|
|
16
17
|
import LazyLoader from './LazyLoader';
|
|
17
18
|
import './LazyAudio.css';
|
|
18
19
|
|
|
19
20
|
type Props = {
|
|
20
21
|
children?: Node,
|
|
21
22
|
dimmable: boolean,
|
|
23
|
+
download?: string,
|
|
22
24
|
duration?: number,
|
|
23
25
|
image?: any,
|
|
26
|
+
name?: string,
|
|
24
27
|
preview?: string,
|
|
25
28
|
size?: string,
|
|
26
29
|
src?: string
|
|
@@ -111,6 +114,13 @@ const LazyAudio = (props: Props) => {
|
|
|
111
114
|
primary
|
|
112
115
|
/>
|
|
113
116
|
)}
|
|
117
|
+
{ props.download && (
|
|
118
|
+
<DownloadButton
|
|
119
|
+
color='green'
|
|
120
|
+
filename={props.name}
|
|
121
|
+
url={props.download}
|
|
122
|
+
/>
|
|
123
|
+
)}
|
|
114
124
|
{ props.children }
|
|
115
125
|
</div>
|
|
116
126
|
</Dimmer>
|
|
@@ -11,7 +11,6 @@ import {
|
|
|
11
11
|
Transition,
|
|
12
12
|
Visibility
|
|
13
13
|
} from 'semantic-ui-react';
|
|
14
|
-
import i18n from '../i18n/i18n';
|
|
15
14
|
import DownloadButton from './DownloadButton';
|
|
16
15
|
import LazyLoader from './LazyLoader';
|
|
17
16
|
import './LazyDocument.css';
|
|
@@ -119,8 +118,6 @@ const LazyDocument = (props: Props) => {
|
|
|
119
118
|
>
|
|
120
119
|
{ props.src && (
|
|
121
120
|
<DownloadButton
|
|
122
|
-
content={i18n.t('LazyDocument.buttons.download')}
|
|
123
|
-
icon='cloud download'
|
|
124
121
|
primary
|
|
125
122
|
url={props.src}
|
|
126
123
|
/>
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
|
|
3
|
+
import React, { useState, type Node } from 'react';
|
|
4
|
+
import { Button } from 'semantic-ui-react';
|
|
5
|
+
import _ from 'underscore';
|
|
6
|
+
import i18n from '../i18n/i18n';
|
|
7
|
+
import IIIFModal from './IIIFModal';
|
|
8
|
+
import LazyMedia from './LazyMedia';
|
|
9
|
+
|
|
10
|
+
type Props = {
|
|
11
|
+
children?: Node,
|
|
12
|
+
manifest?: string,
|
|
13
|
+
options?: any
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const LazyIIIF = ({ manifest, options = {}, ...props }: Props) => {
|
|
17
|
+
const [modal, setModal] = useState(false);
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<>
|
|
21
|
+
<LazyMedia
|
|
22
|
+
{...props}
|
|
23
|
+
>
|
|
24
|
+
{ manifest && (
|
|
25
|
+
<Button
|
|
26
|
+
content={i18n.t('Common.buttons.open')}
|
|
27
|
+
icon='images outline'
|
|
28
|
+
onClick={() => setModal(true)}
|
|
29
|
+
/>
|
|
30
|
+
)}
|
|
31
|
+
{ props.children }
|
|
32
|
+
</LazyMedia>
|
|
33
|
+
{ modal && (
|
|
34
|
+
<IIIFModal
|
|
35
|
+
manifestId={manifest}
|
|
36
|
+
onClose={() => setModal(false)}
|
|
37
|
+
options={_.defaults(options, { showIIIFBadge: false })}
|
|
38
|
+
/>
|
|
39
|
+
)}
|
|
40
|
+
</>
|
|
41
|
+
);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export default LazyIIIF;
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
Visibility
|
|
13
13
|
} from 'semantic-ui-react';
|
|
14
14
|
import i18n from '../i18n/i18n';
|
|
15
|
+
import DownloadButton from './DownloadButton';
|
|
15
16
|
import LazyLoader from './LazyLoader';
|
|
16
17
|
import PhotoViewer from './PhotoViewer';
|
|
17
18
|
import './LazyImage.css';
|
|
@@ -19,8 +20,10 @@ import './LazyImage.css';
|
|
|
19
20
|
type Props = {
|
|
20
21
|
children?: Node,
|
|
21
22
|
dimmable: boolean,
|
|
23
|
+
download?: string,
|
|
22
24
|
duration?: number,
|
|
23
25
|
image?: any,
|
|
26
|
+
name?: string,
|
|
24
27
|
preview?: string,
|
|
25
28
|
size?: string,
|
|
26
29
|
src?: string
|
|
@@ -111,6 +114,13 @@ const LazyImage = (props: Props) => {
|
|
|
111
114
|
primary
|
|
112
115
|
/>
|
|
113
116
|
)}
|
|
117
|
+
{ props.download && (
|
|
118
|
+
<DownloadButton
|
|
119
|
+
color='green'
|
|
120
|
+
filename={props.name}
|
|
121
|
+
url={props.download}
|
|
122
|
+
/>
|
|
123
|
+
)}
|
|
114
124
|
{ props.children }
|
|
115
125
|
</div>
|
|
116
126
|
</Dimmer>
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
|
|
3
|
+
import React, {
|
|
4
|
+
useCallback,
|
|
5
|
+
useEffect,
|
|
6
|
+
useMemo,
|
|
7
|
+
useState,
|
|
8
|
+
type ComponentType,
|
|
9
|
+
type Node
|
|
10
|
+
} from 'react';
|
|
11
|
+
import { Icon } from 'semantic-ui-react';
|
|
12
|
+
import { Trans } from 'react-i18next';
|
|
13
|
+
import _ from 'underscore';
|
|
14
|
+
import FileInputButton from './FileInputButton';
|
|
15
|
+
import i18n from '../i18n/i18n';
|
|
16
|
+
import LazyAudio from './LazyAudio';
|
|
17
|
+
import LazyDocument from './LazyDocument';
|
|
18
|
+
import LazyImage from './LazyImage';
|
|
19
|
+
import LazyVideo from './LazyVideo';
|
|
20
|
+
|
|
21
|
+
type Props = {
|
|
22
|
+
children?: Node,
|
|
23
|
+
contentType: string,
|
|
24
|
+
dimmable?: boolean,
|
|
25
|
+
downloadUrl?: string,
|
|
26
|
+
name?: string,
|
|
27
|
+
onUpload: (file: File) => void,
|
|
28
|
+
preview?: string,
|
|
29
|
+
size?: string,
|
|
30
|
+
src?: string
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const ContentTypes = {
|
|
34
|
+
audio: 'audio',
|
|
35
|
+
image: 'image',
|
|
36
|
+
pdf: 'application/pdf',
|
|
37
|
+
video: 'video'
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const WebContentTypes = [
|
|
41
|
+
'image/png',
|
|
42
|
+
'image/jpeg',
|
|
43
|
+
'image/gif',
|
|
44
|
+
'image/webp',
|
|
45
|
+
'image/bmp',
|
|
46
|
+
'video/m4v',
|
|
47
|
+
'video/mp4'
|
|
48
|
+
];
|
|
49
|
+
|
|
50
|
+
const LazyMedia: ComponentType<any> = (props: Props) => {
|
|
51
|
+
const [contentType, setContentType] = useState(props.contentType || '');
|
|
52
|
+
const [name, setName] = useState(props.name);
|
|
53
|
+
const [preview, setPreview] = useState(props.preview);
|
|
54
|
+
const [source, setSource] = useState(props.src);
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Sets the file extension based on the name.
|
|
58
|
+
*
|
|
59
|
+
* @type {*}
|
|
60
|
+
*/
|
|
61
|
+
const fileExtension = useMemo(() => {
|
|
62
|
+
let value;
|
|
63
|
+
|
|
64
|
+
if (name) {
|
|
65
|
+
value = name.split('.').pop();
|
|
66
|
+
value = value && value.toUpperCase();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return value;
|
|
70
|
+
}, [name]);
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Sets the content type, name, preview, and source attributes. Also calls the onUpload prop.
|
|
74
|
+
*
|
|
75
|
+
* @type {(function(*): void)|*}
|
|
76
|
+
*/
|
|
77
|
+
const onUpload = useCallback((files) => {
|
|
78
|
+
const file = _.first(files);
|
|
79
|
+
|
|
80
|
+
setContentType(file.type);
|
|
81
|
+
setName(file.name);
|
|
82
|
+
setPreview(null);
|
|
83
|
+
|
|
84
|
+
if (_.contains(WebContentTypes, file.type)
|
|
85
|
+
|| file.type.startsWith(ContentTypes.audio)
|
|
86
|
+
|| file.type === ContentTypes.pdf) {
|
|
87
|
+
setSource(URL.createObjectURL(file));
|
|
88
|
+
} else {
|
|
89
|
+
setSource(null);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
props.onUpload(file);
|
|
93
|
+
}, [props.onUpload]);
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Renders the child buttons.
|
|
97
|
+
*
|
|
98
|
+
* @type {unknown}
|
|
99
|
+
*/
|
|
100
|
+
const renderChildren = useCallback(() => (
|
|
101
|
+
<>
|
|
102
|
+
{ props.onUpload && (
|
|
103
|
+
<FileInputButton
|
|
104
|
+
color='orange'
|
|
105
|
+
content={i18n.t('Common.buttons.upload')}
|
|
106
|
+
icon='cloud upload'
|
|
107
|
+
onSelection={onUpload}
|
|
108
|
+
/>
|
|
109
|
+
)}
|
|
110
|
+
{ props.children }
|
|
111
|
+
</>
|
|
112
|
+
));
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Renders the media component.
|
|
116
|
+
*
|
|
117
|
+
* @type {(function(): *)|*}
|
|
118
|
+
*/
|
|
119
|
+
const renderMedia = useCallback(() => {
|
|
120
|
+
if (contentType.startsWith(ContentTypes.image)) {
|
|
121
|
+
return (
|
|
122
|
+
<LazyImage
|
|
123
|
+
dimmable={props.dimmable}
|
|
124
|
+
download={props.downloadUrl}
|
|
125
|
+
preview={preview}
|
|
126
|
+
src={source}
|
|
127
|
+
size={props.size}
|
|
128
|
+
>
|
|
129
|
+
{ renderChildren() }
|
|
130
|
+
</LazyImage>
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (contentType.startsWith(ContentTypes.video)) {
|
|
135
|
+
return (
|
|
136
|
+
<LazyVideo
|
|
137
|
+
dimmable={props.dimmable}
|
|
138
|
+
download={props.downloadUrl}
|
|
139
|
+
preview={preview}
|
|
140
|
+
src={source}
|
|
141
|
+
size={props.size}
|
|
142
|
+
>
|
|
143
|
+
{ renderChildren() }
|
|
144
|
+
</LazyVideo>
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (contentType.startsWith(ContentTypes.audio)) {
|
|
149
|
+
return (
|
|
150
|
+
<LazyAudio
|
|
151
|
+
dimmable={props.dimmable}
|
|
152
|
+
download={props.downloadUrl}
|
|
153
|
+
preview={preview}
|
|
154
|
+
src={source}
|
|
155
|
+
size={props.size}
|
|
156
|
+
>
|
|
157
|
+
{ renderChildren() }
|
|
158
|
+
</LazyAudio>
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return (
|
|
163
|
+
<LazyDocument
|
|
164
|
+
dimmable={props.dimmable}
|
|
165
|
+
pdf={contentType === ContentTypes.pdf}
|
|
166
|
+
preview={preview}
|
|
167
|
+
src={source}
|
|
168
|
+
size={props.size}
|
|
169
|
+
>
|
|
170
|
+
{ renderChildren() }
|
|
171
|
+
</LazyDocument>
|
|
172
|
+
);
|
|
173
|
+
}, [contentType, preview, source, props.dimmable, props.downloadUrl, props.size]);
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Renders the upload message.
|
|
177
|
+
*
|
|
178
|
+
* @type {(function(): (null|*))|*}
|
|
179
|
+
*/
|
|
180
|
+
const renderMessage = useCallback(() => {
|
|
181
|
+
if (!fileExtension) {
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return (
|
|
186
|
+
<div>
|
|
187
|
+
<Icon
|
|
188
|
+
name='info circle'
|
|
189
|
+
/>
|
|
190
|
+
<span>
|
|
191
|
+
<Trans
|
|
192
|
+
components={{ bold: <strong /> }}
|
|
193
|
+
default='Your <bold>{{type}}</bold> has been received'
|
|
194
|
+
i18n={i18n}
|
|
195
|
+
i18nKey='LazyMedia.messages.uploaded'
|
|
196
|
+
values={{
|
|
197
|
+
type: fileExtension
|
|
198
|
+
}}
|
|
199
|
+
/>
|
|
200
|
+
</span>
|
|
201
|
+
</div>
|
|
202
|
+
);
|
|
203
|
+
}, [fileExtension]);
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Sets the content type, name, preview, and source.
|
|
207
|
+
*/
|
|
208
|
+
useEffect(() => {
|
|
209
|
+
if (props.contentType) {
|
|
210
|
+
setContentType(props.contentType);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (props.name) {
|
|
214
|
+
setName(props.name);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
if (props.preview) {
|
|
218
|
+
setPreview(props.preview);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (props.src) {
|
|
222
|
+
setSource(props.src);
|
|
223
|
+
} else {
|
|
224
|
+
setSource(null);
|
|
225
|
+
}
|
|
226
|
+
}, [props.contentType, props.name, props.preview, props.src]);
|
|
227
|
+
|
|
228
|
+
return (
|
|
229
|
+
<div
|
|
230
|
+
className='lazy-media'
|
|
231
|
+
>
|
|
232
|
+
{ renderMedia() }
|
|
233
|
+
{ renderMessage() }
|
|
234
|
+
</div>
|
|
235
|
+
);
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
LazyMedia.defaultProps = {
|
|
239
|
+
dimmable: true,
|
|
240
|
+
size: 'medium'
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
export default LazyMedia;
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
Visibility
|
|
13
13
|
} from 'semantic-ui-react';
|
|
14
14
|
import i18n from '../i18n/i18n';
|
|
15
|
+
import DownloadButton from './DownloadButton';
|
|
15
16
|
import LazyLoader from './LazyLoader';
|
|
16
17
|
import VideoPlayer from './VideoPlayer';
|
|
17
18
|
import './LazyVideo.css';
|
|
@@ -20,10 +21,12 @@ type Props = {
|
|
|
20
21
|
autoPlay?: boolean,
|
|
21
22
|
children?: Node,
|
|
22
23
|
dimmable: boolean,
|
|
24
|
+
download?: string,
|
|
23
25
|
duration?: number,
|
|
24
26
|
embedded?: boolean,
|
|
25
27
|
icon?: string | Element<any>,
|
|
26
28
|
image?: any,
|
|
29
|
+
name?: string,
|
|
27
30
|
preview?: ?string,
|
|
28
31
|
size?: string,
|
|
29
32
|
src?: string
|
|
@@ -132,6 +135,13 @@ const LazyVideo = (props: Props) => {
|
|
|
132
135
|
primary
|
|
133
136
|
/>
|
|
134
137
|
)}
|
|
138
|
+
{ props.download && (
|
|
139
|
+
<DownloadButton
|
|
140
|
+
color='green'
|
|
141
|
+
filename={props.name}
|
|
142
|
+
url={props.download}
|
|
143
|
+
/>
|
|
144
|
+
)}
|
|
135
145
|
{ props.children }
|
|
136
146
|
</div>
|
|
137
147
|
</Dimmer>
|
package/types/index.js.flow
CHANGED
|
@@ -35,6 +35,7 @@ export { default as FuzzyDate } from './components/FuzzyDate';
|
|
|
35
35
|
export { default as GoogleMap } from './components/GoogleMap';
|
|
36
36
|
export { default as GooglePlacesSearch } from './components/GooglePlacesSearch';
|
|
37
37
|
export { default as HorizontalCards } from './components/HorizontalCards';
|
|
38
|
+
export { default as IIIFModal } from './components/IIIFModal';
|
|
38
39
|
export { default as ItemCollection } from './components/ItemCollection';
|
|
39
40
|
export { default as ItemList } from './components/ItemList';
|
|
40
41
|
export { default as Items } from './components/Items';
|
|
@@ -42,7 +43,9 @@ export { default as KeyboardField } from './components/KeyboardField';
|
|
|
42
43
|
export { default as KeyValuePairs } from './components/KeyValuePairs';
|
|
43
44
|
export { default as LazyAudio } from './components/LazyAudio';
|
|
44
45
|
export { default as LazyDocument } from './components/LazyDocument';
|
|
46
|
+
export { default as LazyIIIF } from './components/LazyIIIF';
|
|
45
47
|
export { default as LazyImage } from './components/LazyImage';
|
|
48
|
+
export { default as LazyMedia } from './components/LazyMedia';
|
|
46
49
|
export { default as LazyVideo } from './components/LazyVideo';
|
|
47
50
|
export { default as LinkButton } from './components/LinkButton';
|
|
48
51
|
export { default as ListFilters } from './components/ListFilters';
|