@ankhorage/zora 1.4.7 → 1.4.8

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.
Files changed (46) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +143 -0
  3. package/dist/components/card/meta.d.ts +1 -1
  4. package/dist/foundation/meta.d.ts +4 -4
  5. package/dist/index.d.ts +2 -0
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +1 -0
  8. package/dist/index.js.map +1 -1
  9. package/dist/layout/auth-layout/meta.d.ts +1 -1
  10. package/dist/layout/page/meta.d.ts +1 -1
  11. package/dist/layout/page-section/meta.d.ts +1 -1
  12. package/dist/metadata/allowedChildren.d.ts +3 -3
  13. package/dist/metadata/allowedChildren.d.ts.map +1 -1
  14. package/dist/metadata/allowedChildren.js +1 -0
  15. package/dist/metadata/allowedChildren.js.map +1 -1
  16. package/dist/metadata/componentMeta.d.ts.map +1 -1
  17. package/dist/metadata/componentMeta.js +2 -0
  18. package/dist/metadata/componentMeta.js.map +1 -1
  19. package/dist/patterns/notice/meta.d.ts +1 -1
  20. package/dist/patterns/panel/meta.d.ts +1 -1
  21. package/dist/patterns/post-card/PostCard.d.ts +4 -0
  22. package/dist/patterns/post-card/PostCard.d.ts.map +1 -0
  23. package/dist/patterns/post-card/PostCard.js +133 -0
  24. package/dist/patterns/post-card/PostCard.js.map +1 -0
  25. package/dist/patterns/post-card/index.d.ts +3 -0
  26. package/dist/patterns/post-card/index.d.ts.map +1 -0
  27. package/dist/patterns/post-card/index.js +2 -0
  28. package/dist/patterns/post-card/index.js.map +1 -0
  29. package/dist/patterns/post-card/meta.d.ts +64 -0
  30. package/dist/patterns/post-card/meta.d.ts.map +1 -0
  31. package/dist/patterns/post-card/meta.js +66 -0
  32. package/dist/patterns/post-card/meta.js.map +1 -0
  33. package/dist/patterns/post-card/types.d.ts +64 -0
  34. package/dist/patterns/post-card/types.d.ts.map +1 -0
  35. package/dist/patterns/post-card/types.js +2 -0
  36. package/dist/patterns/post-card/types.js.map +1 -0
  37. package/package.json +1 -1
  38. package/src/index.ts +9 -0
  39. package/src/metadata/allowedChildren.ts +1 -0
  40. package/src/metadata/componentMeta.test.ts +1 -0
  41. package/src/metadata/componentMeta.ts +2 -0
  42. package/src/patterns/post-card/PostCard.test.tsx +11 -0
  43. package/src/patterns/post-card/PostCard.tsx +234 -0
  44. package/src/patterns/post-card/index.ts +9 -0
  45. package/src/patterns/post-card/meta.ts +68 -0
  46. package/src/patterns/post-card/types.ts +71 -0
