@quintype/native-components 2.30.2-center-align-title-beta.2 → 2.30.3
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/package.json +1 -1
- package/src/components/Header/index.js +2 -3
- package/src/components/Header/styles.js +2 -2
- package/src/components/JSEmbedElement/index.js +39 -23
- package/src/components/Story/index.js +1 -3
- package/src/components/StoryHeader/index.js +5 -6
- package/src/components/StoryHeader/styles.js +0 -3
- package/src/components/StoryText/index.js +7 -6
- package/src/components/StoryTitle/index.js +2 -2
- package/src/components/StoryTitle/styles.js +1 -2
- package/src/components/TextSummary/index.js +21 -0
- package/src/components/TitleElement/styles.js +2 -1
- package/src/constants/renderHTML.js +26 -11
package/package.json
CHANGED
|
@@ -12,8 +12,8 @@ import { headerStyles } from "./styles";
|
|
|
12
12
|
|
|
13
13
|
export const Header = (props) => {
|
|
14
14
|
const { theme } = useContext(AppTheme);
|
|
15
|
-
const { noBorder, centerAlignLogo
|
|
16
|
-
const styles = headerStyles(theme, noBorder, centerAlignLogo
|
|
15
|
+
const { noBorder, centerAlignLogo } = props || {};
|
|
16
|
+
const styles = headerStyles(theme, noBorder, centerAlignLogo);
|
|
17
17
|
const headerStyle = StyleSheet.flatten([styles.header, props.style]);
|
|
18
18
|
const logoComponentStyle = StyleSheet.flatten([
|
|
19
19
|
styles.logoComponentStyle,
|
|
@@ -71,5 +71,4 @@ Header.propTypes = {
|
|
|
71
71
|
logoComponentStyle: PropTypes.object,
|
|
72
72
|
onPress: PropTypes.func,
|
|
73
73
|
noBorder: PropTypes.bool,
|
|
74
|
-
customHeight: PropTypes.number,
|
|
75
74
|
};
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { StyleSheet } from 'react-native';
|
|
2
2
|
|
|
3
|
-
export const headerStyles = (appThemeContext, noBorder, centerAlignLogo
|
|
3
|
+
export const headerStyles = (appThemeContext, noBorder, centerAlignLogo) => {
|
|
4
4
|
const { COLORS, DARK_MODE } = appThemeContext;
|
|
5
5
|
const headerContainerStyles = {
|
|
6
6
|
header: {
|
|
7
|
-
height:
|
|
7
|
+
height: 48,
|
|
8
8
|
backgroundColor: DARK_MODE ? COLORS.MONO6 : COLORS.BRAND_WHITE,
|
|
9
9
|
flexDirection: 'row',
|
|
10
10
|
alignItems: 'center',
|
|
@@ -23,7 +23,7 @@ const removeWidthnHeight = (htmlContent) => {
|
|
|
23
23
|
if (temp[0] === '<iframe') {
|
|
24
24
|
for (let i = 0; i < temp.length; i++) {
|
|
25
25
|
if (
|
|
26
|
-
(temp[i].includes('width') || temp[i].includes('height'))
|
|
26
|
+
(temp[i].includes('width=') || temp[i].includes('height='))
|
|
27
27
|
&& !temp[i].includes('/')
|
|
28
28
|
) {
|
|
29
29
|
continue;
|
|
@@ -40,6 +40,7 @@ const getHTMLContent = (embedJs) => {
|
|
|
40
40
|
const width = useWindowDimensions().width;
|
|
41
41
|
const decodedContent = getDecodedContent(embedJs);
|
|
42
42
|
let htmlContent = replaceDefaultProtocol(decodedContent);
|
|
43
|
+
htmlContent = removeWidthnHeight(htmlContent);
|
|
43
44
|
|
|
44
45
|
const webViewScript = `
|
|
45
46
|
<script type="application/javascript">
|
|
@@ -62,8 +63,22 @@ const getHTMLContent = (embedJs) => {
|
|
|
62
63
|
<head>
|
|
63
64
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
64
65
|
<style>
|
|
65
|
-
|
|
66
|
-
|
|
66
|
+
* {
|
|
67
|
+
margin: 0;
|
|
68
|
+
padding: 0;
|
|
69
|
+
box-sizing: border-box;
|
|
70
|
+
}
|
|
71
|
+
body {
|
|
72
|
+
width: 100%;
|
|
73
|
+
overflow-x: hidden;
|
|
74
|
+
}
|
|
75
|
+
iframe {
|
|
76
|
+
width: 100% !important;
|
|
77
|
+
max-width: ${width - 20}px;
|
|
78
|
+
height: ${Math.round((width - 20) * 9 / 16)}px;
|
|
79
|
+
min-height: 200px;
|
|
80
|
+
display: block;
|
|
81
|
+
margin: 0 auto;
|
|
67
82
|
}
|
|
68
83
|
</style>
|
|
69
84
|
</head>
|
|
@@ -93,29 +108,29 @@ export const JSEmbedElement = (props) => {
|
|
|
93
108
|
setHeight(parseInt(event.nativeEvent.data));
|
|
94
109
|
};
|
|
95
110
|
|
|
96
|
-
// Function to manually extract the base URL from an iframe src
|
|
97
|
-
const extractBaseUrlFromIframe = (iframeHtml) => {
|
|
98
|
-
|
|
99
|
-
|
|
111
|
+
// Function to manually extract the base URL from an iframe src
|
|
112
|
+
const extractBaseUrlFromIframe = (iframeHtml) => {
|
|
113
|
+
const regex = /src="([^"]+)"/; // Regex to extract src URL from iframe
|
|
114
|
+
const match = iframeHtml.match(regex);
|
|
100
115
|
|
|
101
|
-
|
|
102
|
-
|
|
116
|
+
if (match && match[1]) {
|
|
117
|
+
const srcUrl = match[1]; // The full src URL from iframe
|
|
103
118
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
119
|
+
// Manually extract the base URL (protocol + host + pathname)
|
|
120
|
+
const urlPattern = /^(https?:\/\/[^/]+(?:\/[^?]*)?)/;
|
|
121
|
+
const baseUrlMatch = srcUrl.match(urlPattern);
|
|
107
122
|
|
|
108
|
-
|
|
109
|
-
|
|
123
|
+
if (baseUrlMatch) {
|
|
124
|
+
return baseUrlMatch[1]; // Return the base URL
|
|
125
|
+
} else {
|
|
126
|
+
console.error('Invalid URL format.');
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
110
129
|
} else {
|
|
111
|
-
console.error('
|
|
130
|
+
console.error('Iframe src not found.');
|
|
112
131
|
return null;
|
|
113
132
|
}
|
|
114
|
-
}
|
|
115
|
-
console.error('Iframe src not found.');
|
|
116
|
-
return null;
|
|
117
|
-
}
|
|
118
|
-
};
|
|
133
|
+
};
|
|
119
134
|
|
|
120
135
|
const constructSource = () => {
|
|
121
136
|
return {
|
|
@@ -125,12 +140,13 @@ const extractBaseUrlFromIframe = (iframeHtml) => {
|
|
|
125
140
|
};
|
|
126
141
|
|
|
127
142
|
if (height > 0) {
|
|
143
|
+
const calculatedHeight = Math.max(Number(height), Math.round((width - 20) * 9 / 16) + 20);
|
|
128
144
|
return <View testID="embed-js">
|
|
129
145
|
<WebView
|
|
130
146
|
ref={webViewRef}
|
|
131
147
|
style={{
|
|
132
148
|
width,
|
|
133
|
-
height: Math.min(
|
|
149
|
+
height: Math.min(calculatedHeight, screenHeight - 100),
|
|
134
150
|
flex: 0,
|
|
135
151
|
opacity: 0.99,
|
|
136
152
|
}}
|
|
@@ -160,7 +176,7 @@ const extractBaseUrlFromIframe = (iframeHtml) => {
|
|
|
160
176
|
ref={webViewRef}
|
|
161
177
|
style={{
|
|
162
178
|
width,
|
|
163
|
-
height: Number(height),
|
|
179
|
+
height: Math.max(Number(height), Math.round((width - 20) * 9 / 16) + 20),
|
|
164
180
|
flex: 0,
|
|
165
181
|
opacity: 0.99,
|
|
166
182
|
}}
|
|
@@ -204,4 +220,4 @@ JSEmbedElement.propTypes = {
|
|
|
204
220
|
height: PropTypes.number,
|
|
205
221
|
orientation: PropTypes.string,
|
|
206
222
|
}),
|
|
207
|
-
};
|
|
223
|
+
};
|
|
@@ -152,8 +152,7 @@ export const Story = ({
|
|
|
152
152
|
gaTrigerredTTS,
|
|
153
153
|
commentData,
|
|
154
154
|
commentLoader,
|
|
155
|
-
storyLayout
|
|
156
|
-
centerAlignStoryTitle
|
|
155
|
+
storyLayout
|
|
157
156
|
}) => {
|
|
158
157
|
const { theme } = useContext(AppTheme);
|
|
159
158
|
const { COLORS, FONT_SIZE, locale, DARK_MODE,translate, enableComments } = theme;
|
|
@@ -377,7 +376,6 @@ export const Story = ({
|
|
|
377
376
|
onAuthorPress={onAuthorPress}
|
|
378
377
|
onSectionPress={onSectionPress}
|
|
379
378
|
storyLayout={storyLayout}
|
|
380
|
-
centerAlignStoryTitle = {centerAlignStoryTitle}
|
|
381
379
|
/>
|
|
382
380
|
{ storyHasAccess === 'granted' && audioS3Key && (!showPlayer ?
|
|
383
381
|
(<TouchableOpacity onPress={async()=>{
|
|
@@ -65,7 +65,7 @@ const getHeroComponent = (props) => {
|
|
|
65
65
|
};
|
|
66
66
|
|
|
67
67
|
export const StoryHeader = (props) => {
|
|
68
|
-
const { story, firstVideoElement, storyLayout
|
|
68
|
+
const { story, firstVideoElement, storyLayout } = props;
|
|
69
69
|
const sectionData = get(story, ['sections', 0], {});
|
|
70
70
|
const { theme } = useContext(AppTheme);
|
|
71
71
|
|
|
@@ -105,11 +105,10 @@ export const StoryHeader = (props) => {
|
|
|
105
105
|
};
|
|
106
106
|
|
|
107
107
|
const getSectionName = (storyLayout = 'default') => {
|
|
108
|
-
const style = isHeadLinePriorityLayout ? styles.headlinePriority.sectionText : styles.sectionText
|
|
109
|
-
const centerAlignStyle = centerAlignStoryTitle? styles?.centerAlign: ''
|
|
108
|
+
const style = isHeadLinePriorityLayout ? styles.headlinePriority.sectionText : styles.sectionText
|
|
110
109
|
return <TouchableOpacity onPress={navigateToSection}>
|
|
111
110
|
<Text
|
|
112
|
-
style={
|
|
111
|
+
style={style}
|
|
113
112
|
testID={COMP_CONTENT_CONSTANTS.sectionName}
|
|
114
113
|
>
|
|
115
114
|
{sectionData['display-name'] || ''}
|
|
@@ -139,7 +138,7 @@ export const StoryHeader = (props) => {
|
|
|
139
138
|
return (
|
|
140
139
|
<View testID={props.testID}>
|
|
141
140
|
{getSectionName(storyLayout)}
|
|
142
|
-
<StoryTitle title={story.headline} subTitle={story.subheadline} isPremiumStory={isPremiumStory} isHeadLinePriorityLayout={isHeadLinePriorityLayout}
|
|
141
|
+
<StoryTitle title={story.headline} subTitle={story.subheadline} isPremiumStory={isPremiumStory} isHeadLinePriorityLayout={isHeadLinePriorityLayout}/>
|
|
143
142
|
{getHeroComponent(props)}
|
|
144
143
|
{showAttribution(storyLayout)}
|
|
145
144
|
<View style={styles.dateBlock}>
|
|
@@ -166,7 +165,7 @@ export const StoryHeader = (props) => {
|
|
|
166
165
|
{getTimeInFormat(story['published-at'], DATE_FORMAT, locale)}
|
|
167
166
|
</Text>
|
|
168
167
|
</View>
|
|
169
|
-
<StoryTitle title={story.headline} subTitle={story.subheadline} isPremiumStory={isPremiumStory}
|
|
168
|
+
<StoryTitle title={story.headline} subTitle={story.subheadline} isPremiumStory={isPremiumStory}/>
|
|
170
169
|
{getAuthorRow()}
|
|
171
170
|
{reviewTitle && <RatingLayout reviewTitle={reviewTitle} ratingValue={reviewData?.value} ratingLabel={reviewData?.label}/>}
|
|
172
171
|
</View>
|
|
@@ -13,7 +13,7 @@ import { AppTheme } from '../../utils/context';
|
|
|
13
13
|
import { storyTextStyles } from './styles';
|
|
14
14
|
|
|
15
15
|
export const StoryText = (props) => {
|
|
16
|
-
const {navigation} = props;
|
|
16
|
+
const { navigation } = props;
|
|
17
17
|
const { theme, useDeeplinkHandler } = useContext(AppTheme);
|
|
18
18
|
const {
|
|
19
19
|
COLORS,
|
|
@@ -46,14 +46,13 @@ export const StoryText = (props) => {
|
|
|
46
46
|
useDeeplinkHandler(href, navigation)
|
|
47
47
|
}}
|
|
48
48
|
listsPrefixesRenderers={{
|
|
49
|
-
ul: () => <View style={customTagsStyles
|
|
49
|
+
ul: () => <View style={customTagsStyles['ul-bullet']} />,
|
|
50
50
|
ol: (htmlAttribs, children, convertedCSSStyles, passProps) => {
|
|
51
51
|
const { index } = passProps;
|
|
52
|
-
const bulletNumber = htmlAttribs.start ? htmlAttribs.start : index + 1;
|
|
52
|
+
const bulletNumber = htmlAttribs.start ? parseInt(htmlAttribs.start) + index : index + 1;
|
|
53
53
|
return (
|
|
54
|
-
<Text style={customTagsStyles
|
|
55
|
-
{bulletNumber}
|
|
56
|
-
)
|
|
54
|
+
<Text style={customTagsStyles['ol-number']}>
|
|
55
|
+
{bulletNumber})
|
|
57
56
|
</Text>
|
|
58
57
|
);
|
|
59
58
|
},
|
|
@@ -63,6 +62,8 @@ export const StoryText = (props) => {
|
|
|
63
62
|
ins: customTagsStyles.ins,
|
|
64
63
|
p: customTagsStyles.p,
|
|
65
64
|
li: customTagsStyles.li,
|
|
65
|
+
ul: customTagsStyles.ul,
|
|
66
|
+
ol: customTagsStyles.ol,
|
|
66
67
|
a: customTagsStyles.a,
|
|
67
68
|
h2: customTagsStyles.h,
|
|
68
69
|
h3: customTagsStyles.h,
|
|
@@ -7,9 +7,9 @@ import { AppTheme } from '../../utils';
|
|
|
7
7
|
import { COMP_CONTENT_CONSTANTS } from '../../constants/component-constants/content-constants/constants';
|
|
8
8
|
import PremiumIcons from '../../Icons/PremiumIcons/index';
|
|
9
9
|
|
|
10
|
-
export const StoryTitle = ({ title, subTitle, isPremiumStory, isHeadLinePriorityLayout
|
|
10
|
+
export const StoryTitle = ({ title, subTitle, isPremiumStory, isHeadLinePriorityLayout }) => {
|
|
11
11
|
const { theme } = useContext(AppTheme);
|
|
12
|
-
const styles = storyTitleStyles(
|
|
12
|
+
const styles = storyTitleStyles(theme);
|
|
13
13
|
const {
|
|
14
14
|
premiumIcon, COLORS, FONT_SIZE
|
|
15
15
|
} = theme;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { StyleSheet } from 'react-native';
|
|
2
2
|
|
|
3
3
|
export const storyTitleStyles = ({
|
|
4
|
-
COLORS, FONT_SIZE, FONT_FAMILY, lineHeightMultiplier,
|
|
4
|
+
COLORS, FONT_SIZE, FONT_FAMILY, lineHeightMultiplier,
|
|
5
5
|
}) => StyleSheet.create({
|
|
6
6
|
container: {
|
|
7
7
|
padding: 10,
|
|
@@ -12,7 +12,6 @@ export const storyTitleStyles = ({
|
|
|
12
12
|
fontFamily: FONT_FAMILY.primaryBold,
|
|
13
13
|
lineHeight: FONT_SIZE.title * lineHeightMultiplier,
|
|
14
14
|
color: COLORS.BRAND_BLACK,
|
|
15
|
-
textAlign: centerAlignStoryTitle ? 'center' : 'auto',
|
|
16
15
|
},
|
|
17
16
|
subTitleStyle: {
|
|
18
17
|
fontSize: FONT_SIZE.h3,
|
|
@@ -36,10 +36,31 @@ export const TextSummary = (props) => {
|
|
|
36
36
|
onLinkPress={(evt, href) => {
|
|
37
37
|
useDeeplinkHandler(href);
|
|
38
38
|
}}
|
|
39
|
+
listsPrefixesRenderers={{
|
|
40
|
+
ul: () => <View style={customTagsStyles['ul-bullet']} />,
|
|
41
|
+
ol: (htmlAttribs, children, convertedCSSStyles, passProps) => {
|
|
42
|
+
const { index } = passProps;
|
|
43
|
+
const bulletNumber = htmlAttribs.start ? parseInt(htmlAttribs.start) + index : index + 1;
|
|
44
|
+
return (
|
|
45
|
+
<Text style={customTagsStyles['ol-number']}>
|
|
46
|
+
{bulletNumber})
|
|
47
|
+
</Text>
|
|
48
|
+
);
|
|
49
|
+
},
|
|
50
|
+
}}
|
|
39
51
|
tagsStyles={{
|
|
40
52
|
del: customTagsStyles.del,
|
|
41
53
|
ins: customTagsStyles.ins,
|
|
42
54
|
p: customTagsStyles.p,
|
|
55
|
+
li: customTagsStyles.li,
|
|
56
|
+
ul: customTagsStyles.ul,
|
|
57
|
+
ol: customTagsStyles.ol,
|
|
58
|
+
a: customTagsStyles.a,
|
|
59
|
+
h2: customTagsStyles.h,
|
|
60
|
+
h3: customTagsStyles.h,
|
|
61
|
+
h4: customTagsStyles.h,
|
|
62
|
+
h5: customTagsStyles.h,
|
|
63
|
+
h6: customTagsStyles.h,
|
|
43
64
|
}}
|
|
44
65
|
/>
|
|
45
66
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { StyleSheet } from 'react-native';
|
|
2
2
|
|
|
3
3
|
export const titleElementStyles = (appThemeContext) => {
|
|
4
|
-
const { COLORS } = appThemeContext;
|
|
4
|
+
const { COLORS, FONT_FAMILY } = appThemeContext;
|
|
5
5
|
return StyleSheet.create({
|
|
6
6
|
titleText: {
|
|
7
7
|
fontSize: 20,
|
|
@@ -10,6 +10,7 @@ export const titleElementStyles = (appThemeContext) => {
|
|
|
10
10
|
paddingRight: 10,
|
|
11
11
|
paddingTop: 8,
|
|
12
12
|
color: COLORS.BRAND_BLACK,
|
|
13
|
+
fontFamily: FONT_FAMILY.primaryBold,
|
|
13
14
|
},
|
|
14
15
|
});
|
|
15
16
|
};
|
|
@@ -26,25 +26,40 @@ export const customHTMLStyles = () => {
|
|
|
26
26
|
opacity: 0.85,
|
|
27
27
|
},
|
|
28
28
|
li: {
|
|
29
|
-
fontSize: FONT_SIZE.
|
|
30
|
-
lineHeight: FONT_SIZE.
|
|
31
|
-
|
|
29
|
+
fontSize: FONT_SIZE.p1,
|
|
30
|
+
lineHeight: FONT_SIZE.p1 * 1.7,
|
|
31
|
+
marginBottom: -10,
|
|
32
32
|
color: COLORS.BRAND_BLACK,
|
|
33
|
-
opacity: 0.
|
|
33
|
+
opacity: 0.95,
|
|
34
34
|
},
|
|
35
35
|
ul: {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
marginTop: 2,
|
|
37
|
+
marginBottom: 2,
|
|
38
|
+
marginLeft: 10
|
|
39
|
+
},
|
|
40
|
+
'ul-bullet': {
|
|
41
|
+
width: 8,
|
|
42
|
+
height: 8,
|
|
43
|
+
borderRadius: 4,
|
|
41
44
|
backgroundColor: COLORS.BRAND_BLACK,
|
|
45
|
+
marginTop: 20,
|
|
46
|
+
marginRight: 8,
|
|
47
|
+
alignSelf: 'flex-start',
|
|
42
48
|
},
|
|
43
49
|
ol: {
|
|
44
|
-
marginTop:
|
|
45
|
-
|
|
50
|
+
marginTop: 7,
|
|
51
|
+
marginBottom: 7,
|
|
52
|
+
marginLeft: 10
|
|
53
|
+
},
|
|
54
|
+
'ol-number': {
|
|
55
|
+
fontSize: FONT_SIZE.p1,
|
|
56
|
+
lineHeight: FONT_SIZE.p1 * 1.7,
|
|
46
57
|
color: COLORS.BRAND_BLACK,
|
|
47
58
|
opacity: 0.85,
|
|
59
|
+
marginTop: 7,
|
|
60
|
+
marginRight: 8,
|
|
61
|
+
alignSelf: 'flex-start',
|
|
62
|
+
fontWeight: 'bold',
|
|
48
63
|
},
|
|
49
64
|
a: {
|
|
50
65
|
marginTop: 7,
|