Skip to content
15 changes: 14 additions & 1 deletion example/src/components/Embedded/Embedded.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,13 @@ import {
container,
hr,
input,
modalButton,
modalButtons,
modalContent,
modalOverlay,
subtitle,
title,
utilityColors,
utilityColors
} from '../../constants';

const styles = StyleSheet.create({
Expand All @@ -26,6 +30,15 @@ const styles = StyleSheet.create({
inputContainer: {
marginVertical: 10,
},
jsonEditor: {
...input,
fontSize: 12,
height: 220,
},
modalButton,
modalButtons,
modalContent,
modalOverlay,
subtitle: { ...subtitle, textAlign: 'center' },
text: { textAlign: 'center' },
textInput: input,
Expand Down
69 changes: 69 additions & 0 deletions example/src/components/Embedded/Embedded.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import {
Alert,
Modal,
ScrollView,
Text,
TextInput,
Expand All @@ -9,20 +11,28 @@ import { useCallback, useState } from 'react';
import {
Iterable,
type IterableEmbeddedMessage,
type IterableEmbeddedViewConfig,
IterableEmbeddedView,
IterableEmbeddedViewType,
} from '@iterable/react-native-sdk';
import { SafeAreaView } from 'react-native-safe-area-context';

import styles from './Embedded.styles';

const DEFAULT_CONFIG_JSON = `{
}`;

export const Embedded = () => {
const [placementIdsInput, setPlacementIdsInput] = useState<string>('');
const [embeddedMessages, setEmbeddedMessages] = useState<
IterableEmbeddedMessage[]
>([]);
const [selectedViewType, setSelectedViewType] =
useState<IterableEmbeddedViewType>(IterableEmbeddedViewType.Banner);
const [viewConfig, setViewConfig] =
useState<IterableEmbeddedViewConfig | null>(null);
const [configEditorVisible, setConfigEditorVisible] = useState(false);
const [configJson, setConfigJson] = useState(DEFAULT_CONFIG_JSON);

// Parse placement IDs from input
const parsedPlacementIds = placementIdsInput
Expand Down Expand Up @@ -55,6 +65,27 @@ export const Embedded = () => {
});
}, [idsToFetch]);

const openConfigEditor = useCallback(() => {
setConfigJson(
viewConfig ? JSON.stringify(viewConfig, null, 2) : DEFAULT_CONFIG_JSON
);
setConfigEditorVisible(true);
}, [viewConfig]);

const applyConfig = useCallback(() => {
try {
const parsed = JSON.parse(configJson) as IterableEmbeddedViewConfig;
setViewConfig(parsed);
setConfigEditorVisible(false);
} catch {
Alert.alert('Error', 'Invalid JSON');
}
}, [configJson]);

const closeConfigEditor = useCallback(() => {
setConfigEditorVisible(false);
}, []);

return (
<SafeAreaView style={styles.container}>
<Text style={styles.title}>Embedded</Text>
Expand Down Expand Up @@ -142,6 +173,9 @@ export const Embedded = () => {
<TouchableOpacity style={styles.button} onPress={endEmbeddedSession}>
<Text style={styles.buttonText}>End session</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.button} onPress={openConfigEditor}>
<Text style={styles.buttonText}>Set view config</Text>
</TouchableOpacity>
<View style={styles.inputContainer}>
<Text style={styles.text}>Placement IDs (comma-separated):</Text>
<TextInput
Expand All @@ -159,6 +193,40 @@ export const Embedded = () => {
</TouchableOpacity>
</View>
</View>
<Modal
visible={configEditorVisible}
animationType="slide"
transparent
onRequestClose={closeConfigEditor}
>
<View style={styles.modalOverlay}>
<View style={styles.modalContent}>
<TextInput
style={styles.jsonEditor}
value={configJson}
onChangeText={setConfigJson}
multiline
textAlignVertical="top"
placeholder={DEFAULT_CONFIG_JSON}
placeholderTextColor="#999"
/>
<View style={styles.modalButtons}>
<TouchableOpacity
style={[styles.button, styles.modalButton]}
onPress={closeConfigEditor}
>
<Text style={styles.buttonText}>Cancel</Text>
</TouchableOpacity>
<TouchableOpacity
style={[styles.button, styles.modalButton]}
onPress={applyConfig}
>
<Text style={styles.buttonText}>Apply</Text>
</TouchableOpacity>
</View>
</View>
</View>
</Modal>
<View style={styles.hr} />
<ScrollView>
<View style={styles.embeddedSection}>
Expand All @@ -167,6 +235,7 @@ export const Embedded = () => {
key={message.metadata.messageId}
viewType={selectedViewType}
message={message}
config={viewConfig}
/>
))}
</View>
Expand Down
1 change: 1 addition & 0 deletions example/src/constants/styles/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ export * from './colors';
export * from './containers';
export * from './formElements';
export * from './miscElements';
export * from './modal';
export * from './shadows';
export * from './typography';
43 changes: 43 additions & 0 deletions example/src/constants/styles/modal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import type { TextStyle, ViewStyle } from "react-native";
import { colors } from "./colors";

export const modalTitle: TextStyle = {
fontSize: 18,
fontWeight: '600',
marginBottom: 12,
textAlign: 'center',
};

export const modalOverlay: ViewStyle = {
backgroundColor: 'rgba(0,0,0,0.5)',
flex: 1,
justifyContent: 'center',
padding: 20,
};

export const modalContent: ViewStyle = {
backgroundColor: colors.backgroundPrimary,
borderRadius: 12,
maxHeight: '80%',
padding: 16,
};

export const modalButtons: ViewStyle = {
flexDirection: 'row',
gap: 12,
justifyContent: 'flex-end',
};

export const modalButton: ViewStyle = {
flex: 1,
};

export const modalButtonText: TextStyle = {
color: colors.brandCyan,
fontSize: 14,
fontWeight: '600',
};

export const modalButtonTextSelected: TextStyle = {
color: colors.backgroundPrimary,
};
40 changes: 39 additions & 1 deletion src/embedded/components/IterableEmbeddedView.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { useMemo } from 'react';
import { View, Text } from 'react-native';

import { IterableEmbeddedViewType } from '../enums/IterableEmbeddedViewType';

import { IterableEmbeddedBanner } from './IterableEmbeddedBanner';
import { IterableEmbeddedCard } from './IterableEmbeddedCard';
import { IterableEmbeddedNotification } from './IterableEmbeddedNotification';
import type { IterableEmbeddedComponentProps } from '../types/IterableEmbeddedComponentProps';
import { useEmbeddedView } from '../hooks/useEmbeddedView/useEmbeddedView';

/**
* The props for the IterableEmbeddedView component.
Expand Down Expand Up @@ -43,5 +45,41 @@ export const IterableEmbeddedView = ({
}
}, [viewType]);

return Cmp ? <Cmp {...props} /> : null;
const { parsedStyles } = useEmbeddedView(viewType, props);

return Cmp ? (
<View>
<Text>
parsedStyles.backgroundColor: {String(parsedStyles.backgroundColor)}
</Text>
<Text>parsedStyles.borderColor: {String(parsedStyles.borderColor)}</Text>
<Text>parsedStyles.borderWidth: {parsedStyles.borderWidth}</Text>
<Text>
parsedStyles.borderCornerRadius: {parsedStyles.borderCornerRadius}
</Text>
<Text>
parsedStyles.primaryBtnBackgroundColor:{' '}
{String(parsedStyles.primaryBtnBackgroundColor)}
</Text>
<Text>
parsedStyles.primaryBtnTextColor:{' '}
{String(parsedStyles.primaryBtnTextColor)}
</Text>
<Text>
parsedStyles.secondaryBtnBackgroundColor:{' '}
{String(parsedStyles.secondaryBtnBackgroundColor)}
</Text>
<Text>
parsedStyles.secondaryBtnTextColor:{' '}
{String(parsedStyles.secondaryBtnTextColor)}
</Text>
<Text>
parsedStyles.titleTextColor: {String(parsedStyles.titleTextColor)}
</Text>
<Text>
parsedStyles.bodyTextColor: {String(parsedStyles.bodyTextColor)}
</Text>
<Cmp {...props} />
</View>
) : null;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found 2 issues:

1. Function with many returns (count = 5): IterableEmbeddedView [qlty:return-statements]


2. Function with high complexity (count = 5): IterableEmbeddedView [qlty:function-complexity]

};
1 change: 1 addition & 0 deletions src/embedded/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './useEmbeddedView';
85 changes: 85 additions & 0 deletions src/embedded/hooks/useEmbeddedView/embeddedViewDefaults.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
export const embeddedBackgroundColors = {
notification: '#ffffff',
card: '#ffffff',
banner: '#ffffff',
};

export const embeddedBorderColors = {
notification: '#E0DEDF',
card: '#E0DEDF',
banner: '#E0DEDF',
};

export const embeddedPrimaryBtnBackgroundColors = {
notification: '#6A266D',
card: 'transparent',
banner: '#6A266D',
};

export const embeddedPrimaryBtnTextColors = {
notification: '#ffffff',
card: '#79347F',
banner: '#ffffff',
};

export const embeddedSecondaryBtnBackgroundColors = {
notification: 'transparent',
card: 'transparent',
banner: 'transparent',
};

export const embeddedSecondaryBtnTextColors = {
notification: '#79347F',
card: '#79347F',
banner: '#79347F',
};

export const embeddedTitleTextColors = {
notification: '#3D3A3B',
card: '#3D3A3B',
banner: '#3D3A3B',
};

export const embeddedBodyTextColors = {
notification: '#787174',
card: '#787174',
banner: '#787174',
};

export const embeddedBorderRadius = {
notification: 8,
card: 6,
banner: 8,
};

export const embeddedBorderWidth = {
notification: 1,
card: 1,
banner: 1,
};

export const embeddedMediaImageBorderColors = {
notification: '#E0DEDF',
card: '#E0DEDF',
banner: '#E0DEDF',
};

export const embeddedMediaImageBackgroundColors = {
notification: '#F5F4F4',
card: '#F5F4F4',
banner: '#F5F4F4',
};

export const embeddedStyles = {
backgroundColor: embeddedBackgroundColors,
bodyText: embeddedBodyTextColors,
borderColor: embeddedBorderColors,
borderCornerRadius: embeddedBorderRadius,
borderWidth: embeddedBorderWidth,
mediaImageBorder: embeddedMediaImageBorderColors,
primaryBtnBackgroundColor: embeddedPrimaryBtnBackgroundColors,
primaryBtnTextColor: embeddedPrimaryBtnTextColors,
secondaryBtnBackground: embeddedSecondaryBtnBackgroundColors,
secondaryBtnTextColor: embeddedSecondaryBtnTextColors,
titleText: embeddedTitleTextColors,
};
Loading