@performant-software/semantic-components 0.5.15 → 0.5.16-beta.10
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/build/main.css +43 -0
- package/package.json +3 -3
- package/src/components/AudioPlayer.css +3 -0
- package/src/components/AudioPlayer.js +54 -0
- package/src/components/DownloadButton.js +63 -12
- package/src/components/IIIFModal.js +26 -0
- package/src/components/LazyAudio.css +23 -0
- package/src/components/LazyAudio.js +150 -0
- package/src/components/LazyDocument.css +2 -0
- package/src/components/LazyDocument.js +29 -20
- package/src/components/LazyIIIF.js +44 -0
- package/src/components/LazyImage.css +3 -1
- package/src/components/LazyImage.js +40 -11
- package/src/components/LazyLoader.css +7 -0
- package/src/components/LazyLoader.js +28 -0
- package/src/components/LazyMedia.js +244 -0
- package/src/components/LazyVideo.css +8 -1
- package/src/components/LazyVideo.js +40 -5
- package/src/components/PhotoViewer.js +38 -25
- package/src/components/VideoPlayer.js +23 -2
- package/src/i18n/en.json +35 -3
- package/src/index.js +5 -0
- package/types/components/AudioPlayer.js.flow +54 -0
- package/types/components/DownloadButton.js.flow +63 -12
- package/types/components/IIIFModal.js.flow +26 -0
- package/types/components/LazyAudio.js.flow +150 -0
- package/types/components/LazyDocument.js.flow +29 -20
- package/types/components/LazyIIIF.js.flow +44 -0
- package/types/components/LazyImage.js.flow +40 -11
- package/types/components/LazyLoader.js.flow +28 -0
- package/types/components/LazyMedia.js.flow +244 -0
- package/types/components/LazyVideo.js.flow +40 -5
- package/types/components/PhotoViewer.js.flow +38 -25
- package/types/components/VideoPlayer.js.flow +23 -2
- package/types/index.js.flow +5 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { Image, Loader } from 'semantic-ui-react';
|
|
5
|
+
import './LazyLoader.css';
|
|
6
|
+
|
|
7
|
+
type Props = {
|
|
8
|
+
active: boolean,
|
|
9
|
+
size: string
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const LazyLoader = (props: Props) => (
|
|
13
|
+
<Image
|
|
14
|
+
className='lazy-loader'
|
|
15
|
+
size={props.size}
|
|
16
|
+
>
|
|
17
|
+
<Loader
|
|
18
|
+
active={props.active}
|
|
19
|
+
/>
|
|
20
|
+
</Image>
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
LazyLoader.defaultProps = {
|
|
24
|
+
active: false,
|
|
25
|
+
size: 'small'
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export default LazyLoader;
|
|
@@ -0,0 +1,244 @@
|
|
|
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
|
+
download={props.downloadUrl}
|
|
166
|
+
pdf={contentType === ContentTypes.pdf}
|
|
167
|
+
preview={preview}
|
|
168
|
+
src={source}
|
|
169
|
+
size={props.size}
|
|
170
|
+
>
|
|
171
|
+
{ renderChildren() }
|
|
172
|
+
</LazyDocument>
|
|
173
|
+
);
|
|
174
|
+
}, [contentType, preview, source, props.dimmable, props.downloadUrl, props.size]);
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Renders the upload message.
|
|
178
|
+
*
|
|
179
|
+
* @type {(function(): (null|*))|*}
|
|
180
|
+
*/
|
|
181
|
+
const renderMessage = useCallback(() => {
|
|
182
|
+
if (!fileExtension) {
|
|
183
|
+
return null;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return (
|
|
187
|
+
<div>
|
|
188
|
+
<Icon
|
|
189
|
+
name='info circle'
|
|
190
|
+
/>
|
|
191
|
+
<span>
|
|
192
|
+
<Trans
|
|
193
|
+
components={{ bold: <strong /> }}
|
|
194
|
+
default='Your <bold>{{type}}</bold> has been received'
|
|
195
|
+
i18n={i18n}
|
|
196
|
+
i18nKey='LazyMedia.messages.uploaded'
|
|
197
|
+
values={{
|
|
198
|
+
type: fileExtension
|
|
199
|
+
}}
|
|
200
|
+
/>
|
|
201
|
+
</span>
|
|
202
|
+
</div>
|
|
203
|
+
);
|
|
204
|
+
}, [fileExtension]);
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Sets the content type, name, preview, and source.
|
|
208
|
+
*/
|
|
209
|
+
useEffect(() => {
|
|
210
|
+
if (props.contentType) {
|
|
211
|
+
setContentType(props.contentType);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (props.name) {
|
|
215
|
+
setName(props.name);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
if (props.preview) {
|
|
219
|
+
setPreview(props.preview);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
if (props.src) {
|
|
223
|
+
setSource(props.src);
|
|
224
|
+
} else {
|
|
225
|
+
setSource(null);
|
|
226
|
+
}
|
|
227
|
+
}, [props.contentType, props.name, props.preview, props.src]);
|
|
228
|
+
|
|
229
|
+
return (
|
|
230
|
+
<div
|
|
231
|
+
className='lazy-media'
|
|
232
|
+
>
|
|
233
|
+
{ renderMedia() }
|
|
234
|
+
{ renderMessage() }
|
|
235
|
+
</div>
|
|
236
|
+
);
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
LazyMedia.defaultProps = {
|
|
240
|
+
dimmable: true,
|
|
241
|
+
size: 'medium'
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
export default LazyMedia;
|
|
@@ -12,6 +12,8 @@ import {
|
|
|
12
12
|
Visibility
|
|
13
13
|
} from 'semantic-ui-react';
|
|
14
14
|
import i18n from '../i18n/i18n';
|
|
15
|
+
import DownloadButton from './DownloadButton';
|
|
16
|
+
import LazyLoader from './LazyLoader';
|
|
15
17
|
import VideoPlayer from './VideoPlayer';
|
|
16
18
|
import './LazyVideo.css';
|
|
17
19
|
|
|
@@ -19,19 +21,23 @@ type Props = {
|
|
|
19
21
|
autoPlay?: boolean,
|
|
20
22
|
children?: Node,
|
|
21
23
|
dimmable: boolean,
|
|
24
|
+
download?: string,
|
|
22
25
|
duration?: number,
|
|
23
26
|
embedded?: boolean,
|
|
24
27
|
icon?: string | Element<any>,
|
|
25
28
|
image?: any,
|
|
29
|
+
name?: string,
|
|
26
30
|
preview?: ?string,
|
|
27
31
|
size?: string,
|
|
28
32
|
src?: string
|
|
29
33
|
};
|
|
30
34
|
|
|
31
35
|
const LazyVideo = (props: Props) => {
|
|
32
|
-
const [visible, setVisible] = useState(false);
|
|
33
|
-
const [modal, setModal] = useState(false);
|
|
34
36
|
const [dimmer, setDimmer] = useState(false);
|
|
37
|
+
const [error, setError] = useState(false);
|
|
38
|
+
const [loaded, setLoaded] = useState(!(props.preview || props.src));
|
|
39
|
+
const [modal, setModal] = useState(false);
|
|
40
|
+
const [visible, setVisible] = useState(false);
|
|
35
41
|
|
|
36
42
|
if (!visible) {
|
|
37
43
|
return (
|
|
@@ -63,24 +69,46 @@ const LazyVideo = (props: Props) => {
|
|
|
63
69
|
onMouseEnter={() => setDimmer(true)}
|
|
64
70
|
onMouseLeave={() => setDimmer(false)}
|
|
65
71
|
>
|
|
66
|
-
{
|
|
72
|
+
{ !loaded && (
|
|
73
|
+
<LazyLoader
|
|
74
|
+
active
|
|
75
|
+
size={props.size}
|
|
76
|
+
/>
|
|
77
|
+
)}
|
|
78
|
+
{ !error && props.preview && (
|
|
67
79
|
<Image
|
|
68
80
|
{...props.image}
|
|
81
|
+
onError={() => {
|
|
82
|
+
setError(true);
|
|
83
|
+
setLoaded(true);
|
|
84
|
+
}}
|
|
85
|
+
onLoad={() => {
|
|
86
|
+
setError(false);
|
|
87
|
+
setLoaded(true);
|
|
88
|
+
}}
|
|
69
89
|
src={props.preview}
|
|
70
90
|
size={props.size}
|
|
71
91
|
/>
|
|
72
92
|
)}
|
|
73
|
-
{ !props.preview && props.src && (
|
|
93
|
+
{ !error && !props.preview && props.src && (
|
|
74
94
|
<Image
|
|
75
95
|
{...props.image}
|
|
76
96
|
size={props.size}
|
|
77
97
|
>
|
|
78
98
|
<video
|
|
99
|
+
onError={() => {
|
|
100
|
+
setError(true);
|
|
101
|
+
setLoaded(true);
|
|
102
|
+
}}
|
|
103
|
+
onLoadedData={() => {
|
|
104
|
+
setError(false);
|
|
105
|
+
setLoaded(true);
|
|
106
|
+
}}
|
|
79
107
|
src={props.src}
|
|
80
108
|
/>
|
|
81
109
|
</Image>
|
|
82
110
|
)}
|
|
83
|
-
{ !props.preview && !props.src && (
|
|
111
|
+
{ (error || (!props.preview && !props.src)) && (
|
|
84
112
|
<Image
|
|
85
113
|
{...props.image}
|
|
86
114
|
className='placeholder-image'
|
|
@@ -107,6 +135,13 @@ const LazyVideo = (props: Props) => {
|
|
|
107
135
|
primary
|
|
108
136
|
/>
|
|
109
137
|
)}
|
|
138
|
+
{ props.download && (
|
|
139
|
+
<DownloadButton
|
|
140
|
+
color='green'
|
|
141
|
+
filename={props.name}
|
|
142
|
+
url={props.download}
|
|
143
|
+
/>
|
|
144
|
+
)}
|
|
110
145
|
{ props.children }
|
|
111
146
|
</div>
|
|
112
147
|
</Dimmer>
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
// @flow
|
|
2
2
|
|
|
3
|
-
import React from 'react';
|
|
4
|
-
import { Image, Modal } from 'semantic-ui-react';
|
|
3
|
+
import React, { useState } from 'react';
|
|
4
|
+
import { Image, Message, Modal } from 'semantic-ui-react';
|
|
5
5
|
import ModalContext from '../context/ModalContext';
|
|
6
6
|
import './PhotoViewer.css';
|
|
7
|
+
import i18n from '../i18n/i18n';
|
|
7
8
|
|
|
8
9
|
type Props = {
|
|
9
10
|
alt?: string,
|
|
@@ -13,29 +14,41 @@ type Props = {
|
|
|
13
14
|
size?: string
|
|
14
15
|
};
|
|
15
16
|
|
|
16
|
-
const PhotoViewer = (props: Props) =>
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
)
|
|
17
|
+
const PhotoViewer = (props: Props) => {
|
|
18
|
+
const [error, setError] = useState(false);
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<ModalContext.Consumer>
|
|
22
|
+
{(mountNode) => (
|
|
23
|
+
<Modal
|
|
24
|
+
centered={false}
|
|
25
|
+
className='photo-viewer'
|
|
26
|
+
closeIcon
|
|
27
|
+
mountNode={mountNode}
|
|
28
|
+
onClose={props.onClose.bind(this)}
|
|
29
|
+
open={props.open}
|
|
30
|
+
size={props.size}
|
|
31
|
+
>
|
|
32
|
+
<Modal.Content>
|
|
33
|
+
{ error && (
|
|
34
|
+
<Message
|
|
35
|
+
content={i18n.t('PhotoViewer.errors.path.content', { path: props.image })}
|
|
36
|
+
header={i18n.t('PhotoViewer.errors.path.header')}
|
|
37
|
+
icon='exclamation circle'
|
|
38
|
+
/>
|
|
39
|
+
)}
|
|
40
|
+
<Image
|
|
41
|
+
alt={props.alt}
|
|
42
|
+
fluid
|
|
43
|
+
onError={() => setError(true)}
|
|
44
|
+
src={props.image}
|
|
45
|
+
/>
|
|
46
|
+
</Modal.Content>
|
|
47
|
+
</Modal>
|
|
48
|
+
)}
|
|
49
|
+
</ModalContext.Consumer>
|
|
50
|
+
);
|
|
51
|
+
};
|
|
39
52
|
|
|
40
53
|
PhotoViewer.defaultProps = {
|
|
41
54
|
size: 'small'
|
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
// @flow
|
|
2
2
|
|
|
3
|
-
import React, {
|
|
4
|
-
|
|
3
|
+
import React, {
|
|
4
|
+
useEffect,
|
|
5
|
+
useRef,
|
|
6
|
+
useState,
|
|
7
|
+
type Element
|
|
8
|
+
} from 'react';
|
|
9
|
+
import {
|
|
10
|
+
Embed,
|
|
11
|
+
Message,
|
|
12
|
+
Modal,
|
|
13
|
+
Ref
|
|
14
|
+
} from 'semantic-ui-react';
|
|
5
15
|
import ModalContext from '../context/ModalContext';
|
|
6
16
|
import './VideoPlayer.css';
|
|
17
|
+
import i18n from '../i18n/i18n';
|
|
7
18
|
|
|
8
19
|
type Props = {
|
|
9
20
|
autoPlay?: boolean,
|
|
@@ -18,6 +29,8 @@ type Props = {
|
|
|
18
29
|
};
|
|
19
30
|
|
|
20
31
|
const VideoPlayer = (props: Props) => {
|
|
32
|
+
const [error, setError] = useState(false);
|
|
33
|
+
|
|
21
34
|
const embedRef = useRef();
|
|
22
35
|
|
|
23
36
|
/**
|
|
@@ -46,6 +59,13 @@ const VideoPlayer = (props: Props) => {
|
|
|
46
59
|
size={props.size}
|
|
47
60
|
>
|
|
48
61
|
<Modal.Content>
|
|
62
|
+
{ error && (
|
|
63
|
+
<Message
|
|
64
|
+
content={i18n.t('VideoPlayer.errors.path.content', { path: props.video })}
|
|
65
|
+
header={i18n.t('VideoPlayer.errors.path.header')}
|
|
66
|
+
icon='exclamation circle'
|
|
67
|
+
/>
|
|
68
|
+
)}
|
|
49
69
|
{ props.embedded && (
|
|
50
70
|
<Ref
|
|
51
71
|
innerRef={embedRef}
|
|
@@ -63,6 +83,7 @@ const VideoPlayer = (props: Props) => {
|
|
|
63
83
|
<video
|
|
64
84
|
autoPlay={props.autoPlay}
|
|
65
85
|
controls
|
|
86
|
+
onError={() => setError(true)}
|
|
66
87
|
src={props.video}
|
|
67
88
|
/>
|
|
68
89
|
)}
|
package/types/index.js.flow
CHANGED
|
@@ -9,6 +9,7 @@ export { default as AccordionList } from './components/AccordionList';
|
|
|
9
9
|
export { default as AccordionSelector } from './components/AccordionSelector';
|
|
10
10
|
export { default as ArrowButtons } from './components/ArrowButtons';
|
|
11
11
|
export { default as AssociatedDropdown } from './components/AssociatedDropdown';
|
|
12
|
+
export { default as AudioPlayer } from './components/AudioPlayer';
|
|
12
13
|
export { default as BooleanIcon } from './components/BooleanIcon';
|
|
13
14
|
export { default as CancelButton } from './components/CancelButton';
|
|
14
15
|
export { default as ColorButton } from './components/ColorButton';
|
|
@@ -34,13 +35,17 @@ export { default as FuzzyDate } from './components/FuzzyDate';
|
|
|
34
35
|
export { default as GoogleMap } from './components/GoogleMap';
|
|
35
36
|
export { default as GooglePlacesSearch } from './components/GooglePlacesSearch';
|
|
36
37
|
export { default as HorizontalCards } from './components/HorizontalCards';
|
|
38
|
+
export { default as IIIFModal } from './components/IIIFModal';
|
|
37
39
|
export { default as ItemCollection } from './components/ItemCollection';
|
|
38
40
|
export { default as ItemList } from './components/ItemList';
|
|
39
41
|
export { default as Items } from './components/Items';
|
|
40
42
|
export { default as KeyboardField } from './components/KeyboardField';
|
|
41
43
|
export { default as KeyValuePairs } from './components/KeyValuePairs';
|
|
44
|
+
export { default as LazyAudio } from './components/LazyAudio';
|
|
42
45
|
export { default as LazyDocument } from './components/LazyDocument';
|
|
46
|
+
export { default as LazyIIIF } from './components/LazyIIIF';
|
|
43
47
|
export { default as LazyImage } from './components/LazyImage';
|
|
48
|
+
export { default as LazyMedia } from './components/LazyMedia';
|
|
44
49
|
export { default as LazyVideo } from './components/LazyVideo';
|
|
45
50
|
export { default as LinkButton } from './components/LinkButton';
|
|
46
51
|
export { default as ListFilters } from './components/ListFilters';
|