@moneylion/react-native-offer-carousel 1.3.1 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/commonjs/capabilities/core/src/system/cnfContext/schemas/Brand.js +44 -45
- package/lib/commonjs/capabilities/core/src/system/cnfContext/schemas/Brand.js.map +1 -1
- package/lib/commonjs/components/DynamicOffers/Render/DynamicOffersRender.js +1 -1
- package/lib/commonjs/components/DynamicOffers/Render/DynamicOffersRender.js.map +1 -1
- package/lib/commonjs/components/ErrorBoundary/index.js +34 -0
- package/lib/commonjs/components/ErrorBoundary/index.js.map +1 -0
- package/lib/commonjs/components/Layouts/HeadlineWithDescriptionCard/index.js.map +1 -1
- package/lib/commonjs/components/Modal/AllOffersModal.js +14 -7
- package/lib/commonjs/components/Modal/AllOffersModal.js.map +1 -1
- package/lib/commonjs/components/Modal/OfferDetailsModal.js +13 -6
- package/lib/commonjs/components/Modal/OfferDetailsModal.js.map +1 -1
- package/lib/commonjs/components/MoneyLionOfferCarousel.js +23 -7
- package/lib/commonjs/components/MoneyLionOfferCarousel.js.map +1 -1
- package/lib/commonjs/config/mocks/cnfContext.js +151 -44
- package/lib/commonjs/config/mocks/cnfContext.js.map +1 -1
- package/lib/commonjs/context/ThemeProvider.js +8 -2
- package/lib/commonjs/context/ThemeProvider.js.map +1 -1
- package/lib/commonjs/utils/getThemeColors.js +24 -0
- package/lib/commonjs/utils/getThemeColors.js.map +1 -0
- package/lib/module/capabilities/core/src/system/cnfContext/schemas/Brand.js +44 -45
- package/lib/module/capabilities/core/src/system/cnfContext/schemas/Brand.js.map +1 -1
- package/lib/module/components/DynamicOffers/Render/DynamicOffersRender.js +1 -1
- package/lib/module/components/DynamicOffers/Render/DynamicOffersRender.js.map +1 -1
- package/lib/module/components/ErrorBoundary/index.js +28 -0
- package/lib/module/components/ErrorBoundary/index.js.map +1 -0
- package/lib/module/components/Layouts/HeadlineWithDescriptionCard/index.js.map +1 -1
- package/lib/module/components/Modal/AllOffersModal.js +14 -7
- package/lib/module/components/Modal/AllOffersModal.js.map +1 -1
- package/lib/module/components/Modal/OfferDetailsModal.js +13 -6
- package/lib/module/components/Modal/OfferDetailsModal.js.map +1 -1
- package/lib/module/components/MoneyLionOfferCarousel.js +23 -8
- package/lib/module/components/MoneyLionOfferCarousel.js.map +1 -1
- package/lib/module/config/mocks/cnfContext.js +151 -44
- package/lib/module/config/mocks/cnfContext.js.map +1 -1
- package/lib/module/context/ThemeProvider.js +8 -2
- package/lib/module/context/ThemeProvider.js.map +1 -1
- package/lib/module/utils/getThemeColors.js +17 -0
- package/lib/module/utils/getThemeColors.js.map +1 -0
- package/lib/typescript/src/capabilities/core/src/system/cnfContext/schemas/Brand.d.ts +312 -89
- package/lib/typescript/src/capabilities/core/src/system/cnfContext/schemas/Brand.d.ts.map +1 -1
- package/lib/typescript/src/capabilities/ui/elements/src/components/MarkdownText/components.d.ts +2 -2
- package/lib/typescript/src/capabilities/ui/elements/src/components/MarkdownText/components.d.ts.map +1 -1
- package/lib/typescript/src/components/ErrorBoundary/index.d.ts +20 -0
- package/lib/typescript/src/components/ErrorBoundary/index.d.ts.map +1 -0
- package/lib/typescript/src/components/Layouts/HeadlineWithDescriptionCard/index.d.ts.map +1 -1
- package/lib/typescript/src/components/Modal/AllOffersModal.d.ts.map +1 -1
- package/lib/typescript/src/components/Modal/OfferDetailsModal.d.ts.map +1 -1
- package/lib/typescript/src/components/MoneyLionOfferCarousel.d.ts +8 -5
- package/lib/typescript/src/components/MoneyLionOfferCarousel.d.ts.map +1 -1
- package/lib/typescript/src/config/mocks/cnfContext.d.ts.map +1 -1
- package/lib/typescript/src/context/ThemeProvider.d.ts +3 -0
- package/lib/typescript/src/context/ThemeProvider.d.ts.map +1 -1
- package/lib/typescript/src/utils/getThemeColors.d.ts +8 -0
- package/lib/typescript/src/utils/getThemeColors.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/capabilities/core/src/system/cnfContext/schemas/Brand.ts +51 -46
- package/src/capabilities/ui/elements/src/components/MarkdownText/components.tsx +1 -1
- package/src/components/DynamicOffers/Render/DynamicOffersRender.tsx +2 -2
- package/src/components/ErrorBoundary/index.tsx +40 -0
- package/src/components/Layouts/HeadlineWithDescriptionCard/index.tsx +1 -0
- package/src/components/Modal/AllOffersModal.tsx +19 -5
- package/src/components/Modal/OfferDetailsModal.tsx +12 -5
- package/src/components/MoneyLionOfferCarousel.tsx +49 -13
- package/src/config/mocks/cnfContext.ts +40 -44
- package/src/context/ThemeProvider.tsx +12 -1
- package/src/utils/getThemeColors.ts +29 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ReshapedThemeColors } from "../capabilities/core/src/system/cnfContext/schemas/Brand";
|
|
2
|
+
import type { ThemeColors } from "../context/ThemeProvider";
|
|
3
|
+
/** This util checks for missing theme colors from reshapedThemeColors in the API response
|
|
4
|
+
* and merges them with fallback theme colors.
|
|
5
|
+
* It returns a ThemeColors object with the appropriate colors based on the isDarkTheme flag.
|
|
6
|
+
*/
|
|
7
|
+
export declare const getThemeColors: (reshapedThemeColors: ReshapedThemeColors, isDarkTheme?: boolean) => ThemeColors;
|
|
8
|
+
//# sourceMappingURL=getThemeColors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getThemeColors.d.ts","sourceRoot":"","sources":["../../../../src/utils/getThemeColors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0DAA0D,CAAC;AAEpG,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAE5D;;;GAGG;AACH,eAAO,MAAM,cAAc,wBACL,mBAAmB,gBAC3B,OAAO,KAClB,WAiBF,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,50 +1,55 @@
|
|
|
1
1
|
import { Schema } from "effect";
|
|
2
2
|
|
|
3
|
-
export type
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
3
|
+
export type ReshapedThemeColorObject = Schema.Schema.Type<
|
|
4
|
+
typeof ReshapedThemeColorObject
|
|
5
|
+
>;
|
|
6
|
+
const ReshapedThemeColorObject = Schema.Struct({
|
|
7
|
+
hex: Schema.String,
|
|
8
|
+
hexDark: Schema.optional(Schema.String),
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
export type ReshapedThemeColors = Schema.Schema.Type<
|
|
12
|
+
typeof ReshapedThemeColors
|
|
13
|
+
>;
|
|
14
|
+
const ReshapedThemeColors = Schema.Struct({
|
|
15
|
+
backgroundCritical: ReshapedThemeColorObject,
|
|
16
|
+
backgroundCriticalFaded: ReshapedThemeColorObject,
|
|
17
|
+
backgroundDisabled: ReshapedThemeColorObject,
|
|
18
|
+
backgroundDisabledFaded: ReshapedThemeColorObject,
|
|
19
|
+
backgroundElevationBase: ReshapedThemeColorObject,
|
|
20
|
+
backgroundElevationOverlay: ReshapedThemeColorObject,
|
|
21
|
+
backgroundElevationRaised: ReshapedThemeColorObject,
|
|
22
|
+
backgroundNeutral: ReshapedThemeColorObject,
|
|
23
|
+
backgroundNeutralFaded: ReshapedThemeColorObject,
|
|
24
|
+
backgroundPage: ReshapedThemeColorObject,
|
|
25
|
+
backgroundPageFaded: ReshapedThemeColorObject,
|
|
26
|
+
backgroundPositive: ReshapedThemeColorObject,
|
|
27
|
+
backgroundPositiveFaded: ReshapedThemeColorObject,
|
|
28
|
+
backgroundPrimary: ReshapedThemeColorObject,
|
|
29
|
+
backgroundPrimaryFaded: ReshapedThemeColorObject,
|
|
30
|
+
backgroundWarning: ReshapedThemeColorObject,
|
|
31
|
+
backgroundWarningFaded: ReshapedThemeColorObject,
|
|
32
|
+
black: ReshapedThemeColorObject,
|
|
33
|
+
borderCritical: ReshapedThemeColorObject,
|
|
34
|
+
borderCriticalFaded: ReshapedThemeColorObject,
|
|
35
|
+
borderDisabled: ReshapedThemeColorObject,
|
|
36
|
+
borderNeutral: ReshapedThemeColorObject,
|
|
37
|
+
borderNeutralFaded: ReshapedThemeColorObject,
|
|
38
|
+
borderPositive: ReshapedThemeColorObject,
|
|
39
|
+
borderPositiveFaded: ReshapedThemeColorObject,
|
|
40
|
+
borderPrimary: ReshapedThemeColorObject,
|
|
41
|
+
borderPrimaryFaded: ReshapedThemeColorObject,
|
|
42
|
+
borderWarning: ReshapedThemeColorObject,
|
|
43
|
+
borderWarningFaded: ReshapedThemeColorObject,
|
|
44
|
+
brand: ReshapedThemeColorObject,
|
|
45
|
+
foregroundCritical: ReshapedThemeColorObject,
|
|
46
|
+
foregroundDisabled: ReshapedThemeColorObject,
|
|
47
|
+
foregroundNeutral: ReshapedThemeColorObject,
|
|
48
|
+
foregroundNeutralFaded: ReshapedThemeColorObject,
|
|
49
|
+
foregroundPositive: ReshapedThemeColorObject,
|
|
50
|
+
foregroundPrimary: ReshapedThemeColorObject,
|
|
51
|
+
foregroundWarning: ReshapedThemeColorObject,
|
|
52
|
+
white: ReshapedThemeColorObject,
|
|
48
53
|
});
|
|
49
54
|
|
|
50
55
|
export type Links = Schema.Schema.Type<typeof Links>;
|
|
@@ -120,7 +125,7 @@ const BrandFields = Schema.Struct({
|
|
|
120
125
|
displayName: Schema.String,
|
|
121
126
|
isLicensed: Schema.optional(Schema.Boolean),
|
|
122
127
|
hideLicensedLogo: Schema.optional(Schema.Boolean),
|
|
123
|
-
|
|
128
|
+
reshapedThemeColors: ReshapedThemeColors,
|
|
124
129
|
links: Schema.optional(Links),
|
|
125
130
|
logos: Schema.optional(Logos),
|
|
126
131
|
font: Schema.optional(Font),
|
|
@@ -10,7 +10,7 @@ import Text, {
|
|
|
10
10
|
type TextWeight,
|
|
11
11
|
type Variant,
|
|
12
12
|
} from "../../../../../../components/Text";
|
|
13
|
-
import type { ThemeColors } from "
|
|
13
|
+
import type { ThemeColors } from "../../../../../../context/ThemeProvider";
|
|
14
14
|
|
|
15
15
|
const BoldText = ({ children }: { children: React.ReactNode }) => {
|
|
16
16
|
const processChildren = (_children: React.ReactNode) => {
|
|
@@ -291,13 +291,13 @@ export const DynamicOffersRender = ({
|
|
|
291
291
|
isHorizontalScroll,
|
|
292
292
|
});
|
|
293
293
|
}, [
|
|
294
|
+
offers,
|
|
295
|
+
isHorizontalScroll,
|
|
294
296
|
displayLayout,
|
|
295
297
|
productTypeBuilder,
|
|
296
|
-
offers,
|
|
297
298
|
showProductTypeLabel,
|
|
298
299
|
fallbackTemplate,
|
|
299
300
|
showCardBorder,
|
|
300
|
-
isHorizontalScroll,
|
|
301
301
|
]);
|
|
302
302
|
|
|
303
303
|
// Wrapped offer components with layout measurement
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import React, { Component } from "react";
|
|
2
|
+
import type { CustomError } from "../MoneyLionOfferCarousel";
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
children: React.ReactNode;
|
|
6
|
+
fallbackUI?: React.ReactNode;
|
|
7
|
+
onError: (error: CustomError) => void;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
interface State {
|
|
11
|
+
hasError: boolean;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
class ErrorBoundary extends Component<Props, State> {
|
|
15
|
+
constructor(props: Props) {
|
|
16
|
+
super(props);
|
|
17
|
+
this.state = { hasError: false };
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
static getDerivedStateFromError(_error: Error) {
|
|
21
|
+
return { hasError: true };
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
componentDidCatch(error: Error) {
|
|
25
|
+
this.props.onError({
|
|
26
|
+
message: error.message,
|
|
27
|
+
timestamp: new Date().toISOString(),
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
render() {
|
|
32
|
+
if (this.state.hasError) {
|
|
33
|
+
return this.props.fallbackUI ?? null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return this.props.children;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export default ErrorBoundary;
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
import Text from "../Text";
|
|
15
15
|
import { DynamicOffersContainer } from "../DynamicOffers/DynamicOffersContainer";
|
|
16
16
|
import type { DynamicOfferProps } from "../DynamicOffers/DynamicOffers";
|
|
17
|
+
import { useTheme } from "../../context/ThemeProvider";
|
|
17
18
|
|
|
18
19
|
type AllOffersModalProps = {
|
|
19
20
|
visible: boolean;
|
|
@@ -50,6 +51,8 @@ export const AllOffersModal = ({
|
|
|
50
51
|
onClose,
|
|
51
52
|
config,
|
|
52
53
|
}: AllOffersModalProps) => {
|
|
54
|
+
const { theme } = useTheme();
|
|
55
|
+
|
|
53
56
|
const { brand, title } = config;
|
|
54
57
|
const footerLinks = brand.links;
|
|
55
58
|
|
|
@@ -100,16 +103,28 @@ export const AllOffersModal = ({
|
|
|
100
103
|
visible={visible}
|
|
101
104
|
onRequestClose={onClose}
|
|
102
105
|
>
|
|
103
|
-
<SafeAreaView
|
|
106
|
+
<SafeAreaView
|
|
107
|
+
style={[
|
|
108
|
+
styles.modalContainer,
|
|
109
|
+
{ backgroundColor: theme.backgroundPageFaded },
|
|
110
|
+
]}
|
|
111
|
+
>
|
|
104
112
|
<View style={styles.modalHeader}>
|
|
105
113
|
<TouchableOpacity
|
|
106
114
|
onPress={onClose}
|
|
107
115
|
style={styles.closeXButton}
|
|
108
116
|
hitSlop={{ top: 15, right: 15, bottom: 15, left: 15 }}
|
|
109
117
|
>
|
|
110
|
-
<Text style={styles.closeXText}
|
|
118
|
+
<Text style={styles.closeXText} color={"foregroundNeutral"}>
|
|
119
|
+
✕
|
|
120
|
+
</Text>
|
|
111
121
|
</TouchableOpacity>
|
|
112
|
-
<Text
|
|
122
|
+
<Text
|
|
123
|
+
variant="title-3"
|
|
124
|
+
weight="bold"
|
|
125
|
+
color={"foregroundNeutral"}
|
|
126
|
+
style={styles.headerTitle}
|
|
127
|
+
>
|
|
113
128
|
{title}
|
|
114
129
|
</Text>
|
|
115
130
|
</View>
|
|
@@ -157,7 +172,6 @@ export const AllOffersModal = ({
|
|
|
157
172
|
const styles = StyleSheet.create({
|
|
158
173
|
modalContainer: {
|
|
159
174
|
flex: 1,
|
|
160
|
-
backgroundColor: "#EEEEEE",
|
|
161
175
|
},
|
|
162
176
|
modalHeader: {
|
|
163
177
|
flexDirection: "row",
|
|
@@ -173,11 +187,11 @@ const styles = StyleSheet.create({
|
|
|
173
187
|
},
|
|
174
188
|
closeXText: {
|
|
175
189
|
fontSize: 20,
|
|
176
|
-
color: "#000000",
|
|
177
190
|
},
|
|
178
191
|
headerTitle: {
|
|
179
192
|
textAlign: "center",
|
|
180
193
|
alignSelf: "center",
|
|
194
|
+
paddingHorizontal: 36, // To ensure title doesn't overlap with close button
|
|
181
195
|
},
|
|
182
196
|
contentWrapper: {
|
|
183
197
|
flex: 1,
|
|
@@ -15,6 +15,7 @@ import { Disclaimer } from "./Disclaimer";
|
|
|
15
15
|
import { CallToAction } from "../Common/DynamicOfferCard/CallToAction";
|
|
16
16
|
import Divider from "../Divider";
|
|
17
17
|
import type { BaseOffer } from "../../capabilities/offer-catalog/src";
|
|
18
|
+
import { useTheme } from "../../context/ThemeProvider";
|
|
18
19
|
|
|
19
20
|
type OfferDetailsModalProps = {
|
|
20
21
|
visible: boolean;
|
|
@@ -31,12 +32,16 @@ export const OfferDetailsModal = ({
|
|
|
31
32
|
onClose,
|
|
32
33
|
offerIndex,
|
|
33
34
|
}: OfferDetailsModalProps) => {
|
|
35
|
+
const { theme } = useTheme();
|
|
36
|
+
|
|
34
37
|
const showDescriptionPoints = Boolean(offer?.descriptionPoints?.length);
|
|
35
38
|
|
|
36
39
|
const showDisclaimer = Boolean(offer?.legalLanguage);
|
|
37
40
|
|
|
38
41
|
const showDivider = showDescriptionPoints && showDisclaimer;
|
|
39
42
|
|
|
43
|
+
const backgroundColor = theme.backgroundElevationOverlay;
|
|
44
|
+
|
|
40
45
|
return (
|
|
41
46
|
<Modal
|
|
42
47
|
animationType="slide"
|
|
@@ -45,10 +50,10 @@ export const OfferDetailsModal = ({
|
|
|
45
50
|
onRequestClose={onClose}
|
|
46
51
|
statusBarTranslucent={true}
|
|
47
52
|
>
|
|
48
|
-
<SafeAreaView style={styles.modalContainer}>
|
|
53
|
+
<SafeAreaView style={[styles.modalContainer, { backgroundColor }]}>
|
|
49
54
|
{visible && (
|
|
50
55
|
<StatusBar
|
|
51
|
-
backgroundColor={
|
|
56
|
+
backgroundColor={backgroundColor}
|
|
52
57
|
barStyle={"dark-content"}
|
|
53
58
|
translucent={false}
|
|
54
59
|
/>
|
|
@@ -59,7 +64,11 @@ export const OfferDetailsModal = ({
|
|
|
59
64
|
style={styles.closeXButton}
|
|
60
65
|
hitSlop={{ top: 15, right: 15, bottom: 15, left: 15 }}
|
|
61
66
|
>
|
|
62
|
-
<Text
|
|
67
|
+
<Text
|
|
68
|
+
style={[styles.closeXText, { color: theme.foregroundNeutral }]}
|
|
69
|
+
>
|
|
70
|
+
✕
|
|
71
|
+
</Text>
|
|
63
72
|
</TouchableOpacity>
|
|
64
73
|
</View>
|
|
65
74
|
|
|
@@ -91,7 +100,6 @@ export const OfferDetailsModal = ({
|
|
|
91
100
|
const styles = StyleSheet.create({
|
|
92
101
|
modalContainer: {
|
|
93
102
|
flex: 1,
|
|
94
|
-
backgroundColor: "#ffffff",
|
|
95
103
|
marginTop: Platform.OS === "android" ? StatusBar.currentHeight : 0,
|
|
96
104
|
},
|
|
97
105
|
modalHeader: {
|
|
@@ -111,7 +119,6 @@ const styles = StyleSheet.create({
|
|
|
111
119
|
},
|
|
112
120
|
closeXText: {
|
|
113
121
|
fontSize: 20,
|
|
114
|
-
color: "#000000",
|
|
115
122
|
},
|
|
116
123
|
modalContent: {
|
|
117
124
|
flex: 1,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useEffect, useState } from "react";
|
|
1
|
+
import React, { useEffect, useMemo, useState } from "react";
|
|
2
2
|
import { localCnfContext } from "../config/mocks/cnfContext";
|
|
3
3
|
import { Text } from "react-native";
|
|
4
4
|
import { getPageData } from "../pageData";
|
|
@@ -16,6 +16,15 @@ import {
|
|
|
16
16
|
import { getConfigApiBaseUrl } from "../apiEnvironment";
|
|
17
17
|
import { ConfigurationProvider } from "../context/ConfigurationProvider";
|
|
18
18
|
import type { CnfContext } from "../capabilities/core/src/system/cnfContext/CnfContext";
|
|
19
|
+
import { getThemeColors } from "../utils/getThemeColors";
|
|
20
|
+
import type { ReshapedThemeColors } from "../capabilities/core/src";
|
|
21
|
+
import ErrorBoundary from "./ErrorBoundary";
|
|
22
|
+
|
|
23
|
+
export type CustomError = {
|
|
24
|
+
code?: number;
|
|
25
|
+
message: string;
|
|
26
|
+
timestamp: string;
|
|
27
|
+
};
|
|
19
28
|
|
|
20
29
|
export type MoneyLionOfferCarouselProps = {
|
|
21
30
|
channel: string;
|
|
@@ -34,11 +43,9 @@ export type MoneyLionOfferCarouselProps = {
|
|
|
34
43
|
showDescriptionPoints?: boolean;
|
|
35
44
|
title?: string;
|
|
36
45
|
subtitle?: string;
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
timestamp: string;
|
|
41
|
-
}) => void;
|
|
46
|
+
isDarkTheme?: boolean;
|
|
47
|
+
fallbackUI?: React.ReactNode;
|
|
48
|
+
onError?: (error: CustomError) => void;
|
|
42
49
|
onLoad?: (numOffers: number) => void;
|
|
43
50
|
};
|
|
44
51
|
|
|
@@ -91,8 +98,8 @@ const getConfiguration = async ({
|
|
|
91
98
|
}
|
|
92
99
|
};
|
|
93
100
|
|
|
94
|
-
|
|
95
|
-
props: MoneyLionOfferCarouselProps &
|
|
101
|
+
const InternalMoneyLionOfferCarousel = (
|
|
102
|
+
props: Omit<MoneyLionOfferCarouselProps, "fallbackUI"> &
|
|
96
103
|
Omit<EventHandlerContextType, "rateTableUuid" | "leadUuid">
|
|
97
104
|
) => {
|
|
98
105
|
const {
|
|
@@ -106,6 +113,7 @@ export const MoneyLionOfferCarousel = (
|
|
|
106
113
|
onLoad,
|
|
107
114
|
title,
|
|
108
115
|
subtitle,
|
|
116
|
+
isDarkTheme = false,
|
|
109
117
|
} = props;
|
|
110
118
|
|
|
111
119
|
const {
|
|
@@ -227,6 +235,17 @@ export const MoneyLionOfferCarousel = (
|
|
|
227
235
|
onLoad,
|
|
228
236
|
]);
|
|
229
237
|
|
|
238
|
+
const themeColors = useMemo(
|
|
239
|
+
() =>
|
|
240
|
+
context
|
|
241
|
+
? getThemeColors(
|
|
242
|
+
context.brand.reshapedThemeColors || ({} as ReshapedThemeColors),
|
|
243
|
+
isDarkTheme
|
|
244
|
+
)
|
|
245
|
+
: getThemeColors({} as ReshapedThemeColors, isDarkTheme),
|
|
246
|
+
[context, isDarkTheme]
|
|
247
|
+
);
|
|
248
|
+
|
|
230
249
|
if (isLoading) {
|
|
231
250
|
return <DynamicOfferSkeleton displayLayout={"fixed"} />;
|
|
232
251
|
}
|
|
@@ -264,12 +283,12 @@ export const MoneyLionOfferCarousel = (
|
|
|
264
283
|
brand: context.brand,
|
|
265
284
|
};
|
|
266
285
|
|
|
267
|
-
const themeColor = {
|
|
268
|
-
...context.brand.themeColors,
|
|
269
|
-
};
|
|
270
|
-
|
|
271
286
|
return (
|
|
272
|
-
<ThemeProvider
|
|
287
|
+
<ThemeProvider
|
|
288
|
+
themeColors={themeColors}
|
|
289
|
+
fontFamily={fontFamily}
|
|
290
|
+
isDarkTheme={isDarkTheme}
|
|
291
|
+
>
|
|
273
292
|
<EventHandlerProvider
|
|
274
293
|
eventHandlers={{
|
|
275
294
|
...eventHandlers,
|
|
@@ -284,3 +303,20 @@ export const MoneyLionOfferCarousel = (
|
|
|
284
303
|
</ThemeProvider>
|
|
285
304
|
);
|
|
286
305
|
};
|
|
306
|
+
|
|
307
|
+
export const MoneyLionOfferCarousel = (
|
|
308
|
+
props: MoneyLionOfferCarouselProps &
|
|
309
|
+
Omit<EventHandlerContextType, "rateTableUuid" | "leadUuid">
|
|
310
|
+
) => {
|
|
311
|
+
const { fallbackUI, onError } = props;
|
|
312
|
+
|
|
313
|
+
const handleError = (err: CustomError): void => {
|
|
314
|
+
onError?.(err);
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
return (
|
|
318
|
+
<ErrorBoundary fallbackUI={fallbackUI} onError={handleError}>
|
|
319
|
+
<InternalMoneyLionOfferCarousel {...props} />
|
|
320
|
+
</ErrorBoundary>
|
|
321
|
+
);
|
|
322
|
+
};
|
|
@@ -36,50 +36,46 @@ export const localCnfContext: CnfContext = {
|
|
|
36
36
|
icon: null,
|
|
37
37
|
},
|
|
38
38
|
type: "business",
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
backgroundDisabled: "#
|
|
44
|
-
backgroundDisabledFaded: "#
|
|
45
|
-
backgroundElevationBase: "#ffffff",
|
|
46
|
-
backgroundElevationOverlay: "#ffffff",
|
|
47
|
-
backgroundElevationRaised: "#ffffff",
|
|
48
|
-
backgroundNeutral: "#e2e2e2",
|
|
49
|
-
backgroundNeutralFaded: "#
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
foregroundPositive: "#007362",
|
|
80
|
-
foregroundPrimary: "#007362",
|
|
81
|
-
foregroundWarning: "#7b6305",
|
|
82
|
-
white: "#ffffff",
|
|
39
|
+
// reshapedThemeColors is being used as fallback in the getThemeColors util
|
|
40
|
+
reshapedThemeColors: {
|
|
41
|
+
backgroundCritical: { hex: "#ff7200", hexDark: "#ff7200" },
|
|
42
|
+
backgroundCriticalFaded: { hex: "#fff2ec", hexDark: "#361e11" },
|
|
43
|
+
backgroundDisabled: { hex: "#eeeeed", hexDark: "#252523" },
|
|
44
|
+
backgroundDisabledFaded: { hex: "#f7f6f6", hexDark: "#1c1b19" },
|
|
45
|
+
backgroundElevationBase: { hex: "#ffffff", hexDark: "#171615" },
|
|
46
|
+
backgroundElevationOverlay: { hex: "#ffffff", hexDark: "#1e1e1c" },
|
|
47
|
+
backgroundElevationRaised: { hex: "#ffffff", hexDark: "#191917" },
|
|
48
|
+
backgroundNeutral: { hex: "#e2e2e2", hexDark: "#3f3c35" },
|
|
49
|
+
backgroundNeutralFaded: { hex: "#f4f4f4", hexDark: "#24221e" },
|
|
50
|
+
backgroundPage: { hex: "#ffffff", hexDark: "#0e0e0e" },
|
|
51
|
+
backgroundPageFaded: { hex: "#fbfbfb", hexDark: "#141413" },
|
|
52
|
+
backgroundPositive: { hex: "#00e5c4", hexDark: "#00e5c4" },
|
|
53
|
+
backgroundPositiveFaded: { hex: "#ebfff9", hexDark: "#122a24" },
|
|
54
|
+
backgroundPrimary: { hex: "#00e5c4", hexDark: "#00e5c4" },
|
|
55
|
+
backgroundPrimaryFaded: { hex: "#ebfff9", hexDark: "#122a24" },
|
|
56
|
+
backgroundWarning: { hex: "#facc15", hexDark: "#facc15" },
|
|
57
|
+
backgroundWarningFaded: { hex: "#fff6dd", hexDark: "#2b2410" },
|
|
58
|
+
black: { hex: "#000000" },
|
|
59
|
+
borderCritical: { hex: "#aa4a00", hexDark: "#f4b89b" },
|
|
60
|
+
borderCriticalFaded: { hex: "#f3dcd0", hexDark: "#553220" },
|
|
61
|
+
borderDisabled: { hex: "#e3e2e0", hexDark: "#282725" },
|
|
62
|
+
borderNeutral: { hex: "#0000001f", hexDark: "#ffffff24" },
|
|
63
|
+
borderNeutralFaded: { hex: "#00000014", hexDark: "#ffffff14" },
|
|
64
|
+
borderPositive: { hex: "#007c6a", hexDark: "#bbf7e7" },
|
|
65
|
+
borderPositiveFaded: { hex: "#cfede5", hexDark: "#21443c" },
|
|
66
|
+
borderPrimary: { hex: "#007c6a", hexDark: "#bbf7e7" },
|
|
67
|
+
borderPrimaryFaded: { hex: "#cfede5", hexDark: "#21443c" },
|
|
68
|
+
borderWarning: { hex: "#816802", hexDark: "#fbf3db" },
|
|
69
|
+
borderWarningFaded: { hex: "#ece2c4", hexDark: "#453c1e" },
|
|
70
|
+
brand: { hex: "#00e5c4" },
|
|
71
|
+
foregroundCritical: { hex: "#aa4a00", hexDark: "#f4b89b" },
|
|
72
|
+
foregroundDisabled: { hex: "#cdccc9", hexDark: "#4c4a47" },
|
|
73
|
+
foregroundNeutral: { hex: "#2e2e2e", hexDark: "#f4f4f4" },
|
|
74
|
+
foregroundNeutralFaded: { hex: "#6a6a6a", hexDark: "#c9c9c9" },
|
|
75
|
+
foregroundPositive: { hex: "#007c6a", hexDark: "#bbf7e7" },
|
|
76
|
+
foregroundPrimary: { hex: "#007c6a", hexDark: "#bbf7e7" },
|
|
77
|
+
foregroundWarning: { hex: "#816802", hexDark: "#fbf3db" },
|
|
78
|
+
white: { hex: "#ffffff" },
|
|
83
79
|
},
|
|
84
80
|
isLicensed: true,
|
|
85
81
|
allowedMarks: { logo: true, name: true },
|
|
@@ -68,8 +68,10 @@ const defaultFontFamily: FontFamily = {
|
|
|
68
68
|
interface ThemeContextType {
|
|
69
69
|
theme: ThemeColors;
|
|
70
70
|
fontFamily: FontFamily;
|
|
71
|
+
isDarkTheme: boolean;
|
|
71
72
|
updateTheme: (newTheme: Partial<ThemeColors>) => void;
|
|
72
73
|
updateFontFamily: (newFontFamily: Partial<FontFamily>) => void;
|
|
74
|
+
setIsDarkTheme: (isDark: boolean) => void;
|
|
73
75
|
}
|
|
74
76
|
|
|
75
77
|
export const ThemeContext = createContext<ThemeContextType | null>(null);
|
|
@@ -85,12 +87,14 @@ export const useTheme = () => {
|
|
|
85
87
|
interface ThemeProviderProps {
|
|
86
88
|
themeColors?: ThemeColors;
|
|
87
89
|
fontFamily?: Partial<FontFamily>;
|
|
90
|
+
isDarkTheme?: boolean;
|
|
88
91
|
children: ReactNode;
|
|
89
92
|
}
|
|
90
93
|
|
|
91
94
|
export const ThemeProvider: FC<ThemeProviderProps> = ({
|
|
92
|
-
themeColors = {} as ThemeColors,
|
|
95
|
+
themeColors = {} as ThemeColors,
|
|
93
96
|
fontFamily = {},
|
|
97
|
+
isDarkTheme = false,
|
|
94
98
|
children,
|
|
95
99
|
}) => {
|
|
96
100
|
const [theme, setTheme] = useState<ThemeColors>(themeColors);
|
|
@@ -98,6 +102,7 @@ export const ThemeProvider: FC<ThemeProviderProps> = ({
|
|
|
98
102
|
...defaultFontFamily,
|
|
99
103
|
...fontFamily,
|
|
100
104
|
});
|
|
105
|
+
const [darkTheme, setDarkTheme] = useState<boolean>(isDarkTheme);
|
|
101
106
|
|
|
102
107
|
const updateTheme = (newTheme: Partial<ThemeColors>) => {
|
|
103
108
|
setTheme((prevTheme) => ({
|
|
@@ -113,11 +118,17 @@ export const ThemeProvider: FC<ThemeProviderProps> = ({
|
|
|
113
118
|
}));
|
|
114
119
|
};
|
|
115
120
|
|
|
121
|
+
const setIsDarkTheme = (isDark: boolean) => {
|
|
122
|
+
setDarkTheme(isDark);
|
|
123
|
+
};
|
|
124
|
+
|
|
116
125
|
const contextValue = {
|
|
117
126
|
theme,
|
|
118
127
|
fontFamily: fonts,
|
|
128
|
+
isDarkTheme: darkTheme,
|
|
119
129
|
updateTheme,
|
|
120
130
|
updateFontFamily,
|
|
131
|
+
setIsDarkTheme,
|
|
121
132
|
};
|
|
122
133
|
|
|
123
134
|
return (
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { ReshapedThemeColors } from "../capabilities/core/src/system/cnfContext/schemas/Brand";
|
|
2
|
+
import { localCnfContext } from "../config/mocks/cnfContext";
|
|
3
|
+
import type { ThemeColors } from "../context/ThemeProvider";
|
|
4
|
+
|
|
5
|
+
/** This util checks for missing theme colors from reshapedThemeColors in the API response
|
|
6
|
+
* and merges them with fallback theme colors.
|
|
7
|
+
* It returns a ThemeColors object with the appropriate colors based on the isDarkTheme flag.
|
|
8
|
+
*/
|
|
9
|
+
export const getThemeColors = (
|
|
10
|
+
reshapedThemeColors: ReshapedThemeColors,
|
|
11
|
+
isDarkTheme: boolean = false
|
|
12
|
+
): ThemeColors => {
|
|
13
|
+
const defaultThemeColors = localCnfContext.brand.reshapedThemeColors;
|
|
14
|
+
|
|
15
|
+
const themeColors = Object.keys(defaultThemeColors).reduce((acc, key) => {
|
|
16
|
+
const reshapedColor = reshapedThemeColors[key as keyof ReshapedThemeColors];
|
|
17
|
+
const defaultColor = defaultThemeColors[key as keyof ReshapedThemeColors];
|
|
18
|
+
|
|
19
|
+
const themeColor = reshapedColor ?? defaultColor;
|
|
20
|
+
|
|
21
|
+
acc[key as keyof ThemeColors] = isDarkTheme
|
|
22
|
+
? (themeColor.hexDark ?? themeColor.hex)
|
|
23
|
+
: themeColor.hex;
|
|
24
|
+
|
|
25
|
+
return acc;
|
|
26
|
+
}, {} as ThemeColors);
|
|
27
|
+
|
|
28
|
+
return themeColors;
|
|
29
|
+
};
|