@shoutem/ui 5.1.0 → 5.2.2

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.
Files changed (67) hide show
  1. package/components/ActionSheet/ActionSheet.js +15 -8
  2. package/components/ActionSheet/ActionSheetOption.js +7 -2
  3. package/components/Button.js +5 -9
  4. package/components/CategoryPicker/Category.js +45 -0
  5. package/components/CategoryPicker/CategoryPicker.js +62 -0
  6. package/components/CategoryPicker/index.js +1 -0
  7. package/components/CategoryPicker/shapes.js +7 -0
  8. package/components/DateTimePicker.js +4 -1
  9. package/components/DropDownMenu/DropDownMenu.js +20 -23
  10. package/components/DropDownMenu/DropDownModal.js +56 -54
  11. package/components/EmptyStateView.js +16 -12
  12. package/components/FormGroup.js +7 -1
  13. package/components/GridRow.js +1 -1
  14. package/components/HorizontalPager/HorizontalPager.js +61 -49
  15. package/components/HorizontalPager/Page.js +12 -7
  16. package/components/Icon/Icon.js +1 -1
  17. package/components/Image.js +4 -4
  18. package/components/ImageBackground.js +4 -4
  19. package/components/ImageGallery/ImageGallery.android.js +8 -0
  20. package/components/ImageGallery/ImageGallery.ios.js +8 -0
  21. package/components/ImageGallery/ImageGalleryBase.js +65 -48
  22. package/components/ImageGalleryOverlay.js +12 -7
  23. package/components/ImagePreview.js +19 -14
  24. package/components/InlineDropDownMenu/InlineDropDownMenu.js +27 -18
  25. package/components/InlineDropDownMenu/InlineDropDownMenuItem.js +17 -9
  26. package/components/InlineGallery.js +42 -35
  27. package/components/LinearGradient.js +15 -5
  28. package/components/ListView.js +1 -2
  29. package/components/LoadingContainer.js +1 -2
  30. package/components/NavigationBar/NavigationBar.js +18 -13
  31. package/components/NumberInput.js +32 -24
  32. package/components/PageIndicators.js +19 -17
  33. package/components/ScrollView/ScrollDriverProvider.js +20 -10
  34. package/components/ScrollView/ScrollView.js +15 -13
  35. package/components/SearchField.js +24 -18
  36. package/components/ShareButton.js +21 -11
  37. package/components/Spinner.js +1 -1
  38. package/components/Switch.js +19 -14
  39. package/components/TabMenu/TabMenu.js +12 -7
  40. package/components/TabMenu/TabMenuItem.js +13 -7
  41. package/components/TextInput.js +3 -1
  42. package/components/Touchable.js +19 -23
  43. package/components/TouchableNativeFeedback.js +15 -21
  44. package/components/TouchableOpacity.js +6 -12
  45. package/components/Video/Video.js +21 -25
  46. package/components/View.js +7 -9
  47. package/components/YearRangePicker/YearRangePicker.js +22 -17
  48. package/components/YearRangePicker/YearRangePickerButton.js +13 -7
  49. package/components/YearRangePicker/YearRangePickerModal.js +23 -16
  50. package/examples/components/NavigationBars.js +4 -0
  51. package/examples/components/Stage.js +6 -1
  52. package/html/Html.js +14 -8
  53. package/html/components/Gallery.js +9 -5
  54. package/html/components/Image.js +16 -16
  55. package/html/components/SimpleHtml.js +19 -10
  56. package/html/elements/A.js +11 -6
  57. package/html/elements/Inline.js +13 -14
  58. package/html/elements/Text.js +6 -0
  59. package/html/elements/Video.js +3 -1
  60. package/html/elements/list/Li.js +0 -2
  61. package/html/elements/list/Ol.js +4 -0
  62. package/html/elements/list/Ul.js +4 -0
  63. package/html/elements/list/prefix/Bullet.js +4 -0
  64. package/html/elements/list/prefix/Number.js +6 -1
  65. package/index.js +42 -54
  66. package/package.json +1 -1
  67. package/theme.js +51 -0
@@ -33,14 +33,6 @@ class ActionSheet extends PureComponent {
33
33
  return null;
34
34
  }
35
35
 
