@shoutem/ui 7.2.2-rc.2 → 7.3.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.
@@ -5,12 +5,8 @@ import _ from 'lodash';
5
5
  import PropTypes from 'prop-types';
6
6
  import { DriverShape, ScrollDriver } from '@shoutem/animation';
7
7
  import { connectStyle } from '@shoutem/theme';
8
- import { Device } from '../../helpers';
9
8
  import { ScrollDriverProvider } from './ScrollDriverProvider.js';
10
9
 
11
- const isTabBarOnScreen = true;
12
- const IPHONE_X_HOME_INDICATOR_PADDING = isTabBarOnScreen ? 0 : 34;
13
-
14
10
  class ScrollView extends PureComponent {
15
11
  static contextTypes = {
16
12
  animationDriver: DriverShape,
@@ -63,21 +59,6 @@ class ScrollView extends PureComponent {
63
59
  this.wrappedInstance = component;
64
60
  }
65
61
 
66
- addIphoneXPadding(style) {
67
- const resolvedStyle = { ...style };
68
-
69
- if (typeof resolvedStyle.paddingBottom !== 'number') {
70
- resolvedStyle.paddingBottom = 0;
71
- }
72
-
73
- resolvedStyle.paddingBottom = Device.select({
74
- iPhoneX: resolvedStyle.paddingBottom + IPHONE_X_HOME_INDICATOR_PADDING,
75
- default: resolvedStyle.paddingBottom,
76
- });
77
-
78
- return resolvedStyle;
79
- }
80
-
81
62
  render() {
82
63
  const { style, ...otherProps } = this.props;
83
64
  const { scrollViewProps } = this.animationDriver;
@@ -86,7 +67,7 @@ class ScrollView extends PureComponent {
86
67
  return (
87
68
  <Animated.ScrollView
88
69
  ref={this.setWrappedInstance}
89
- contentContainerStyle={this.addIphoneXPadding(contentContainerStyle)}
70
+ contentContainerStyle={contentContainerStyle}
90
71
  {...scrollViewProps}
91
72
  {..._.omit(otherProps, 'onScroll')}
92
73
  style={otherStyle}
package/const.js CHANGED
@@ -1,14 +1,9 @@
1
1
  import { Platform, StatusBar } from 'react-native';
2
2
  import {
3
- IPHONE_12_LONG_SIDE,
4
- IPHONE_12_MAX_LONG_SIDE,
5
- IPHONE_X_HOME_INDICATOR_PADDING,
6
- IPHONE_X_LONG_SIDE,
7
- IPHONE_X_NOTCH_PADDING,
8
- IPHONE_XR_LONG_SIDE,
9
- IPHONE_XR_NOTCH_PADDING,
3
+ HOME_INDICATOR_PADDING,
10
4
  NAVIGATION_BAR_HEIGHT,
11
5
  NAVIGATION_HEADER_HEIGHT,
6
+ NOTCH_AREA_HEIGHT,
12
7
  } from './helpers';
13
8
 
14
9
  const STATUS_BAR_OFFSET =
@@ -17,14 +12,9 @@ const STATUS_BAR_OFFSET =
17
12
  // TODO: Deprecate and remove exports from here
18
13
  // Currently leaving for backwards compatibility
19
14
  export {
20
- IPHONE_12_LONG_SIDE,
21
- IPHONE_12_MAX_LONG_SIDE,
22
- IPHONE_X_HOME_INDICATOR_PADDING,
23
- IPHONE_X_LONG_SIDE,
24
- IPHONE_X_NOTCH_PADDING,
25
- IPHONE_XR_LONG_SIDE,
26
- IPHONE_XR_NOTCH_PADDING,
15
+ HOME_INDICATOR_PADDING,
27
16
  NAVIGATION_BAR_HEIGHT,
28
17
  NAVIGATION_HEADER_HEIGHT,
18
+ NOTCH_AREA_HEIGHT,
29
19
  STATUS_BAR_OFFSET,
30
20
  };
@@ -1,124 +1,32 @@
1
- import { Dimensions, Platform, StatusBar } from 'react-native';
1
+ import { Platform, StatusBar } from 'react-native';
2
2
  import DeviceInfo from 'react-native-device-info';
3
- import _ from 'lodash';
4
-
5
- const { OS, isPad, isTVOS } = Platform;
6
- const { width, height } = Dimensions.get('window');
7
-
8
- export const IPHONE_X_HOME_INDICATOR_PADDING = 34;
9
- export const IPHONE_X_LONG_SIDE = 812;
10
- export const IPHONE_X_NOTCH_PADDING = 30;
11
-
12
- export const IPHONE_XR_LONG_SIDE = 896;
13
- export const IPHONE_XR_NOTCH_PADDING = 34;
14
-
15
- export const IPHONE_12_LONG_SIDE = 844;
16
- export const IPHONE_12_MAX_LONG_SIDE = 926;
3
+ import { initialWindowMetrics } from 'react-native-safe-area-context';
17
4
 
18
5
  export const NAVIGATION_HEADER_HEIGHT = 64;
19
6
 
20
- const xDimensionsMatch =
21
- height === IPHONE_X_LONG_SIDE || width === IPHONE_X_LONG_SIDE;
22
-
23
- const xrDimensionsMatch =
24
- height === IPHONE_XR_LONG_SIDE || width === IPHONE_XR_LONG_SIDE;
25
-
26
- const twelveDimensionsMatch =
27
- height === IPHONE_12_LONG_SIDE || width === IPHONE_12_LONG_SIDE;
28
-
29
- const twelveMaxDimensionsMatch =
30
- height === IPHONE_12_MAX_LONG_SIDE || width === IPHONE_12_MAX_LONG_SIDE;
31
-
32
- const isIphoneX = OS === 'ios' && !isPad && !isTVOS && xDimensionsMatch;
33
- // isIphoneXR also includes iPhone 12, iPhone 12 Pro, iPhone 12 Pro Max
34
- const isIphoneXR =
35
- OS === 'ios' &&
36
- !isPad &&
37
- !isTVOS &&
38
- (xrDimensionsMatch || twelveDimensionsMatch || twelveMaxDimensionsMatch);
39
-
40
- const isNotchedAndroid = OS === 'android' && DeviceInfo.hasNotch();
41
-
42
- /**
43
- * Receives settings for different devices
44
- * If the device is recognized, it returns only settings for that device
45
- * If not, it returns settings for 'default'
46
- *
47
- * @param {object} settings The settings provided for
48
- * @return {settings} Returns device specific (or 'default') settings
49
- */
50
-
51
- function select(settings) {
52
- if (settings.iPhoneX && isIphoneX) {
53
- return settings.iPhoneX;
54
- }
55
-
56
- if (settings.iPhoneXR && isIphoneXR) {
57
- return settings.iPhoneXR;
58
- }
7
+ export const isNotchedAndroid =
8
+ Platform.OS === 'android' && DeviceInfo.hasNotch();
59
9
 
60
- if (settings.notchedAndroid && isNotchedAndroid) {
61
- return settings.notchedAndroid;
62
- }
63
-
64
- return _.get(settings, 'default');
65
- }
66
-
67
- export const NAVIGATION_BAR_HEIGHT = select({
68
- iPhoneX: NAVIGATION_HEADER_HEIGHT + IPHONE_X_NOTCH_PADDING,
69
- iPhoneXR: NAVIGATION_HEADER_HEIGHT + IPHONE_XR_NOTCH_PADDING,
70
- notchedAndroid: NAVIGATION_HEADER_HEIGHT + StatusBar.currentHeight,
10
+ export const NAVIGATION_BAR_HEIGHT = Platform.select({
11
+ ios: NAVIGATION_HEADER_HEIGHT + initialWindowMetrics.insets.top,
12
+ android: isNotchedAndroid
13
+ ? NAVIGATION_HEADER_HEIGHT + StatusBar.currentHeight
14
+ : NAVIGATION_HEADER_HEIGHT,
71
15
  default: NAVIGATION_HEADER_HEIGHT,
72
16
  });
73
17
 
74
- export const getHomeIndicatorPadding = () => {
75
- if (Platform.OS === 'android' || Platform.OS === 'web') {
76
- return 0;
77
- }
78
-
79
- // Apple identifier
80
- const deviceId = DeviceInfo.getDeviceId();
81
-
82
- // Extract the numbers from the deviceId string using a regular expression
83
- const versions = deviceId.match(/(\d+),(\d+)/);
84
-
85
- // Only checks if regex found X,Y, it does not resolve any of device ID-padding logic.
86
- // If version is present, e.g. in iPhone 9,1, it'll always return array of length 3.
87
- if (!versions && versions.length < 3) {
88
- return 0;
89
- }
90
-
91
- // Extracted numbers as strings
92
- const majorVersion = versions[1];
93
- const minorVersion = versions[2];
18
+ export const HOME_INDICATOR_PADDING =
19
+ Platform.OS === 'ios' ? HOME_INDICATOR_PADDING.insets.bottom : 0;
94
20
 
95
- const numericVersion = parseFloat(`${majorVersion}.${minorVersion}`);
96
-
97
- const excludedIphones = {
98
- iPhone8: 10.4,
99
- iPhone8plus: 10.5,
100
- iPhoneSeGen2: 12.8,
101
- iPhoneSeGen3: 14.6,
102
- };
103
-
104
- // Home indicator is present since iPhone X series with id of iPhone10,3.
105
- // There are few newer models that do not have home indicator.
106
- // They're included in excludedIphones object above.
107
- if (
108
- numericVersion >= 10.3 &&
109
- !Object.values(excludedIphones).includes(numericVersion)
110
- ) {
111
- // Devices with home indicator
112
- return 34;
113
- }
114
-
115
- // Devices without home indicator
116
- return 0;
117
- };
21
+ export const NOTCH_AREA_HEIGHT = Platform.select({
22
+ ios: initialWindowMetrics.insets.top,
23
+ android: isNotchedAndroid ? StatusBar.currentHeight : 0,
24
+ default: 0,
25
+ });
118
26
 
119
27
  export const Device = {
120
- isIphoneX,
121
- isIphoneXR,
122
28
  isNotchedAndroid,
123
- select,
29
+ HOME_INDICATOR_PADDING,
30
+ NOTCH_AREA_HEIGHT,
31
+ NAVIGATION_HEADER_HEIGHT,
124
32
  };
package/helpers/index.js CHANGED
@@ -1,13 +1,9 @@
1
1
  export {
2
2
  Device,
3
- IPHONE_12_LONG_SIDE,
4
- IPHONE_12_MAX_LONG_SIDE,
5
- IPHONE_X_HOME_INDICATOR_PADDING,
6
- IPHONE_X_LONG_SIDE,
7
- IPHONE_X_NOTCH_PADDING,
8
- IPHONE_XR_LONG_SIDE,
9
- IPHONE_XR_NOTCH_PADDING,
3
+ HOME_INDICATOR_PADDING,
4
+ isNotchedAndroid,
10
5
  NAVIGATION_BAR_HEIGHT,
11
6
  NAVIGATION_HEADER_HEIGHT,
7
+ NOTCH_AREA_HEIGHT,
12
8
  } from './device-selector';
13
9
  export { calculateKeyboardOffset, default as Keyboard } from './keyboard';
@@ -1,14 +1,18 @@
1
1
  import { Platform, StatusBar } from 'react-native';
2
- import { NAVIGATION_BAR_HEIGHT } from './device-selector';
2
+ import { isNotchedAndroid, NAVIGATION_BAR_HEIGHT } from './device-selector';
3
3
 
4
4
  export function calculateKeyboardOffset(extraOffset = 0) {
5
5
  const resolvedOffset = NAVIGATION_BAR_HEIGHT + extraOffset;
6
6
 
7
- if (Platform.OS === 'ios') {
7
+ if (Platform.OS === 'ios' || isNotchedAndroid) {
8
8
  return resolvedOffset;
9
9
  }
10
10
 
11
- return StatusBar.currentHeight + resolvedOffset;
11
+ if (Platform.OS === 'android' && !isNotchedAndroid) {
12
+ return StatusBar.currentHeight + resolvedOffset;
13
+ }
14
+
15
+ return resolvedOffset;
12
16
  }
13
17
 
14
18
  // TODO: Deprecate and remove Keyboard.calculateKeyboardOffset
package/index.js CHANGED
@@ -50,8 +50,6 @@ export { LinearGradient } from './components/LinearGradient';
50
50
  export { ListView } from './components/ListView';
51
51
  export { LoadingContainer } from './components/LoadingContainer';
52
52
  export { LoadingIndicator } from './components/LoadingIndicator';
53
- export { NavigationBar } from './components/NavigationBar';
54
- export { NavigationBarAnimations } from './components/NavigationBar/NavigationBarAnimations';
55
53
  export { NumberInput } from './components/NumberInput';
56
54
  export { Overlay } from './components/Overlay';
57
55
  export { PageIndicators } from './components/PageIndicators';
@@ -83,12 +81,9 @@ export { SimpleHtml } from './html';
83
81
 
84
82
  // Constants
85
83
  export {
86
- IPHONE_X_HOME_INDICATOR_PADDING,
87
- IPHONE_X_LONG_SIDE,
88
- IPHONE_X_NOTCH_PADDING,
89
- IPHONE_XR_LONG_SIDE,
90
- IPHONE_XR_NOTCH_PADDING,
84
+ HOME_INDICATOR_PADDING,
91
85
  NAVIGATION_BAR_HEIGHT,
92
86
  NAVIGATION_HEADER_HEIGHT,
87
+ NOTCH_AREA_HEIGHT,
93
88
  STATUS_BAR_OFFSET,
94
89
  } from './const';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shoutem/ui",
3
- "version": "7.2.2-rc.2",
3
+ "version": "7.3.0-rc.0",
4
4
  "description": "Styleable set of components for React Native applications",
5
5
  "scripts": {
6
6
  "lint": "eslint .",
@@ -49,7 +49,8 @@
49
49
  "peerDependencies": {
50
50
  "react": ">=16.9.0",
51
51
  "react-native": ">=0.61.5",
52
- "react-native-gesture-handler": "*"
52
+ "react-native-gesture-handler": "*",
53
+ "react-native-safe-area-context": "*"
53
54
  },
54
55
  "devDependencies": {
55
56
  "@babel/core": "7.16.7",
package/theme.js CHANGED
@@ -7,16 +7,12 @@ import {
7
7
  INCLUDE,
8
8
  inverseColorBrightnessForAmount,
9
9
  } from '@shoutem/theme';
10
- import { getHomeIndicatorPadding } from './helpers/device-selector';
11
10
  import {
12
- IPHONE_X_NOTCH_PADDING,
13
- IPHONE_XR_NOTCH_PADDING,
11
+ HOME_INDICATOR_PADDING,
14
12
  NAVIGATION_BAR_HEIGHT,
15
- NAVIGATION_HEADER_HEIGHT,
16
13
  STATUS_BAR_OFFSET,
17
14
  } from './const';
18
- import { Device } from './helpers';
19
- import { isAndroid, isIos, resolveVariable } from './services';
15
+ import { isIos, resolveVariable } from './services';
20
16
 
21
17
  const window = Dimensions.get('window');
22
18
 
@@ -869,7 +865,7 @@ export default () => {
869
865
  [INCLUDE]: ['commonVariants', 'guttersPadding'],
870
866
 
871
867
  '.with-home-indicator-padding': {
872
- paddingBottom: getHomeIndicatorPadding(),
868
+ paddingBottom: HOME_INDICATOR_PADDING,
873
869
  },
874
870
 
875
871
  '.horizontal': {
@@ -974,16 +970,16 @@ export default () => {
974
970
  // This was created with home indicator padding in mind. Use with-home-indicator-padding
975
971
  // if you need bottom padding. For actual notch - top of the screen padding, use SafeAreaView component instead.
976
972
  '.with-notch-padding': {
977
- paddingBottom: getHomeIndicatorPadding(),
973
+ paddingBottom: HOME_INDICATOR_PADDING,
978
974
  },
979
975
 
980
976
  '.with-home-indicator-padding': {
981
- paddingBottom: getHomeIndicatorPadding(),
977
+ paddingBottom: HOME_INDICATOR_PADDING,
982
978
  },
983
979
 
984
980
  'shoutem.ui.ListView': {
985
981
  listContent: {
986
- paddingBottom: getHomeIndicatorPadding(),
982
+ paddingBottom: HOME_INDICATOR_PADDING,
987
983
  },
988
984
  },
989
985
 
@@ -1537,332 +1533,6 @@ export default () => {
1537
1533
  //
1538
1534
  // Other
1539
1535
  //
1540
- // Deprecated on ShoutEm platform ( not used for navigationBar elements )
1541
- navigationBar: {
1542
- '.featured': {
1543
- 'shoutem.ui.Button': {
1544
- 'shoutem.ui.Icon': {
1545
- color: resolveVariable('featuredNavBarIconsColor'),
1546
- },
1547
- 'shoutem.ui.Text': {
1548
- color: resolveVariable('featuredNavBarIconsColor'),
1549
- },
1550
-
1551
- 'shoutem.ui.View': {
1552
- '.badge': {
1553
- backgroundColor: resolveVariable('featuredNavBarIconsColor'),
1554
- borderColor: resolveVariable('featuredColor'),
1555
-
1556
- 'shoutem.ui.Text': {
1557
- color: resolveVariable('featuredColor'),
1558
- },
1559
- },
1560
- },
1561
- },
1562
-
1563
- 'shoutem.ui.DropDownMenu': {
1564
- selectedOption: {
1565
- 'shoutem.ui.Icon': {
1566
- color: resolveVariable('featuredNavBarIconsColor'),
1567
- },
1568
- 'shoutem.ui.Text': {
1569
- color: resolveVariable('featuredNavBarIconsColor'),
1570
- },
1571
- },
1572
- },
1573
-
1574
- ...createSharedStyle(
1575
- ['shoutem.ui.Title', 'shoutem.ui.Icon', 'shoutem.ui.Text'],
1576
- {
1577
- fontFamily: resolveFontFamily(
1578
- resolveVariable('title.fontFamily'),
1579
- resolveVariable('title.fontWeight'),
1580
- resolveVariable('title.fontStyle'),
1581
- ),
1582
- fontWeight: resolveFontWeight(resolveVariable('title.fontWeight')),
1583
- fontStyle: resolveFontStyle(resolveVariable('title.fontStyle')),
1584
- color: resolveVariable('featuredNavBarTitleColor'),
1585
- },
1586
- ),
1587
-
1588
- container: {
1589
- [INCLUDE]: ['featuredBackground'],
1590
- borderBottomWidth: 0,
1591
- },
1592
- },
1593
-
1594
- 'shoutem.ui.Icon': {
1595
- color: resolveVariable('navBarIconsColor'),
1596
- width: 24,
1597
- height: 24,
1598
- paddingHorizontal: 9,
1599
- },
1600
-
1601
- 'shoutem.ui.Text': {
1602
- ...resolveVariable('navBarText'),
1603
- fontFamily: resolveFontFamily(
1604
- resolveVariable('navBarText.fontFamily'),
1605
- resolveVariable('navBarText.fontWeight'),
1606
- resolveVariable('navBarText.fontStyle'),
1607
- ),
1608
- fontWeight: resolveFontWeight(resolveVariable('navBarText.fontWeight')),
1609
- fontStyle: resolveFontStyle(resolveVariable('navBarText.fontStyle')),
1610
- paddingHorizontal: 9,
1611
- },
1612
-
1613
- 'shoutem.ui.ShareButton': {
1614
- '.clear': {
1615
- 'shoutem.ui.Button': {
1616
- [INCLUDE]: ['clearButton'],
1617
- },
1618
- },
1619
- },
1620
-
1621
- 'shoutem.ui.Button': {
1622
- [INCLUDE]: ['clearButton', 'tightButton'],
1623
- 'shoutem.ui.Icon': {
1624
- color: resolveVariable('navBarIconsColor'),
1625
- marginVertical: 9,
1626
- },
1627
- 'shoutem.ui.Text': {
1628
- ...resolveVariable('navBarText'),
1629
- fontFamily: resolveFontFamily(
1630
- resolveVariable('navBarText.fontFamily'),
1631
- 'normal',
1632
- resolveVariable('navBarText.fontStyle'),
1633
- ),
1634
- fontWeight: resolveFontWeight('normal'),
1635
- fontStyle: resolveFontStyle(resolveVariable('navBarText.fontStyle')),
1636
- color: resolveVariable('navBarIconsColor'),
1637
- letterSpacing: 0,
1638
- },
1639
- 'shoutem.ui.View': {
1640
- '.badge': {
1641
- top: 5,
1642
- right: 5,
1643
- },
1644
- },
1645
- paddingHorizontal: 9,
1646
- },
1647
- },
1648
-
1649
- 'shoutem.ui.NavigationBar': {
1650
- title: {
1651
- color: resolveVariable('navBarText.color'),
1652
- lineHeight: calculateLineHeight(resolveVariable('navBarText.fontSize')),
1653
- ...resolveVariable('navBarText'),
1654
- fontFamily: resolveFontFamily(
1655
- resolveVariable('navBarText.fontFamily'),
1656
- resolveVariable('navBarText.fontWeight'),
1657
- resolveVariable('navBarText.fontStyle'),
1658
- ),
1659
- fontWeight: resolveFontWeight(resolveVariable('navBarText.fontWeight')),
1660
- fontStyle: resolveFontStyle(resolveVariable('navBarText.fontStyle')),
1661
- },
1662
- icon: {
1663
- color: resolveVariable('navBarIconsColor'),
1664
- },
1665
- statusBar: {
1666
- backgroundColor: resolveVariable('statusBarColor'),
1667
- statusBarStyle: resolveVariable('statusBarStyle'),
1668
- },
1669
- container: {
1670
- backgroundColor: resolveVariable('navBarBackground'),
1671
- borderBottomColor: resolveVariable('navBarBorderColor'),
1672
- borderBottomWidth: StyleSheet.hairlineWidth,
1673
- },
1674
- leftContainer: {
1675
- paddingLeft: resolveVariable('mediumGutter'),
1676
- },
1677
- rightContainer: {
1678
- paddingRight: resolveVariable('mediumGutter'),
1679
- },
1680
-
1681
- '.clear': {
1682
- container: {
1683
- backgroundColor: 'transparent',
1684
- borderBottomColor: 'transparent',
1685
- },
1686
- },
1687
-
1688
- '.featured': {
1689
- title: {
1690
- color: resolveVariable('featuredNavBarTitleColor'),
1691
- },
1692
- icon: {
1693
- color: resolveVariable('featuredNavBarIconsColor'),
1694
- },
1695
-
1696
- container: {
1697
- backgroundColor: resolveVariable('featuredColor'),
1698
- borderBottomWidth: 0,
1699
- shadowOpacity: 0,
1700
- },
1701
- },
1702
-
1703
- '.no-border': {
1704
- container: {
1705
- borderBottomWidth: 0,
1706
- shadowOpacity: 0,
1707
- },
1708
- },
1709
-
1710
- boxingAnimation(driver) {
1711
- return {
1712
- container: {
1713
- borderBottomColor: driver.interpolate({
1714
- // Animate to approx title top offset
1715
- inputRange: [0, 45],
1716
- outputRange: [
1717
- 'transparent',
1718
- resolveVariable('navBarBorderColor'),
1719
- ],
1720
- extrapolate: 'clamp',
1721
- }),
1722
- borderBottomWidth: 1,
1723
- },
1724
- title: {
1725
- opacity: driver.interpolate({
1726
- inputRange: [250, 300],
1727
- outputRange: [0, 1],
1728
- extrapolate: 'clamp',
1729
- }),
1730
- },
1731
- };
1732
- },
1733
-
1734
- solidifyAnimation(driver) {
1735
- return {
1736
- icon: {
1737
- opacity: driver.interpolate({
1738
- inputRange: [250, 300],
1739
- outputRange: [0, 1],
1740
- extrapolate: 'clamp',
1741
- }),
1742
- },
1743
- title: {
1744
- color: driver.interpolate({
1745
- inputRange: [250, 300],
1746
- outputRange: ['transparent', resolveVariable('navBarText.color')],
1747
- extrapolate: 'clamp',
1748
- }),
1749
- },
1750
- container: {
1751
- backgroundColor: driver.interpolate({
1752
- inputRange: [250, 300],
1753
- outputRange: ['transparent', resolveVariable('navBarBackground')],
1754
- extrapolate: 'clamp',
1755
- }),
1756
- borderBottomColor: driver.interpolate({
1757
- inputRange: [250, 300],
1758
- outputRange: [
1759
- 'transparent',
1760
- resolveVariable('navBarBorderColor'),
1761
- ],
1762
- extrapolate: 'clamp',
1763
- }),
1764
- opacity: driver.interpolate({
1765
- inputRange: [250, 300],
1766
- outputRange: [0, 1],
1767
- extrapolate: 'clamp',
1768
- }),
1769
- },
1770
- };
1771
- },
1772
-
1773
- fadeAnimation(driver) {
1774
- return {
1775
- container: {
1776
- gradient: {
1777
- colors: ['transparent', 'rgba(0, 0, 0, 0.5)', 'transparent'],
1778
- locations: [0.0, 0.25, 1.0],
1779
- opacity: driver.interpolate({
1780
- inputRange: [250, 300],
1781
- outputRange: [1, 0],
1782
- }),
1783
- },
1784
- },
1785
- };
1786
- },
1787
- },
1788
-
1789
- // Deprecated on ShoutEm platform ( not used for navigationBar elements )
1790
- 'shoutem.ui.navigation.NavigationBar': {
1791
- [INCLUDE]: ['navigationBar'],
1792
-
1793
- '.fade': {
1794
- // Clear navigation bar is currently disabled on Android
1795
- // due to overflow issues.
1796
- gradient: {
1797
- [INCLUDE]: ['fillParent'],
1798
- colors: ['transparent', 'rgba(0, 0, 0, 0.15)', 'transparent'],
1799
- locations: [0.0, 0.25, 1.0],
1800
- solidifyAnimation(driver) {
1801
- return {
1802
- opacity: driver.interpolate({
1803
- inputRange: [250, 300],
1804
- outputRange: [1, 0],
1805
- }),
1806
- };
1807
- },
1808
- },
1809
- },
1810
-
1811
- container: {
1812
- paddingTop: NAVIGATION_BAR_HEIGHT,
1813
- backgroundColor: resolveVariable('navBarBackground'),
1814
- borderBottomColor: resolveVariable('navBarBorderColor'),
1815
- borderBottomWidth: StyleSheet.hairlineWidth,
1816
- },
1817
- navigationHeader: {
1818
- position: 'absolute',
1819
- top: Device.select({
1820
- iPhoneX: 6,
1821
- iPhoneXR: 8,
1822
- default: isAndroid ? 0 : -4,
1823
- }),
1824
- left: 0,
1825
- right: 0,
1826
- height: NAVIGATION_BAR_HEIGHT,
1827
- },
1828
- statusBar: {
1829
- backgroundColor: resolveVariable('statusBarColor'),
1830
- statusBarStyle: resolveVariable('statusBarStyle'),
1831
- height: Device.select({
1832
- iPhoneX: IPHONE_X_NOTCH_PADDING,
1833
- iPhoneXR: IPHONE_XR_NOTCH_PADDING,
1834
- default: 0,
1835
- }),
1836
- },
1837
- screenBackground: resolveVariable('backgroundColor'),
1838
- navigationBarImage: {
1839
- marginTop: Device.select({
1840
- iPhoneX: IPHONE_X_NOTCH_PADDING,
1841
- iPhoneXR: IPHONE_XR_NOTCH_PADDING,
1842
- default: 0,
1843
- }),
1844
- flex: 1,
1845
- flexGrow: 1,
1846
- height: NAVIGATION_HEADER_HEIGHT,
1847
- left: 0,
1848
- solidifyAnimation(driver) {
1849
- return {
1850
- opacity: driver.interpolate({
1851
- inputRange: [250, 300],
1852
- outputRange: [0, 1],
1853
- extrapolate: 'clamp',
1854
- }),
1855
- };
1856
- },
1857
- boxingAnimation() {
1858
- return {};
1859
- },
1860
- position: 'absolute',
1861
- right: 0,
1862
- top: 0,
1863
- width: window.width,
1864
- },
1865
- },
1866
1536
 
1867
1537
  sectionHeaderDivider: {
1868
1538
  'shoutem.ui.Caption': {
@@ -1,113 +0,0 @@
1
- import React, { PureComponent } from 'react';
2
- import { Animated, Platform, StatusBar, View } from 'react-native';
3
- import _ from 'lodash';
4
- import PropTypes from 'prop-types';
5
- import color from 'tinycolor2';
6
- import { connectAnimation } from '@shoutem/animation';
7
- import { connectStyle } from '@shoutem/theme';
8
- import { Device } from '../../helpers';
9
- import composeChildren from './composeChildren';
10
-
11
- function getBackgroundColor(style) {
12
- const styleWithBg = _.find(
13
- style,
14
- styleDef =>
15
- styleDef.backgroundColor && styleDef.backgroundColor !== 'transparent',
16
- );
17
-
18
- return (styleWithBg && styleWithBg.backgroundColor) || 'transparent';
19
- }
20
-
21
- // eslint-disable-next-line react/prefer-stateless-function
22
- class NavigationBar extends PureComponent {
23
- setStatusBarStyle(backgroundColor) {
24
- function chooseBarStyle(bgColor) {
25
- return color(bgColor).isDark() ? 'light-content' : 'default';
26
- }
27
-
28
- function setStyle(bgColor) {
29
- const statusBarColor = _.get(this.props, 'statusBarColor', bgColor);
30
-
31
- const color = statusBarColor || bgColor;
32
-
33
- if (Platform.OS === 'android') {
34
- StatusBar.setBackgroundColor('rgba(0, 0, 0, 0.2)');
35
- } else {
36
- const barStyle = chooseBarStyle(color);
37
- StatusBar.setBarStyle(barStyle);
38
- }
39
- }
40
-
41
- // This is little bit hacky, but is the only way
42
- // to determine the current value of interpolated Animated.Value
43
- // Other way would be to ask developer to provide Animated.Value
44
- // used to interpolate backgroundColor. But this way developer doesn't
45
- // have to concern about status bar if he animates navigation bar color
46
- if (backgroundColor && backgroundColor._parent instanceof Animated.Value) {
47
- backgroundColor._parent.addListener(animation => {
48
- setStyle(backgroundColor._interpolation(animation.value));
49
- });
50
- setStyle(backgroundColor._interpolation(0));
51
- } else {
52
- setStyle(backgroundColor);
53
- }
54
- }
55
-
56
- renderStatusBar() {
57
- const { style } = this.props;
58
-
59
- return Device.select({
60
- iPhoneX: <View style={style.statusBar} />,
61
- default: null,
62
- });
63
- }
64
-
65
- render() {
66
- const {
67
- leftComponent,
68
- rightComponent,
69
- centerComponent,
70
- style,
71
- id,
72
- } = this.props;
73
-
74
- const backgroundColor = getBackgroundColor(style);
75
- this.setStatusBarStyle(backgroundColor);
76
- // Key must be set to render new screen NavigationBar
77
- return (
78
- <Animated.View style={style.container} key={id}>
79
- {this.renderStatusBar()}
80
- <View style={style.componentsContainer}>
81
- <View style={style.leftComponent}>{leftComponent}</View>
82
- <View style={style.centerComponent}>{centerComponent}</View>
83
- <View style={style.rightComponent}>{rightComponent}</View>
84
- </View>
85
- </Animated.View>
86
- );
87
- }
88
- }
89
-
90
- NavigationBar.propTypes = {
91
- style: PropTypes.object.isRequired,
92
- centerComponent: PropTypes.node,
93
- id: PropTypes.string,
94
- leftComponent: PropTypes.node,
95
- rightComponent: PropTypes.node,
96
- // eslint-disable-next-line react/no-unused-prop-types
97
- statusBarColor: PropTypes.string,
98
- };
99
-
100
- NavigationBar.defaultProps = {
101
- id: 'default',
102
- leftComponent: undefined,
103
- centerComponent: undefined,
104
- rightComponent: undefined,
105
- statusBarColor: undefined,
106
- };
107
-
108
- const AnimatedNavigationBar = connectAnimation(composeChildren(NavigationBar));
109
- const StyledNavigationBar = connectStyle('shoutem.ui.NavigationBar')(
110
- AnimatedNavigationBar,
111
- );
112
-
113
- export { StyledNavigationBar as NavigationBar };
@@ -1,47 +0,0 @@
1
- import _ from 'lodash';
2
-
3
- class ColorAnimation {
4
- constructor(options) {
5
- _.assign(this, options);
6
- if (!_.isFunction(this[this.preset])) {
7
- throw new Error(`Color animation preset:(${options.preset})
8
- you tried to create doesn't exist`);
9
- }
10
- this.animatedValue = this.driver.value;
11
- this.style = {};
12
- }
13
-
14
- setColors(backgroundColor, textColor) {
15
- this.backgroundColor = backgroundColor;
16
- this.textColor = textColor;
17
-
18
- this.style = this[this.preset](this.scrollOffset);
19
- }
20
-
21
- clearToStandard(atAnimatedValue) {
22
- const defaultAnimatedValue = atAnimatedValue || 150;
23
- const standardTextColor = this.textColor || 'rgba(0,0,0,1)';
24
- const { animatedValue } = this;
25
- return {
26
- color: animatedValue.interpolate({
27
- inputRange: [0, defaultAnimatedValue],
28
- outputRange: ['rgba(0,0,0,0)', standardTextColor],
29
- extrapolate: 'clamp',
30
- }),
31
- backgroundColor: animatedValue.interpolate({
32
- inputRange: [0, defaultAnimatedValue],
33
- outputRange: ['rgba(0,0,0,0)', 'rgba(255,255,255,1)'],
34
- extrapolate: 'clamp',
35
- }),
36
- borderBottomColor: animatedValue.interpolate({
37
- inputRange: [defaultAnimatedValue / 2, defaultAnimatedValue],
38
- outputRange: ['rgba(0,0,0,0)', 'rgba(51, 51, 51, 0.2)'],
39
- extrapolate: 'clamp',
40
- }),
41
- };
42
- }
43
- }
44
-
45
- export const NavigationBarAnimations = {
46
- ColorAnimation,
47
- };
@@ -1,86 +0,0 @@
1
- import React, { PureComponent } from 'react';
2
- import _ from 'lodash';
3
- import { Button } from '../Button';
4
- import { Icon } from '../Icon';
5
- import { ShareButton } from '../ShareButton';
6
- import { Title } from '../Text';
7
-
8
- const composers = {
9
- title: (value, props) => ({
10
- centerComponent: (
11
- <Title animationName={props.animationName} numberOfLines={1}>
12
- {value || ''}
13
- </Title>
14
- ),
15
- }),
16
- share: (value, props) => {
17
- if (!value.link) {
18
- return null;
19
- }
20
-
21
- const { title, text, link } = value;
22
-
23
- return {
24
- rightComponent: (
25
- <ShareButton
26
- animationName={props.animationName}
27
- title={title || props.title}
28
- message={text}
29
- url={link}
30
- />
31
- ),
32
- };
33
- },
34
- hasHistory: (value, props) => {
35
- const { navigateBack } = props;
36
-
37
- /**
38
- * onPress sets `event` as first param, which leads to ignoring default navigateBack
39
- * first argument (navigator) so we have to wrap navigateBack into function to leave first
40
- * argument empty, default
41
- */
42
- function navigateBackWithoutEventParameter() {
43
- navigateBack();
44
- }
45
-
46
- const leftComponent = value ? (
47
- <Button styleName="clear" onPress={navigateBackWithoutEventParameter}>
48
- <Icon name="back" animationName={props.animationName} />
49
- </Button>
50
- ) : null;
51
-
52
- return { leftComponent };
53
- },
54
- };
55
-
56
- /**
57
- * If source (usually state set by component) has undefined
58
- * property values, ignore those properties.
59
- * @param objValue
60
- * @param srcValue
61
- * @returns {*}
62
- */
63
- function skipUndefined(objValue, srcValue) {
64
- return _.isUndefined(srcValue) ? objValue : srcValue;
65
- }
66
-
67
- // eslint-disable-next-line react/prefer-stateless-function
68
- const composeChildren = NavigationBarComponent =>
69
- class extends PureComponent {
70
- render() {
71
- const newProps = {};
72
- _.forEach(this.props, (value, key) => {
73
- if (_.isFunction(composers[key])) {
74
- _.assign(newProps, composers[key](value, this.props));
75
- }
76
- });
77
-
78
- return (
79
- <NavigationBarComponent
80
- {..._.assignWith(newProps, this.props, skipUndefined)}
81
- />
82
- );
83
- }
84
- };
85
-
86
- export default composeChildren;
@@ -1,2 +0,0 @@
1
- export { NavigationBar } from './NavigationBar';
2
- export { NavigationBarAnimations } from './NavigationBarAnimations';