@@ -0,0 +1,133 @@
1
+ import React from 'react';
2
+ import { Image as ReactNativeImage } from 'react-native';
3
+ import { Avatar } from '../../components/avatar';
4
+ import { Button } from '../../components/button';
5
+ import { Card } from '../../components/card';
6
+ import { Text } from '../../components/text';
7
+ import { Box, Divider, Inline, Stack } from '../../foundation';
8
+ import { useZoraTheme } from '../../theme/useZoraTheme';
9
+ import { withZoraThemeScope } from '../../theme/withZoraThemeScope';
10
+ function resolveAuthorName(author) {
11
+ return typeof author.name === 'string' ? author.name : author.avatar?.name;
12
+ }
13
+ function resolveMediaAspectRatio(aspectRatio) {
14
+ if (aspectRatio === undefined || !Number.isFinite(aspectRatio) || aspectRatio <= 0) {
15
+ return 16 / 9;
16
+ }
17
+ return aspectRatio;
18
+ }
19
+ function isPostCardMediaList(media) {
20
+ return Array.isArray(media);
21
+ }
22
+ function normalizeMedia(media) {
23
+ if (!media) {
24
+ return [];
25
+ }
26
+ if (isPostCardMediaList(media)) {
27
+ return media;
28
+ }
29
+ return [media];
30
+ }
31
+ function PostCardAuthor({ author, compact = false }) {
32
+ const avatarName = resolveAuthorName(author);
33
+ const { avatar } = author;
34
+ return (<Inline align="center" gap="s" wrap="nowrap">
35
+ <Avatar initials={avatar?.initials} label={avatar?.label ?? avatarName} name={avatarName} shape={avatar?.shape} size={avatar?.size ?? (compact ? 's' : 'm')} source={avatar?.source} tone={avatar?.tone}/>
36
+ <Box flex={1}>
37
+ <Stack gap="xxs">
38
+ <Text variant="bodySmall" weight="semiBold">
39
+ {author.name}
40
+ </Text>
41
+ {author.subtitle ? (<Text tone="muted" variant="caption">
42
+ {author.subtitle}
43
+ </Text>) : null}
44
+ </Stack>
45
+ </Box>
46
+ </Inline>);
47
+ }
48
+ function PostCardMediaItem({ media }) {
49
+ const { theme } = useZoraTheme();
50
+ const aspectRatio = resolveMediaAspectRatio(media.aspectRatio);
51
+ if (!('source' in media)) {
52
+ return (<Box radius="m" style={{ overflow: 'hidden' }}>
53
+ {media.children}
54
+ </Box>);
55
+ }
56
+ return (<Box bg={theme.semantics.neutral.surface} radius="m" style={{ overflow: 'hidden' }}>
57
+ <Box style={{ aspectRatio, width: '100%' }}>
58
+ <ReactNativeImage accessibilityLabel={media.label} source={media.source} style={{ height: '100%', width: '100%' }}/>
59
+ </Box>
60
+ </Box>);
61
+ }
62
+ function PostActionLabel({ action }) {
63
+ if (!action.count) {
64
+ return <>{action.label}</>;
65
+ }
66
+ return (<>
67
+ {action.label} {action.count}
68
+ </>);
69
+ }
70
+ function PostCardActions({ actions }) {
71
+ if (actions.length === 0) {
72
+ return null;
73
+ }
74
+ return (<Inline align="center" gap="s" wrap="wrap">
75
+ {actions.map((action) => (<Button key={action.id} disabled={action.disabled} emphasis={action.selected ? 'soft' : 'ghost'} leadingIcon={action.icon} onPress={action.onPress} size="s" tone={action.selected ? 'primary' : 'neutral'}>
76
+ <PostActionLabel action={action}/>
77
+ </Button>))}
78
+ </Inline>);
79
+ }
80
+ function PostCommentPreviewItem({ comment }) {
81
+ return (<Inline align="flex-start" gap="s" wrap="nowrap">
82
+ {comment.author ? <PostCardAuthor author={comment.author} compact/> : null}
83
+ <Box flex={1}>
84
+ <Stack gap="xxs">
85
+ <Text variant="bodySmall">{comment.text}</Text>
86
+ {comment.meta ? (<Text tone="subtle" variant="caption">
87
+ {comment.meta}
88
+ </Text>) : null}
89
+ {comment.action ? <Box>{comment.action}</Box> : null}
90
+ </Stack>
91
+ </Box>
92
+ </Inline>);
93
+ }
94
+ function PostCardComments({ comments }) {
95
+ if (comments.length === 0) {
96
+ return null;
97
+ }
98
+ return (<Stack gap="s">
99
+ {comments.map((comment) => (<PostCommentPreviewItem key={comment.id} comment={comment}/>))}
100
+ </Stack>);
101
+ }
102
+ function PostCardInner({ themeId: _themeId, mode: _mode, testID, author, text, children, media, actions = [], comments = [], headerAction, footer, tone = 'default', compact = false, onPress, }) {
103
+ const mediaItems = normalizeMedia(media);
104
+ const gap = compact ? 's' : 'm';
105
+ const isInteractive = Boolean(onPress) && !headerAction;
106
+ const hasBody = text != null || children != null || mediaItems.length > 0;
107
+ const hasEngagement = actions.length > 0 || comments.length > 0;
108
+ return (<Card compact={compact} onPress={isInteractive ? onPress : undefined} testID={testID} tone={tone}>
109
+ <Stack gap={gap}>
110
+ <Inline align="center" gap="m" justify="space-between" wrap="nowrap">
111
+ <Box flex={1}>
112
+ <PostCardAuthor author={author} compact={compact}/>
113
+ </Box>
114
+ {headerAction ? <Box>{headerAction}</Box> : null}
115
+ </Inline>
116
+
117
+ {hasBody ? (<Stack gap={gap}>
118
+ {text ? <Text variant="body">{text}</Text> : null}
119
+ {children ? <Box>{children}</Box> : null}
120
+ {mediaItems.length > 0 ? (<Stack gap="s">
121
+ {mediaItems.map((item, index) => (<PostCardMediaItem key={`${index}`} media={item}/>))}
122
+ </Stack>) : null}
123
+ </Stack>) : null}
124
+
125
+ {hasEngagement ? <Divider /> : null}
126
+ <PostCardActions actions={actions}/>
127
+ <PostCardComments comments={comments}/>
128
+ {footer ? <Box pt="xs">{footer}</Box> : null}
129
+ </Stack>
130
+ </Card>);
131
+ }
132
+ export const PostCard = withZoraThemeScope(PostCardInner);
133
+ //# sourceMappingURL=PostCard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PostCard.js","sourceRoot":"","sources":["../../../src/patterns/post-card/PostCard.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from 'react';\nimport { Image as ReactNativeImage } from 'react-native';\n\nimport { Avatar } from '../../components/avatar';\nimport { Button } from '../../components/button';\nimport { Card } from '../../components/card';\nimport { Text } from '../../components/text';\nimport { Box, Divider, Inline, Stack } from '../../foundation';\nimport { useZoraTheme } from '../../theme/useZoraTheme';\nimport { withZoraThemeScope } from '../../theme/withZoraThemeScope';\nimport type {\n PostAction,\n PostAuthor,\n PostCardMedia,\n PostCardProps,\n PostCommentPreview,\n} from './types';\n\nfunction resolveAuthorName(author: PostAuthor): string | undefined {\n return typeof author.name === 'string' ? author.name : author.avatar?.name;\n}\n\nfunction resolveMediaAspectRatio(aspectRatio: number | undefined): number {\n if (aspectRatio === undefined || !Number.isFinite(aspectRatio) || aspectRatio <= 0) {\n return 16 / 9;\n }\n\n return aspectRatio;\n}\n\nfunction isPostCardMediaList(\n media: NonNullable<PostCardProps['media']>,\n): media is readonly PostCardMedia[] {\n return Array.isArray(media);\n}\n\nfunction normalizeMedia(media: PostCardProps['media']): readonly PostCardMedia[] {\n if (!media) {\n return [];\n }\n\n if (isPostCardMediaList(media)) {\n return media;\n }\n\n return [media];\n}\n\nfunction PostCardAuthor({ author, compact = false }: { author: PostAuthor; compact?: boolean }) {\n const avatarName = resolveAuthorName(author);\n const { avatar } = author;\n\n return (\n <Inline align=\"center\" gap=\"s\" wrap=\"nowrap\">\n <Avatar\n initials={avatar?.initials}\n label={avatar?.label ?? avatarName}\n name={avatarName}\n shape={avatar?.shape}\n size={avatar?.size ?? (compact ? 's' : 'm')}\n source={avatar?.source}\n tone={avatar?.tone}\n />\n <Box flex={1}>\n <Stack gap=\"xxs\">\n <Text variant=\"bodySmall\" weight=\"semiBold\">\n {author.name}\n </Text>\n {author.subtitle ? (\n <Text tone=\"muted\" variant=\"caption\">\n {author.subtitle}\n </Text>\n ) : null}\n </Stack>\n </Box>\n </Inline>\n );\n}\n\nfunction PostCardMediaItem({ media }: { media: PostCardMedia }) {\n const { theme } = useZoraTheme();\n const aspectRatio = resolveMediaAspectRatio(media.aspectRatio);\n\n if (!('source' in media)) {\n return (\n <Box radius=\"m\" style={{ overflow: 'hidden' }}>\n {media.children}\n </Box>\n );\n }\n\n return (\n <Box bg={theme.semantics.neutral.surface} radius=\"m\" style={{ overflow: 'hidden' }}>\n <Box style={{ aspectRatio, width: '100%' }}>\n <ReactNativeImage\n accessibilityLabel={media.label}\n source={media.source}\n style={{ height: '100%', width: '100%' }}\n />\n </Box>\n </Box>\n );\n}\n\nfunction PostActionLabel({ action }: { action: PostAction }) {\n if (!action.count) {\n return <>{action.label}</>;\n }\n\n return (\n <>\n {action.label} {action.count}\n </>\n );\n}\n\nfunction PostCardActions({ actions }: { actions: readonly PostAction[] }) {\n if (actions.length === 0) {\n return null;\n }\n\n return (\n <Inline align=\"center\" gap=\"s\" wrap=\"wrap\">\n {actions.map((action) => (\n <Button\n key={action.id}\n disabled={action.disabled}\n emphasis={action.selected ? 'soft' : 'ghost'}\n leadingIcon={action.icon}\n onPress={action.onPress}\n size=\"s\"\n tone={action.selected ? 'primary' : 'neutral'}\n >\n <PostActionLabel action={action} />\n </Button>\n ))}\n </Inline>\n );\n}\n\nfunction PostCommentPreviewItem({ comment }: { comment: PostCommentPreview }) {\n return (\n <Inline align=\"flex-start\" gap=\"s\" wrap=\"nowrap\">\n {comment.author ? <PostCardAuthor author={comment.author} compact /> : null}\n <Box flex={1}>\n <Stack gap=\"xxs\">\n <Text variant=\"bodySmall\">{comment.text}</Text>\n {comment.meta ? (\n <Text tone=\"subtle\" variant=\"caption\">\n {comment.meta}\n </Text>\n ) : null}\n {comment.action ? <Box>{comment.action}</Box> : null}\n </Stack>\n </Box>\n </Inline>\n );\n}\n\nfunction PostCardComments({ comments }: { comments: readonly PostCommentPreview[] }) {\n if (comments.length === 0) {\n return null;\n }\n\n return (\n <Stack gap=\"s\">\n {comments.map((comment) => (\n <PostCommentPreviewItem key={comment.id} comment={comment} />\n ))}\n </Stack>\n );\n}\n\nfunction PostCardInner({\n themeId: _themeId,\n mode: _mode,\n testID,\n author,\n text,\n children,\n media,\n actions = [],\n comments = [],\n headerAction,\n footer,\n tone = 'default',\n compact = false,\n onPress,\n}: PostCardProps) {\n const mediaItems = normalizeMedia(media);\n const gap = compact ? 's' : 'm';\n const isInteractive = Boolean(onPress) && !headerAction;\n const hasBody = text != null || children != null || mediaItems.length > 0;\n const hasEngagement = actions.length > 0 || comments.length > 0;\n\n return (\n <Card\n compact={compact}\n onPress={isInteractive ? onPress : undefined}\n testID={testID}\n tone={tone}\n >\n <Stack gap={gap}>\n <Inline align=\"center\" gap=\"m\" justify=\"space-between\" wrap=\"nowrap\">\n <Box flex={1}>\n <PostCardAuthor author={author} compact={compact} />\n </Box>\n {headerAction ? <Box>{headerAction}</Box> : null}\n </Inline>\n\n {hasBody ? (\n <Stack gap={gap}>\n {text ? <Text variant=\"body\">{text}</Text> : null}\n {children ? <Box>{children}</Box> : null}\n {mediaItems.length > 0 ? (\n <Stack gap=\"s\">\n {mediaItems.map((item, index) => (\n <PostCardMediaItem key={`${index}`} media={item} />\n ))}\n </Stack>\n ) : null}\n </Stack>\n ) : null}\n\n {hasEngagement ? <Divider /> : null}\n <PostCardActions actions={actions} />\n <PostCardComments comments={comments} />\n {footer ? <Box pt=\"xs\">{footer}</Box> : null}\n </Stack>\n </Card>\n );\n}\n\nexport const PostCard = withZoraThemeScope(PostCardInner);\n"]}
@@ -0,0 +1,3 @@
1
+ export { PostCard } from './PostCard';
2
+ export type { PostAction, PostAuthor, PostAuthorAvatar, PostCardMedia, PostCardProps, PostCommentPreview, } from './types';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/patterns/post-card/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,YAAY,EACV,UAAU,EACV,UAAU,EACV,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,kBAAkB,GACnB,MAAM,SAAS,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { PostCard } from './PostCard';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/patterns/post-card/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC","sourcesContent":["export { PostCard } from './PostCard';\nexport type {\n PostAction,\n PostAuthor,\n PostAuthorAvatar,\n PostCardMedia,\n PostCardProps,\n PostCommentPreview,\n} from './types';\n"]}
@@ -0,0 +1,64 @@
1
+ export declare const postCardMeta: {
2
+ readonly name: "PostCard";
3
+ readonly category: "pattern";
4
+ readonly description: "Social/content post card with author identity, body, media, actions, and comment previews.";
5
+ readonly directManifestNode: true;
6
+ readonly allowedChildren: readonly ["Box", "Stack", "Grid", "Container", "Divider", "Text", "Heading", "Button", "Input", "Textarea", "FormField", "Card", "Panel", "Notice", "EmptyState", "SectionHeader", "SettingsRow", "PostCard"];
7
+ readonly blueprint: {
8
+ readonly label: "Post card";
9
+ readonly icon: {
10
+ readonly name: "chatbubble-ellipses-outline";
11
+ };
12
+ readonly defaultProps: {
13
+ readonly author: {
14
+ readonly name: "Ada Lovelace";
15
+ readonly subtitle: "@ada · 2h";
16
+ readonly avatar: {
17
+ readonly name: "Ada Lovelace";
18
+ };
19
+ };
20
+ readonly text: "Share an update, image, or announcement with a reusable ZORA PostCard.";
21
+ };
22
+ };
23
+ readonly props: {
24
+ readonly author: {
25
+ readonly type: "array";
26
+ readonly category: "Content";
27
+ readonly label: "Author";
28
+ readonly itemSchema: readonly [{
29
+ readonly key: "name";
30
+ readonly schema: {
31
+ readonly type: "string";
32
+ readonly category: "Content";
33
+ readonly label: "Name";
34
+ };
35
+ }, {
36
+ readonly key: "subtitle";
37
+ readonly schema: {
38
+ readonly type: "string";
39
+ readonly category: "Content";
40
+ readonly label: "Subtitle";
41
+ };
42
+ }];
43
+ };
44
+ readonly text: {
45
+ readonly type: "string";
46
+ readonly category: "Content";
47
+ readonly label: "Text";
48
+ };
49
+ readonly compact: {
50
+ readonly type: "boolean";
51
+ readonly category: "Layout";
52
+ readonly label: "Compact";
53
+ readonly default: false;
54
+ };
55
+ readonly tone: {
56
+ readonly type: "enum";
57
+ readonly category: "Style";
58
+ readonly label: "Tone";
59
+ readonly enum: readonly ["default", "subtle", "outline"];
60
+ readonly default: "default";
61
+ };
62
+ };
63
+ };
64
+ //# sourceMappingURL=meta.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"meta.d.ts","sourceRoot":"","sources":["../../../src/patterns/post-card/meta.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgEa,CAAC"}
@@ -0,0 +1,66 @@
1
+ import { CONTAINER_ALLOWED_CHILDREN } from '../../metadata/allowedChildren';
2
+ export const postCardMeta = {
3
+ name: 'PostCard',
4
+ category: 'pattern',
5
+ description: 'Social/content post card with author identity, body, media, actions, and comment previews.',
6
+ directManifestNode: true,
7
+ allowedChildren: [...CONTAINER_ALLOWED_CHILDREN],
8
+ blueprint: {
9
+ label: 'Post card',
10
+ icon: { name: 'chatbubble-ellipses-outline' },
11
+ defaultProps: {
12
+ author: {
13
+ name: 'Ada Lovelace',
14
+ subtitle: '@ada · 2h',
15
+ avatar: {
16
+ name: 'Ada Lovelace',
17
+ },
18
+ },
19
+ text: 'Share an update, image, or announcement with a reusable ZORA PostCard.',
20
+ },
21
+ },
22
+ props: {
23
+ author: {
24
+ type: 'array',
25
+ category: 'Content',
26
+ label: 'Author',
27
+ itemSchema: [
28
+ {
29
+ key: 'name',
30
+ schema: {
31
+ type: 'string',
32
+ category: 'Content',
33
+ label: 'Name',
34
+ },
35
+ },
36
+ {
37
+ key: 'subtitle',
38
+ schema: {
39
+ type: 'string',
40
+ category: 'Content',
41
+ label: 'Subtitle',
42
+ },
43
+ },
44
+ ],
45
+ },
46
+ text: {
47
+ type: 'string',
48
+ category: 'Content',
49
+ label: 'Text',
50
+ },
51
+ compact: {
52
+ type: 'boolean',
53
+ category: 'Layout',
54
+ label: 'Compact',
55
+ default: false,
56
+ },
57
+ tone: {
58
+ type: 'enum',
59
+ category: 'Style',
60
+ label: 'Tone',
61
+ enum: ['default', 'subtle', 'outline'],
62
+ default: 'default',
63
+ },
64
+ },
65
+ };
66
+ //# sourceMappingURL=meta.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"meta.js","sourceRoot":"","sources":["../../../src/patterns/post-card/meta.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,0BAA0B,EAAE,MAAM,gCAAgC,CAAC;AAE5E,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,IAAI,EAAE,UAAU;IAChB,QAAQ,EAAE,SAAS;IACnB,WAAW,EACT,4FAA4F;IAC9F,kBAAkB,EAAE,IAAI;IACxB,eAAe,EAAE,CAAC,GAAG,0BAA0B,CAAC;IAChD,SAAS,EAAE;QACT,KAAK,EAAE,WAAW;QAClB,IAAI,EAAE,EAAE,IAAI,EAAE,6BAA6B,EAAE;QAC7C,YAAY,EAAE;YACZ,MAAM,EAAE;gBACN,IAAI,EAAE,cAAc;gBACpB,QAAQ,EAAE,WAAW;gBACrB,MAAM,EAAE;oBACN,IAAI,EAAE,cAAc;iBACrB;aACF;YACD,IAAI,EAAE,wEAAwE;SAC/E;KACF;IACD,KAAK,EAAE;QACL,MAAM,EAAE;YACN,IAAI,EAAE,OAAO;YACb,QAAQ,EAAE,SAAS;YACnB,KAAK,EAAE,QAAQ;YACf,UAAU,EAAE;gBACV;oBACE,GAAG,EAAE,MAAM;oBACX,MAAM,EAAE;wBACN,IAAI,EAAE,QAAQ;wBACd,QAAQ,EAAE,SAAS;wBACnB,KAAK,EAAE,MAAM;qBACd;iBACF;gBACD;oBACE,GAAG,EAAE,UAAU;oBACf,MAAM,EAAE;wBACN,IAAI,EAAE,QAAQ;wBACd,QAAQ,EAAE,SAAS;wBACnB,KAAK,EAAE,UAAU;qBAClB;iBACF;aACF;SACF;QACD,IAAI,EAAE;YACJ,IAAI,EAAE,QAAQ;YACd,QAAQ,EAAE,SAAS;YACnB,KAAK,EAAE,MAAM;SACd;QACD,OAAO,EAAE;YACP,IAAI,EAAE,SAAS;YACf,QAAQ,EAAE,QAAQ;YAClB,KAAK,EAAE,SAAS;YAChB,OAAO,EAAE,KAAK;SACf;QACD,IAAI,EAAE;YACJ,IAAI,EAAE,MAAM;YACZ,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,MAAM;YACb,IAAI,EAAE,CAAC,SAAS,EAAE,QAAQ,EAAE,SAAS,CAAC;YACtC,OAAO,EAAE,SAAS;SACnB;KACF;CACmC,CAAC","sourcesContent":["import type { ZoraComponentMeta } from '../../metadata';\nimport { CONTAINER_ALLOWED_CHILDREN } from '../../metadata/allowedChildren';\n\nexport const postCardMeta = {\n name: 'PostCard',\n category: 'pattern',\n description:\n 'Social/content post card with author identity, body, media, actions, and comment previews.',\n directManifestNode: true,\n allowedChildren: [...CONTAINER_ALLOWED_CHILDREN],\n blueprint: {\n label: 'Post card',\n icon: { name: 'chatbubble-ellipses-outline' },\n defaultProps: {\n author: {\n name: 'Ada Lovelace',\n subtitle: '@ada · 2h',\n avatar: {\n name: 'Ada Lovelace',\n },\n },\n text: 'Share an update, image, or announcement with a reusable ZORA PostCard.',\n },\n },\n props: {\n author: {\n type: 'array',\n category: 'Content',\n label: 'Author',\n itemSchema: [\n {\n key: 'name',\n schema: {\n type: 'string',\n category: 'Content',\n label: 'Name',\n },\n },\n {\n key: 'subtitle',\n schema: {\n type: 'string',\n category: 'Content',\n label: 'Subtitle',\n },\n },\n ],\n },\n text: {\n type: 'string',\n category: 'Content',\n label: 'Text',\n },\n compact: {\n type: 'boolean',\n category: 'Layout',\n label: 'Compact',\n default: false,\n },\n tone: {\n type: 'enum',\n category: 'Style',\n label: 'Tone',\n enum: ['default', 'subtle', 'outline'],\n default: 'default',\n },\n },\n} as const satisfies ZoraComponentMeta;\n"]}
@@ -0,0 +1,64 @@
1
+ import type { ButtonIconSpec } from '@ankhorage/surface';
2
+ import type React from 'react';
3
+ import type { ImageSourcePropType } from 'react-native';
4
+ import type { AvatarShape, AvatarSize } from '../../components/avatar';
5
+ import type { ZoraCardTone, ZoraTone } from '../../internal/recipes';
6
+ import type { ZoraBaseProps } from '../../theme/ZoraBaseProps';
7
+ export interface PostAuthorAvatar {
8
+ source?: ImageSourcePropType;
9
+ name?: string;
10
+ initials?: string;
11
+ label?: string;
12
+ size?: AvatarSize;
13
+ shape?: AvatarShape;
14
+ tone?: ZoraTone;
15
+ }
16
+ export interface PostAuthor {
17
+ name: React.ReactNode;
18
+ subtitle?: React.ReactNode;
19
+ avatar?: PostAuthorAvatar;
20
+ }
21
+ interface PostCardSourceMedia {
22
+ source: ImageSourcePropType;
23
+ label: string;
24
+ aspectRatio?: number;
25
+ children?: never;
26
+ }
27
+ interface PostCardCustomMedia {
28
+ children: React.ReactNode;
29
+ label?: string;
30
+ aspectRatio?: number;
31
+ source?: never;
32
+ }
33
+ export type PostCardMedia = PostCardSourceMedia | PostCardCustomMedia;
34
+ export interface PostAction {
35
+ id: string;
36
+ label: string;
37
+ icon?: ButtonIconSpec;
38
+ count?: React.ReactNode;
39
+ selected?: boolean;
40
+ disabled?: boolean;
41
+ onPress?: () => void;
42
+ }
43
+ export interface PostCommentPreview {
44
+ id: string;
45
+ author?: PostAuthor;
46
+ text: React.ReactNode;
47
+ meta?: React.ReactNode;
48
+ action?: React.ReactNode;
49
+ }
50
+ export interface PostCardProps extends ZoraBaseProps {
51
+ author: PostAuthor;
52
+ text?: React.ReactNode;
53
+ children?: React.ReactNode;
54
+ media?: PostCardMedia | readonly PostCardMedia[];
55
+ actions?: readonly PostAction[];
56
+ comments?: readonly PostCommentPreview[];
57
+ headerAction?: React.ReactNode;
58
+ footer?: React.ReactNode;
59
+ tone?: ZoraCardTone;
60
+ compact?: boolean;
61
+ onPress?: () => void;
62
+ }
63
+ export {};
64
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/patterns/post-card/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAExD,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACvE,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACrE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE/D,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,IAAI,CAAC,EAAE,QAAQ,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC;IACtB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,MAAM,CAAC,EAAE,gBAAgB,CAAC;CAC3B;AAED,UAAU,mBAAmB;IAC3B,MAAM,EAAE,mBAAmB,CAAC;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,KAAK,CAAC;CAClB;AAED,UAAU,mBAAmB;IAC3B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,KAAK,CAAC;CAChB;AAED,MAAM,MAAM,aAAa,GAAG,mBAAmB,GAAG,mBAAmB,CAAC;AAEtE,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC;IACtB,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC1B;AAED,MAAM,WAAW,aAAc,SAAQ,aAAa;IAClD,MAAM,EAAE,UAAU,CAAC;IACnB,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,KAAK,CAAC,EAAE,aAAa,GAAG,SAAS,aAAa,EAAE,CAAC;IACjD,OAAO,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;IAChC,QAAQ,CAAC,EAAE,SAAS,kBAAkB,EAAE,CAAC;IACzC,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC/B,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/patterns/post-card/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { ButtonIconSpec } from '@ankhorage/surface';\nimport type React from 'react';\nimport type { ImageSourcePropType } from 'react-native';\n\nimport type { AvatarShape, AvatarSize } from '../../components/avatar';\nimport type { ZoraCardTone, ZoraTone } from '../../internal/recipes';\nimport type { ZoraBaseProps } from '../../theme/ZoraBaseProps';\n\nexport interface PostAuthorAvatar {\n source?: ImageSourcePropType;\n name?: string;\n initials?: string;\n label?: string;\n size?: AvatarSize;\n shape?: AvatarShape;\n tone?: ZoraTone;\n}\n\nexport interface PostAuthor {\n name: React.ReactNode;\n subtitle?: React.ReactNode;\n avatar?: PostAuthorAvatar;\n}\n\ninterface PostCardSourceMedia {\n source: ImageSourcePropType;\n label: string;\n aspectRatio?: number;\n children?: never;\n}\n\ninterface PostCardCustomMedia {\n children: React.ReactNode;\n label?: string;\n aspectRatio?: number;\n source?: never;\n}\n\nexport type PostCardMedia = PostCardSourceMedia | PostCardCustomMedia;\n\nexport interface PostAction {\n id: string;\n label: string;\n icon?: ButtonIconSpec;\n count?: React.ReactNode;\n selected?: boolean;\n disabled?: boolean;\n onPress?: () => void;\n}\n\nexport interface PostCommentPreview {\n id: string;\n author?: PostAuthor;\n text: React.ReactNode;\n meta?: React.ReactNode;\n action?: React.ReactNode;\n}\n\nexport interface PostCardProps extends ZoraBaseProps {\n author: PostAuthor;\n text?: React.ReactNode;\n children?: React.ReactNode;\n media?: PostCardMedia | readonly PostCardMedia[];\n actions?: readonly PostAction[];\n comments?: readonly PostCommentPreview[];\n headerAction?: React.ReactNode;\n footer?: React.ReactNode;\n tone?: ZoraCardTone;\n compact?: boolean;\n onPress?: () => void;\n}\n"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ankhorage/zora",
3
3
  "type": "module",