36
- static propTypes = {
37
- style: PropTypes.any,
38
- confirmOptions: PropTypes.arrayOf(optionPropType),
39
- cancelOptions: PropTypes.arrayOf(optionPropType),
40
- active: PropTypes.bool,
41
- onDismiss: PropTypes.func,
42
- };
43
-
44
36
  constructor(props) {
45
37
  super(props);
46
38
 
@@ -187,4 +179,19 @@ class ActionSheet extends PureComponent {
187
179
  }
188
180
  }
189
181
 
182
+ ActionSheet.propTypes = {
183
+ style: PropTypes.object.isRequired,
184
+ active: PropTypes.bool,
185
+ cancelOptions: PropTypes.arrayOf(optionPropType),
186
+ confirmOptions: PropTypes.arrayOf(optionPropType),
187
+ onDismiss: PropTypes.func,
188
+ };
189
+
190
+ ActionSheet.defaultProps = {
191
+ active: false,
192
+ cancelOptions: undefined,
193
+ confirmOptions: undefined,
194
+ onDismiss: undefined,
195
+ };
196
+
190
197
  export default connectStyle('shoutem.ui.ActionSheet')(ActionSheet);
@@ -26,9 +26,14 @@ function ActionSheetOption({ style, option, cancelOption }) {
26
26
  }
27
27
 
28
28
  ActionSheetOption.propTypes = {
29
- style: PropTypes.any,
30
- option: optionPropType,
29
+ style: PropTypes.object.isRequired,
31
30
  cancelOption: PropTypes.bool,
31
+ option: optionPropType,
32
+ };
33
+
34
+ ActionSheetOption.defaultProps = {
35
+ option: undefined,
36
+ cancelOption: false,
32
37
  };
33
38
 
34
39
  export default connectStyle('shoutem.ui.ActionSheetOption')(ActionSheetOption);
@@ -5,18 +5,14 @@ import { connectStyle } from '@shoutem/theme';
5
5
 
