@quintype/native-components 2.21.5 → 2.22.0-beta.1
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/.watchmanconfig +6 -0
- package/bin-dev-scripts/standard-version-release.sh +11 -11
- package/package.json +1 -1
- package/src/components/CollectionCardNew/index.js +1 -1
- package/src/components/CollectionTitleNew/styles.js +2 -1
- package/src/components/PrimaryStoryCardNew/index.js +14 -36
- package/src/components/PrimaryStoryCardNew/styles.js +21 -14
- package/src/components/ResponsiveImage/index.js +15 -4
- package/src/components/SecondaryStoryCardNew/index.js +21 -38
- package/src/components/SecondaryStoryCardNew/styles.js +32 -14
- package/src/components/ShareButton/index.js +16 -3
- package/src/components/ShareButton/styles.js +2 -2
- package/src/components/StoryCardDetailsRow/index.js +52 -0
- package/src/components/StoryCardDetailsRow/styles.js +14 -0
- package/src/components/index.js +3 -2
package/.watchmanconfig
ADDED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
#!/bin/bash -e
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
npm install
|
|
4
|
+
git diff --quiet
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
BRANCH=$(git symbolic-ref --short HEAD)
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
if [ "$BRANCH" == 'master' ]
|
|
9
|
+
then
|
|
10
|
+
npx standard-version
|
|
11
|
+
else
|
|
12
|
+
npx standard-version --prerelease "$(git symbolic-ref --short HEAD | sed s:/:-:g )" --skip.changelog=true
|
|
13
|
+
fi
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
git push --follow-tags origin "$BRANCH"
|
package/package.json
CHANGED
|
@@ -55,7 +55,7 @@ const CollectionCardNewBase = ({
|
|
|
55
55
|
cdn={cdn}
|
|
56
56
|
story={secondaryStory}
|
|
57
57
|
iconComponent={<ShareButton story={secondaryStory} />}
|
|
58
|
-
imageWidth={getScreenPercentageWidth(
|
|
58
|
+
imageWidth={getScreenPercentageWidth(29)}
|
|
59
59
|
horizontalPadding={horizontalPadding}
|
|
60
60
|
/>
|
|
61
61
|
);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { StyleSheet } from 'react-native';
|
|
2
2
|
|
|
3
3
|
export const collectionTitleStyles = (appThemeContext) => {
|
|
4
|
-
const { COLORS, FONT_SIZE } = appThemeContext;
|
|
4
|
+
const { COLORS, FONT_SIZE, FONT_FAMILY } = appThemeContext;
|
|
5
5
|
|
|
6
6
|
return StyleSheet.create({
|
|
7
7
|
container: {
|
|
@@ -13,6 +13,7 @@ export const collectionTitleStyles = (appThemeContext) => {
|
|
|
13
13
|
},
|
|
14
14
|
title: {
|
|
15
15
|
fontSize: FONT_SIZE.h3,
|
|
16
|
+
fontFamily: FONT_FAMILY.secondaryBold,
|
|
16
17
|
color: COLORS.BRAND_5,
|
|
17
18
|
},
|
|
18
19
|
});
|
|
@@ -7,10 +7,9 @@ import {
|
|
|
7
7
|
AppTheme,
|
|
8
8
|
getImageMetadata,
|
|
9
9
|
getImageSlug,
|
|
10
|
-
getTimeForStoryCards,
|
|
11
10
|
} from '../../utils';
|
|
12
11
|
import { getStoryHeadline } from '../../utils/story';
|
|
13
|
-
import { ResponsiveImage, Text } from '../index';
|
|
12
|
+
import { ResponsiveImage, Text, StoryCardDetailsRow } from '../index';
|
|
14
13
|
import { storyStyles } from './styles';
|
|
15
14
|
import {
|
|
16
15
|
COMP_GENERAL_CONSTANTS,
|
|
@@ -24,18 +23,13 @@ const PrimaryStoryCardNewBase = (props) => {
|
|
|
24
23
|
const {
|
|
25
24
|
COLORS,
|
|
26
25
|
FONT_SIZE,
|
|
27
|
-
|
|
28
|
-
DARK_MODE,
|
|
29
|
-
reverseTimeAdverbPosition,
|
|
30
|
-
enableReadTimeOnStoryCards,
|
|
31
|
-
DATE_TIME_FORMAT,
|
|
26
|
+
FONT_FAMILY,
|
|
32
27
|
premiumIcon,
|
|
33
28
|
lineHeightMultiplier,
|
|
29
|
+
storyCardOptions,
|
|
34
30
|
} = theme || {};
|
|
35
31
|
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
const styles = storyStyles(COLORS, FONT_SIZE, lineHeightMultiplier);
|
|
32
|
+
const styles = storyStyles(theme);
|
|
39
33
|
const containerStyle = StyleSheet.flatten([
|
|
40
34
|
styles.container,
|
|
41
35
|
{ paddingHorizontal: props.horizontalPadding },
|
|
@@ -44,15 +38,7 @@ const PrimaryStoryCardNewBase = (props) => {
|
|
|
44
38
|
styles.headline,
|
|
45
39
|
props.headlineStyle,
|
|
46
40
|
]);
|
|
47
|
-
const timestampStyle = StyleSheet.flatten([
|
|
48
|
-
styles.timestamp,
|
|
49
|
-
props.timestampStyle,
|
|
50
|
-
]);
|
|
51
41
|
|
|
52
|
-
const DATE_FORMAT = DATE_TIME_FORMAT.dateFormat;
|
|
53
|
-
const readTime = enableReadTimeOnStoryCards && story['read-time']
|
|
54
|
-
? `${story['read-time']} ${translate('min read')} · `
|
|
55
|
-
: '';
|
|
56
42
|
const isPremiumStory = story['access'] === 'subscription';
|
|
57
43
|
|
|
58
44
|
const throttledOnpress = throttle(props.onPress, 1000);
|
|
@@ -85,6 +71,7 @@ const PrimaryStoryCardNewBase = (props) => {
|
|
|
85
71
|
};
|
|
86
72
|
|
|
87
73
|
return (
|
|
74
|
+
<>
|
|
88
75
|
<TouchableOpacity
|
|
89
76
|
testID={COMP_GENERAL_CONSTANTS.primaryStoryCard}
|
|
90
77
|
onPress={throttledOnpress}
|
|
@@ -101,12 +88,11 @@ const PrimaryStoryCardNewBase = (props) => {
|
|
|
101
88
|
</ResponsiveImage>
|
|
102
89
|
<View style={styles.contentContainer}>
|
|
103
90
|
<View style={styles.headlineAndTimestampContainer}>
|
|
91
|
+
{storyCardOptions.enableSectionName && <Text numberOfLines={1} ellipsizeMode="tail" style={styles.sectionName}>{get(story, ['sections', 0, 'display-name'], '')}</Text>}
|
|
104
92
|
<View style={{display:'flex', flexDirection:'row'}}>
|
|
105
|
-
|
|
106
|
-
|
|
107
93
|
<Text
|
|
108
94
|
primary
|
|
109
|
-
numberOfLines={
|
|
95
|
+
numberOfLines={storyCardOptions.numberOfLinesForTitle}
|
|
110
96
|
ellipsizeMode="tail"
|
|
111
97
|
style={headlineStyle}
|
|
112
98
|
testID={COMP_GENERAL_CONSTANTS.primaryStoryHeadline}
|
|
@@ -116,24 +102,17 @@ const PrimaryStoryCardNewBase = (props) => {
|
|
|
116
102
|
{getStoryHeadline(story)}
|
|
117
103
|
</Text>
|
|
118
104
|
</View>
|
|
119
|
-
<
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
{readTime
|
|
125
|
-
+ getTimeForStoryCards(
|
|
126
|
-
story['published-at'],
|
|
127
|
-
DATE_FORMAT,
|
|
128
|
-
locale,
|
|
129
|
-
translate,
|
|
130
|
-
reverseTimeAdverbPosition,
|
|
131
|
-
)}
|
|
132
|
-
</Text>
|
|
105
|
+
<StoryCardDetailsRow
|
|
106
|
+
authorName={get(story.authors, [0, 'name'])}
|
|
107
|
+
publishedAt={story["published-at"]}
|
|
108
|
+
readTime={story['read-time']}
|
|
109
|
+
/>
|
|
133
110
|
</View>
|
|
134
111
|
<View style={styles.icon}>{props.iconComponent}</View>
|
|
135
112
|
</View>
|
|
136
113
|
</TouchableOpacity>
|
|
114
|
+
<View style={[styles.separatorLine, {marginHorizontal: props.horizontalPadding}]}/>
|
|
115
|
+
</>
|
|
137
116
|
);
|
|
138
117
|
};
|
|
139
118
|
|
|
@@ -141,7 +120,6 @@ PrimaryStoryCardNewBase.propTypes = {
|
|
|
141
120
|
cdn: PropTypes.string,
|
|
142
121
|
imageWidth: PropTypes.number,
|
|
143
122
|
headlineStyle: PropTypes.func,
|
|
144
|
-
timestampStyle: PropTypes.func,
|
|
145
123
|
story: PropTypes.object.isRequired,
|
|
146
124
|
onPress: PropTypes.func,
|
|
147
125
|
horizontalPadding: PropTypes.number,
|
|
@@ -1,32 +1,34 @@
|
|
|
1
|
-
export const storyStyles = (COLORS
|
|
1
|
+
export const storyStyles = ({COLORS, FONT_SIZE, FONT_FAMILY, lineHeightMultiplier, storyCardOptions}) => ({
|
|
2
2
|
container: {
|
|
3
3
|
backgroundColor: COLORS.BRAND_WHITE,
|
|
4
|
-
|
|
4
|
+
paddingVertical: 10,
|
|
5
|
+
gap: 10,
|
|
5
6
|
},
|
|
6
7
|
contentContainer: {
|
|
7
8
|
flexDirection: 'row',
|
|
8
9
|
justifyContent: 'space-between',
|
|
9
|
-
alignItems: '
|
|
10
|
+
alignItems: 'flex-start',
|
|
11
|
+
gap: 10,
|
|
10
12
|
},
|
|
11
13
|
headlineAndTimestampContainer: {
|
|
12
14
|
flexShrink: 1,
|
|
13
|
-
|
|
15
|
+
gap: 4,
|
|
14
16
|
},
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
icon: {
|
|
18
|
+
marginBottom: 4,
|
|
19
|
+
marginTop: storyCardOptions.enableSectionName ? FONT_SIZE.h4 * lineHeightMultiplier + 8 : 4,
|
|
20
|
+
},
|
|
21
|
+
sectionName: {
|
|
22
|
+
color: COLORS.BRAND_1,
|
|
23
|
+
fontSize: FONT_SIZE.h4,
|
|
24
|
+
lineHeight: FONT_SIZE.h4 * lineHeightMultiplier,
|
|
21
25
|
},
|
|
22
26
|
headline: {
|
|
27
|
+
fontFamily: FONT_FAMILY.primaryBold,
|
|
23
28
|
fontSize: FONT_SIZE.title,
|
|
24
29
|
lineHeight: FONT_SIZE.title * lineHeightMultiplier,
|
|
25
30
|
color: COLORS.BRAND_BLACK,
|
|
26
|
-
|
|
27
|
-
},
|
|
28
|
-
icon: {
|
|
29
|
-
marginLeft: 8,
|
|
31
|
+
marginBottom: 4,
|
|
30
32
|
},
|
|
31
33
|
storyTypeContainer: {
|
|
32
34
|
position: 'absolute',
|
|
@@ -60,4 +62,9 @@ export const storyStyles = (COLORS = {}, FONT_SIZE = {}, lineHeightMultiplier) =
|
|
|
60
62
|
marginTop: FONT_SIZE.h3 * 0.92,
|
|
61
63
|
marginRight: 5,
|
|
62
64
|
},
|
|
65
|
+
separatorLine: {
|
|
66
|
+
height: 0.8,
|
|
67
|
+
opacity: 0.1,
|
|
68
|
+
backgroundColor: COLORS.BRAND_BLACK,
|
|
69
|
+
},
|
|
63
70
|
});
|
|
@@ -16,7 +16,11 @@ const ResponsiveImageBase = (props) => {
|
|
|
16
16
|
const [placeholder, setPlaceholder] = useState(true);
|
|
17
17
|
const { theme } = useContext(AppTheme);
|
|
18
18
|
const {
|
|
19
|
-
COLORS,
|
|
19
|
+
COLORS,
|
|
20
|
+
CustomFallBackIcon,
|
|
21
|
+
CustomFallBackBackground,
|
|
22
|
+
resizeImagesToFit,
|
|
23
|
+
roundedImageCorners,
|
|
20
24
|
} = theme;
|
|
21
25
|
|
|
22
26
|
const flattenedImageStyle = StyleSheet.flatten([
|
|
@@ -29,13 +33,20 @@ const ResponsiveImageBase = (props) => {
|
|
|
29
33
|
props?.elementType === 'gallery' && {
|
|
30
34
|
backgroundColor: COLORS.BRAND_BLACK,
|
|
31
35
|
},
|
|
36
|
+
roundedImageCorners && {
|
|
37
|
+
borderRadius: 12,
|
|
38
|
+
overflow: "hidden",
|
|
39
|
+
},
|
|
32
40
|
]);
|
|
33
41
|
|
|
34
42
|
const placeholderStyle = {
|
|
35
43
|
...StyleSheet.absoluteFillObject,
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
44
|
+
...props.styles,
|
|
45
|
+
backgroundColor:
|
|
46
|
+
(CustomFallBackIcon && CustomFallBackBackground) ?? COLORS.MONO6,
|
|
47
|
+
justifyContent: "center",
|
|
48
|
+
alignItems: "center",
|
|
49
|
+
borderRadius: roundedImageCorners ? 12 : 0,
|
|
39
50
|
};
|
|
40
51
|
|
|
41
52
|
const fallBackIcon = CustomFallBackIcon ? (
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { get, isNull, throttle } from 'lodash';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
|
-
import React, { useContext, memo
|
|
3
|
+
import React, { useContext, memo } from 'react';
|
|
4
4
|
import {
|
|
5
5
|
StyleSheet,
|
|
6
6
|
TouchableOpacity,
|
|
@@ -13,10 +13,9 @@ import {
|
|
|
13
13
|
AppTheme,
|
|
14
14
|
getImageMetadata,
|
|
15
15
|
getImageSlug,
|
|
16
|
-
getTimeForStoryCards,
|
|
17
16
|
} from '../../utils';
|
|
18
17
|
import { getStoryHeadline } from '../../utils/story';
|
|
19
|
-
import { ResponsiveImage, Text } from '../index';
|
|
18
|
+
import { ResponsiveImage, Text, StoryCardDetailsRow } from '../index';
|
|
20
19
|
import { storyStyles } from './styles';
|
|
21
20
|
import {
|
|
22
21
|
COMP_GENERAL_CONSTANTS,
|
|
@@ -28,18 +27,13 @@ const SecondaryStoryCardNewBase = (props) => {
|
|
|
28
27
|
const { story = {} } = props;
|
|
29
28
|
const { theme } = useContext(AppTheme);
|
|
30
29
|
const {
|
|
31
|
-
locale,
|
|
32
|
-
DARK_MODE,
|
|
33
30
|
COLORS,
|
|
34
|
-
reverseTimeAdverbPosition,
|
|
35
|
-
enableReadTimeOnStoryCards,
|
|
36
|
-
DATE_TIME_FORMAT,
|
|
37
31
|
premiumIcon,
|
|
38
|
-
FONT_SIZE
|
|
32
|
+
FONT_SIZE,
|
|
33
|
+
storyCardOptions,
|
|
39
34
|
} = theme;
|
|
40
35
|
|
|
41
|
-
const
|
|
42
|
-
const styles = storyStyles(theme, DARK_MODE);
|
|
36
|
+
const styles = storyStyles(theme);
|
|
43
37
|
const containerStyle = StyleSheet.flatten([
|
|
44
38
|
styles.container,
|
|
45
39
|
{ paddingHorizontal: props.horizontalPadding },
|
|
@@ -48,15 +42,7 @@ const SecondaryStoryCardNewBase = (props) => {
|
|
|
48
42
|
styles.headline,
|
|
49
43
|
props.headlineStyle,
|
|
50
44
|
]);
|
|
51
|
-
const timestampStyle = StyleSheet.flatten([
|
|
52
|
-
styles.timestamp,
|
|
53
|
-
props.timestampStyle,
|
|
54
|
-
]);
|
|
55
45
|
|
|
56
|
-
const DATE_FORMAT = DATE_TIME_FORMAT.dateFormat;
|
|
57
|
-
const readTime = enableReadTimeOnStoryCards && story['read-time']
|
|
58
|
-
? `${story['read-time']} ${translate('min read')} · `
|
|
59
|
-
: '';
|
|
60
46
|
const isPremiumStory = story['access'] === 'subscription';
|
|
61
47
|
|
|
62
48
|
const throttledOnpress = throttle(props.onPress, 1000);
|
|
@@ -90,25 +76,30 @@ const SecondaryStoryCardNewBase = (props) => {
|
|
|
90
76
|
};
|
|
91
77
|
|
|
92
78
|
return (
|
|
79
|
+
<>
|
|
93
80
|
<TouchableOpacity
|
|
94
81
|
testID={COMP_GENERAL_CONSTANTS.secondaryStoryCard}
|
|
95
82
|
onPress={throttledOnpress}
|
|
96
83
|
activeOpacity={0.8}
|
|
97
84
|
style={containerStyle}
|
|
98
85
|
>
|
|
99
|
-
<
|
|
86
|
+
<View style={[styles.imageAndDetails, storyCardOptions.alignSmallCardImage === "right" && { flexDirection: 'row-reverse'}]}>
|
|
87
|
+
{storyCardOptions.enableSmallCardImage && (<ResponsiveImage
|
|
88
|
+
styles={styles.image}
|
|
100
89
|
metaData={getImageMetadata(story)}
|
|
101
90
|
slug={getImageSlug(story) || ''}
|
|
102
91
|
cdn={props.cdn || ''}
|
|
103
92
|
imageWidth={props.imageWidth}
|
|
104
93
|
>
|
|
105
94
|
<View style={styles.storyTypeContainer}>{showStoryType()}</View>
|
|
106
|
-
</ResponsiveImage>
|
|
95
|
+
</ResponsiveImage>)
|
|
96
|
+
}
|
|
107
97
|
<View style={styles.headlineAndTimestampBlockContainer}>
|
|
98
|
+
{storyCardOptions.enableSectionName && <Text numberOfLines={1} ellipsizeMode="tail" style={styles.sectionName}>{get(story, ['sections', 0, 'display-name'], '')}</Text>}
|
|
108
99
|
<View style={{display:'flex', flexDirection:'row'}}>
|
|
109
100
|
<Text
|
|
110
101
|
primary
|
|
111
|
-
numberOfLines={
|
|
102
|
+
numberOfLines={storyCardOptions.numberOfLinesForTitle}
|
|
112
103
|
ellipsizeMode="tail"
|
|
113
104
|
style={headlineStyle}
|
|
114
105
|
testID={COMP_GENERAL_CONSTANTS.secondaryStoryHeadline}
|
|
@@ -118,24 +109,17 @@ const SecondaryStoryCardNewBase = (props) => {
|
|
|
118
109
|
{getStoryHeadline(story)?.trim()}
|
|
119
110
|
</Text>
|
|
120
111
|
</View>
|
|
121
|
-
<
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
{readTime
|
|
128
|
-
+ getTimeForStoryCards(
|
|
129
|
-
story['published-at'],
|
|
130
|
-
DATE_FORMAT,
|
|
131
|
-
locale,
|
|
132
|
-
translate,
|
|
133
|
-
reverseTimeAdverbPosition,
|
|
134
|
-
)}
|
|
135
|
-
</Text>
|
|
112
|
+
<StoryCardDetailsRow
|
|
113
|
+
authorName={get(story.authors, [0, 'name'])}
|
|
114
|
+
publishedAt={story["published-at"]}
|
|
115
|
+
readTime={story['read-time']}
|
|
116
|
+
/>
|
|
117
|
+
</View>
|
|
136
118
|
</View>
|
|
137
119
|
<View style={styles.icon}>{props.iconComponent}</View>
|
|
138
120
|
</TouchableOpacity>
|
|
121
|
+
<View style={[styles.separatorLine, { marginHorizontal: props.horizontalPadding }]}/>
|
|
122
|
+
</>
|
|
139
123
|
);
|
|
140
124
|
};
|
|
141
125
|
|
|
@@ -143,7 +127,6 @@ SecondaryStoryCardNewBase.propTypes = TouchableOpacityProps && {
|
|
|
143
127
|
cdn: PropTypes.string.isRequired,
|
|
144
128
|
imageWidth: PropTypes.number,
|
|
145
129
|
headlineStyle: TextStyle,
|
|
146
|
-
timestampStyle: TextStyle,
|
|
147
130
|
story: PropTypes.any.isRequired,
|
|
148
131
|
iconComponent: PropTypes.element,
|
|
149
132
|
horizontalPadding: PropTypes.number,
|
|
@@ -1,33 +1,46 @@
|
|
|
1
1
|
import { StyleSheet } from 'react-native';
|
|
2
2
|
|
|
3
|
-
export const storyStyles = ({ COLORS, FONT_SIZE, lineHeightMultiplier }) => StyleSheet.create({
|
|
3
|
+
export const storyStyles = ({ COLORS, FONT_SIZE, FONT_FAMILY, lineHeightMultiplier, storyCardOptions }) => StyleSheet.create({
|
|
4
4
|
container: {
|
|
5
5
|
flexDirection: 'row',
|
|
6
|
+
justifyContent: 'space-between',
|
|
6
7
|
backgroundColor: COLORS.BRAND_WHITE,
|
|
7
|
-
|
|
8
|
-
alignItems: '
|
|
8
|
+
paddingVertical: 10,
|
|
9
|
+
alignItems: 'flex-start',
|
|
10
|
+
gap: 10,
|
|
11
|
+
},
|
|
12
|
+
imageAndDetails: {
|
|
13
|
+
flexDirection: 'row',
|
|
14
|
+
flexShrink: 1,
|
|
15
|
+
alignItems: 'flex-start',
|
|
16
|
+
gap: 10,
|
|
17
|
+
},
|
|
18
|
+
image: {
|
|
19
|
+
marginBottom: 4,
|
|
20
|
+
marginTop: storyCardOptions.enableSectionName ? FONT_SIZE.h4 * lineHeightMultiplier + 8 : 4,
|
|
21
|
+
},
|
|
22
|
+
icon: {
|
|
23
|
+
marginBottom: 4,
|
|
24
|
+
marginTop: storyCardOptions.enableSectionName ? FONT_SIZE.h4 * lineHeightMultiplier + 8 : 4,
|
|
9
25
|
},
|
|
10
26
|
headlineAndTimestampBlockContainer: {
|
|
11
27
|
flexShrink: 1,
|
|
12
|
-
|
|
28
|
+
flexGrow: 1,
|
|
29
|
+
gap: 4,
|
|
13
30
|
justifyContent: 'space-between',
|
|
14
|
-
paddingLeft: 12,
|
|
15
31
|
},
|
|
16
|
-
|
|
17
|
-
color: COLORS.
|
|
18
|
-
fontSize: FONT_SIZE.
|
|
19
|
-
lineHeight: FONT_SIZE.
|
|
20
|
-
opacity: 0.6,
|
|
21
|
-
marginTop: 4,
|
|
32
|
+
sectionName: {
|
|
33
|
+
color: COLORS.BRAND_1,
|
|
34
|
+
fontSize: FONT_SIZE.h4,
|
|
35
|
+
lineHeight: FONT_SIZE.h4 * lineHeightMultiplier,
|
|
22
36
|
},
|
|
23
37
|
headline: {
|
|
24
38
|
color: COLORS.BRAND_BLACK,
|
|
25
39
|
flexWrap: 'wrap',
|
|
26
40
|
fontSize: FONT_SIZE.h3,
|
|
41
|
+
fontFamily: FONT_FAMILY.primaryBold,
|
|
27
42
|
lineHeight: FONT_SIZE.h3 * lineHeightMultiplier,
|
|
28
|
-
|
|
29
|
-
icon: {
|
|
30
|
-
marginLeft: 8,
|
|
43
|
+
marginBottom: 4,
|
|
31
44
|
},
|
|
32
45
|
storyTypeContainer: {
|
|
33
46
|
position: 'absolute',
|
|
@@ -61,4 +74,9 @@ export const storyStyles = ({ COLORS, FONT_SIZE, lineHeightMultiplier }) => Styl
|
|
|
61
74
|
marginTop: FONT_SIZE.h3 * 0.45,
|
|
62
75
|
marginRight: 3,
|
|
63
76
|
},
|
|
77
|
+
separatorLine: {
|
|
78
|
+
height: 0.8,
|
|
79
|
+
opacity: 0.1,
|
|
80
|
+
backgroundColor: COLORS.BRAND_BLACK,
|
|
81
|
+
},
|
|
64
82
|
});
|
|
@@ -2,6 +2,7 @@ import React, { useContext, memo } from 'react';
|
|
|
2
2
|
import { TouchableOpacity } from 'react-native';
|
|
3
3
|
import PropTypes from 'prop-types';
|
|
4
4
|
import Icon from 'react-native-vector-icons/Ionicons';
|
|
5
|
+
import IconAlt from 'react-native-vector-icons/MaterialCommunityIcons';
|
|
5
6
|
import Share from 'react-native-share';
|
|
6
7
|
import { AppTheme } from '../../utils';
|
|
7
8
|
import { shareButtonStyles } from './styles';
|
|
@@ -11,7 +12,7 @@ import { COMP_GENERAL_CONSTANTS } from '../../constants/component-constants';
|
|
|
11
12
|
const ShareButtonBase = (props) => {
|
|
12
13
|
const { theme } = useContext(AppTheme);
|
|
13
14
|
const styles = shareButtonStyles(theme);
|
|
14
|
-
const {
|
|
15
|
+
const { storyCardOptions } = theme;
|
|
15
16
|
const { story, type = 'story', slug } = props;
|
|
16
17
|
|
|
17
18
|
const getShareURL = () => {
|
|
@@ -48,12 +49,24 @@ const ShareButtonBase = (props) => {
|
|
|
48
49
|
return null;
|
|
49
50
|
}
|
|
50
51
|
|
|
51
|
-
|
|
52
|
+
const renderIcon = () => {
|
|
53
|
+
switch (storyCardOptions.shareButtonIcon) {
|
|
54
|
+
case 'right-arrow':
|
|
55
|
+
return <IconAlt style={styles.iconStyle} name="share-outline" size={20} />;
|
|
56
|
+
case 'up-arrow':
|
|
57
|
+
return <Icon style={styles.iconStyle} name="share-outline" size={20} />;
|
|
58
|
+
case 'classic':
|
|
59
|
+
default:
|
|
60
|
+
return <Icon style={styles.iconStyle} name="share-social-outline" size={20} />;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
return storyCardOptions.enableShareButton ? (
|
|
52
65
|
<TouchableOpacity
|
|
53
66
|
onPress={share}
|
|
54
67
|
testID={COMP_GENERAL_CONSTANTS.shareButtonTouch}
|
|
55
68
|
>
|
|
56
|
-
|
|
69
|
+
{renderIcon()}
|
|
57
70
|
</TouchableOpacity>
|
|
58
71
|
) : null;
|
|
59
72
|
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { get } from 'lodash';
|
|
2
|
+
import PropTypes from "prop-types";
|
|
3
|
+
import React, { useContext, memo } from "react";
|
|
4
|
+
import { View } from "react-native";
|
|
5
|
+
import { Text } from "../index";
|
|
6
|
+
import { storyCardDetailsRowStyles } from "./styles";
|
|
7
|
+
import { AppTheme, getTimeForStoryCards } from "../../utils";
|
|
8
|
+
|
|
9
|
+
const StoryCardDetailsRowBase = ({ authorName, publishedAt, readTime }) => {
|
|
10
|
+
const { theme } = useContext(AppTheme);
|
|
11
|
+
const styles = storyCardDetailsRowStyles(theme);
|
|
12
|
+
const {
|
|
13
|
+
locale,
|
|
14
|
+
reverseTimeAdverbPosition,
|
|
15
|
+
DATE_TIME_FORMAT,
|
|
16
|
+
storyCardOptions,
|
|
17
|
+
} = theme;
|
|
18
|
+
const translate = get(theme, ["translate"], (word) => word);
|
|
19
|
+
|
|
20
|
+
const authorNameText = authorName;
|
|
21
|
+
const publishedAtText = getTimeForStoryCards(
|
|
22
|
+
publishedAt,
|
|
23
|
+
DATE_TIME_FORMAT.dateFormat,
|
|
24
|
+
locale,
|
|
25
|
+
translate,
|
|
26
|
+
reverseTimeAdverbPosition
|
|
27
|
+
);
|
|
28
|
+
const readTimeText = readTime ? readTime + " " + translate("min read") : "";
|
|
29
|
+
const details = [
|
|
30
|
+
storyCardOptions.enableAuthorName && authorNameText,
|
|
31
|
+
storyCardOptions.enablePublishedAt && publishedAtText,
|
|
32
|
+
storyCardOptions.enableReadTime && readTimeText,
|
|
33
|
+
].filter((detail) => detail && detail.trim());
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<View style={styles.container}>
|
|
37
|
+
{details.map((detail, index) => (
|
|
38
|
+
<Text key={index} style={styles.detailText}>
|
|
39
|
+
{detail}
|
|
40
|
+
{index < details.length - 1 && ' · '}
|
|
41
|
+
</Text>
|
|
42
|
+
))}
|
|
43
|
+
</View>
|
|
44
|
+
);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
StoryCardDetailsRowBase.propTypes = {
|
|
48
|
+
authorName: PropTypes.string,
|
|
49
|
+
readTime: PropTypes.string,
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export const StoryCardDetailsRow = memo(StoryCardDetailsRowBase);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { StyleSheet } from 'react-native';
|
|
2
|
+
|
|
3
|
+
export const storyCardDetailsRowStyles = ({ COLORS, FONT_SIZE, lineHeightMultiplier }) => StyleSheet.create({
|
|
4
|
+
container: {
|
|
5
|
+
flexDirection: 'row',
|
|
6
|
+
flexWrap: 'wrap',
|
|
7
|
+
},
|
|
8
|
+
detailText: {
|
|
9
|
+
color: COLORS.BRAND_BLACK,
|
|
10
|
+
fontSize: FONT_SIZE.h5,
|
|
11
|
+
lineHeight: FONT_SIZE.h5 * lineHeightMultiplier,
|
|
12
|
+
opacity: 0.6,
|
|
13
|
+
},
|
|
14
|
+
});
|
package/src/components/index.js
CHANGED
|
@@ -44,5 +44,6 @@ export { IconText } from './IconText';
|
|
|
44
44
|
export { CustomSwitch } from './CustomSwitch';
|
|
45
45
|
export { RelatedStoriesCard } from './RelatedStoriesCard';
|
|
46
46
|
export { References } from './References';
|
|
47
|
-
export {
|
|
48
|
-
export {
|
|
47
|
+
export { StoryCardDetailsRow } from './StoryCardDetailsRow';
|
|
48
|
+
export { TextA } from './TextA'
|
|
49
|
+
export { TextQ } from './TextQ'
|