@shoutem/ui 5.5.0 → 6.0.0-rc.0
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/components/Icon/assets/camera.svg +2 -2
- package/components/Icon/assets/gallery.svg +2 -2
- package/components/ImageGallery.js +161 -0
- package/components/Lightbox.js +10 -1
- package/components/TabMenu/TabMenu.js +74 -4
- package/components/TabMenu/TabMenuItem.js +14 -3
- package/package.json +5 -4
- package/theme.js +6 -2
- package/components/ImageGallery/ImageGallery.android.js +0 -42
- package/components/ImageGallery/ImageGallery.ios.js +0 -120
- package/components/ImageGallery/ImageGalleryBase.js +0 -199
- package/components/ImageGallery/index.js +0 -1
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
<svg width="24" height="24" viewBox="0 0 24 24"
|
|
2
|
-
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.82322 4.82322C8.87011 4.77634 8.9337 4.75 9 4.75H15C15.0663 4.75 15.1299 4.77634 15.1768 4.82322C15.2237 4.87011 15.25 4.9337 15.25 5C15.25 5.72935 15.5397 6.42882 16.0555 6.94454C16.5712 7.46027 17.2707 7.75 18 7.75H19C19.3315 7.75 19.6495 7.8817 19.8839 8.11612C20.1183 8.35054 20.25 8.66848 20.25 9V18C20.25 18.3315 20.1183 18.6495 19.8839 18.8839C19.6495 19.1183 19.3315 19.25 19 19.25H5C4.66848 19.25 4.35054 19.1183 4.11612 18.8839C3.8817 18.6495 3.75 18.3315 3.75 18V9C3.75 8.66848 3.8817 8.35054 4.11612 8.11612C4.35054 7.8817 4.66848 7.75 5 7.75H6C6.72935 7.75 7.42882 7.46027 7.94454 6.94454C8.46027 6.42882 8.75 5.72935 8.75 5C8.75 4.9337 8.77634 4.87011 8.82322 4.82322ZM3.05546 7.05546C3.57118 6.53973 4.27065 6.25 5 6.25H6C6.33152 6.25 6.64946 6.1183 6.88388 5.88388C7.1183 5.64946 7.25 5.33152 7.25 5C7.25 4.53587 7.43437 4.09075 7.76256 3.76256C8.09075 3.43438 8.53587 3.25 9 3.25H15C15.4641 3.25 15.9092 3.43438 16.2374 3.76256C16.5656 4.09075 16.75 4.53587 16.75 5C16.75 5.33152 16.8817 5.64946 17.1161 5.88388C17.3505 6.1183 17.6685 6.25 18 6.25H19C19.7293 6.25 20.4288 6.53973 20.9445 7.05546C21.4603 7.57118 21.75 8.27065 21.75 9V18C21.75 18.7293 21.4603 19.4288 20.9445 19.9445C20.4288 20.4603 19.7293 20.75 19 20.75H5C4.27065 20.75 3.57118 20.4603 3.05546 19.9445C2.53973 19.4288 2.25 18.7293 2.25 18V9C2.25 8.27065 2.53973 7.57118 3.05546 7.05546ZM9.75 13C9.75 11.7574 10.7574 10.75 12 10.75C13.2426 10.75 14.25 11.7574 14.25 13C14.25 14.2426 13.2426 15.25 12 15.25C10.7574 15.25 9.75 14.2426 9.75 13ZM12 9.25C9.92893 9.25 8.25 10.9289 8.25 13C8.25 15.0711 9.92893 16.75 12 16.75C14.0711 16.75 15.75 15.0711 15.75 13C15.75 10.9289 14.0711 9.25 12 9.25Z"
|
|
1
|
+
<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.82322 4.82322C8.87011 4.77634 8.9337 4.75 9 4.75H15C15.0663 4.75 15.1299 4.77634 15.1768 4.82322C15.2237 4.87011 15.25 4.9337 15.25 5C15.25 5.72935 15.5397 6.42882 16.0555 6.94454C16.5712 7.46027 17.2707 7.75 18 7.75H19C19.3315 7.75 19.6495 7.8817 19.8839 8.11612C20.1183 8.35054 20.25 8.66848 20.25 9V18C20.25 18.3315 20.1183 18.6495 19.8839 18.8839C19.6495 19.1183 19.3315 19.25 19 19.25H5C4.66848 19.25 4.35054 19.1183 4.11612 18.8839C3.8817 18.6495 3.75 18.3315 3.75 18V9C3.75 8.66848 3.8817 8.35054 4.11612 8.11612C4.35054 7.8817 4.66848 7.75 5 7.75H6C6.72935 7.75 7.42882 7.46027 7.94454 6.94454C8.46027 6.42882 8.75 5.72935 8.75 5C8.75 4.9337 8.77634 4.87011 8.82322 4.82322ZM3.05546 7.05546C3.57118 6.53973 4.27065 6.25 5 6.25H6C6.33152 6.25 6.64946 6.1183 6.88388 5.88388C7.1183 5.64946 7.25 5.33152 7.25 5C7.25 4.53587 7.43437 4.09075 7.76256 3.76256C8.09075 3.43438 8.53587 3.25 9 3.25H15C15.4641 3.25 15.9092 3.43438 16.2374 3.76256C16.5656 4.09075 16.75 4.53587 16.75 5C16.75 5.33152 16.8817 5.64946 17.1161 5.88388C17.3505 6.1183 17.6685 6.25 18 6.25H19C19.7293 6.25 20.4288 6.53973 20.9445 7.05546C21.4603 7.57118 21.75 8.27065 21.75 9V18C21.75 18.7293 21.4603 19.4288 20.9445 19.9445C20.4288 20.4603 19.7293 20.75 19 20.75H5C4.27065 20.75 3.57118 20.4603 3.05546 19.9445C2.53973 19.4288 2.25 18.7293 2.25 18V9C2.25 8.27065 2.53973 7.57118 3.05546 7.05546ZM9.75 13C9.75 11.7574 10.7574 10.75 12 10.75C13.2426 10.75 14.25 11.7574 14.25 13C14.25 14.2426 13.2426 15.25 12 15.25C10.7574 15.25 9.75 14.2426 9.75 13ZM12 9.25C9.92893 9.25 8.25 10.9289 8.25 13C8.25 15.0711 9.92893 16.75 12 16.75C14.0711 16.75 15.75 15.0711 15.75 13C15.75 10.9289 14.0711 9.25 12 9.25Z"/>
|
|
3
3
|
</svg>
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
<svg width="16" height="16" viewBox="0 0 16 16"
|
|
2
|
-
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.16602 4.66602C3.16602 3.83759 3.83759 3.16602 4.66602 3.16602H11.3327C12.1611 3.16602 12.8327 3.83759 12.8327 4.66602V8.79221L12.3542 8.31373L12.3543 8.31367L12.3473 8.307C11.9701 7.94404 11.5063 7.7207 11.0007 7.7207C10.495 7.7207 10.0312 7.94404 9.65396 8.307L9.6539 8.30693L9.6471 8.31373L9.33366 8.62717L7.68624 6.97975L7.6863 6.97968L7.67937 6.97301C7.30217 6.61005 6.83835 6.38672 6.33268 6.38672C5.82701 6.38672 5.36319 6.61005 4.98599 6.97301L4.98593 6.97295L4.97913 6.97975L3.16602 8.79286V4.66602ZM10.0408 9.33428L11.0196 10.3131C11.2148 10.5083 11.2148 10.8249 11.0196 11.0202C10.8243 11.2155 10.5077 11.2155 10.3125 11.0202L6.98275 7.69048C6.753 7.47063 6.52824 7.38672 6.33268 7.38672C6.13712 7.38672 5.91236 7.47064 5.6826 7.69049L3.16602 10.2071V11.3327C3.16602 12.1611 3.83759 12.8327 4.66602 12.8327H11.3327C12.1611 12.8327 12.8327 12.1611 12.8327 11.3327V10.2064L11.6507 9.02447C11.421 8.80462 11.1962 8.7207 11.0007 8.7207C10.8051 8.7207 10.5803 8.80462 10.3506 9.02447L10.0408 9.33428ZM13.8327 10.0368V11.3327C13.8327 12.7134 12.7134 13.8327 11.3327 13.8327H4.66602C3.2853 13.8327 2.16602 12.7134 2.16602 11.3327V10.0001V9.99988V4.66602C2.16602 3.2853 3.2853 2.16602 4.66602 2.16602H11.3327C12.7134 2.16602 13.8327 3.2853 13.8327 4.66602V9.96445C13.8344 9.98853 13.8344 10.0127 13.8327 10.0368ZM10 4.83398C9.72386 4.83398 9.5 5.05784 9.5 5.33398C9.5 5.61013 9.72386 5.83398 10 5.83398H10.0075C10.2836 5.83398 10.5075 5.61013 10.5075 5.33398C10.5075 5.05784 10.2836 4.83398 10.0075 4.83398H10Z"
|
|
1
|
+
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.16602 4.66602C3.16602 3.83759 3.83759 3.16602 4.66602 3.16602H11.3327C12.1611 3.16602 12.8327 3.83759 12.8327 4.66602V8.79221L12.3542 8.31373L12.3543 8.31367L12.3473 8.307C11.9701 7.94404 11.5063 7.7207 11.0007 7.7207C10.495 7.7207 10.0312 7.94404 9.65396 8.307L9.6539 8.30693L9.6471 8.31373L9.33366 8.62717L7.68624 6.97975L7.6863 6.97968L7.67937 6.97301C7.30217 6.61005 6.83835 6.38672 6.33268 6.38672C5.82701 6.38672 5.36319 6.61005 4.98599 6.97301L4.98593 6.97295L4.97913 6.97975L3.16602 8.79286V4.66602ZM10.0408 9.33428L11.0196 10.3131C11.2148 10.5083 11.2148 10.8249 11.0196 11.0202C10.8243 11.2155 10.5077 11.2155 10.3125 11.0202L6.98275 7.69048C6.753 7.47063 6.52824 7.38672 6.33268 7.38672C6.13712 7.38672 5.91236 7.47064 5.6826 7.69049L3.16602 10.2071V11.3327C3.16602 12.1611 3.83759 12.8327 4.66602 12.8327H11.3327C12.1611 12.8327 12.8327 12.1611 12.8327 11.3327V10.2064L11.6507 9.02447C11.421 8.80462 11.1962 8.7207 11.0007 8.7207C10.8051 8.7207 10.5803 8.80462 10.3506 9.02447L10.0408 9.33428ZM13.8327 10.0368V11.3327C13.8327 12.7134 12.7134 13.8327 11.3327 13.8327H4.66602C3.2853 13.8327 2.16602 12.7134 2.16602 11.3327V10.0001V9.99988V4.66602C2.16602 3.2853 3.2853 2.16602 4.66602 2.16602H11.3327C12.7134 2.16602 13.8327 3.2853 13.8327 4.66602V9.96445C13.8344 9.98853 13.8344 10.0127 13.8327 10.0368ZM10 4.83398C9.72386 4.83398 9.5 5.05784 9.5 5.33398C9.5 5.61013 9.72386 5.83398 10 5.83398H10.0075C10.2836 5.83398 10.5075 5.61013 10.5075 5.33398C10.5075 5.05784 10.2836 4.83398 10.0075 4.83398H10Z"/>
|
|
3
3
|
</svg>
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import React, { useCallback, useState } from 'react';
|
|
2
|
+
import { Pressable } from 'react-native';
|
|
3
|
+
import { ReactNativeZoomableView } from '@openspacelabs/react-native-zoomable-view';
|
|
4
|
+
import _ from 'lodash';
|
|
5
|
+
import PropTypes from 'prop-types';
|
|
6
|
+
import { connectStyle } from '@shoutem/theme';
|
|
7
|
+
import { HorizontalPager } from './HorizontalPager';
|
|
8
|
+
import { Image } from './Image';
|
|
9
|
+
import { LoadingIndicator } from './LoadingIndicator';
|
|
10
|
+
import { View } from './View';
|
|
11
|
+
|
|
12
|
+
const IMAGE_PREVIEW_MODE = 'imagePreview';
|
|
13
|
+
const IMAGE_GALLERY_MODE = 'gallery';
|
|
14
|
+
|
|
15
|
+
function ImageGallery({
|
|
16
|
+
data,
|
|
17
|
+
onIndexSelected,
|
|
18
|
+
onModeChanged,
|
|
19
|
+
renderOverlay,
|
|
20
|
+
renderImageOverlay,
|
|
21
|
+
renderPlaceholder,
|
|
22
|
+
selectedIndex,
|
|
23
|
+
showNextPage,
|
|
24
|
+
style,
|
|
25
|
+
}) {
|
|
26
|
+
const [currentIndex, setCurrentIndex] = useState(selectedIndex);
|
|
27
|
+
const [mode, setMode] = useState(IMAGE_GALLERY_MODE);
|
|
28
|
+
|
|
29
|
+
const handleImageTap = useCallback(
|
|
30
|
+
newMode => {
|
|
31
|
+
if (mode === IMAGE_PREVIEW_MODE) {
|
|
32
|
+
setMode(IMAGE_GALLERY_MODE);
|
|
33
|
+
} else {
|
|
34
|
+
setMode(IMAGE_PREVIEW_MODE);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (_.isFunction(onModeChanged)) {
|
|
38
|
+
onModeChanged(newMode);
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
[mode, onModeChanged],
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
const handleIndexSelected = useCallback(
|
|
45
|
+
newIndex => {
|
|
46
|
+
setCurrentIndex(newIndex);
|
|
47
|
+
|
|
48
|
+
if (_.isFunction(onIndexSelected)) {
|
|
49
|
+
onIndexSelected(newIndex);
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
[onIndexSelected],
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
const renderImage = useCallback(
|
|
56
|
+
imageProps => {
|
|
57
|
+
const imageStyle = imageProps?.style;
|
|
58
|
+
const resolvedImageProps = _.omit(imageProps, 'style');
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<ReactNativeZoomableView
|
|
62
|
+
maxZoom={1.5}
|
|
63
|
+
minZoom={0.5}
|
|
64
|
+
zoomStep={0.5}
|
|
65
|
+
initialZoom={1}
|
|
66
|
+
bindToBorders
|
|
67
|
+
>
|
|
68
|
+
<Pressable style={[imageStyle, style.image]} onPress={handleImageTap}>
|
|
69
|
+
<Image style={[imageStyle, style.image]} {...resolvedImageProps} />
|
|
70
|
+
</Pressable>
|
|
71
|
+
</ReactNativeZoomableView>
|
|
72
|
+
);
|
|
73
|
+
},
|
|
74
|
+
[handleImageTap, style.image],
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
function renderPage(pageData, pageIndex) {
|
|
78
|
+
const image = _.get(pageData, 'source.uri');
|
|
79
|
+
|
|
80
|
+
if (!image) {
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const isImageVisible = pageIndex === selectedIndex;
|
|
85
|
+
const transformImageProps = Image.getPropsTransformer();
|
|
86
|
+
const imageProps = {
|
|
87
|
+
source: { uri: image },
|
|
88
|
+
};
|
|
89
|
+
const transformedImageProps = _.isFunction(transformImageProps)
|
|
90
|
+
? transformImageProps(imageProps)
|
|
91
|
+
: imageProps;
|
|
92
|
+
|
|
93
|
+
const showOverlay =
|
|
94
|
+
_.isFunction(renderImageOverlay) &&
|
|
95
|
+
// Nothing should be rendered above an image if the user is in
|
|
96
|
+
// the preview mode (pinching, and panning the image).
|
|
97
|
+
mode !== IMAGE_PREVIEW_MODE &&
|
|
98
|
+
// We are not rendering overlays above images that are not visible
|
|
99
|
+
isImageVisible;
|
|
100
|
+
const overlay = showOverlay && renderImageOverlay(pageData, pageIndex);
|
|
101
|
+
|
|
102
|
+
return (
|
|
103
|
+
<View key={pageIndex} style={style.page}>
|
|
104
|
+
{renderImage(transformedImageProps, pageData, pageIndex)}
|
|
105
|
+
{overlay}
|
|
106
|
+
</View>
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return (
|
|
111
|
+
<View style={style.container}>
|
|
112
|
+
<HorizontalPager
|
|
113
|
+
data={data}
|
|
114
|
+
onIndexSelected={handleIndexSelected}
|
|
115
|
+
selectedIndex={currentIndex}
|
|
116
|
+
renderPage={renderPage}
|
|
117
|
+
bounces
|
|
118
|
+
pageMargin={style.pageMargin}
|
|
119
|
+
showNextPage={showNextPage}
|
|
120
|
+
renderOverlay={renderOverlay}
|
|
121
|
+
renderPlaceholder={renderPlaceholder}
|
|
122
|
+
scrollEnabled
|
|
123
|
+
/>
|
|
124
|
+
</View>
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
ImageGallery.propTypes = {
|
|
129
|
+
data: PropTypes.arrayOf(
|
|
130
|
+
PropTypes.shape({
|
|
131
|
+
description: PropTypes.string,
|
|
132
|
+
source: PropTypes.shape({
|
|
133
|
+
uri: PropTypes.string,
|
|
134
|
+
}),
|
|
135
|
+
title: PropTypes.string,
|
|
136
|
+
}),
|
|
137
|
+
).isRequired,
|
|
138
|
+
style: PropTypes.object.isRequired,
|
|
139
|
+
renderImageOverlay: PropTypes.func,
|
|
140
|
+
renderOverlay: PropTypes.func,
|
|
141
|
+
renderPlaceholder: PropTypes.func,
|
|
142
|
+
selectedIndex: PropTypes.number,
|
|
143
|
+
showNextPage: PropTypes.bool,
|
|
144
|
+
onIndexSelected: PropTypes.func,
|
|
145
|
+
onModeChanged: PropTypes.func,
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
ImageGallery.defaultProps = {
|
|
149
|
+
renderImageOverlay: undefined,
|
|
150
|
+
renderOverlay: undefined,
|
|
151
|
+
renderPlaceholder: () => <LoadingIndicator />,
|
|
152
|
+
selectedIndex: 0,
|
|
153
|
+
showNextPage: false,
|
|
154
|
+
onIndexSelected: undefined,
|
|
155
|
+
onModeChanged: undefined,
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
const StyledImageGallery = connectStyle('shoutem.ui.ImageGallery')(
|
|
159
|
+
ImageGallery,
|
|
160
|
+
);
|
|
161
|
+
export { StyledImageGallery as ImageGallery };
|
package/components/Lightbox.js
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
|
-
import
|
|
1
|
+
import React, { PureComponent } from 'react';
|
|
2
|
+
import RNLightbox from 'react-native-lightbox-v2';
|
|
2
3
|
import { connectAnimation } from '@shoutem/animation';
|
|
3
4
|
import { connectStyle } from '@shoutem/theme';
|
|
4
5
|
|
|
6
|
+
// Exporting as class because Animated.createAnimatedComponent
|
|
7
|
+
// doesn't support stateless functional components
|
|
8
|
+
class Lightbox extends PureComponent {
|
|
9
|
+
render() {
|
|
10
|
+
return <RNLightbox {...this.props} />;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
5
14
|
const AnimatedLightbox = connectAnimation(Lightbox);
|
|
6
15
|
const StyledLightbox = connectStyle('shoutem.ui.Lightbox')(AnimatedLightbox);
|
|
7
16
|
|
|
@@ -12,26 +12,91 @@ class TabMenu extends PureComponent {
|
|
|
12
12
|
super(props);
|
|
13
13
|
|
|
14
14
|
autoBindReact(this);
|
|
15
|
+
|
|
16
|
+
this.state = {
|
|
17
|
+
itemWidths: {},
|
|
18
|
+
scrollOffset: 0,
|
|
19
|
+
};
|
|
15
20
|
}
|
|
16
21
|
|
|
17
|
-
handleOptionSelected(option) {
|
|
22
|
+
handleOptionSelected(key, option) {
|
|
18
23
|
const { onOptionSelected } = this.props;
|
|
24
|
+
const { scrollOffset, itemWidths, viewportHorizontal } = this.state;
|
|
25
|
+
|
|
26
|
+
let itemStart = 0;
|
|
27
|
+
|
|
28
|
+
_.forEach(itemWidths, (itemWidth, index) => {
|
|
29
|
+
if (index < key) {
|
|
30
|
+
itemStart += itemWidth;
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const itemEnd = itemStart + itemWidths[key];
|
|
19
35
|
|
|
20
36
|
LayoutAnimation.easeInEaseOut();
|
|
21
37
|
onOptionSelected(option);
|
|
38
|
+
|
|
39
|
+
if (itemEnd > _.last(viewportHorizontal)) {
|
|
40
|
+
const extraScroll = itemEnd - _.last(viewportHorizontal);
|
|
41
|
+
|
|
42
|
+
this.scroll.scrollTo({
|
|
43
|
+
x: extraScroll + scrollOffset,
|
|
44
|
+
y: 0,
|
|
45
|
+
animated: true,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (itemStart < _.head(viewportHorizontal)) {
|
|
50
|
+
const extraScroll = _.head(viewportHorizontal) - itemStart;
|
|
51
|
+
|
|
52
|
+
this.scroll.scrollTo({
|
|
53
|
+
x: scrollOffset - extraScroll,
|
|
54
|
+
y: 0,
|
|
55
|
+
animated: true,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
handleItemLayout(key, width) {
|
|
61
|
+
const { itemWidths } = this.state;
|
|
62
|
+
|
|
63
|
+
this.setState({
|
|
64
|
+
itemWidths: {
|
|
65
|
+
...itemWidths,
|
|
66
|
+
[key]: width,
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
handleScroll({
|
|
72
|
+
nativeEvent: {
|
|
73
|
+
contentOffset: { x },
|
|
74
|
+
layoutMeasurement: { width },
|
|
75
|
+
},
|
|
76
|
+
}) {
|
|
77
|
+
this.setState({ scrollOffset: x, viewportHorizontal: [x, x + width] });
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
handleScrollLayout({
|
|
81
|
+
nativeEvent: {
|
|
82
|
+
layout: { width },
|
|
83
|
+
},
|
|
84
|
+
}) {
|
|
85
|
+
this.setState({ viewportHorizontal: [0, width] });
|
|
22
86
|
}
|
|
23
87
|
|
|
24
|
-
renderOption(option) {
|
|
88
|
+
renderOption(option, key) {
|
|
25
89
|
const { selectedOption } = this.props;
|
|
26
90
|
|
|
27
91
|
const isSelected = selectedOption && option.title === selectedOption.title;
|
|
28
92
|
|
|
29
93
|
return (
|
|
30
94
|
<TabMenuItem
|
|
31
|
-
key={
|
|
95
|
+
key={key}
|
|
32
96
|
isSelected={isSelected}
|
|
33
97
|
item={option}
|
|
34
|
-
onItemPressed={this.handleOptionSelected}
|
|
98
|
+
onItemPressed={option => this.handleOptionSelected(key, option)}
|
|
99
|
+
onLayoutMeasured={width => this.handleItemLayout(key, width)}
|
|
35
100
|
/>
|
|
36
101
|
);
|
|
37
102
|
}
|
|
@@ -43,6 +108,11 @@ class TabMenu extends PureComponent {
|
|
|
43
108
|
<ScrollView
|
|
44
109
|
horizontal
|
|
45
110
|
contentContainerStyle={style.container}
|
|
111
|
+
onScroll={this.handleScroll}
|
|
112
|
+
onLayout={this.handleScrollLayout}
|
|
113
|
+
ref={ref => {
|
|
114
|
+
this.scroll = ref;
|
|
115
|
+
}}
|
|
46
116
|
showsHorizontalScrollIndicator={false}
|
|
47
117
|
style={style.list}
|
|
48
118
|
>
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import React, { PureComponent } from 'react';
|
|
2
2
|
import { LayoutAnimation } from 'react-native';
|
|
3
3
|
import autoBindReact from 'auto-bind/react';
|
|
4
|
-
import _ from 'lodash';
|
|
5
4
|
import PropTypes from 'prop-types';
|
|
6
5
|
import { connectStyle } from '@shoutem/theme';
|
|
7
6
|
import { Text } from '../Text';
|
|
@@ -26,7 +25,7 @@ class TabMenuItem extends PureComponent {
|
|
|
26
25
|
onItemPressed(item);
|
|
27
26
|
}
|
|
28
27
|
|
|
29
|
-
|
|
28
|
+
handleTextLayout({
|
|
30
29
|
nativeEvent: {
|
|
31
30
|
layout: { width },
|
|
32
31
|
},
|
|
@@ -35,6 +34,16 @@ class TabMenuItem extends PureComponent {
|
|
|
35
34
|
this.setState({ baseWidth: width });
|
|
36
35
|
}
|
|
37
36
|
|
|
37
|
+
handleContainerLayout({
|
|
38
|
+
nativeEvent: {
|
|
39
|
+
layout: { width },
|
|
40
|
+
},
|
|
41
|
+
}) {
|
|
42
|
+
const { onLayoutMeasured } = this.props;
|
|
43
|
+
|
|
44
|
+
onLayoutMeasured(width);
|
|
45
|
+
}
|
|
46
|
+
|
|
38
47
|
render() {
|
|
39
48
|
const { style, isSelected, item } = this.props;
|
|
40
49
|
const { baseWidth } = this.state;
|
|
@@ -42,11 +51,12 @@ class TabMenuItem extends PureComponent {
|
|
|
42
51
|
return (
|
|
43
52
|
<TouchableOpacity
|
|
44
53
|
onPress={this.handleItemPressed}
|
|
54
|
+
onLayout={this.handleContainerLayout}
|
|
45
55
|
styleName="vertical h-center"
|
|
46
56
|
>
|
|
47
57
|
<Text
|
|
48
58
|
style={[style.text, isSelected && style.selectedText]}
|
|
49
|
-
onLayout={this.
|
|
59
|
+
onLayout={this.handleTextLayout}
|
|
50
60
|
>
|
|
51
61
|
{item.title}
|
|
52
62
|
</Text>
|
|
@@ -58,6 +68,7 @@ class TabMenuItem extends PureComponent {
|
|
|
58
68
|
|
|
59
69
|
TabMenuItem.propTypes = {
|
|
60
70
|
style: PropTypes.object.isRequired,
|
|
71
|
+
onLayoutMeasured: PropTypes.func.isRequired,
|
|
61
72
|
isSelected: PropTypes.bool,
|
|
62
73
|
item: optionShape,
|
|
63
74
|
onItemPressed: PropTypes.func,
|
package/package.json
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shoutem/ui",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.0.0-rc.0",
|
|
4
4
|
"description": "Styleable set of components for React Native applications",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"lint": "eslint .",
|
|
7
7
|
"lint-fix": "eslint . --fix",
|
|
8
8
|
"postinstall": "node ./scripts/add-native-deps",
|
|
9
|
+
"release": "npm publish --access public --tag latest",
|
|
10
|
+
"release-rc": "npm publish --access public --tag rc",
|
|
9
11
|
"test": "jest"
|
|
10
12
|
},
|
|
11
13
|
"dependencies": {
|
|
14
|
+
"@openspacelabs/react-native-zoomable-view": "2.0.4",
|
|
12
15
|
"@react-native-community/datetimepicker": "6.2.0",
|
|
13
16
|
"@shoutem/animation": "~0.15.0",
|
|
14
17
|
"@shoutem/eslint-config-react": "~1.0.6",
|
|
@@ -27,15 +30,13 @@
|
|
|
27
30
|
"prop-types": "15.8.1",
|
|
28
31
|
"qs": "6.9.3",
|
|
29
32
|
"react-native-device-info": "9.0.2",
|
|
30
|
-
"react-native-lightbox": "
|
|
33
|
+
"react-native-lightbox-v2": "0.9.0",
|
|
31
34
|
"react-native-linear-gradient": "2.6.2",
|
|
32
35
|
"react-native-modal": "11.7.0",
|
|
33
|
-
"react-native-photo-view": "github:shoutem/react-native-photo-view#a296aa2",
|
|
34
36
|
"react-native-render-html": "4.2.5",
|
|
35
37
|
"react-native-render-html-table-bridge": "0.6.0",
|
|
36
38
|
"react-native-svg": "12.3.0",
|
|
37
39
|
"react-native-svg-transformer": "1.0.0",
|
|
38
|
-
"react-native-transformable-image": "github:shoutem/react-native-transformable-image#v0.0.20",
|
|
39
40
|
"react-native-webview": "11.23.0",
|
|
40
41
|
"react-native-youtube-iframe": "2.2.2",
|
|
41
42
|
"stream": "0.0.2",
|
package/theme.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Dimensions, Platform,
|
|
1
|
+
import { Dimensions, Platform, StyleSheet } from 'react-native';
|
|
2
2
|
import {
|
|
3
3
|
changeColorAlpha,
|
|
4
4
|
createSharedStyle,
|
|
@@ -2637,6 +2637,11 @@ export default () => {
|
|
|
2637
2637
|
justifyContent: 'center',
|
|
2638
2638
|
overflow: 'hidden',
|
|
2639
2639
|
},
|
|
2640
|
+
image: {
|
|
2641
|
+
width: '100%',
|
|
2642
|
+
height: '100%',
|
|
2643
|
+
resizeMode: 'contain',
|
|
2644
|
+
},
|
|
2640
2645
|
},
|
|
2641
2646
|
|
|
2642
2647
|
'shoutem.ui.ImageGalleryOverlay': {
|
|
@@ -2899,7 +2904,6 @@ export default () => {
|
|
|
2899
2904
|
borderRadius: 1,
|
|
2900
2905
|
flexDirection: 'row',
|
|
2901
2906
|
marginBottom: 8,
|
|
2902
|
-
marginLeft: 8,
|
|
2903
2907
|
},
|
|
2904
2908
|
text: {
|
|
2905
2909
|
marginTop: 12,
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import PhotoView from 'react-native-photo-view';
|
|
3
|
-
import { connectStyle } from '@shoutem/theme';
|
|
4
|
-
import { ImageGalleryBase } from './ImageGalleryBase';
|
|
5
|
-
|
|
6
|
-
class ImageGallery extends ImageGalleryBase {
|
|
7
|
-
static IMAGE_PREVIEW_MODE = ImageGalleryBase.IMAGE_PREVIEW_MODE;
|
|
8
|
-
|
|
9
|
-
static IMAGE_GALLERY_MODE = ImageGalleryBase.IMAGE_GALLERY_MODE;
|
|
10
|
-
|
|
11
|
-
renderImage(imageProps, imageData, imageIndex) {
|
|
12
|
-
const { selectedIndex } = this.state;
|
|
13
|
-
|
|
14
|
-
const isImageVisible = imageIndex === selectedIndex;
|
|
15
|
-
const androidProps = {
|
|
16
|
-
...imageProps,
|
|
17
|
-
// Reset the image scale on images that are not
|
|
18
|
-
// currently visible
|
|
19
|
-
scale: isImageVisible ? null : 1,
|
|
20
|
-
minimumZoomScale: 1,
|
|
21
|
-
maximumZoomScale: 3,
|
|
22
|
-
androidScaleType: 'fitCenter',
|
|
23
|
-
onTap: this.onImageTap,
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
return <PhotoView {...androidProps} />;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
ImageGallery.propTypes = {
|
|
31
|
-
...ImageGalleryBase.propTypes,
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
ImageGallery.defaultProps = {
|
|
35
|
-
...ImageGalleryBase.defaultProps,
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
const StyledImageGallery = connectStyle('shoutem.ui.ImageGallery')(
|
|
39
|
-
ImageGallery,
|
|
40
|
-
);
|
|
41
|
-
|
|
42
|
-
export { StyledImageGallery as ImageGallery };
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { InteractionManager } from 'react-native';
|
|
3
|
-
import TransformableImage from 'react-native-transformable-image';
|
|
4
|
-
import autoBindReact from 'auto-bind/react';
|
|
5
|
-
import { connectStyle } from '@shoutem/theme';
|
|
6
|
-
import { ImageGalleryBase } from './ImageGalleryBase';
|
|
7
|
-
|
|
8
|
-
class ImageGallery extends ImageGalleryBase {
|
|
9
|
-
static IMAGE_PREVIEW_MODE = ImageGalleryBase.IMAGE_PREVIEW_MODE;
|
|
10
|
-
|
|
11
|
-
static IMAGE_GALLERY_MODE = ImageGalleryBase.IMAGE_GALLERY_MODE;
|
|
12
|
-
|
|
13
|
-
constructor(props) {
|
|
14
|
-
super(props);
|
|
15
|
-
|
|
16
|
-
autoBindReact(this);
|
|
17
|
-
|
|
18
|
-
this.imageRefs = new Map();
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
getImageTransformer(index) {
|
|
22
|
-
const { data } = this.props;
|
|
23
|
-
if (index >= 0 && index < data.length) {
|
|
24
|
-
const ref = this.imageRefs.get(index);
|
|
25
|
-
if (ref) {
|
|
26
|
-
return ref.getViewTransformerInstance();
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
return null;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
resetImageTransformer(transformer) {
|
|
33
|
-
if (!transformer) {
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
transformer.updateTransform({
|
|
38
|
-
scale: 1,
|
|
39
|
-
translateX: 0,
|
|
40
|
-
translateY: 0,
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
resetSurroundingImageTransformations(index) {
|
|
45
|
-
this.resetImageTransformer(this.getImageTransformer(index - 1));
|
|
46
|
-
this.resetImageTransformer(this.getImageTransformer(index + 1));
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
updateImageSwitchingStatus() {
|
|
50
|
-
const { imageSwitchingEnabled, selectedIndex } = this.state;
|
|
51
|
-
|
|
52
|
-
const imageTransformer = this.getImageTransformer(selectedIndex);
|
|
53
|
-
if (!imageTransformer) {
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const translationSpace = imageTransformer.getAvailableTranslateSpace();
|
|
58
|
-
if (!translationSpace) {
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
const imageBoundaryReached =
|
|
63
|
-
translationSpace.right <= 0 || translationSpace.left <= 0;
|
|
64
|
-
|
|
65
|
-
if (imageSwitchingEnabled !== imageBoundaryReached) {
|
|
66
|
-
// We want to allow switching between gallery images only if
|
|
67
|
-
// the image is at its left or right boundary. This happens if the
|
|
68
|
-
// image is fully zoomed out, or if the image is zoomed in but the
|
|
69
|
-
// user moved it to one of its boundaries.
|
|
70
|
-
this.setState({
|
|
71
|
-
imageSwitchingEnabled: imageBoundaryReached,
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
onViewTransformed() {
|
|
77
|
-
this.updateImageSwitchingStatus();
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
onIndexSelected(newIndex) {
|
|
81
|
-
super.onIndexSelected(newIndex);
|
|
82
|
-
|
|
83
|
-
InteractionManager.runAfterInteractions(() => {
|
|
84
|
-
// After swipe interaction finishes, we'll have new selected index in state
|
|
85
|
-
// And we're resetting surrounding image transformations,
|
|
86
|
-
// So that images aren't left zoomed in when user swipes to next/prev image
|
|
87
|
-
this.resetSurroundingImageTransformations(newIndex);
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
renderImage(imageProps, imageData, imageIndex) {
|
|
92
|
-
const { imageSwitchingEnabled } = this.state;
|
|
93
|
-
|
|
94
|
-
const iosProps = {
|
|
95
|
-
...imageProps,
|
|
96
|
-
onSingleTapConfirmed: this.onImageTap,
|
|
97
|
-
onViewTransformed: this.onViewTransformed,
|
|
98
|
-
enableTranslate: !imageSwitchingEnabled,
|
|
99
|
-
ref: transformer => {
|
|
100
|
-
this.imageRefs.set(imageIndex, transformer);
|
|
101
|
-
},
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
return <TransformableImage {...iosProps} />;
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
ImageGallery.propTypes = {
|
|
109
|
-
...ImageGalleryBase.propTypes,
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
ImageGallery.defaultProps = {
|
|
113
|
-
...ImageGalleryBase.defaultProps,
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
const StyledImageGallery = connectStyle('shoutem.ui.ImageGallery')(
|
|
117
|
-
ImageGallery,
|
|
118
|
-
);
|
|
119
|
-
|
|
120
|
-
export { StyledImageGallery as ImageGallery };
|
|
@@ -1,199 +0,0 @@
|
|
|
1
|
-
import React, { PureComponent } from 'react';
|
|
2
|
-
import autoBindReact from 'auto-bind/react';
|
|
3
|
-
import _ from 'lodash';
|
|
4
|
-
import PropTypes from 'prop-types';
|
|
5
|
-
import { HorizontalPager } from '../HorizontalPager';
|
|
6
|
-
import { Image } from '../Image';
|
|
7
|
-
import { LoadingIndicator } from '../LoadingIndicator';
|
|
8
|
-
import { View } from '../View';
|
|
9
|
-
|
|
10
|
-
const IMAGE_PREVIEW_MODE = 'imagePreview';
|
|
11
|
-
const IMAGE_GALLERY_MODE = 'gallery';
|
|
12
|
-
|
|
13
|
-
export class ImageGalleryBase extends PureComponent {
|
|
14
|
-
/**
|
|
15
|
-
* The image preview mode is the mode in which
|
|
16
|
-
* the user can zoom in/out and pan the image around.
|
|
17
|
-
*/
|
|
18
|
-
static IMAGE_PREVIEW_MODE = IMAGE_PREVIEW_MODE;
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* The gallery mode is the mode in which
|
|
22
|
-
* the user can scroll between images, and can see
|
|
23
|
-
* additional info about each image.
|
|
24
|
-
*/
|
|
25
|
-
static IMAGE_GALLERY_MODE = IMAGE_GALLERY_MODE;
|
|
26
|
-
|
|
27
|
-
constructor(props) {
|
|
28
|
-
super(props);
|
|
29
|
-
|
|
30
|
-
autoBindReact(this);
|
|
31
|
-
|
|
32
|
-
const { selectedIndex } = props;
|
|
33
|
-
|
|
34
|
-
this.state = {
|
|
35
|
-
selectedIndex,
|
|
36
|
-
imageSwitchingEnabled: true,
|
|
37
|
-
mode: IMAGE_GALLERY_MODE,
|
|
38
|
-
// Disabling rule as this flag is used via inheritance in other classes.
|
|
39
|
-
// eslint-disable-next-line react/no-unused-state
|
|
40
|
-
collapsed: true,
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
onImageTap() {
|
|
45
|
-
const { mode } = this.state;
|
|
46
|
-
|
|
47
|
-
// We are toggling between image preview and
|
|
48
|
-
// gallery modes when the user taps on an image.
|
|
49
|
-
if (mode === IMAGE_PREVIEW_MODE) {
|
|
50
|
-
this.setMode(IMAGE_GALLERY_MODE);
|
|
51
|
-
} else {
|
|
52
|
-
this.setMode(IMAGE_PREVIEW_MODE);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
onIndexSelected(newIndex) {
|
|
57
|
-
const { onIndexSelected } = this.props;
|
|
58
|
-
this.setState(
|
|
59
|
-
{
|
|
60
|
-
selectedIndex: newIndex,
|
|
61
|
-
},
|
|
62
|
-
() => {
|
|
63
|
-
if (_.isFunction(onIndexSelected)) {
|
|
64
|
-
onIndexSelected(newIndex);
|
|
65
|
-
}
|
|
66
|
-
},
|
|
67
|
-
);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
setMode(newMode) {
|
|
71
|
-
const { onModeChanged } = this.props;
|
|
72
|
-
const { mode } = this.state;
|
|
73
|
-
|
|
74
|
-
if (mode === newMode) {
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
this.setState({ mode }, () => {
|
|
79
|
-
if (_.isFunction(onModeChanged)) {
|
|
80
|
-
onModeChanged(mode);
|
|
81
|
-
}
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
renderImage() {
|
|
86
|
-
// Override this to provide platform specific UI
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
renderPage(pageData, pageIndex) {
|
|
90
|
-
const { mode, selectedIndex } = this.state;
|
|
91
|
-
const { style, renderImageOverlay } = this.props;
|
|
92
|
-
const image = _.get(pageData, 'source.uri');
|
|
93
|
-
|
|
94
|
-
if (!image) {
|
|
95
|
-
return null;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
const isImageVisible = pageIndex === selectedIndex;
|
|
99
|
-
const transformImageProps = Image.getPropsTransformer();
|
|
100
|
-
const imageProps = {
|
|
101
|
-
source: { uri: image },
|
|
102
|
-
style: { flex: 1 },
|
|
103
|
-
};
|
|
104
|
-
const transformedImageProps = _.isFunction(transformImageProps)
|
|
105
|
-
? transformImageProps(imageProps)
|
|
106
|
-
: imageProps;
|
|
107
|
-
|
|
108
|
-
const showOverlay =
|
|
109
|
-
_.isFunction(renderImageOverlay) &&
|
|
110
|
-
// Nothing should be rendered above an image if the user is in
|
|
111
|
-
// the preview mode (pinching, and panning the image).
|
|
112
|
-
mode !== IMAGE_PREVIEW_MODE &&
|
|
113
|
-
// We are not rendering overlays above images that are not visible
|
|
114
|
-
isImageVisible;
|
|
115
|
-
const overlay = showOverlay && renderImageOverlay(pageData, pageIndex);
|
|
116
|
-
|
|
117
|
-
return (
|
|
118
|
-
<View key={pageIndex} style={style.page}>
|
|
119
|
-
{this.renderImage(transformedImageProps, pageData, pageIndex)}
|
|
120
|
-
{overlay}
|
|
121
|
-
</View>
|
|
122
|
-
);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
render() {
|
|
126
|
-
const {
|
|
127
|
-
data,
|
|
128
|
-
renderOverlay,
|
|
129
|
-
renderPlaceholder,
|
|
130
|
-
showNextPage,
|
|
131
|
-
style,
|
|
132
|
-
} = this.props;
|
|
133
|
-
const { selectedIndex, imageSwitchingEnabled } = this.state;
|
|
134
|
-
|
|
135
|
-
return (
|
|
136
|
-
<View style={style.container} driver={this.timingDriver}>
|
|
137
|
-
<HorizontalPager
|
|
138
|
-
data={data}
|
|
139
|
-
onIndexSelected={this.onIndexSelected}
|
|
140
|
-
selectedIndex={selectedIndex}
|
|
141
|
-
renderPage={this.renderPage}
|
|
142
|
-
bounces
|
|
143
|
-
pageMargin={style.pageMargin}
|
|
144
|
-
showNextPage={showNextPage}
|
|
145
|
-
renderOverlay={renderOverlay}
|
|
146
|
-
renderPlaceholder={renderPlaceholder}
|
|
147
|
-
scrollEnabled={imageSwitchingEnabled}
|
|
148
|
-
/>
|
|
149
|
-
</View>
|
|
150
|
-
);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
ImageGalleryBase.propTypes = {
|
|
155
|
-
// Array containing objects with gallery data (shape defined below)
|
|
156
|
-
data: PropTypes.arrayOf(
|
|
157
|
-
PropTypes.shape({
|
|
158
|
-
description: PropTypes.string,
|
|
159
|
-
source: PropTypes.shape({
|
|
160
|
-
uri: PropTypes.string,
|
|
161
|
-
}),
|
|
162
|
-
title: PropTypes.string,
|
|
163
|
-
}),
|
|
164
|
-
).isRequired,
|
|
165
|
-
// Style prop used to override default (theme) styling
|
|
166
|
-
style: PropTypes.object.isRequired,
|
|
167
|
-
// Renders an overlay over a single image
|
|
168
|
-
// For example image gallery overlay using the `ImageGalleryOverlay` component
|
|
169
|
-
// renderOverlay(imageData, imageIndex)
|
|
170
|
-
renderImageOverlay: PropTypes.func,
|
|
171
|
-
// Renders an overlay over all images
|
|
172
|
-
// For example page indicators using the `PageIndicators` component
|
|
173
|
-
// renderOverlay(imageData, imageIndex)
|
|
174
|
-
renderOverlay: PropTypes.func,
|
|
175
|
-
// Callback function that can be used to define placeholder
|
|
176
|
-
// that appears when content is loading
|
|
177
|
-
renderPlaceholder: PropTypes.func,
|
|
178
|
-
// Initially selected page in gallery
|
|
179
|
-
selectedIndex: PropTypes.number,
|
|
180
|
-
showNextPage: PropTypes.bool,
|
|
181
|
-
// Callback function called when user swipes between pages (images)
|
|
182
|
-
// Index of new (selected) page is passed to this callback
|
|
183
|
-
onIndexSelected: PropTypes.func,
|
|
184
|
-
// onModeChanged(mode), callback function triggered when user taps on single photo
|
|
185
|
-
// Or when user transforms (zooms etc.) image
|
|
186
|
-
// Useful for hiding external controls (i.e. navigation bar)
|
|
187
|
-
// Mode can be `gallery` or `imagePreview`
|
|
188
|
-
onModeChanged: PropTypes.func,
|
|
189
|
-
};
|
|
190
|
-
|
|
191
|
-
ImageGalleryBase.defaultProps = {
|
|
192
|
-
selectedIndex: 0,
|
|
193
|
-
showNextPage: false,
|
|
194
|
-
renderPlaceholder: () => <LoadingIndicator />,
|
|
195
|
-
renderImageOverlay: undefined,
|
|
196
|
-
renderOverlay: undefined,
|
|
197
|
-
onIndexSelected: undefined,
|
|
198
|
-
onModeChanged: undefined,
|
|
199
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { ImageGallery } from './ImageGallery';
|