From 4ae5ee3893ff514bb4f05273e05f6f9c066bac71 Mon Sep 17 00:00:00 2001 From: Julia Kartasheva Date: Thu, 2 Oct 2025 10:18:46 -0700 Subject: [PATCH 01/12] adding content card container ui component --- .../app/ContentCardsView.tsx | 120 +++++++----------- .../ContentCardContainer.tsx | 120 ++++++++++++++++-- .../EmptyStateContainer.tsx | 38 ++++++ .../ui/components/UnreadIcon/UnreadIcon.tsx | 6 +- .../src/ui/hooks/useContentContainer.ts | 10 ++ 5 files changed, 205 insertions(+), 89 deletions(-) create mode 100644 packages/messaging/src/ui/components/EmptyStateContainer/EmptyStateContainer.tsx diff --git a/apps/AEPSampleAppNewArchEnabled/app/ContentCardsView.tsx b/apps/AEPSampleAppNewArchEnabled/app/ContentCardsView.tsx index 96d7308c..cc343b0f 100644 --- a/apps/AEPSampleAppNewArchEnabled/app/ContentCardsView.tsx +++ b/apps/AEPSampleAppNewArchEnabled/app/ContentCardsView.tsx @@ -13,8 +13,8 @@ governing permissions and limitations under the License. import { MobileCore } from '@adobe/react-native-aepcore'; import { ContentCardView, - ThemeProvider, - useContentCardUI + ContentCardContainer, + ThemeProvider } from '@adobe/react-native-aepmessaging'; import React, { memo, useCallback, useEffect, useState } from 'react'; import { @@ -261,7 +261,6 @@ const ContentCardsView = () => { Platform.OS === 'android' ? 'rn/android/remote_image' : 'rn/ios/remote_image'; - const { content, isLoading, refetch } = useContentCardUI(surface); const items = ITEMS_BY_VIEW[selectedView]; @@ -271,87 +270,58 @@ const ContentCardsView = () => { MobileCore.trackAction('small_image'); }, []); + if (selectedView === 'Remote') { + return ( + <> + {}} + selectedView={selectedView} + setSelectedView={setSelectedView} + /> + null} + /> + + ); + } + return ( - selectedView !== 'Remote' ? item.key : item.id - } + data={items || []} + keyExtractor={(item: any) => item.key} renderItem={({ item }: any) => { - if (selectedView !== 'Remote') { - const node = ( - - ); - return ( - - - {item.customThemes ? ( - - {node} - - ) : ( - node - )} - - ); - } - return ; + const node = ( + + ); + return ( + + + {item.customThemes ? ( + + {node} + + ) : ( + node + )} + + ); }} ListHeaderComponent={ - {}} selectedView={selectedView} setSelectedView={setSelectedView} /> } - ListEmptyComponent={() => - selectedView === 'Remote' && ( - - - No Content Cards Available - - - Content cards will appear here when they are configured in Adobe - Journey Optimizer for surface: "rn/ios/remote_image" - - - Try tracking an action above to refresh content cards. - - - ) - } contentContainerStyle={styles.listContent} /> ); diff --git a/packages/messaging/src/ui/components/ContentCardContainer/ContentCardContainer.tsx b/packages/messaging/src/ui/components/ContentCardContainer/ContentCardContainer.tsx index 495fbe09..f46ecfa3 100644 --- a/packages/messaging/src/ui/components/ContentCardContainer/ContentCardContainer.tsx +++ b/packages/messaging/src/ui/components/ContentCardContainer/ContentCardContainer.tsx @@ -1,18 +1,27 @@ +import { useCallback } from "react"; import { ActivityIndicator, FlatList, FlatListProps, ListRenderItem, StyleSheet, + Platform, + DynamicColorIOS, + Text, + useColorScheme, + View, } from "react-native"; +import { useContentCardUI, useContentContainer } from "../../hooks"; import ContentCardContainerProvider, { ContainerSettings, } from "../../providers/ContentCardContainerProvider"; -import { ContentCardView } from "../ContentCardView/ContentCardView"; import { ContentTemplate } from "../../types/Templates"; -import { useCallback } from "react"; -import { useContentCardUI, useContentContainer } from "../../hooks"; +import { ContentCardView } from "../ContentCardView/ContentCardView"; +import EmptyStateContainer from "../EmptyStateContainer/EmptyStateContainer"; +import Pagination from "../Pagination/Pagination"; +import UnreadIcon from "../UnreadIcon/UnreadIcon"; +// Public props for the container. Extends FlatList props but manages data internally. export interface ContentCardContainerProps extends FlatListProps { LoadingComponent?: React.ReactNode; ErrorComponent?: React.ReactNode; @@ -20,7 +29,8 @@ export interface ContentCardContainerProps extends FlatListProps { surface: string; } -function ContentCardContainerInner({ +// Core renderer: fetches content for a surface, derives layout, and renders a list of cards +function ContentCardContainerInner({ contentContainerStyle, LoadingComponent = , ErrorComponent = null, @@ -32,11 +42,73 @@ function ContentCardContainerInner({ }: ContentCardContainerProps & { settings: ContainerSettings; }): React.ReactElement { + // Pull content cards for the given surface const { content, error, isLoading } = useContentCardUI(surface); + const scheme = useColorScheme(); + const headingColor = Platform.OS === 'ios' + ? DynamicColorIOS({ light: '#000000', dark: '#FFFFFF' }) + : (scheme === 'dark' ? '#FFFFFF' : '#000000'); + // Normalize/alias frequently used settings + const { content: contentSettings, templateType, showPagination } = settings; + const { heading, layout, capacity, emptyStateSettings, unread_indicator, isUnreadEnabled } = contentSettings; + + // Derived flags used across renders + const isHorizontal = layout?.orientation === 'horizontal'; + const showUnread = Boolean( + isUnreadEnabled && (templateType === 'inbox' || templateType === 'custom') + ); + const unreadIcon = unread_indicator?.unread_icon; + const unreadBg = unread_indicator?.unread_bg?.clr; + const bg = scheme === 'dark' ? unreadBg?.dark : unreadBg?.light; + + // Stable item renderer: maps template -> variant, builds style overrides, overlays unread icon const renderItem: ListRenderItem = useCallback(({ item }) => { - return ; - }, []); + const template = item.type; + let key: 'smallImageStyle' | 'largeImageStyle' | 'imageOnlyStyle'; + switch (template) { + case 'SmallImage': + key = 'smallImageStyle'; + break; + case 'LargeImage': + key = 'largeImageStyle'; + break; + default: + key = 'imageOnlyStyle'; + break; + } + + // Base override: unread background color + let styleOverrides: any = showUnread + ? { [key]: { card: { backgroundColor: bg } } } + : undefined; + + // LargeImage + horizontal: cap image height and ensure min content height + if (isHorizontal && template === 'LargeImage') { + styleOverrides = { + [key]: { + ...styleOverrides?.[key], + image: styles.imageHeight, + imageContainer: styles.imageHeight, + contentContainer: styles.contentContainer, + }, + } as any; + } + + return ( + + + { + showUnread + ? + : null + } + + ); + }, [isHorizontal, showUnread, bg, unreadIcon]); if (isLoading) { return LoadingComponent as React.ReactElement; @@ -52,18 +124,28 @@ function ContentCardContainerInner({ return ( + {showPagination ? : null} + {heading.content} ( + isHorizontal ? : + )} + ListEmptyComponent={ + templateType === 'inbox' || templateType === 'custom' + ? + : null + } + contentContainerStyle={contentContainerStyle} + horizontal={isHorizontal} renderItem={renderItem} /> ); } -export function ContentCardContainer({ +export function ContentCardContainer({ LoadingComponent = , ErrorComponent = null, FallbackComponent = null, @@ -96,6 +178,22 @@ export function ContentCardContainer({ const styles = StyleSheet.create({ contentContainer: { - flex: 1, + minHeight: 140, + }, + imageHeight: { + height: 180 + }, + cardWidth: { + width: 380 + }, + heading: { + fontWeight: '600', + fontSize: 18, + lineHeight: 28, + textAlign: 'center', + marginBottom: 16, + color: '#000000', }, + horizontalSeparator: { width: 12 }, + verticalSeparator: { height: 12 }, }); diff --git a/packages/messaging/src/ui/components/EmptyStateContainer/EmptyStateContainer.tsx b/packages/messaging/src/ui/components/EmptyStateContainer/EmptyStateContainer.tsx new file mode 100644 index 00000000..c38524ad --- /dev/null +++ b/packages/messaging/src/ui/components/EmptyStateContainer/EmptyStateContainer.tsx @@ -0,0 +1,38 @@ +import { Text,Image, useColorScheme } from "react-native"; +import { ContainerSettings } from "../../providers/ContentCardContainerProvider"; +import { StyleSheet } from "react-native"; + +// Renders a configured empty state (optional image + message) +function EmptyStateContainer({ emptyStateSettings }: { emptyStateSettings: ContainerSettings['content']['emptyStateSettings'] }) { + const scheme = useColorScheme(); + const img = emptyStateSettings?.image; + const uri = (scheme === 'dark' && img?.darkUrl) ? img.darkUrl : img?.url; + + return ( + <> + {uri ? ( + + + + ) : null} + {emptyStateSettings?.message?.content ? ( + + {emptyStateSettings.message.content} + + ) : null} + + ); + } +export default EmptyStateContainer; + +const styles = StyleSheet.create({ + emptyStateImageContainer: { + marginBottom: 16, + textAlign: "center", + }, + emptyStateMessageContainer: { + textAlign: "center", + color: "#888" + } +}); + \ No newline at end of file diff --git a/packages/messaging/src/ui/components/UnreadIcon/UnreadIcon.tsx b/packages/messaging/src/ui/components/UnreadIcon/UnreadIcon.tsx index f24e902e..9cf81284 100644 --- a/packages/messaging/src/ui/components/UnreadIcon/UnreadIcon.tsx +++ b/packages/messaging/src/ui/components/UnreadIcon/UnreadIcon.tsx @@ -1,9 +1,9 @@ -import { Text, View } from "react-native"; + import { Text, View } from "react-native"; -function UnreadIcon() { + function UnreadIcon({ placement, image }: { placement: string|undefined, image: { url: string; darkUrl?: string | undefined; } | undefined }) { return ( - UnreadIcon + UnreadIcon: {placement} {image?.darkUrl} {image?.url} ); } diff --git a/packages/messaging/src/ui/hooks/useContentContainer.ts b/packages/messaging/src/ui/hooks/useContentContainer.ts index a19c6aea..fb5f1082 100644 --- a/packages/messaging/src/ui/hooks/useContentContainer.ts +++ b/packages/messaging/src/ui/hooks/useContentContainer.ts @@ -12,6 +12,16 @@ export function useContentContainer(surface: string) { setIsLoading(true); const settings = await Messaging.getContentCardContainer(surface); setSettings(settings); + console.log('--------------------------------'); + console.log('--------------------------------'); + console.log('--------------------------------'); + console.log( + '[ContentCardContainer] settings\n' + + JSON.stringify({ surface, settings }, null, 2) + ); + console.log('--------------------------------'); + console.log('--------------------------------'); + console.log('--------------------------------'); setIsLoading(false); } catch (error) { setError(error); From e0df378badcc00580f64fd5f1cc5c7d42dc4d88f Mon Sep 17 00:00:00 2001 From: Julia Kartasheva Date: Thu, 2 Oct 2025 10:27:23 -0700 Subject: [PATCH 02/12] removing console logs --- packages/messaging/src/ui/hooks/useContentContainer.ts | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/packages/messaging/src/ui/hooks/useContentContainer.ts b/packages/messaging/src/ui/hooks/useContentContainer.ts index fb5f1082..a19c6aea 100644 --- a/packages/messaging/src/ui/hooks/useContentContainer.ts +++ b/packages/messaging/src/ui/hooks/useContentContainer.ts @@ -12,16 +12,6 @@ export function useContentContainer(surface: string) { setIsLoading(true); const settings = await Messaging.getContentCardContainer(surface); setSettings(settings); - console.log('--------------------------------'); - console.log('--------------------------------'); - console.log('--------------------------------'); - console.log( - '[ContentCardContainer] settings\n' + - JSON.stringify({ surface, settings }, null, 2) - ); - console.log('--------------------------------'); - console.log('--------------------------------'); - console.log('--------------------------------'); setIsLoading(false); } catch (error) { setError(error); From 98b3a4f24dc49dd80bfee01953b97f3877cdf34d Mon Sep 17 00:00:00 2001 From: Julia Kartasheva Date: Fri, 3 Oct 2025 16:13:53 -0700 Subject: [PATCH 03/12] removing templateType & capacity logic, fixing up styling --- packages/messaging/src/Messaging.ts | 8 +- .../ContentCardContainer.tsx | 74 ++++++++++--------- .../ContentCardView/ContentCardView.tsx | 1 + .../ui/components/UnreadIcon/UnreadIcon.tsx | 2 +- 4 files changed, 47 insertions(+), 38 deletions(-) diff --git a/packages/messaging/src/Messaging.ts b/packages/messaging/src/Messaging.ts index dff61945..dcf5559d 100644 --- a/packages/messaging/src/Messaging.ts +++ b/packages/messaging/src/Messaging.ts @@ -296,19 +296,19 @@ class Messaging { unread_indicator: { unread_bg: { clr: { - light: "#000000", - dark: "#000000", + light: "#FFF3E0", + dark: "#2D1B0E", }, }, unread_icon: { placement: "topright", image: { - url: "https://www.adobe.com", + url: "https://icons.veryicon.com/png/o/leisure/crisp-app-icon-library-v3/notification-5.png", darkUrl: "https://www.adobe.com", }, }, }, - isUnreadEnabled: false, + isUnreadEnabled: true, }, showPagination: false, }; diff --git a/packages/messaging/src/ui/components/ContentCardContainer/ContentCardContainer.tsx b/packages/messaging/src/ui/components/ContentCardContainer/ContentCardContainer.tsx index f46ecfa3..b0dec4f1 100644 --- a/packages/messaging/src/ui/components/ContentCardContainer/ContentCardContainer.tsx +++ b/packages/messaging/src/ui/components/ContentCardContainer/ContentCardContainer.tsx @@ -50,14 +50,11 @@ function ContentCardContainerInner({ : (scheme === 'dark' ? '#FFFFFF' : '#000000'); // Normalize/alias frequently used settings - const { content: contentSettings, templateType, showPagination } = settings; - const { heading, layout, capacity, emptyStateSettings, unread_indicator, isUnreadEnabled } = contentSettings; + const { content: contentSettings, showPagination } = settings; + const { heading, layout, emptyStateSettings, unread_indicator, isUnreadEnabled } = contentSettings; // Derived flags used across renders const isHorizontal = layout?.orientation === 'horizontal'; - const showUnread = Boolean( - isUnreadEnabled && (templateType === 'inbox' || templateType === 'custom') - ); const unreadIcon = unread_indicator?.unread_icon; const unreadBg = unread_indicator?.unread_bg?.clr; const bg = scheme === 'dark' ? unreadBg?.dark : unreadBg?.light; @@ -78,37 +75,38 @@ function ContentCardContainerInner({ break; } - // Base override: unread background color - let styleOverrides: any = showUnread - ? { [key]: { card: { backgroundColor: bg } } } - : undefined; + // Single merged overrides object (preserves LargeImage behavior) + const cardBase = { + ...(isHorizontal ? { alignSelf: 'center', width: '100%' } : null), + ...(isUnreadEnabled && bg ? { backgroundColor: bg } : null) + } as any; - // LargeImage + horizontal: cap image height and ensure min content height - if (isHorizontal && template === 'LargeImage') { - styleOverrides = { - [key]: { - ...styleOverrides?.[key], + const largeImageExtras = isHorizontal && template === 'LargeImage' + ? { image: styles.imageHeight, - imageContainer: styles.imageHeight, + imageContainer: [ + styles.imageHeight, + isUnreadEnabled && bg ? { backgroundColor: bg } : null + ], contentContainer: styles.contentContainer, - }, - } as any; - } + card: isUnreadEnabled && bg ? { backgroundColor: bg } : null + } + : null; + + const styleOverrides = { + [key]: { + card: cardBase, + ...(largeImageExtras || {}) + } + } as any; return ( - - - { - showUnread - ? - : null - } + + + ); - }, [isHorizontal, showUnread, bg, unreadIcon]); + }, [isHorizontal, isUnreadEnabled, bg, unreadIcon]); if (isLoading) { return LoadingComponent as React.ReactElement; @@ -128,16 +126,19 @@ function ContentCardContainerInner({ {heading.content} ( isHorizontal ? : )} ListEmptyComponent={ - templateType === 'inbox' || templateType === 'custom' + settings.content.emptyStateSettings ? : null } - contentContainerStyle={contentContainerStyle} + contentContainerStyle={[ + contentContainerStyle, + isHorizontal && styles.listContent + ]} horizontal={isHorizontal} renderItem={renderItem} /> @@ -184,7 +185,9 @@ const styles = StyleSheet.create({ height: 180 }, cardWidth: { - width: 380 + width: 380, + flexDirection: 'column', + alignItems: 'center' }, heading: { fontWeight: '600', @@ -196,4 +199,9 @@ const styles = StyleSheet.create({ }, horizontalSeparator: { width: 12 }, verticalSeparator: { height: 12 }, + listContent: { + alignItems: 'center', + paddingLeft: 10, + paddingRight: 10 + }, }); diff --git a/packages/messaging/src/ui/components/ContentCardView/ContentCardView.tsx b/packages/messaging/src/ui/components/ContentCardView/ContentCardView.tsx index 34636f02..12536fc1 100644 --- a/packages/messaging/src/ui/components/ContentCardView/ContentCardView.tsx +++ b/packages/messaging/src/ui/components/ContentCardView/ContentCardView.tsx @@ -333,6 +333,7 @@ const smallImageStyles = StyleSheet.create({ flexDirection: 'row', gap: 8, maxWidth: '100%', + width: '100%', alignItems: 'center' }, container: { diff --git a/packages/messaging/src/ui/components/UnreadIcon/UnreadIcon.tsx b/packages/messaging/src/ui/components/UnreadIcon/UnreadIcon.tsx index 9cf81284..70bbeb3b 100644 --- a/packages/messaging/src/ui/components/UnreadIcon/UnreadIcon.tsx +++ b/packages/messaging/src/ui/components/UnreadIcon/UnreadIcon.tsx @@ -3,7 +3,7 @@ function UnreadIcon({ placement, image }: { placement: string|undefined, image: { url: string; darkUrl?: string | undefined; } | undefined }) { return ( - UnreadIcon: {placement} {image?.darkUrl} {image?.url} + {/* UnreadIcon: {placement} {image?.darkUrl} {image?.url} */} ); } From 7c04b403bef7cbf1164d3f2c7582af5136d6deb6 Mon Sep 17 00:00:00 2001 From: Julia Kartasheva Date: Tue, 7 Oct 2025 15:35:35 -0700 Subject: [PATCH 04/12] addressing PR feedback --- .../ContentCardContainer.tsx | 88 ++++--------------- .../ContentCardView/ContentCardView.tsx | 11 ++- 2 files changed, 27 insertions(+), 72 deletions(-) diff --git a/packages/messaging/src/ui/components/ContentCardContainer/ContentCardContainer.tsx b/packages/messaging/src/ui/components/ContentCardContainer/ContentCardContainer.tsx index 2025a980..54da0710 100644 --- a/packages/messaging/src/ui/components/ContentCardContainer/ContentCardContainer.tsx +++ b/packages/messaging/src/ui/components/ContentCardContainer/ContentCardContainer.tsx @@ -1,11 +1,9 @@ -import { cloneElement, ReactElement, useCallback } from "react"; +import { cloneElement, ReactElement, useCallback, useMemo } from "react"; import { ActivityIndicator, - DynamicColorIOS, FlatList, FlatListProps, ListRenderItem, - Platform, StyleSheet, Text, useColorScheme, @@ -46,64 +44,35 @@ function ContentCardContainerInner({ const colorScheme = useColorScheme(); const { content, error, isLoading } = useContentCardUI(surface); const scheme = useColorScheme(); - const headingColor = Platform.OS === 'ios' - ? DynamicColorIOS({ light: '#000000', dark: '#FFFFFF' }) - : (scheme === 'dark' ? '#FFFFFF' : '#000000'); // Normalize/alias frequently used settings const { content: contentSettings } = settings; const { heading, layout, emptyStateSettings, unread_indicator, isUnreadEnabled } = contentSettings; // Derived flags used across renders - const isHorizontal = layout?.orientation === 'horizontal'; - const unreadIcon = unread_indicator?.unread_icon; - const unreadBg = unread_indicator?.unread_bg?.clr; - const bg = scheme === 'dark' ? unreadBg?.dark : unreadBg?.light; + const headingColor = useMemo(() => scheme === 'dark' ? '#FFFFFF' : '#000000', [scheme]); + const isHorizontal = useMemo(() => layout?.orientation === 'horizontal', [layout?.orientation]); + const unreadIcon = useMemo(() => unread_indicator?.unread_icon, [unread_indicator?.unread_icon]); + const unreadBg = useMemo(() => unread_indicator?.unread_bg?.clr, [unread_indicator?.unread_bg?.clr]); + const bg = useMemo(() => scheme === 'dark' ? unreadBg?.dark : unreadBg?.light, [scheme, unreadBg?.dark, unreadBg?.light]); // Stable item renderer: maps template -> variant, builds style overrides, overlays unread icon const renderItem: ListRenderItem = useCallback(({ item }) => { const template = item.type; - let key: 'smallImageStyle' | 'largeImageStyle' | 'imageOnlyStyle'; - switch (template) { - case 'SmallImage': - key = 'smallImageStyle'; - break; - case 'LargeImage': - key = 'largeImageStyle'; - break; - default: - key = 'imageOnlyStyle'; - break; - } - - // Single merged overrides object (preserves LargeImage behavior) - const cardBase = { - ...(isHorizontal ? { alignSelf: 'center', width: '100%' } : null), - ...(isUnreadEnabled && bg ? { backgroundColor: bg } : null) - } as any; - - const largeImageExtras = isHorizontal && template === 'LargeImage' - ? { - image: styles.imageHeight, - imageContainer: [ - styles.imageHeight, - isUnreadEnabled && bg ? { backgroundColor: bg } : null - ], - contentContainer: styles.contentContainer, - card: isUnreadEnabled && bg ? { backgroundColor: bg } : null - } - : null; + const key = ({ SmallImage: 'smallImageStyle', LargeImage: 'largeImageStyle', ImageOnly: 'imageOnlyStyle' })[template]; const styleOverrides = { [key]: { - card: cardBase, - ...(largeImageExtras || {}) + card: { + ...(isUnreadEnabled && bg ? { backgroundColor: bg } : null), + ...(isHorizontal && styles.horizontalContentContainer), + }, } - } as any; + }; return ( - - + + ); @@ -145,13 +114,7 @@ function ContentCardContainerInner({ ( - isHorizontal ? : - )} - contentContainerStyle={[ - contentContainerStyle, - isHorizontal && styles.listContent - ]} + contentContainerStyle={contentContainerStyle} horizontal={isHorizontal} renderItem={renderItem} /> @@ -191,18 +154,6 @@ export function ContentCardContainer({ } const styles = StyleSheet.create({ - contentContainer: { - minHeight: 140, - flex: 0 - }, - imageHeight: { - height: 180 - }, - cardWidth: { - width: 380, - flexDirection: 'column', - alignItems: 'center' - }, heading: { fontWeight: '600', fontSize: 18, @@ -211,11 +162,8 @@ const styles = StyleSheet.create({ marginBottom: 16, color: '#000000', }, - horizontalSeparator: { width: 12 }, - verticalSeparator: { height: 12 }, - listContent: { - alignItems: 'center', - paddingLeft: 10, - paddingRight: 10 + horizontalContentContainer: { + justifyContent: 'center', + width: 300, }, }); diff --git a/packages/messaging/src/ui/components/ContentCardView/ContentCardView.tsx b/packages/messaging/src/ui/components/ContentCardView/ContentCardView.tsx index 0c99c5fd..cf45122a 100644 --- a/packages/messaging/src/ui/components/ContentCardView/ContentCardView.tsx +++ b/packages/messaging/src/ui/components/ContentCardView/ContentCardView.tsx @@ -228,7 +228,9 @@ export const ContentCardView: React.FC = ({ )} {cardVariant !== "ImageOnly" && ( {content?.title?.content && ( @@ -312,7 +314,6 @@ const styles = StyleSheet.create({ resizeMode: "contain", }, contentContainer: { - flex: 1, paddingVertical: 16, paddingHorizontal: 16, justifyContent: "flex-start", @@ -355,6 +356,12 @@ const smallImageStyles = StyleSheet.create({ container: { flexDirection: "row", }, + contentContainer: { + flex: 1, + paddingVertical: 16, + paddingHorizontal: 16, + justifyContent: "flex-start", + }, imageContainer: { borderRadius: 12, maxWidth: "35%", From 42ca649ff4be6546028eb339e48d7a1310c6e753 Mon Sep 17 00:00:00 2001 From: Julia Kartasheva Date: Tue, 7 Oct 2025 16:29:13 -0700 Subject: [PATCH 05/12] more styling adjustments --- .../ContentCardContainer.tsx | 28 ++++++++----------- .../ui/components/UnreadIcon/UnreadIcon.tsx | 6 ++-- 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/packages/messaging/src/ui/components/ContentCardContainer/ContentCardContainer.tsx b/packages/messaging/src/ui/components/ContentCardContainer/ContentCardContainer.tsx index 54da0710..c4a498ec 100644 --- a/packages/messaging/src/ui/components/ContentCardContainer/ContentCardContainer.tsx +++ b/packages/messaging/src/ui/components/ContentCardContainer/ContentCardContainer.tsx @@ -1,13 +1,13 @@ import { cloneElement, ReactElement, useCallback, useMemo } from "react"; import { ActivityIndicator, + Dimensions, FlatList, FlatListProps, ListRenderItem, StyleSheet, Text, - useColorScheme, - View + useColorScheme } from "react-native"; import { useContentCardUI, useContentContainer } from "../../hooks"; import ContentCardContainerProvider, { @@ -15,7 +15,6 @@ import ContentCardContainerProvider, { } from "../../providers/ContentCardContainerProvider"; import { ContentTemplate } from "../../types/Templates"; import { ContentCardView } from "../ContentCardView/ContentCardView"; -import UnreadIcon from "../UnreadIcon/UnreadIcon"; import EmptyState from "./EmptyState"; // Public props for the container. Extends FlatList props but manages data internally. @@ -65,17 +64,12 @@ function ContentCardContainerInner({ [key]: { card: { ...(isUnreadEnabled && bg ? { backgroundColor: bg } : null), - ...(isHorizontal && styles.horizontalContentContainer), + ...(isHorizontal && styles.horizontalCardStyles), }, } }; - return ( - - - - - ); + return (); }, [isHorizontal, isUnreadEnabled, bg, unreadIcon]); if (isLoading) { @@ -114,7 +108,7 @@ function ContentCardContainerInner({ @@ -159,11 +153,13 @@ const styles = StyleSheet.create({ fontSize: 18, lineHeight: 28, textAlign: 'center', - marginBottom: 16, - color: '#000000', + marginBottom: 16 + }, + horizontalCardStyles: { + width: Math.floor(Dimensions.get('window').width * 0.75), + flex: 0 }, - horizontalContentContainer: { - justifyContent: 'center', - width: 300, + horizontalListContent: { + alignItems: 'center' }, }); diff --git a/packages/messaging/src/ui/components/UnreadIcon/UnreadIcon.tsx b/packages/messaging/src/ui/components/UnreadIcon/UnreadIcon.tsx index 70bbeb3b..1a9bdeb2 100644 --- a/packages/messaging/src/ui/components/UnreadIcon/UnreadIcon.tsx +++ b/packages/messaging/src/ui/components/UnreadIcon/UnreadIcon.tsx @@ -1,9 +1,9 @@ - import { Text, View } from "react-native"; +import { Text, View } from "react-native"; - function UnreadIcon({ placement, image }: { placement: string|undefined, image: { url: string; darkUrl?: string | undefined; } | undefined }) { +function UnreadIcon() { return ( - {/* UnreadIcon: {placement} {image?.darkUrl} {image?.url} */} + UnreadIcon ); } From 5422924c15d59dfa3e10945036d0f77cde6db513 Mon Sep 17 00:00:00 2001 From: Julia Kartasheva Date: Tue, 7 Oct 2025 16:29:48 -0700 Subject: [PATCH 06/12] removing trailing space --- packages/messaging/src/ui/components/UnreadIcon/UnreadIcon.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/messaging/src/ui/components/UnreadIcon/UnreadIcon.tsx b/packages/messaging/src/ui/components/UnreadIcon/UnreadIcon.tsx index 1a9bdeb2..f24e902e 100644 --- a/packages/messaging/src/ui/components/UnreadIcon/UnreadIcon.tsx +++ b/packages/messaging/src/ui/components/UnreadIcon/UnreadIcon.tsx @@ -3,7 +3,7 @@ import { Text, View } from "react-native"; function UnreadIcon() { return ( - UnreadIcon + UnreadIcon ); } From 10b496e157d7c1d44b16f1732848d61452446ca5 Mon Sep 17 00:00:00 2001 From: Julia Kartasheva Date: Wed, 8 Oct 2025 11:43:04 -0700 Subject: [PATCH 07/12] updating metro file --- apps/AEPSampleAppNewArchEnabled/metro.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/AEPSampleAppNewArchEnabled/metro.config.js b/apps/AEPSampleAppNewArchEnabled/metro.config.js index 3b7e18a3..39c5f9a8 100644 --- a/apps/AEPSampleAppNewArchEnabled/metro.config.js +++ b/apps/AEPSampleAppNewArchEnabled/metro.config.js @@ -23,7 +23,7 @@ config.resolver.blockList = [ // Block any nested node_modules directories /.*\/node_modules\/.*\/node_modules\/.*/, ]; - +config.resolver.disableHierarchicalLookup = true; // Use a separate cache for the monorepo to avoid conflicts config.cacheStores = [ new FileStore({ From 6ba8afa5244b7cd07dd9aeebbfe3d7587319f629 Mon Sep 17 00:00:00 2001 From: Julia Kartasheva Date: Wed, 8 Oct 2025 13:55:59 -0700 Subject: [PATCH 08/12] adding some basic unit tests for content card container + removing duplicate color scheme variable --- .../ContentCardContainer.spec.tsx | 119 ++++++++++++++++++ .../ContentCardContainer.tsx | 5 +- 2 files changed, 121 insertions(+), 3 deletions(-) create mode 100644 packages/messaging/src/ui/components/ContentCardContainer/ContentCardContainer.spec.tsx diff --git a/packages/messaging/src/ui/components/ContentCardContainer/ContentCardContainer.spec.tsx b/packages/messaging/src/ui/components/ContentCardContainer/ContentCardContainer.spec.tsx new file mode 100644 index 00000000..edb08bc7 --- /dev/null +++ b/packages/messaging/src/ui/components/ContentCardContainer/ContentCardContainer.spec.tsx @@ -0,0 +1,119 @@ +/* + Copyright 2025 Adobe. All rights reserved. + This file is licensed to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance with the License. + You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law + or agreed to in writing, software distributed under the License is + distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF + ANY KIND, either express or implied. See the License for the specific + language governing permissions and limitations under the License. +*/ + +import React from 'react'; +import { render, screen } from '@testing-library/react-native'; +import { Dimensions, Text } from 'react-native'; +import { ContentCardContainer } from './ContentCardContainer'; + +// Mock hooks used by the container +jest.mock('../../hooks', () => ({ + useContentCardUI: jest.fn(), + useContentContainer: jest.fn(), +})); + +// Capture props passed to ContentCardView (name must start with mock for Jest scope rules) +const mockContentCardView: jest.Mock = jest.fn((..._args: any[]) => null); +jest.mock('../ContentCardView/ContentCardView', () => { + return { + ContentCardView: (props: any) => { + mockContentCardView(props); + return null; + }, + }; +}); + +// Provide a pass-through for the provider +jest.mock('../../providers/ContentCardContainerProvider', () => ({ + __esModule: true, + default: ({ children }: any) => children, +})); + +const { useContentCardUI, useContentContainer } = jest.requireMock('../../hooks'); + +describe('ContentCardContainer', () => { + const surface = 'test-surface'; + + const baseSettings = { + templateType: 'inbox', + content: { + heading: { content: 'Heading' }, + layout: { orientation: 'horizontal' as const }, + capacity: 10, + emptyStateSettings: { + message: { content: 'No Content Available' }, + image: { light: { url: 'https://example.com/image.png' } }, + }, + unread_indicator: { + unread_bg: { clr: { light: '#EEE', dark: '#111' } }, + unread_icon: { placement: 'topright', image: { url: 'https://example.com/icon.png' } }, + }, + isUnreadEnabled: true, + }, + showPagination: false, + }; + + const template = { + type: 'SmallImage', + // minimal shape used by ContentCardView when mocked + data: { content: {} }, + track: jest.fn(), + isRead: false, + } as any; + + beforeEach(() => { + jest.clearAllMocks(); + // Default Dimensions width for deterministic style assertions + jest.spyOn(Dimensions, 'get').mockReturnValue({ width: 400, height: 800, scale: 2, fontScale: 2 } as any); + }); + + it('renders loading state', () => { + (useContentContainer as jest.Mock).mockReturnValue({ settings: baseSettings, isLoading: false, error: null }); + (useContentCardUI as jest.Mock).mockReturnValue({ content: undefined, isLoading: true, error: null }); + + const Loading = Loading... as any; + const CC: any = ContentCardContainer; + render(); + expect(screen.getByText('Loading...')).toBeTruthy(); + }); + + it('renders error state', () => { + // Outer container handles ErrorComponent when useContentContainer has an error + (useContentContainer as jest.Mock).mockReturnValue({ settings: baseSettings, isLoading: false, error: new Error('x') }); + (useContentCardUI as jest.Mock).mockReturnValue({ content: undefined, isLoading: false, error: null }); + + const ErrorComp = Error! as any; + const CC: any = ContentCardContainer; + render(); + expect(screen.getByText('Error!')).toBeTruthy(); + }); + + it('renders fallback when no content yet', () => { + // Outer container handles FallbackComponent when settings are missing + (useContentContainer as jest.Mock).mockReturnValue({ settings: undefined, isLoading: false, error: null }); + (useContentCardUI as jest.Mock).mockReturnValue({ content: undefined, isLoading: false, error: null }); + + const Fallback = Fallback as any; + const CC: any = ContentCardContainer; + render(); + expect(screen.getByText('Fallback')).toBeTruthy(); + }); + + it('renders empty state when content is empty', () => { + (useContentContainer as jest.Mock).mockReturnValue({ settings: baseSettings, isLoading: false, error: null }); + (useContentCardUI as jest.Mock).mockReturnValue({ content: [], isLoading: false, error: null }); + + const CC: any = ContentCardContainer; + render(); + expect(screen.getByText('No Content Available')).toBeTruthy(); + }); +}); \ No newline at end of file diff --git a/packages/messaging/src/ui/components/ContentCardContainer/ContentCardContainer.tsx b/packages/messaging/src/ui/components/ContentCardContainer/ContentCardContainer.tsx index c4a498ec..e9e347bb 100644 --- a/packages/messaging/src/ui/components/ContentCardContainer/ContentCardContainer.tsx +++ b/packages/messaging/src/ui/components/ContentCardContainer/ContentCardContainer.tsx @@ -42,18 +42,17 @@ function ContentCardContainerInner({ }) { const colorScheme = useColorScheme(); const { content, error, isLoading } = useContentCardUI(surface); - const scheme = useColorScheme(); // Normalize/alias frequently used settings const { content: contentSettings } = settings; const { heading, layout, emptyStateSettings, unread_indicator, isUnreadEnabled } = contentSettings; // Derived flags used across renders - const headingColor = useMemo(() => scheme === 'dark' ? '#FFFFFF' : '#000000', [scheme]); + const headingColor = useMemo(() => colorScheme === 'dark' ? '#FFFFFF' : '#000000', [colorScheme]); const isHorizontal = useMemo(() => layout?.orientation === 'horizontal', [layout?.orientation]); const unreadIcon = useMemo(() => unread_indicator?.unread_icon, [unread_indicator?.unread_icon]); const unreadBg = useMemo(() => unread_indicator?.unread_bg?.clr, [unread_indicator?.unread_bg?.clr]); - const bg = useMemo(() => scheme === 'dark' ? unreadBg?.dark : unreadBg?.light, [scheme, unreadBg?.dark, unreadBg?.light]); + const bg = useMemo(() => colorScheme === 'dark' ? unreadBg?.dark : unreadBg?.light, [colorScheme, unreadBg?.dark, unreadBg?.light]); // Stable item renderer: maps template -> variant, builds style overrides, overlays unread icon const renderItem: ListRenderItem = useCallback(({ item }) => { From c061ab9be5dc4922081f8cd3830c6d3a70edd75a Mon Sep 17 00:00:00 2001 From: Julia Kartasheva Date: Wed, 8 Oct 2025 14:01:15 -0700 Subject: [PATCH 09/12] removed unnecessary variable --- .../ContentCardContainer/ContentCardContainer.spec.tsx | 8 -------- 1 file changed, 8 deletions(-) diff --git a/packages/messaging/src/ui/components/ContentCardContainer/ContentCardContainer.spec.tsx b/packages/messaging/src/ui/components/ContentCardContainer/ContentCardContainer.spec.tsx index edb08bc7..4c335ee8 100644 --- a/packages/messaging/src/ui/components/ContentCardContainer/ContentCardContainer.spec.tsx +++ b/packages/messaging/src/ui/components/ContentCardContainer/ContentCardContainer.spec.tsx @@ -62,14 +62,6 @@ describe('ContentCardContainer', () => { showPagination: false, }; - const template = { - type: 'SmallImage', - // minimal shape used by ContentCardView when mocked - data: { content: {} }, - track: jest.fn(), - isRead: false, - } as any; - beforeEach(() => { jest.clearAllMocks(); // Default Dimensions width for deterministic style assertions From e6c3c0204d6581602f7fd56db2500a95bef334db Mon Sep 17 00:00:00 2001 From: Julia Kartasheva Date: Thu, 9 Oct 2025 11:29:12 -0700 Subject: [PATCH 10/12] fixing typing --- apps/AEPSampleAppNewArchEnabled/app/ContentCardsView.tsx | 2 -- .../components/ContentCardContainer/ContentCardContainer.tsx | 3 +-- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/apps/AEPSampleAppNewArchEnabled/app/ContentCardsView.tsx b/apps/AEPSampleAppNewArchEnabled/app/ContentCardsView.tsx index ab4517a3..6c7cfb60 100644 --- a/apps/AEPSampleAppNewArchEnabled/app/ContentCardsView.tsx +++ b/apps/AEPSampleAppNewArchEnabled/app/ContentCardsView.tsx @@ -137,8 +137,6 @@ const ContentCardsView = () => { null} /> ); diff --git a/packages/messaging/src/ui/components/ContentCardContainer/ContentCardContainer.tsx b/packages/messaging/src/ui/components/ContentCardContainer/ContentCardContainer.tsx index e9e347bb..344d84d2 100644 --- a/packages/messaging/src/ui/components/ContentCardContainer/ContentCardContainer.tsx +++ b/packages/messaging/src/ui/components/ContentCardContainer/ContentCardContainer.tsx @@ -17,8 +17,7 @@ import { ContentTemplate } from "../../types/Templates"; import { ContentCardView } from "../ContentCardView/ContentCardView"; import EmptyState from "./EmptyState"; -// Public props for the container. Extends FlatList props but manages data internally. -export interface ContentCardContainerProps extends FlatListProps { +export interface ContentCardContainerProps extends Partial> { LoadingComponent?: ReactElement | null; ErrorComponent?: ReactElement | null; FallbackComponent?: ReactElement | null; From a0ed03fb41699e038bf2349263bb507cb1cf60ac Mon Sep 17 00:00:00 2001 From: Julia Kartasheva Date: Thu, 9 Oct 2025 15:08:21 -0700 Subject: [PATCH 11/12] addressing more pr feedback --- .../ContentCardContainer.tsx | 43 +++++++++---------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/packages/messaging/src/ui/components/ContentCardContainer/ContentCardContainer.tsx b/packages/messaging/src/ui/components/ContentCardContainer/ContentCardContainer.tsx index 344d84d2..31cdf5f1 100644 --- a/packages/messaging/src/ui/components/ContentCardContainer/ContentCardContainer.tsx +++ b/packages/messaging/src/ui/components/ContentCardContainer/ContentCardContainer.tsx @@ -1,20 +1,20 @@ import { cloneElement, ReactElement, useCallback, useMemo } from "react"; import { ActivityIndicator, - Dimensions, FlatList, FlatListProps, ListRenderItem, StyleSheet, Text, - useColorScheme + useColorScheme, + useWindowDimensions } from "react-native"; import { useContentCardUI, useContentContainer } from "../../hooks"; import ContentCardContainerProvider, { ContainerSettings, } from "../../providers/ContentCardContainerProvider"; import { ContentTemplate } from "../../types/Templates"; -import { ContentCardView } from "../ContentCardView/ContentCardView"; +import { ContentCardView, ContentViewProps } from "../ContentCardView/ContentCardView"; import EmptyState from "./EmptyState"; export interface ContentCardContainerProps extends Partial> { @@ -23,6 +23,7 @@ export interface ContentCardContainerProps extends Partial> FallbackComponent?: ReactElement | null; EmptyComponent?: ReactElement | null; surface: string; + contentCardViewProps?: Partial; } // Core renderer: fetches content for a surface, derives layout, and renders a list of cards @@ -35,40 +36,37 @@ function ContentCardContainerInner({ settings, surface, style, + contentCardViewProps, ...props }: ContentCardContainerProps & { settings: ContainerSettings; }) { const colorScheme = useColorScheme(); + const { width: windowWidth } = useWindowDimensions(); const { content, error, isLoading } = useContentCardUI(surface); // Normalize/alias frequently used settings const { content: contentSettings } = settings; - const { heading, layout, emptyStateSettings, unread_indicator, isUnreadEnabled } = contentSettings; + const { heading, layout, emptyStateSettings } = contentSettings; // Derived flags used across renders const headingColor = useMemo(() => colorScheme === 'dark' ? '#FFFFFF' : '#000000', [colorScheme]); const isHorizontal = useMemo(() => layout?.orientation === 'horizontal', [layout?.orientation]); - const unreadIcon = useMemo(() => unread_indicator?.unread_icon, [unread_indicator?.unread_icon]); - const unreadBg = useMemo(() => unread_indicator?.unread_bg?.clr, [unread_indicator?.unread_bg?.clr]); - const bg = useMemo(() => colorScheme === 'dark' ? unreadBg?.dark : unreadBg?.light, [colorScheme, unreadBg?.dark, unreadBg?.light]); - // Stable item renderer: maps template -> variant, builds style overrides, overlays unread icon const renderItem: ListRenderItem = useCallback(({ item }) => { - const template = item.type; - const key = ({ SmallImage: 'smallImageStyle', LargeImage: 'largeImageStyle', ImageOnly: 'imageOnlyStyle' })[template]; - - const styleOverrides = { - [key]: { - card: { - ...(isUnreadEnabled && bg ? { backgroundColor: bg } : null), - ...(isHorizontal && styles.horizontalCardStyles), - }, - } - }; - - return (); - }, [isHorizontal, isUnreadEnabled, bg, unreadIcon]); + return ( + + ); + }, [isHorizontal, contentCardViewProps, windowWidth]); if (isLoading) { return LoadingComponent; @@ -154,7 +152,6 @@ const styles = StyleSheet.create({ marginBottom: 16 }, horizontalCardStyles: { - width: Math.floor(Dimensions.get('window').width * 0.75), flex: 0 }, horizontalListContent: { From 78d14c00bd69f3565c9eea03025e12608c127d22 Mon Sep 17 00:00:00 2001 From: Julia Kartasheva Date: Thu, 9 Oct 2025 17:02:49 -0700 Subject: [PATCH 12/12] renaming to CardProps --- .../ContentCardContainer/ContentCardContainer.js | 6 +++--- .../ContentCardContainer/ContentCardContainer.js.map | 2 +- .../ContentCardContainer/ContentCardContainer.d.ts | 2 +- .../ContentCardContainer/ContentCardContainer.d.ts.map | 2 +- .../ContentCardContainer/ContentCardContainer.tsx | 8 ++++---- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/messaging/dist/module/ui/components/ContentCardContainer/ContentCardContainer.js b/packages/messaging/dist/module/ui/components/ContentCardContainer/ContentCardContainer.js index 44cdb2f5..97c37819 100644 --- a/packages/messaging/dist/module/ui/components/ContentCardContainer/ContentCardContainer.js +++ b/packages/messaging/dist/module/ui/components/ContentCardContainer/ContentCardContainer.js @@ -17,7 +17,7 @@ function ContentCardContainerInner({ settings, surface, style, - contentCardViewProps, + CardProps, ...props }) { const colorScheme = useColorScheme(); @@ -48,12 +48,12 @@ function ContentCardContainerInner({ }) => { return /*#__PURE__*/React.createElement(ContentCardView, _extends({ template: item - }, contentCardViewProps, { + }, CardProps, { style: [isHorizontal && [styles.horizontalCardStyles, { width: Math.floor(windowWidth * 0.75) }]] })); - }, [isHorizontal, contentCardViewProps, windowWidth]); + }, [isHorizontal, CardProps, windowWidth]); if (isLoading) { return LoadingComponent; } diff --git a/packages/messaging/dist/module/ui/components/ContentCardContainer/ContentCardContainer.js.map b/packages/messaging/dist/module/ui/components/ContentCardContainer/ContentCardContainer.js.map index a7b0f247..93fe0afd 100644 --- a/packages/messaging/dist/module/ui/components/ContentCardContainer/ContentCardContainer.js.map +++ b/packages/messaging/dist/module/ui/components/ContentCardContainer/ContentCardContainer.js.map @@ -1 +1 @@ -{"version":3,"names":["cloneElement","useCallback","useMemo","ActivityIndicator","FlatList","StyleSheet","Text","useColorScheme","useWindowDimensions","useContentCardUI","useContentContainer","ContentCardContainerProvider","ContentCardView","EmptyState","ContentCardContainerInner","contentContainerStyle","LoadingComponent","React","createElement","ErrorComponent","FallbackComponent","EmptyComponent","settings","surface","style","contentCardViewProps","props","colorScheme","width","windowWidth","content","error","isLoading","contentSettings","heading","layout","emptyStateSettings","headingColor","isHorizontal","orientation","renderItem","item","_extends","template","styles","horizontalCardStyles","Math","floor","length","image","url","text","message","accessibilityRole","color","data","horizontalListContent","horizontal","ContentCardContainer","create","fontWeight","fontSize","lineHeight","textAlign","marginBottom","flex","alignItems"],"sourceRoot":"../../../../../src","sources":["ui/components/ContentCardContainer/ContentCardContainer.tsx"],"mappings":"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","ignoreList":[]} +{"version":3,"names":["cloneElement","useCallback","useMemo","ActivityIndicator","FlatList","StyleSheet","Text","useColorScheme","useWindowDimensions","useContentCardUI","useContentContainer","ContentCardContainerProvider","ContentCardView","EmptyState","ContentCardContainerInner","contentContainerStyle","LoadingComponent","React","createElement","ErrorComponent","FallbackComponent","EmptyComponent","settings","surface","style","CardProps","props","colorScheme","width","windowWidth","content","error","isLoading","contentSettings","heading","layout","emptyStateSettings","headingColor","isHorizontal","orientation","renderItem","item","_extends","template","styles","horizontalCardStyles","Math","floor","length","image","url","text","message","accessibilityRole","color","data","horizontalListContent","horizontal","ContentCardContainer","create","fontWeight","fontSize","lineHeight","textAlign","marginBottom","flex","alignItems"],"sourceRoot":"../../../../../src","sources":["ui/components/ContentCardContainer/ContentCardContainer.tsx"],"mappings":"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","ignoreList":[]} diff --git a/packages/messaging/dist/typescript/ui/components/ContentCardContainer/ContentCardContainer.d.ts b/packages/messaging/dist/typescript/ui/components/ContentCardContainer/ContentCardContainer.d.ts index b53a0d4e..4f144579 100644 --- a/packages/messaging/dist/typescript/ui/components/ContentCardContainer/ContentCardContainer.d.ts +++ b/packages/messaging/dist/typescript/ui/components/ContentCardContainer/ContentCardContainer.d.ts @@ -8,7 +8,7 @@ export interface ContentCardContainerProps extends Partial> FallbackComponent?: ReactElement | null; EmptyComponent?: ReactElement | null; surface: string; - contentCardViewProps?: Partial; + CardProps?: Partial; } export declare function ContentCardContainer({ LoadingComponent, ErrorComponent, FallbackComponent, surface, ...props }: ContentCardContainerProps): React.ReactElement; //# sourceMappingURL=ContentCardContainer.d.ts.map \ No newline at end of file diff --git a/packages/messaging/dist/typescript/ui/components/ContentCardContainer/ContentCardContainer.d.ts.map b/packages/messaging/dist/typescript/ui/components/ContentCardContainer/ContentCardContainer.d.ts.map index c39d24d3..d4713ef3 100644 --- a/packages/messaging/dist/typescript/ui/components/ContentCardContainer/ContentCardContainer.d.ts.map +++ b/packages/messaging/dist/typescript/ui/components/ContentCardContainer/ContentCardContainer.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"ContentCardContainer.d.ts","sourceRoot":"","sources":["../../../../../src/ui/components/ContentCardContainer/ContentCardContainer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAgB,YAAY,EAAwB,MAAM,OAAO,CAAC;AACzE,OAAO,EAGL,aAAa,EAMd,MAAM,cAAc,CAAC;AAKtB,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAmB,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAGvF,MAAM,WAAW,yBAAyB,CAAC,CAAC,CAAE,SAAQ,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IAC7E,gBAAgB,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IACvC,cAAc,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IACrC,iBAAiB,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IACxC,cAAc,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,oBAAoB,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;CAClD;AAwFD,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,eAAe,EAAE,EAC9D,gBAAwC,EACxC,cAAqB,EACrB,iBAAwB,EACxB,OAAO,EACP,GAAG,KAAK,EACT,EAAE,yBAAyB,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,YAAY,CAuBnD"} \ No newline at end of file +{"version":3,"file":"ContentCardContainer.d.ts","sourceRoot":"","sources":["../../../../../src/ui/components/ContentCardContainer/ContentCardContainer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAgB,YAAY,EAAwB,MAAM,OAAO,CAAC;AACzE,OAAO,EAGL,aAAa,EAMd,MAAM,cAAc,CAAC;AAKtB,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAmB,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAGvF,MAAM,WAAW,yBAAyB,CAAC,CAAC,CAAE,SAAQ,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IAC7E,gBAAgB,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IACvC,cAAc,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IACrC,iBAAiB,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IACxC,cAAc,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;CACvC;AAwFD,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,eAAe,EAAE,EAC9D,gBAAwC,EACxC,cAAqB,EACrB,iBAAwB,EACxB,OAAO,EACP,GAAG,KAAK,EACT,EAAE,yBAAyB,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,YAAY,CAuBnD"} \ No newline at end of file diff --git a/packages/messaging/src/ui/components/ContentCardContainer/ContentCardContainer.tsx b/packages/messaging/src/ui/components/ContentCardContainer/ContentCardContainer.tsx index 31cdf5f1..d866498e 100644 --- a/packages/messaging/src/ui/components/ContentCardContainer/ContentCardContainer.tsx +++ b/packages/messaging/src/ui/components/ContentCardContainer/ContentCardContainer.tsx @@ -23,7 +23,7 @@ export interface ContentCardContainerProps extends Partial> FallbackComponent?: ReactElement | null; EmptyComponent?: ReactElement | null; surface: string; - contentCardViewProps?: Partial; + CardProps?: Partial; } // Core renderer: fetches content for a surface, derives layout, and renders a list of cards @@ -36,7 +36,7 @@ function ContentCardContainerInner({ settings, surface, style, - contentCardViewProps, + CardProps, ...props }: ContentCardContainerProps & { settings: ContainerSettings; @@ -57,7 +57,7 @@ function ContentCardContainerInner({ return ( ({ ]} /> ); - }, [isHorizontal, contentCardViewProps, windowWidth]); + }, [isHorizontal, CardProps, windowWidth]); if (isLoading) { return LoadingComponent;