import React from 'react'; import { Image as ReactNativeImage } from 'react-native'; import type { PostAction, PostAuthor, PostCardMedia, PostCardProps, PostCommentPreview, } from '../../../../types/post-card'; import { Avatar } from '../../../avatar/public'; import { Button } from '../../../button/public'; import { Divider, View } from '../../../layout/public'; import { withZoraThemeScope } from '../../../theme/adapters/inbound/withZoraThemeScope'; import { useZoraTheme } from '../../../theme/composition/useZoraTheme'; import { Text } from '../../../typography/public'; import { Card } from '../../public'; /*** * Social-style post card pattern with author, content, media, and actions. * */ export const PostCard = withZoraThemeScope(PostCardInner); function resolveAuthorName(author: PostAuthor): string | undefined { return typeof author.name === 'string' ? author.name : author.avatar?.name; } function resolveMediaAspectRatio(aspectRatio: number | undefined): number { if (aspectRatio === undefined || !Number.isFinite(aspectRatio) || aspectRatio <= 0) { return 16 / 9; } return aspectRatio; } function isPostCardMediaList( media: NonNullable, ): media is readonly PostCardMedia[] { return Array.isArray(media); } function normalizeMedia(media: PostCardProps['media']): readonly PostCardMedia[] { if (!media) { return []; } if (isPostCardMediaList(media)) { return media; } return [media]; } function PostCardAuthor({ author, compact = false }: { author: PostAuthor; compact?: boolean }) { const avatarName = resolveAuthorName(author); const { avatar } = author; return ( {author.name} {author.subtitle ? ( {author.subtitle} ) : null} ); } function PostCardMediaItem({ media }: { media: PostCardMedia }) { const { theme } = useZoraTheme(); const aspectRatio = resolveMediaAspectRatio(media.aspectRatio); if (!('source' in media)) { return ( {media.children} ); } return ( ); } function PostActionLabel({ action }: { action: PostAction }) { if (!action.count) { return <>{action.label}; } return ( <> {action.label} {action.count} ); } function PostCardActions({ actions }: { actions: readonly PostAction[] }) { if (actions.length === 0) { return null; } return ( {actions.map((action) => ( ))} ); } function PostCommentPreviewItem({ comment }: { comment: PostCommentPreview }) { return ( {comment.author ? : null} {comment.text} {comment.meta ? ( {comment.meta} ) : null} {comment.action ? {comment.action} : null} ); } function PostCardComments({ comments }: { comments: readonly PostCommentPreview[] }) { if (comments.length === 0) { return null; } return ( {comments.map((comment) => ( ))} ); } function PostCardInner({ themeId: _themeId, mode: _mode, interactionPolicy, testID, author, text, children, media, actions = [], comments = [], headerAction, footer, tone = 'default', compact = false, onPress, }: PostCardProps) { const mediaItems = normalizeMedia(media); const gap = compact ? 's' : 'm'; const isInteractive = Boolean(onPress) && !headerAction; const hasBody = text != null || children != null || mediaItems.length > 0; const hasEngagement = actions.length > 0 || comments.length > 0; return ( {headerAction ? {headerAction} : null} {hasBody ? ( {text ? {text} : null} {children ? {children} : null} {mediaItems.length > 0 ? ( {mediaItems.map((item, index) => ( ))} ) : null} ) : null} {hasEngagement ? : null} {footer ? {footer} : null} ); }