@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.
@@ -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>
@@ -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';