@ankhorage/zora 1.4.7 → 1.4.9
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/CHANGELOG.md +12 -0
- package/README.md +262 -0
- package/dist/components/card/meta.d.ts +1 -1
- package/dist/foundation/meta.d.ts +4 -4
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/layout/auth-layout/meta.d.ts +1 -1
- package/dist/layout/page/meta.d.ts +1 -1
- package/dist/layout/page-section/meta.d.ts +1 -1
- package/dist/metadata/allowedChildren.d.ts +3 -3
- package/dist/metadata/allowedChildren.d.ts.map +1 -1
- package/dist/metadata/allowedChildren.js +2 -0
- package/dist/metadata/allowedChildren.js.map +1 -1
- package/dist/metadata/componentMeta.d.ts.map +1 -1
- package/dist/metadata/componentMeta.js +4 -0
- package/dist/metadata/componentMeta.js.map +1 -1
- package/dist/patterns/chat-list-item/ChatListItem.d.ts +4 -0
- package/dist/patterns/chat-list-item/ChatListItem.d.ts.map +1 -0
- package/dist/patterns/chat-list-item/ChatListItem.js +110 -0
- package/dist/patterns/chat-list-item/ChatListItem.js.map +1 -0
- package/dist/patterns/chat-list-item/index.d.ts +3 -0
- package/dist/patterns/chat-list-item/index.d.ts.map +1 -0
- package/dist/patterns/chat-list-item/index.js +2 -0
- package/dist/patterns/chat-list-item/index.js.map +1 -0
- package/dist/patterns/chat-list-item/meta.d.ts +74 -0
- package/dist/patterns/chat-list-item/meta.d.ts.map +1 -0
- package/dist/patterns/chat-list-item/meta.js +72 -0
- package/dist/patterns/chat-list-item/meta.js.map +1 -0
- package/dist/patterns/chat-list-item/types.d.ts +31 -0
- package/dist/patterns/chat-list-item/types.d.ts.map +1 -0
- package/dist/patterns/chat-list-item/types.js +2 -0
- package/dist/patterns/chat-list-item/types.js.map +1 -0
- package/dist/patterns/notice/meta.d.ts +1 -1
- package/dist/patterns/panel/meta.d.ts +1 -1
- package/dist/patterns/post-card/PostCard.d.ts +4 -0
- package/dist/patterns/post-card/PostCard.d.ts.map +1 -0
- package/dist/patterns/post-card/PostCard.js +133 -0
- package/dist/patterns/post-card/PostCard.js.map +1 -0
- package/dist/patterns/post-card/index.d.ts +3 -0
- package/dist/patterns/post-card/index.d.ts.map +1 -0
- package/dist/patterns/post-card/index.js +2 -0
- package/dist/patterns/post-card/index.js.map +1 -0
- package/dist/patterns/post-card/meta.d.ts +64 -0
- package/dist/patterns/post-card/meta.d.ts.map +1 -0
- package/dist/patterns/post-card/meta.js +66 -0
- package/dist/patterns/post-card/meta.js.map +1 -0
- package/dist/patterns/post-card/types.d.ts +64 -0
- package/dist/patterns/post-card/types.d.ts.map +1 -0
- package/dist/patterns/post-card/types.js +2 -0
- package/dist/patterns/post-card/types.js.map +1 -0
- package/package.json +1 -1
- package/src/index.ts +11 -0
- package/src/metadata/allowedChildren.ts +2 -0
- package/src/metadata/componentMeta.test.ts +2 -0
- package/src/metadata/componentMeta.ts +4 -0
- package/src/patterns/chat-list-item/ChatListItem.test.tsx +11 -0
- package/src/patterns/chat-list-item/ChatListItem.tsx +219 -0
- package/src/patterns/chat-list-item/index.ts +2 -0
- package/src/patterns/chat-list-item/meta.ts +74 -0
- package/src/patterns/chat-list-item/types.ts +33 -0
- package/src/patterns/post-card/PostCard.test.tsx +11 -0
- package/src/patterns/post-card/PostCard.tsx +234 -0
- package/src/patterns/post-card/index.ts +9 -0
- package/src/patterns/post-card/meta.ts +68 -0
- package/src/patterns/post-card/types.ts +71 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { ZoraComponentMeta } from '../../metadata';
|
|
2
|
+
|
|
3
|
+
export const chatListItemMeta = {
|
|
4
|
+
name: 'ChatListItem',
|
|
5
|
+
category: 'pattern',
|
|
6
|
+
description:
|
|
7
|
+
'Conversation preview row with avatar, title, preview text, timestamp, and unread state.',
|
|
8
|
+
directManifestNode: true,
|
|
9
|
+
allowedChildren: [],
|
|
10
|
+
blueprint: {
|
|
11
|
+
label: 'Chat list item',
|
|
12
|
+
icon: { name: 'chatbubble-outline' },
|
|
13
|
+
defaultProps: {
|
|
14
|
+
title: 'Ada Lovelace',
|
|
15
|
+
preview: 'Can you review the latest UI update?',
|
|
16
|
+
timestamp: '2m',
|
|
17
|
+
avatar: {
|
|
18
|
+
name: 'Ada Lovelace',
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
props: {
|
|
23
|
+
title: {
|
|
24
|
+
type: 'string',
|
|
25
|
+
category: 'Content',
|
|
26
|
+
label: 'Title',
|
|
27
|
+
default: 'Ada Lovelace',
|
|
28
|
+
},
|
|
29
|
+
preview: {
|
|
30
|
+
type: 'string',
|
|
31
|
+
category: 'Content',
|
|
32
|
+
label: 'Preview',
|
|
33
|
+
},
|
|
34
|
+
meta: {
|
|
35
|
+
type: 'string',
|
|
36
|
+
category: 'Content',
|
|
37
|
+
label: 'Meta',
|
|
38
|
+
},
|
|
39
|
+
timestamp: {
|
|
40
|
+
type: 'string',
|
|
41
|
+
category: 'Content',
|
|
42
|
+
label: 'Timestamp',
|
|
43
|
+
},
|
|
44
|
+
unread: {
|
|
45
|
+
type: 'boolean',
|
|
46
|
+
category: 'State',
|
|
47
|
+
label: 'Unread',
|
|
48
|
+
default: false,
|
|
49
|
+
},
|
|
50
|
+
unreadCount: {
|
|
51
|
+
type: 'string',
|
|
52
|
+
category: 'State',
|
|
53
|
+
label: 'Unread count',
|
|
54
|
+
},
|
|
55
|
+
selected: {
|
|
56
|
+
type: 'boolean',
|
|
57
|
+
category: 'State',
|
|
58
|
+
label: 'Selected',
|
|
59
|
+
default: false,
|
|
60
|
+
},
|
|
61
|
+
disabled: {
|
|
62
|
+
type: 'boolean',
|
|
63
|
+
category: 'State',
|
|
64
|
+
label: 'Disabled',
|
|
65
|
+
default: false,
|
|
66
|
+
},
|
|
67
|
+
compact: {
|
|
68
|
+
type: 'boolean',
|
|
69
|
+
category: 'Layout',
|
|
70
|
+
label: 'Compact',
|
|
71
|
+
default: false,
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
} as const satisfies ZoraComponentMeta;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type React from 'react';
|
|
2
|
+
import type { ImageSourcePropType } from 'react-native';
|
|
3
|
+
|
|
4
|
+
import type { AvatarShape, AvatarSize } from '../../components/avatar';
|
|
5
|
+
import type { ZoraTone } from '../../internal/recipes';
|
|
6
|
+
import type { ZoraBaseProps } from '../../theme/ZoraBaseProps';
|
|
7
|
+
|
|
8
|
+
export interface ChatListAvatar {
|
|
9
|
+
source?: ImageSourcePropType;
|
|
10
|
+
name?: string;
|
|
11
|
+
initials?: string;
|
|
12
|
+
label?: string;
|
|
13
|
+
size?: AvatarSize;
|
|
14
|
+
shape?: AvatarShape;
|
|
15
|
+
tone?: ZoraTone;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface ChatListItemProps extends ZoraBaseProps {
|
|
19
|
+
title: React.ReactNode;
|
|
20
|
+
preview?: React.ReactNode;
|
|
21
|
+
meta?: React.ReactNode;
|
|
22
|
+
timestamp?: React.ReactNode;
|
|
23
|
+
avatar?: ChatListAvatar;
|
|
24
|
+
leading?: React.ReactNode;
|
|
25
|
+
trailing?: React.ReactNode;
|
|
26
|
+
unread?: boolean;
|
|
27
|
+
unreadCount?: React.ReactNode;
|
|
28
|
+
selected?: boolean;
|
|
29
|
+
disabled?: boolean;
|
|
30
|
+
compact?: boolean;
|
|
31
|
+
accessibilityLabel?: string;
|
|
32
|
+
onPress?: () => void;
|
|
33
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { describe, expect, test } from 'bun:test';
|
|
2
|
+
|
|
3
|
+
import { ZORA_COMPONENT_META } from '../../metadata';
|
|
4
|
+
|
|
5
|
+
describe('PostCard', () => {
|
|
6
|
+
test('is registered as a public ZORA pattern', () => {
|
|
7
|
+
expect(ZORA_COMPONENT_META.PostCard?.name).toBe('PostCard');
|
|
8
|
+
expect(ZORA_COMPONENT_META.PostCard?.category).toBe('pattern');
|
|
9
|
+
expect(ZORA_COMPONENT_META.PostCard?.directManifestNode).toBe(true);
|
|
10
|
+
});
|
|
11
|
+
});
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Image as ReactNativeImage } from 'react-native';
|
|
3
|
+
|
|
4
|
+
import { Avatar } from '../../components/avatar';
|
|
5
|
+
import { Button } from '../../components/button';
|
|
6
|
+
import { Card } from '../../components/card';
|
|
7
|
+
import { Text } from '../../components/text';
|
|
8
|
+
import { Box, Divider, Inline, Stack } from '../../foundation';
|
|
9
|
+
import { useZoraTheme } from '../../theme/useZoraTheme';
|
|
10
|
+
import { withZoraThemeScope } from '../../theme/withZoraThemeScope';
|
|
11
|
+
import type {
|
|
12
|
+
PostAction,
|
|
13
|
+
PostAuthor,
|
|
14
|
+
PostCardMedia,
|
|
15
|
+
PostCardProps,
|
|
16
|
+
PostCommentPreview,
|
|
17
|
+
} from './types';
|
|
18
|
+
|
|
19
|
+
function resolveAuthorName(author: PostAuthor): string | undefined {
|
|
20
|
+
return typeof author.name === 'string' ? author.name : author.avatar?.name;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function resolveMediaAspectRatio(aspectRatio: number | undefined): number {
|
|
24
|
+
if (aspectRatio === undefined || !Number.isFinite(aspectRatio) || aspectRatio <= 0) {
|
|
25
|
+
return 16 / 9;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return aspectRatio;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function isPostCardMediaList(
|
|
32
|
+
media: NonNullable<PostCardProps['media']>,
|
|
33
|
+
): media is readonly PostCardMedia[] {
|
|
34
|
+
return Array.isArray(media);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function normalizeMedia(media: PostCardProps['media']): readonly PostCardMedia[] {
|
|
38
|
+
if (!media) {
|
|
39
|
+
return [];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (isPostCardMediaList(media)) {
|
|
43
|
+
return media;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return [media];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function PostCardAuthor({ author, compact = false }: { author: PostAuthor; compact?: boolean }) {
|
|
50
|
+
const avatarName = resolveAuthorName(author);
|
|
51
|
+
const { avatar } = author;
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<Inline align="center" gap="s" wrap="nowrap">
|
|
55
|
+
<Avatar
|
|
56
|
+
initials={avatar?.initials}
|
|
57
|
+
label={avatar?.label ?? avatarName}
|
|
58
|
+
name={avatarName}
|
|
59
|
+
shape={avatar?.shape}
|
|
60
|
+
size={avatar?.size ?? (compact ? 's' : 'm')}
|
|
61
|
+
source={avatar?.source}
|
|
62
|
+
tone={avatar?.tone}
|
|
63
|
+
/>
|
|
64
|
+
<Box flex={1}>
|
|
65
|
+
<Stack gap="xxs">
|
|
66
|
+
<Text variant="bodySmall" weight="semiBold">
|
|
67
|
+
{author.name}
|
|
68
|
+
</Text>
|
|
69
|
+
{author.subtitle ? (
|
|
70
|
+
<Text tone="muted" variant="caption">
|
|
71
|
+
{author.subtitle}
|
|
72
|
+
</Text>
|
|
73
|
+
) : null}
|
|
74
|
+
</Stack>
|
|
75
|
+
</Box>
|
|
76
|
+
</Inline>
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function PostCardMediaItem({ media }: { media: PostCardMedia }) {
|
|
81
|
+
const { theme } = useZoraTheme();
|
|
82
|
+
const aspectRatio = resolveMediaAspectRatio(media.aspectRatio);
|
|
83
|
+
|
|
84
|
+
if (!('source' in media)) {
|
|
85
|
+
return (
|
|
86
|
+
<Box radius="m" style={{ overflow: 'hidden' }}>
|
|
87
|
+
{media.children}
|
|
88
|
+
</Box>
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return (
|
|
93
|
+
<Box bg={theme.semantics.neutral.surface} radius="m" style={{ overflow: 'hidden' }}>
|
|
94
|
+
<Box style={{ aspectRatio, width: '100%' }}>
|
|
95
|
+
<ReactNativeImage
|
|
96
|
+
accessibilityLabel={media.label}
|
|
97
|
+
source={media.source}
|
|
98
|
+
style={{ height: '100%', width: '100%' }}
|
|
99
|
+
/>
|
|
100
|
+
</Box>
|
|
101
|
+
</Box>
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function PostActionLabel({ action }: { action: PostAction }) {
|
|
106
|
+
if (!action.count) {
|
|
107
|
+
return <>{action.label}</>;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return (
|
|
111
|
+
<>
|
|
112
|
+
{action.label} {action.count}
|
|
113
|
+
</>
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function PostCardActions({ actions }: { actions: readonly PostAction[] }) {
|
|
118
|
+
if (actions.length === 0) {
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return (
|
|
123
|
+
<Inline align="center" gap="s" wrap="wrap">
|
|
124
|
+
{actions.map((action) => (
|
|
125
|
+
<Button
|
|
126
|
+
key={action.id}
|
|
127
|
+
disabled={action.disabled}
|
|
128
|
+
emphasis={action.selected ? 'soft' : 'ghost'}
|
|
129
|
+
leadingIcon={action.icon}
|
|
130
|
+
onPress={action.onPress}
|
|
131
|
+
size="s"
|
|
132
|
+
tone={action.selected ? 'primary' : 'neutral'}
|
|
133
|
+
>
|
|
134
|
+
<PostActionLabel action={action} />
|
|
135
|
+
</Button>
|
|
136
|
+
))}
|
|
137
|
+
</Inline>
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function PostCommentPreviewItem({ comment }: { comment: PostCommentPreview }) {
|
|
142
|
+
return (
|
|
143
|
+
<Inline align="flex-start" gap="s" wrap="nowrap">
|
|
144
|
+
{comment.author ? <PostCardAuthor author={comment.author} compact /> : null}
|
|
145
|
+
<Box flex={1}>
|
|
146
|
+
<Stack gap="xxs">
|
|
147
|
+
<Text variant="bodySmall">{comment.text}</Text>
|
|
148
|
+
{comment.meta ? (
|
|
149
|
+
<Text tone="subtle" variant="caption">
|
|
150
|
+
{comment.meta}
|
|
151
|
+
</Text>
|
|
152
|
+
) : null}
|
|
153
|
+
{comment.action ? <Box>{comment.action}</Box> : null}
|
|
154
|
+
</Stack>
|
|
155
|
+
</Box>
|
|
156
|
+
</Inline>
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function PostCardComments({ comments }: { comments: readonly PostCommentPreview[] }) {
|
|
161
|
+
if (comments.length === 0) {
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return (
|
|
166
|
+
<Stack gap="s">
|
|
167
|
+
{comments.map((comment) => (
|
|
168
|
+
<PostCommentPreviewItem key={comment.id} comment={comment} />
|
|
169
|
+
))}
|
|
170
|
+
</Stack>
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function PostCardInner({
|
|
175
|
+
themeId: _themeId,
|
|
176
|
+
mode: _mode,
|
|
177
|
+
testID,
|
|
178
|
+
author,
|
|
179
|
+
text,
|
|
180
|
+
children,
|
|
181
|
+
media,
|
|
182
|
+
actions = [],
|
|
183
|
+
comments = [],
|
|
184
|
+
headerAction,
|
|
185
|
+
footer,
|
|
186
|
+
tone = 'default',
|
|
187
|
+
compact = false,
|
|
188
|
+
onPress,
|
|
189
|
+
}: PostCardProps) {
|
|
190
|
+
const mediaItems = normalizeMedia(media);
|
|
191
|
+
const gap = compact ? 's' : 'm';
|
|
192
|
+
const isInteractive = Boolean(onPress) && !headerAction;
|
|
193
|
+
const hasBody = text != null || children != null || mediaItems.length > 0;
|
|
194
|
+
const hasEngagement = actions.length > 0 || comments.length > 0;
|
|
195
|
+
|
|
196
|
+
return (
|
|
197
|
+
<Card
|
|
198
|
+
compact={compact}
|
|
199
|
+
onPress={isInteractive ? onPress : undefined}
|
|
200
|
+
testID={testID}
|
|
201
|
+
tone={tone}
|
|
202
|
+
>
|
|
203
|
+
<Stack gap={gap}>
|
|
204
|
+
<Inline align="center" gap="m" justify="space-between" wrap="nowrap">
|
|
205
|
+
<Box flex={1}>
|
|
206
|
+
<PostCardAuthor author={author} compact={compact} />
|
|
207
|
+
</Box>
|
|
208
|
+
{headerAction ? <Box>{headerAction}</Box> : null}
|
|
209
|
+
</Inline>
|
|
210
|
+
|
|
211
|
+
{hasBody ? (
|
|
212
|
+
<Stack gap={gap}>
|
|
213
|
+
{text ? <Text variant="body">{text}</Text> : null}
|
|
214
|
+
{children ? <Box>{children}</Box> : null}
|
|
215
|
+
{mediaItems.length > 0 ? (
|
|
216
|
+
<Stack gap="s">
|
|
217
|
+
{mediaItems.map((item, index) => (
|
|
218
|
+
<PostCardMediaItem key={`${index}`} media={item} />
|
|
219
|
+
))}
|
|
220
|
+
</Stack>
|
|
221
|
+
) : null}
|
|
222
|
+
</Stack>
|
|
223
|
+
) : null}
|
|
224
|
+
|
|
225
|
+
{hasEngagement ? <Divider /> : null}
|
|
226
|
+
<PostCardActions actions={actions} />
|
|
227
|
+
<PostCardComments comments={comments} />
|
|
228
|
+
{footer ? <Box pt="xs">{footer}</Box> : null}
|
|
229
|
+
</Stack>
|
|
230
|
+
</Card>
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
export const PostCard = withZoraThemeScope(PostCardInner);
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { ZoraComponentMeta } from '../../metadata';
|
|
2
|
+
import { CONTAINER_ALLOWED_CHILDREN } from '../../metadata/allowedChildren';
|
|
3
|
+
|
|
4
|
+
export const postCardMeta = {
|
|
5
|
+
name: 'PostCard',
|
|
6
|
+
category: 'pattern',
|
|
7
|
+
description:
|
|
8
|
+
'Social/content post card with author identity, body, media, actions, and comment previews.',
|
|
9
|
+
directManifestNode: true,
|
|
10
|
+
allowedChildren: [...CONTAINER_ALLOWED_CHILDREN],
|
|
11
|
+
blueprint: {
|
|
12
|
+
label: 'Post card',
|
|
13
|
+
icon: { name: 'chatbubble-ellipses-outline' },
|
|
14
|
+
defaultProps: {
|
|
15
|
+
author: {
|
|
16
|
+
name: 'Ada Lovelace',
|
|
17
|
+
subtitle: '@ada · 2h',
|
|
18
|
+
avatar: {
|
|
19
|
+
name: 'Ada Lovelace',
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
text: 'Share an update, image, or announcement with a reusable ZORA PostCard.',
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
props: {
|
|
26
|
+
author: {
|
|
27
|
+
type: 'array',
|
|
28
|
+
category: 'Content',
|
|
29
|
+
label: 'Author',
|
|
30
|
+
itemSchema: [
|
|
31
|
+
{
|
|
32
|
+
key: 'name',
|
|
33
|
+
schema: {
|
|
34
|
+
type: 'string',
|
|
35
|
+
category: 'Content',
|
|
36
|
+
label: 'Name',
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
key: 'subtitle',
|
|
41
|
+
schema: {
|
|
42
|
+
type: 'string',
|
|
43
|
+
category: 'Content',
|
|
44
|
+
label: 'Subtitle',
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
},
|
|
49
|
+
text: {
|
|
50
|
+
type: 'string',
|
|
51
|
+
category: 'Content',
|
|
52
|
+
label: 'Text',
|
|
53
|
+
},
|
|
54
|
+
compact: {
|
|
55
|
+
type: 'boolean',
|
|
56
|
+
category: 'Layout',
|
|
57
|
+
label: 'Compact',
|
|
58
|
+
default: false,
|
|
59
|
+
},
|
|
60
|
+
tone: {
|
|
61
|
+
type: 'enum',
|
|
62
|
+
category: 'Style',
|
|
63
|
+
label: 'Tone',
|
|
64
|
+
enum: ['default', 'subtle', 'outline'],
|
|
65
|
+
default: 'default',
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
} as const satisfies ZoraComponentMeta;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { ButtonIconSpec } from '@ankhorage/surface';
|
|
2
|
+
import type React from 'react';
|
|
3
|
+
import type { ImageSourcePropType } from 'react-native';
|
|
4
|
+
|
|
5
|
+
import type { AvatarShape, AvatarSize } from '../../components/avatar';
|
|
6
|
+
import type { ZoraCardTone, ZoraTone } from '../../internal/recipes';
|
|
7
|
+
import type { ZoraBaseProps } from '../../theme/ZoraBaseProps';
|
|
8
|
+
|
|
9
|
+
export interface PostAuthorAvatar {
|
|
10
|
+
source?: ImageSourcePropType;
|
|
11
|
+
name?: string;
|
|
12
|
+
initials?: string;
|
|
13
|
+
label?: string;
|
|
14
|
+
size?: AvatarSize;
|
|
15
|
+
shape?: AvatarShape;
|
|
16
|
+
tone?: ZoraTone;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface PostAuthor {
|
|
20
|
+
name: React.ReactNode;
|
|
21
|
+
subtitle?: React.ReactNode;
|
|
22
|
+
avatar?: PostAuthorAvatar;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
interface PostCardSourceMedia {
|
|
26
|
+
source: ImageSourcePropType;
|
|
27
|
+
label: string;
|
|
28
|
+
aspectRatio?: number;
|
|
29
|
+
children?: never;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
interface PostCardCustomMedia {
|
|
33
|
+
children: React.ReactNode;
|
|
34
|
+
label?: string;
|
|
35
|
+
aspectRatio?: number;
|
|
36
|
+
source?: never;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export type PostCardMedia = PostCardSourceMedia | PostCardCustomMedia;
|
|
40
|
+
|
|
41
|
+
export interface PostAction {
|
|
42
|
+
id: string;
|
|
43
|
+
label: string;
|
|
44
|
+
icon?: ButtonIconSpec;
|
|
45
|
+
count?: React.ReactNode;
|
|
46
|
+
selected?: boolean;
|
|
47
|
+
disabled?: boolean;
|
|
48
|
+
onPress?: () => void;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface PostCommentPreview {
|
|
52
|
+
id: string;
|
|
53
|
+
author?: PostAuthor;
|
|
54
|
+
text: React.ReactNode;
|
|
55
|
+
meta?: React.ReactNode;
|
|
56
|
+
action?: React.ReactNode;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface PostCardProps extends ZoraBaseProps {
|
|
60
|
+
author: PostAuthor;
|
|
61
|
+
text?: React.ReactNode;
|
|
62
|
+
children?: React.ReactNode;
|
|
63
|
+
media?: PostCardMedia | readonly PostCardMedia[];
|
|
64
|
+
actions?: readonly PostAction[];
|
|
65
|
+
comments?: readonly PostCommentPreview[];
|
|
66
|
+
headerAction?: React.ReactNode;
|
|
67
|
+
footer?: React.ReactNode;
|
|
68
|
+
tone?: ZoraCardTone;
|
|
69
|
+
compact?: boolean;
|
|
70
|
+
onPress?: () => void;
|
|
71
|
+
}
|