4
- "version": "1.4.7",
4
+ "version": "1.4.8",
5
5
  "description": "Opinionated React Native and React Native Web UI kit built on @ankhorage/surface.",
6
6
  "homepage": "https://github.com/ankhorage/zora#readme",
7
7
  "bugs": {
package/src/index.ts CHANGED
@@ -205,6 +205,15 @@ export type { NoticeProps } from './patterns/notice';
205
205
  export { Notice } from './patterns/notice';
206
206
  export type { PanelProps } from './patterns/panel';
207
207
  export { Panel } from './patterns/panel';
208
+ export type {
209
+ PostAction,
210
+ PostAuthor,
211
+ PostAuthorAvatar,
212
+ PostCardMedia,
213
+ PostCardProps,
214
+ PostCommentPreview,
215
+ } from './patterns/post-card';
216
+ export { PostCard } from './patterns/post-card';
208
217
  export type {
209
218
  ResponsivePanelDesktopMode,
210
219
  ResponsivePanelMobileMode,
@@ -16,6 +16,7 @@ export const CONTAINER_ALLOWED_CHILDREN = [
16
16
  'EmptyState',
17
17
  'SectionHeader',
18
18
  'SettingsRow',
19
+ 'PostCard',
19
20
  ] as const;
20
21
 
21
22
  export const PAGE_SECTION_ALLOWED_CHILDREN = [...CONTAINER_ALLOWED_CHILDREN] as const;
@@ -151,6 +151,7 @@ describe('ZORA_COMPONENT_META invariants', () => {
151
151
  'Card',
152
152
  'Panel',
153
153
  'Notice',
154
+ 'PostCard',
154
155
  'Box',
155
156
  'Stack',
156
157
  'Grid',
@@ -55,6 +55,7 @@ import { inspectorFieldMeta } from '../patterns/inspector-field/meta';
55
55
  import { listMeta, listRowMeta, listSectionMeta } from '../patterns/list/meta';
56
56
  import { noticeMeta } from '../patterns/notice/meta';
57
57
  import { panelMeta } from '../patterns/panel/meta';
58
+ import { postCardMeta } from '../patterns/post-card/meta';
58
59
  import { responsivePanelMeta } from '../patterns/responsive-panel/meta';
59
60
  import { sectionHeaderMeta } from '../patterns/section-header/meta';
60
61
  import { selectableItemMeta, selectionProviderMeta } from '../patterns/selection/meta';
@@ -132,6 +133,7 @@ export const ZORA_COMPONENT_META: ZoraComponentMetaRegistry = {
132
133
  ListSection: listSectionMeta,
133
134
  Notice: noticeMeta,
134
135
  Panel: panelMeta,
136
+ PostCard: postCardMeta,
135
137
  ResponsivePanel: responsivePanelMeta,
136
138
  SectionHeader: sectionHeaderMeta,
137
139
  SelectableItem: selectableItemMeta,
@@ -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
+ });