6
6
  class Button extends PureComponent {
7
7
  render() {
8
- // The underlayColor is not a valid RN style
9
- // property, so we have to unset it here.
10
- const style = {
11
- ...this.props.style,
12
- };
13
- delete style.underlayColor;
8
+ const { style, ...otherProps } = this.props;
9
+ const { underlayColor, ...otherStyle } = style;
14
10
 
15
11
  return (
16
12
  <TouchableOpacity
17
- {...this.props}
18
- style={style}
19
- underlayColor={this.props.style.underlayColor}
13
+ {...otherProps}
14
+ style={otherStyle}
15
+ underlayColor={underlayColor}
20
16
  />
21
17
  );
22
18
  }
@@ -0,0 +1,45 @@
1
+ import React, { useMemo } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { connectStyle } from '@shoutem/theme';
4
+ import { Text } from '../Text';
5
+ import { TouchableOpacity } from '../TouchableOpacity';
6
+ import { categoryShape } from './shapes';
7
+
8
+ function Category({ category, style, isSelected, onPress }) {
9
+ const textStyle = useMemo(
10
+ () => [style.category, !isSelected && style.selectedCategory],
11
+
12
+ [isSelected, style.category, style.selectedCategory],
13
+ );
14
+
15
+ function handlePress() {
16
+ if (isSelected) {
17
+ return;
18
+ }
19
+
20
+ if (onPress) {
21
+ onPress(category);
22
+ }
23
+ }
24
+
25
+ return (
26
+ <TouchableOpacity onPress={handlePress} style={style.container}>
27
+ <Text style={textStyle}>{category.name}</Text>
28
+ </TouchableOpacity>
29
+ );
30
+ }
31
+
32
+ Category.propTypes = {
33
+ category: categoryShape.isRequired,
34
+ isSelected: PropTypes.bool,
35
+ style: PropTypes.object,
36
+ onPress: PropTypes.func,
37
+ };
38
+
39
+ Category.defaultProps = {
40
+ style: {},
41
+ isSelected: false,
42
+ onPress: undefined,
43
+ };
44
+
45
+ export default React.memo(connectStyle('shoutem.ui.Category')(Category));
@@ -0,0 +1,62 @@
1
+ import React, { useCallback } from 'react';
2
+ import { FlatList } from 'react-native';
3
+ import _ from 'lodash';
4
+ import PropTypes from 'prop-types';
5
+ import { connectStyle } from '@shoutem/theme';
6
+ import { View } from '../View';
7
+ import Category from './Category';
8
+ import { categoryShape } from './shapes';
9
+
10
+ export function CategoryPicker({
11
+ categories,
12
+ onCategorySelected,
13
+ style,
14
+ selectedCategory,
15
+ }) {
16
+ const renderItem = useCallback(
17
+ ({ item: category }) => (
18
+ <Category
19
+ category={category}
20
+ key={category.id}
21
+ onPress={onCategorySelected}
22
+ isSelected={selectedCategory.id === category.id}
23
+ />
24
+ ),
25
+ [selectedCategory.id, onCategorySelected],
26
+ );
27
+
28
+ if (_.size(categories) < 2) {
29
+ return null;
30
+ }
31
+
32
+ return (
33
+ <View style={style.container}>
34
+ <FlatList
35
+ horizontal
36
+ scrollToOverflowEnabled
37
+ contentContainerStyle={style.listContainer}
38
+ showsHorizontalScrollIndicator={false}
39
+ data={categories}
40
+ renderItem={renderItem}
41
+ />
42
+ </View>
43
+ );
44
+ }
45
+
46
+ CategoryPicker.propTypes = {
47
+ categories: PropTypes.arrayOf(categoryShape),
48
+ selectedCategory: categoryShape,
49
+ style: PropTypes.object,
50
+ onCategorySelected: PropTypes.func,
51
+ };
52
+
53
+ CategoryPicker.defaultProps = {
54
+ categories: [],
55
+ style: {},
56
+ selectedCategory: undefined,
57
+ onCategorySelected: undefined,
58
+ };
59
+
60
+ export default React.memo(
61
+ connectStyle('shoutem.ui.CategoryPicker')(CategoryPicker),
62
+ );
@@ -0,0 +1 @@
1
+ export { default as CategoryPicker } from './CategoryPicker';
@@ -0,0 +1,7 @@
1
+ import PropTypes from 'prop-types';
2
+
3
+ export const categoryShape = PropTypes.shape({
4
+ id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired,
5
+ name: PropTypes.string.isRequired,
6
+ description: PropTypes.string,
7
+ });
@@ -198,13 +198,14 @@ class DateTimePicker extends PureComponent {
198
198
  }
199
199
 
200
200
  DateTimePicker.propTypes = {
201
+ style: PropTypes.object.isRequired,
201
202
  cancelButtonText: PropTypes.string,
202
203
  confirmButtonText: PropTypes.string,
203
204
  is24Hour: PropTypes.bool,
204
205
  mode: PropTypes.oneOf(Object.values(DATEPICKER_MODES)),
205
- onValueChanged: PropTypes.func,
206
206
  textValue: PropTypes.string,
207
207
  value: PropTypes.oneOfType([PropTypes.string, PropTypes.instanceOf(Date)]),
208
+ onValueChanged: PropTypes.func,
208
209
  };
209
210
 
210
211
  DateTimePicker.defaultProps = {
@@ -212,7 +213,9 @@ DateTimePicker.defaultProps = {
212
213
  confirmButtonText: 'Confirm',
213
214
  is24Hour: false,
214
215
  mode: 'datetime',
216
+ textValue: undefined,
215
217
  value: new Date(),
218
+ onValueChanged: undefined,
216
219
  };
217
220
 
218
221
  const StyledDateTimePicker = connectStyle('shoutem.ui.DateTimePicker')(
@@ -10,31 +10,8 @@ import { View } from '../View';
10
10
  import { DropDownModal } from './DropDownModal';
11
11
 
12
12
  const modalSpecificProps = ['visible', 'onClose'];
13
- const dropDownMenuPropTypes = {
14
- ..._.omit(DropDownModal.propTypes, modalSpecificProps),
15
- };
16
13
 
17
14
  class DropDownMenu extends PureComponent {
18
- /**
19
- * @see DropDownModal.propTypes
20
- */
21
- static propTypes = {
22
- /**
23
- * Icon displayed on dropdown menu button
24
- */
25
- iconName: PropTypes.string,
26
- /**
27
- * Whether the text should be displayed next to dropdown icon or not
28
- */
29
- showSelectedOption: PropTypes.bool,
30
- ...dropDownMenuPropTypes,
31
- };
32
-
33
- static defaultProps = {
34
- iconName: 'drop-down',
35
- showSelectedOption: true,
36
- };
37
-
38
15
  constructor(props) {
39
16
  super(props);
40
17
 
@@ -105,6 +82,26 @@ class DropDownMenu extends PureComponent {
105
82
  }
106
83
  }
107
84
 
85
+ /**
86
+ * @see DropDownModal.propTypes
87
+ */
88
+ DropDownMenu.propTypes = {
89
+ /**
90
+ * Icon displayed on dropdown menu button
91
+ */
92
+ iconName: PropTypes.string,
93
+ /**
94
+ * Whether the text should be displayed next to dropdown icon or not
95
+ */
96
+ showSelectedOption: PropTypes.bool,
97
+ ..._.omit(DropDownModal.propTypes, modalSpecificProps),
98
+ };
99
+
100
+ DropDownMenu.defaultProps = {
101
+ iconName: 'drop-down',
102
+ showSelectedOption: true,
103
+ };
104
+
108
105
  const StyledDropDownMenu = connectStyle('shoutem.ui.DropDownMenu')(
109
106
  DropDownMenu,
110
107
  );
@@ -15,57 +15,6 @@ import { View } from '../View';
15
15
  const window = Dimensions.get('window');
16
16
 
17
17
  class DropDownModal extends PureComponent {
18
- static propTypes = {
19
- /**
20
- * Callback that is called when dropdown option is selected
21
- */
22
- onOptionSelected: PropTypes.func,
23
- /**
24
- * Collection of objects which will be shown as options in DropDownMenu
25
- */
26
- options: PropTypes.array.isRequired,
27
- /**
28
- * Selected option that will be shown.
29
- */
30
- selectedOption: PropTypes.any.isRequired,
31
- /**
32
- * Key name that represents option's string value,
33
- * and it will be displayed to the user in the UI
34
- */
35
- titleProperty: PropTypes.string.isRequired,
36
- /**
37
- * Key name that represents option's value
38
- */
39
- valueProperty: PropTypes.string.isRequired,
40
- /**
41
- * Number of options shown without scroll.
42
- * Can be set trough DropDown style.visibleOptions.
43
- * Prop definition overrides style.
44
- */
45
- visibleOptions: PropTypes.number,
46
- /**
47
- * Optional render function, for every item in the list.
48
- * Input parameter should be shaped as one of the items from the
49
- * options object
50
- */
51
- renderOption: PropTypes.func,
52
- /**
53
- * Visibility flag, controling the modal visibility
54
- */
55
- visible: PropTypes.bool,
56
- /**
57
- * Callback that is called when modal should be closed
58
- */
59
- onClose: PropTypes.func,
60
- style: PropTypes.object,
61
- };
62
-
63
- static defaultProps = {
64
- renderOption: (option, titleProperty) => (
65
- <Text>{option[titleProperty].toUpperCase()}</Text>
66
- ),
67
- };
68
-
69
18
  static DEFAULT_VISIBLE_OPTIONS = 8;
70
19
 
71
20
  constructor(props) {
@@ -111,14 +60,16 @@ class DropDownModal extends PureComponent {
111
60
  close() {
112
61
  const { onClose } = this.props;
113
62
 
114
- if (onClose) {
63
+ if (_.isFunction(onClose)) {
115
64
  onClose();
116
65
  }
117
66
  }
118
67
 
119
68
  emitOnOptionSelectedEvent(option) {
120
- if (this.props.onOptionSelected) {
121
- this.props.onOptionSelected(option);
69
+ const { onOptionSelected } = this.props;
70
+
71
+ if (_.isFunction(onOptionSelected)) {
72
+ onOptionSelected(option);
122
73
  }
123
74
  }
124
75
 
@@ -299,6 +250,57 @@ class DropDownModal extends PureComponent {
299
250
  }
300
251
  }
301
252
 
253
+ DropDownModal.propTypes = {
254
+ /**
255
+ * Collection of objects which will be shown as options in DropDownMenu
256
+ */
257
+ options: PropTypes.array.isRequired,
258
+ /**
259
+ * Selected option that will be shown.
260
+ */
261
+ selectedOption: PropTypes.any.isRequired,
262
+ style: PropTypes.object.isRequired,
263
+ /**
264
+ * Key name that represents option's string value,
265
+ * and it will be displayed to the user in the UI
266
+ */
267
+ titleProperty: PropTypes.string.isRequired,
268
+ /**
269
+ * Optional render function, for every item in the list.
270
+ * Input parameter should be shaped as one of the items from the
271
+ * options object
272
+ */
273
+ renderOption: PropTypes.func,
274
+ /**
275
+ * Visibility flag, controling the modal visibility
276
+ */
277
+ visible: PropTypes.bool,
278
+ /**
279
+ * Number of options shown without scroll.
280
+ * Can be set trough DropDown style.visibleOptions.
281
+ * Prop definition overrides style.
282
+ */
283
+ visibleOptions: PropTypes.number,
284
+ /**
285
+ * Callback that is called when modal should be closed
286
+ */
287
+ onClose: PropTypes.func,
288
+ /**
289
+ * Callback that is called when dropdown option is selected
290
+ */
291
+ onOptionSelected: PropTypes.func,
292
+ };
293
+
294
+ DropDownModal.defaultProps = {
295
+ renderOption: (option, titleProperty) => (
296
+ <Text>{option[titleProperty].toUpperCase()}</Text>
297
+ ),
298
+ visible: false,
299
+ visibleOptions: undefined,
300
+ onClose: undefined,
301
+ onOptionSelected: undefined,
302
+ };
303
+
302
304
  const StyledModal = connectStyle('shoutem.ui.DropDownModal')(DropDownModal);
303
305
 
304
306
  export { StyledModal as DropDownModal };
@@ -8,11 +8,6 @@ import { Subtitle, Text } from './Text';
8
8
  import { View } from './View';
9
9
 
10
10
  class EmptyStateView extends PureComponent {
11
- static defaultProps = {
12
- retryButtonTitle: 'TRY AGAIN',
13
- icon: 'error',
14
- };
15
-
16
11
  constructor(props) {
17
12
  super(props);
18
13
 
@@ -20,13 +15,15 @@ class EmptyStateView extends PureComponent {
20
15
  }
21
16
 
22
17
  onRetry() {
23
- this.props.onRetry();
18
+ const { onRetry } = this.props;
19
+
20
+ onRetry();
24
21
  }
25
22
 
26
23
  renderRetryButton() {
27
24
  const { retryButtonTitle } = this.props;
28
25
 
29
- // Show retry button at the bottom only if there is an onRetry action passed.
26
+ // Show retry button at the bottom only if there is an onRetry action passed
30
27
  return (
31
28
  <View styleName="horizontal anchor-bottom">
32
29
  <Button styleName="full-width" onPress={this.onRetry}>
@@ -37,10 +34,10 @@ class EmptyStateView extends PureComponent {
37
34
  }
38
35
 
39
36
  render() {
40
- const { icon, message, onRetry } = this.props;
37
+ const { icon, message, onRetry, ...otherProps } = this.props;
41
38
 
42
39
  return (
43
- <View {...this.props} styleName="vertical flexible h-center v-center">
40
+ <View {...otherProps} styleName="vertical flexible h-center v-center">
44
41
  <View styleName="icon-placeholder">
45
42
  <Icon name={icon} />
46
43
  </View>
@@ -54,10 +51,17 @@ class EmptyStateView extends PureComponent {
54
51
  }
55
52
 
56
53
  EmptyStateView.propTypes = {
57
- ...EmptyStateView.propTypes,
58
- onRetry: PropTypes.func,
59
- message: PropTypes.string,
60
54
  icon: PropTypes.string,
55
+ message: PropTypes.string,
56
+ retryButtonTitle: PropTypes.string,
57
+ onRetry: PropTypes.func,
58
+ };
59
+
60
+ EmptyStateView.defaultProps = {
61
+ icon: 'error',
62
+ message: undefined,
63
+ retryButtonTitle: 'TRY AGAIN',
64
+ onRetry: undefined,
61
65
  };
62
66
 
63
67
  const StyledView = connectStyle('shoutem.ui.EmptyStateView')(EmptyStateView);
@@ -5,7 +5,9 @@ import { View } from './View';
5
5
 
6
6
  class FormGroup extends PureComponent {
7
7
  render() {
8
- return <View {...this.props}>{this.props.children}</View>;
8
+ const { children, ...otherProps } = this.props;
9
+
10
+ return <View {...otherProps}>{children}</View>;
9
11
  }
10
12
  }
11
13
 
@@ -13,6 +15,10 @@ FormGroup.propTypes = {
13
15
  ...View.propTypes,
14
16
  };
15
17
 
18
+ FormGroup.defaultProps = {
19
+ ...View.defaultProps,
20
+ };
21
+
16
22
  const AnimatedFormGroup = connectAnimation(FormGroup);
17
23
  const StyledFormGroup = connectStyle('shoutem.ui.FormGroup')(AnimatedFormGroup);
18
24
 
@@ -35,8 +35,8 @@ class GridRow extends PureComponent {
35
35
  }
36
36
 
37
37
  GridRow.propTypes = {
38
- columns: PropTypes.number.isRequired,
39
38
  ...ViewPropTypes,
39
+ columns: PropTypes.number.isRequired,
40
40
  };
41
41
 
42
42
  /* eslint-disable no-param-reassign */
@@ -19,61 +19,20 @@ import { Page } from './Page';
19
19
  *
20
20
  */
21
21
  class HorizontalPager extends PureComponent {
22
- static propTypes = {
23
- // Prop defining whether the Pager will bounce back
24
- // when user tries to swipe beyond end of content (iOS only)
25
- bounces: PropTypes.bool,
26
- // Array containing objects (pages)
27
- data: PropTypes.arrayOf(PropTypes.object).isRequired,
28
- // Callback function called when user swipes between pages (images)
29
- // Index of new (selected) page is passed to this callback
30
- onIndexSelected: PropTypes.func,
31
- // Page margin, margin visible between pages, during swipe gesture.
32
- pageMargin: PropTypes.number,
33
- // A function which renders a single page
34
- // renderPage(pageData, pageIndex)
35
- renderPage: PropTypes.func,
36
- // Callback function that can be used to render overlay over pages
37
- // For example page indicators using `PageIndicators` component
38
- // renderOverlay(pageData, pageIndex, layout)
39
- renderOverlay: PropTypes.func,
40
- // Callback function that can be used to define placeholder
41
- // that appears when content is loading
42
- renderPlaceholder: PropTypes.func,
43
- // Initially selected page in gallery
44
- selectedIndex: PropTypes.number,
45
- // Prop that forces enables or disables swiping
46
- scrollEnabled: PropTypes.bool,
47
- // Style prop used to override default (theme) styling
48
- style: PropTypes.object,
49
- // Prop that reduces page size by pageMargin, allowing 'sneak peak' of next page
50
- showNextPage: PropTypes.bool,
51
- // Always render only central (currently loaded) page plus `surroundingPagesToLoad`
52
- // to the left and to the right. If currently rendered page is out of bounds,
53
- // empty `View` (with set dimensions for proper scrolling) will be rendered
54
- // Defaults to 2.
55
- surroundingPagesToLoad: PropTypes.number,
56
- };
57
-
58
- static defaultProps = {
59
- pageMargin: 0,
60
- selectedIndex: 0,
61
- showNextPage: false,
62
- surroundingPagesToLoad: 2,
63
- };
64
-
65
22
  constructor(props) {
66
23
  super(props);
67
24
 
68
25
  autoBindReact(this);
69
26
 
27
+ const { selectedIndex, pageMargin, showNextPage } = props;
28
+
70
29
  this.state = {
71
30
  width: 0,
72
31
  height: 0,
73
- selectedIndex: this.props.selectedIndex,
74
- initialSelectedIndex: this.props.selectedIndex,
75
- pageMargin: this.props.pageMargin,
76
- showNextPage: this.props.showNextPage,
32
+ selectedIndex,
33
+ initialSelectedIndex: selectedIndex,
34
+ pageMargin,
35
+ showNextPage,
77
36
  shouldRenderContent: false,
78
37
  scrolledToInitialIndex: false,
79
38
  };
@@ -99,9 +58,13 @@ class HorizontalPager extends PureComponent {
99
58
 
100
59
  onLayoutContainer(event) {
101
60
  const { width, height } = event.nativeEvent.layout;
102
- const { scrolledToInitialIndex } = this.state;
61
+ const {
62
+ width: currentWidth,
63
+ height: currentHeight,
64
+ scrolledToInitialIndex,
65
+ } = this.state;
103
66
 
104
- if (this.state.width === width && this.state.height === height) {
67
+ if (currentWidth === width && currentHeight === height) {
105
68
  return;
106
69
  }
107
70
 
@@ -312,6 +275,55 @@ class HorizontalPager extends PureComponent {
312
275
  }
313
276
  }
314
277
 
278
+ HorizontalPager.propTypes = {
279
+ // Array containing objects (pages)
280
+ data: PropTypes.arrayOf(PropTypes.object).isRequired,
281
+ // Style prop used to override default (theme) styling
282
+ style: PropTypes.object.isRequired,
283
+ // Prop defining whether the Pager will bounce back
284
+ // when user tries to swipe beyond end of content (iOS only)
285
+ bounces: PropTypes.bool,
286
+ // Page margin, margin visible between pages, during swipe gesture.
287
+ pageMargin: PropTypes.number,
288
+ // Callback function that can be used to render overlay over pages
289
+ // For example page indicators using `PageIndicators` component
290
+ // renderOverlay(pageData, pageIndex, layout)
291
+ renderOverlay: PropTypes.func,
292
+ // A function which renders a single page
293
+ // renderPage(pageData, pageIndex)
294
+ renderPage: PropTypes.func,
295
+ // Callback function that can be used to define placeholder
296
+ // that appears when content is loading
297
+ renderPlaceholder: PropTypes.func,
298
+ // Prop that forces enables or disables swiping
299
+ scrollEnabled: PropTypes.bool,
300
+ // Initially selected page in gallery
301
+ selectedIndex: PropTypes.number,
302
+ // Prop that reduces page size by pageMargin, allowing 'sneak peak' of next page
303
+ showNextPage: PropTypes.bool,
304
+ // Always render only central (currently loaded) page plus `surroundingPagesToLoad`
305
+ // to the left and to the right. If currently rendered page is out of bounds,
306
+ // empty `View` (with set dimensions for proper scrolling) will be rendered
307
+ // Defaults to 2.
308
+ surroundingPagesToLoad: PropTypes.number,
309
+ // Callback function called when user swipes between pages (images)
310
+ // Index of new (selected) page is passed to this callback
311
+ onIndexSelected: PropTypes.func,
312
+ };
313
+
314
+ HorizontalPager.defaultProps = {
315
+ bounces: false,
316
+ pageMargin: 0,
317
+ renderOverlay: undefined,
318
+ renderPage: undefined,
319
+ renderPlaceholder: undefined,
320
+ scrollEnabled: true,
321
+ selectedIndex: 0,
322
+ showNextPage: false,
323
+ surroundingPagesToLoad: 2,
324
+ onIndexSelected: undefined,
325
+ };
326
+
315
327
  const StyledHorizontalPager = connectStyle('shoutem.ui.HorizontalPager')(
316
328
  HorizontalPager,
317
329
  );
@@ -8,13 +8,6 @@ import { View } from '../View';
8
8
  * rendering of pages that are not currently visible.
9
9
  */
10
10
  export class Page extends Component {
11
- static propTypes = {
12
- isActive: PropTypes.bool.isRequired,
13
- width: PropTypes.number.isRequired,
14
- style: PropTypes.object,
15
- children: PropTypes.node,
16
- };
17
-
18
11
  shouldComponentUpdate(nextProps) {
19
12
  return nextProps.isActive;
20
13
  }
@@ -29,3 +22,15 @@ export class Page extends Component {
29
22
  );
30
23
  }
31
24
  }
25
+
26
+ Page.propTypes = {
27
+ isActive: PropTypes.bool.isRequired,
28
+ width: PropTypes.number.isRequired,
29
+ children: PropTypes.node,
30
+ style: PropTypes.object,
31
+ };
32
+
33
+ Page.defaultProps = {
34
+ children: undefined,
35
+ style: {},
36
+ };
@@ -28,7 +28,7 @@ function Icon({ name, style, ...otherProps }) {
28
28
 
29
29
  Icon.propTypes = {
30
30
  name: PropTypes.string.isRequired,
31
- style: PropTypes.any,
31
+ style: PropTypes.object.isRequired,
32
32
  };
33
33
 
34
34
  export default connectStyle('shoutem.ui.Icon')(Icon);