@ankhorage/zora 1.4.8 → 1.4.10
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 +222 -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/message-bubble/MessageBubble.d.ts +4 -0
- package/dist/patterns/message-bubble/MessageBubble.d.ts.map +1 -0
- package/dist/patterns/message-bubble/MessageBubble.js +126 -0
- package/dist/patterns/message-bubble/MessageBubble.js.map +1 -0
- package/dist/patterns/message-bubble/index.d.ts +3 -0
- package/dist/patterns/message-bubble/index.d.ts.map +1 -0
- package/dist/patterns/message-bubble/index.js +2 -0
- package/dist/patterns/message-bubble/index.js.map +1 -0
- package/dist/patterns/message-bubble/meta.d.ts +67 -0
- package/dist/patterns/message-bubble/meta.d.ts.map +1 -0
- package/dist/patterns/message-bubble/meta.js +66 -0
- package/dist/patterns/message-bubble/meta.js.map +1 -0
- package/dist/patterns/message-bubble/types.d.ts +40 -0
- package/dist/patterns/message-bubble/types.d.ts.map +1 -0
- package/dist/patterns/message-bubble/types.js +2 -0
- package/dist/patterns/message-bubble/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/meta.d.ts +1 -1
- package/package.json +1 -1
- package/src/index.ts +10 -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/message-bubble/MessageBubble.tsx +261 -0
- package/src/patterns/message-bubble/index.ts +8 -0
- package/src/patterns/message-bubble/meta.ts +68 -0
- package/src/patterns/message-bubble/types.ts +43 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/patterns/message-bubble/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC","sourcesContent":["export { MessageBubble } from './MessageBubble';\nexport type {\n MessageBubbleAuthor,\n MessageBubbleAvatar,\n MessageBubbleDirection,\n MessageBubbleProps,\n MessageBubbleStatus,\n} from './types';\n"]}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
export declare const messageBubbleMeta: {
|
|
2
|
+
readonly name: "MessageBubble";
|
|
3
|
+
readonly category: "pattern";
|
|
4
|
+
readonly description: "Chat/message bubble with direction, author, text, meta, and delivery status presentation.";
|
|
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", "ChatListItem", "MessageBubble"];
|
|
7
|
+
readonly blueprint: {
|
|
8
|
+
readonly label: "Message bubble";
|
|
9
|
+
readonly icon: {
|
|
10
|
+
readonly name: "chatbubble-outline";
|
|
11
|
+
};
|
|
12
|
+
readonly defaultProps: {
|
|
13
|
+
readonly direction: "incoming";
|
|
14
|
+
readonly text: "Can you review the latest message pattern?";
|
|
15
|
+
readonly timestamp: "10:41";
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
readonly props: {
|
|
19
|
+
readonly direction: {
|
|
20
|
+
readonly type: "enum";
|
|
21
|
+
readonly category: "Content";
|
|
22
|
+
readonly label: "Direction";
|
|
23
|
+
readonly enum: readonly ["incoming", "outgoing", "system"];
|
|
24
|
+
readonly default: "incoming";
|
|
25
|
+
};
|
|
26
|
+
readonly text: {
|
|
27
|
+
readonly type: "string";
|
|
28
|
+
readonly category: "Content";
|
|
29
|
+
readonly label: "Text";
|
|
30
|
+
};
|
|
31
|
+
readonly timestamp: {
|
|
32
|
+
readonly type: "string";
|
|
33
|
+
readonly category: "Content";
|
|
34
|
+
readonly label: "Timestamp";
|
|
35
|
+
};
|
|
36
|
+
readonly meta: {
|
|
37
|
+
readonly type: "string";
|
|
38
|
+
readonly category: "Content";
|
|
39
|
+
readonly label: "Meta";
|
|
40
|
+
};
|
|
41
|
+
readonly status: {
|
|
42
|
+
readonly type: "enum";
|
|
43
|
+
readonly category: "Content";
|
|
44
|
+
readonly label: "Status";
|
|
45
|
+
readonly enum: readonly ["sending", "sent", "delivered", "read", "failed"];
|
|
46
|
+
};
|
|
47
|
+
readonly selected: {
|
|
48
|
+
readonly type: "boolean";
|
|
49
|
+
readonly category: "State";
|
|
50
|
+
readonly label: "Selected";
|
|
51
|
+
readonly default: false;
|
|
52
|
+
};
|
|
53
|
+
readonly disabled: {
|
|
54
|
+
readonly type: "boolean";
|
|
55
|
+
readonly category: "State";
|
|
56
|
+
readonly label: "Disabled";
|
|
57
|
+
readonly default: false;
|
|
58
|
+
};
|
|
59
|
+
readonly compact: {
|
|
60
|
+
readonly type: "boolean";
|
|
61
|
+
readonly category: "Layout";
|
|
62
|
+
readonly label: "Compact";
|
|
63
|
+
readonly default: false;
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
//# sourceMappingURL=meta.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"meta.d.ts","sourceRoot":"","sources":["../../../src/patterns/message-bubble/meta.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgEQ,CAAC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { CONTAINER_ALLOWED_CHILDREN } from '../../metadata/allowedChildren';
|
|
2
|
+
export const messageBubbleMeta = {
|
|
3
|
+
name: 'MessageBubble',
|
|
4
|
+
category: 'pattern',
|
|
5
|
+
description: 'Chat/message bubble with direction, author, text, meta, and delivery status presentation.',
|
|
6
|
+
directManifestNode: true,
|
|
7
|
+
allowedChildren: [...CONTAINER_ALLOWED_CHILDREN],
|
|
8
|
+
blueprint: {
|
|
9
|
+
label: 'Message bubble',
|
|
10
|
+
icon: { name: 'chatbubble-outline' },
|
|
11
|
+
defaultProps: {
|
|
12
|
+
direction: 'incoming',
|
|
13
|
+
text: 'Can you review the latest message pattern?',
|
|
14
|
+
timestamp: '10:41',
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
props: {
|
|
18
|
+
direction: {
|
|
19
|
+
type: 'enum',
|
|
20
|
+
category: 'Content',
|
|
21
|
+
label: 'Direction',
|
|
22
|
+
enum: ['incoming', 'outgoing', 'system'],
|
|
23
|
+
default: 'incoming',
|
|
24
|
+
},
|
|
25
|
+
text: {
|
|
26
|
+
type: 'string',
|
|
27
|
+
category: 'Content',
|
|
28
|
+
label: 'Text',
|
|
29
|
+
},
|
|
30
|
+
timestamp: {
|
|
31
|
+
type: 'string',
|
|
32
|
+
category: 'Content',
|
|
33
|
+
label: 'Timestamp',
|
|
34
|
+
},
|
|
35
|
+
meta: {
|
|
36
|
+
type: 'string',
|
|
37
|
+
category: 'Content',
|
|
38
|
+
label: 'Meta',
|
|
39
|
+
},
|
|
40
|
+
status: {
|
|
41
|
+
type: 'enum',
|
|
42
|
+
category: 'Content',
|
|
43
|
+
label: 'Status',
|
|
44
|
+
enum: ['sending', 'sent', 'delivered', 'read', 'failed'],
|
|
45
|
+
},
|
|
46
|
+
selected: {
|
|
47
|
+
type: 'boolean',
|
|
48
|
+
category: 'State',
|
|
49
|
+
label: 'Selected',
|
|
50
|
+
default: false,
|
|
51
|
+
},
|
|
52
|
+
disabled: {
|
|
53
|
+
type: 'boolean',
|
|
54
|
+
category: 'State',
|
|
55
|
+
label: 'Disabled',
|
|
56
|
+
default: false,
|
|
57
|
+
},
|
|
58
|
+
compact: {
|
|
59
|
+
type: 'boolean',
|
|
60
|
+
category: 'Layout',
|
|
61
|
+
label: 'Compact',
|
|
62
|
+
default: false,
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
//# sourceMappingURL=meta.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"meta.js","sourceRoot":"","sources":["../../../src/patterns/message-bubble/meta.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,0BAA0B,EAAE,MAAM,gCAAgC,CAAC;AAE5E,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,IAAI,EAAE,eAAe;IACrB,QAAQ,EAAE,SAAS;IACnB,WAAW,EACT,2FAA2F;IAC7F,kBAAkB,EAAE,IAAI;IACxB,eAAe,EAAE,CAAC,GAAG,0BAA0B,CAAC;IAChD,SAAS,EAAE;QACT,KAAK,EAAE,gBAAgB;QACvB,IAAI,EAAE,EAAE,IAAI,EAAE,oBAAoB,EAAE;QACpC,YAAY,EAAE;YACZ,SAAS,EAAE,UAAU;YACrB,IAAI,EAAE,4CAA4C;YAClD,SAAS,EAAE,OAAO;SACnB;KACF;IACD,KAAK,EAAE;QACL,SAAS,EAAE;YACT,IAAI,EAAE,MAAM;YACZ,QAAQ,EAAE,SAAS;YACnB,KAAK,EAAE,WAAW;YAClB,IAAI,EAAE,CAAC,UAAU,EAAE,UAAU,EAAE,QAAQ,CAAC;YACxC,OAAO,EAAE,UAAU;SACpB;QACD,IAAI,EAAE;YACJ,IAAI,EAAE,QAAQ;YACd,QAAQ,EAAE,SAAS;YACnB,KAAK,EAAE,MAAM;SACd;QACD,SAAS,EAAE;YACT,IAAI,EAAE,QAAQ;YACd,QAAQ,EAAE,SAAS;YACnB,KAAK,EAAE,WAAW;SACnB;QACD,IAAI,EAAE;YACJ,IAAI,EAAE,QAAQ;YACd,QAAQ,EAAE,SAAS;YACnB,KAAK,EAAE,MAAM;SACd;QACD,MAAM,EAAE;YACN,IAAI,EAAE,MAAM;YACZ,QAAQ,EAAE,SAAS;YACnB,KAAK,EAAE,QAAQ;YACf,IAAI,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,CAAC;SACzD;QACD,QAAQ,EAAE;YACR,IAAI,EAAE,SAAS;YACf,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,UAAU;YACjB,OAAO,EAAE,KAAK;SACf;QACD,QAAQ,EAAE;YACR,IAAI,EAAE,SAAS;YACf,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,UAAU;YACjB,OAAO,EAAE,KAAK;SACf;QACD,OAAO,EAAE;YACP,IAAI,EAAE,SAAS;YACf,QAAQ,EAAE,QAAQ;YAClB,KAAK,EAAE,SAAS;YAChB,OAAO,EAAE,KAAK;SACf;KACF;CACmC,CAAC","sourcesContent":["import type { ZoraComponentMeta } from '../../metadata';\nimport { CONTAINER_ALLOWED_CHILDREN } from '../../metadata/allowedChildren';\n\nexport const messageBubbleMeta = {\n name: 'MessageBubble',\n category: 'pattern',\n description:\n 'Chat/message bubble with direction, author, text, meta, and delivery status presentation.',\n directManifestNode: true,\n allowedChildren: [...CONTAINER_ALLOWED_CHILDREN],\n blueprint: {\n label: 'Message bubble',\n icon: { name: 'chatbubble-outline' },\n defaultProps: {\n direction: 'incoming',\n text: 'Can you review the latest message pattern?',\n timestamp: '10:41',\n },\n },\n props: {\n direction: {\n type: 'enum',\n category: 'Content',\n label: 'Direction',\n enum: ['incoming', 'outgoing', 'system'],\n default: 'incoming',\n },\n text: {\n type: 'string',\n category: 'Content',\n label: 'Text',\n },\n timestamp: {\n type: 'string',\n category: 'Content',\n label: 'Timestamp',\n },\n meta: {\n type: 'string',\n category: 'Content',\n label: 'Meta',\n },\n status: {\n type: 'enum',\n category: 'Content',\n label: 'Status',\n enum: ['sending', 'sent', 'delivered', 'read', 'failed'],\n },\n selected: {\n type: 'boolean',\n category: 'State',\n label: 'Selected',\n default: false,\n },\n disabled: {\n type: 'boolean',\n category: 'State',\n label: 'Disabled',\n default: false,\n },\n compact: {\n type: 'boolean',\n category: 'Layout',\n label: 'Compact',\n default: false,\n },\n },\n} as const satisfies ZoraComponentMeta;\n"]}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type React from 'react';
|
|
2
|
+
import type { ImageSourcePropType } from 'react-native';
|
|
3
|
+
import type { AvatarShape, AvatarSize } from '../../components/avatar';
|
|
4
|
+
import type { ZoraTone } from '../../internal/recipes';
|
|
5
|
+
import type { ZoraBaseProps } from '../../theme/ZoraBaseProps';
|
|
6
|
+
export type MessageBubbleDirection = 'incoming' | 'outgoing' | 'system';
|
|
7
|
+
export type MessageBubbleStatus = 'sending' | 'sent' | 'delivered' | 'read' | 'failed';
|
|
8
|
+
type MessageBubbleStatusContent = MessageBubbleStatus | Exclude<React.ReactNode, string>;
|
|
9
|
+
export interface MessageBubbleAvatar {
|
|
10
|
+
source?: ImageSourcePropType;
|
|
11
|
+
name?: string;
|
|
12
|
+
initials?: string;
|
|
13
|
+
label?: string;
|
|
14
|
+
size?: AvatarSize;
|
|
15
|
+
shape?: AvatarShape;
|
|
16
|
+
tone?: ZoraTone;
|
|
17
|
+
}
|
|
18
|
+
export interface MessageBubbleAuthor {
|
|
19
|
+
name?: React.ReactNode;
|
|
20
|
+
avatar?: MessageBubbleAvatar;
|
|
21
|
+
}
|
|
22
|
+
export interface MessageBubbleProps extends ZoraBaseProps {
|
|
23
|
+
direction?: MessageBubbleDirection;
|
|
24
|
+
text?: React.ReactNode;
|
|
25
|
+
children?: React.ReactNode;
|
|
26
|
+
author?: MessageBubbleAuthor;
|
|
27
|
+
timestamp?: React.ReactNode;
|
|
28
|
+
meta?: React.ReactNode;
|
|
29
|
+
status?: MessageBubbleStatusContent;
|
|
30
|
+
leading?: React.ReactNode;
|
|
31
|
+
trailing?: React.ReactNode;
|
|
32
|
+
footer?: React.ReactNode;
|
|
33
|
+
selected?: boolean;
|
|
34
|
+
disabled?: boolean;
|
|
35
|
+
compact?: boolean;
|
|
36
|
+
accessibilityLabel?: string;
|
|
37
|
+
onPress?: () => void;
|
|
38
|
+
}
|
|
39
|
+
export {};
|
|
40
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/patterns/message-bubble/types.ts"],"names":[],"mappings":"AAAA,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,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE/D,MAAM,MAAM,sBAAsB,GAAG,UAAU,GAAG,UAAU,GAAG,QAAQ,CAAC;AACxE,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,MAAM,GAAG,WAAW,GAAG,MAAM,GAAG,QAAQ,CAAC;AACvF,KAAK,0BAA0B,GAAG,mBAAmB,GAAG,OAAO,CAAC,KAAK,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;AAEzF,MAAM,WAAW,mBAAmB;IAClC,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,mBAAmB;IAClC,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,MAAM,CAAC,EAAE,mBAAmB,CAAC;CAC9B;AAED,MAAM,WAAW,kBAAmB,SAAQ,aAAa;IACvD,SAAS,CAAC,EAAE,sBAAsB,CAAC;IACnC,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAC7B,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC5B,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,MAAM,CAAC,EAAE,0BAA0B,CAAC;IACpC,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/patterns/message-bubble/types.ts"],"names":[],"mappings":"","sourcesContent":["import type React from 'react';\nimport type { ImageSourcePropType } from 'react-native';\n\nimport type { AvatarShape, AvatarSize } from '../../components/avatar';\nimport type { ZoraTone } from '../../internal/recipes';\nimport type { ZoraBaseProps } from '../../theme/ZoraBaseProps';\n\nexport type MessageBubbleDirection = 'incoming' | 'outgoing' | 'system';\nexport type MessageBubbleStatus = 'sending' | 'sent' | 'delivered' | 'read' | 'failed';\ntype MessageBubbleStatusContent = MessageBubbleStatus | Exclude<React.ReactNode, string>;\n\nexport interface MessageBubbleAvatar {\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 MessageBubbleAuthor {\n name?: React.ReactNode;\n avatar?: MessageBubbleAvatar;\n}\n\nexport interface MessageBubbleProps extends ZoraBaseProps {\n direction?: MessageBubbleDirection;\n text?: React.ReactNode;\n children?: React.ReactNode;\n author?: MessageBubbleAuthor;\n timestamp?: React.ReactNode;\n meta?: React.ReactNode;\n status?: MessageBubbleStatusContent;\n leading?: React.ReactNode;\n trailing?: React.ReactNode;\n footer?: React.ReactNode;\n selected?: boolean;\n disabled?: boolean;\n compact?: boolean;\n accessibilityLabel?: string;\n onPress?: () => void;\n}\n"]}
|
|
@@ -2,7 +2,7 @@ export declare const noticeMeta: {
|
|
|
2
2
|
readonly name: "Notice";
|
|
3
3
|
readonly category: "pattern";
|
|
4
4
|
readonly directManifestNode: true;
|
|
5
|
-
readonly allowedChildren: readonly ["Box", "Stack", "Grid", "Container", "Divider", "Text", "Heading", "Button", "Input", "Textarea", "FormField", "Card", "Panel", "Notice", "EmptyState", "SectionHeader", "SettingsRow", "PostCard"];
|
|
5
|
+
readonly allowedChildren: readonly ["Box", "Stack", "Grid", "Container", "Divider", "Text", "Heading", "Button", "Input", "Textarea", "FormField", "Card", "Panel", "Notice", "EmptyState", "SectionHeader", "SettingsRow", "PostCard", "ChatListItem", "MessageBubble"];
|
|
6
6
|
readonly blueprint: {
|
|
7
7
|
readonly label: "Notice";
|
|
8
8
|
readonly defaultProps: {
|
|
@@ -2,7 +2,7 @@ export declare const panelMeta: {
|
|
|
2
2
|
readonly name: "Panel";
|
|
3
3
|
readonly category: "pattern";
|
|
4
4
|
readonly directManifestNode: true;
|
|
5
|
-
readonly allowedChildren: readonly ["Box", "Stack", "Grid", "Container", "Divider", "Text", "Heading", "Button", "Input", "Textarea", "FormField", "Card", "Panel", "Notice", "EmptyState", "SectionHeader", "SettingsRow", "PostCard"];
|
|
5
|
+
readonly allowedChildren: readonly ["Box", "Stack", "Grid", "Container", "Divider", "Text", "Heading", "Button", "Input", "Textarea", "FormField", "Card", "Panel", "Notice", "EmptyState", "SectionHeader", "SettingsRow", "PostCard", "ChatListItem", "MessageBubble"];
|
|
6
6
|
readonly blueprint: {
|
|
7
7
|
readonly label: "Panel";
|
|
8
8
|
readonly defaultProps: {
|
|
@@ -3,7 +3,7 @@ export declare const postCardMeta: {
|
|
|
3
3
|
readonly category: "pattern";
|
|
4
4
|
readonly description: "Social/content post card with author identity, body, media, actions, and comment previews.";
|
|
5
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"];
|
|
6
|
+
readonly allowedChildren: readonly ["Box", "Stack", "Grid", "Container", "Divider", "Text", "Heading", "Button", "Input", "Textarea", "FormField", "Card", "Panel", "Notice", "EmptyState", "SectionHeader", "SettingsRow", "PostCard", "ChatListItem", "MessageBubble"];
|
|
7
7
|
readonly blueprint: {
|
|
8
8
|
readonly label: "Post card";
|
|
9
9
|
readonly icon: {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ankhorage/zora",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.4.
|
|
4
|
+
"version": "1.4.10",
|
|
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
|
@@ -163,6 +163,8 @@ export type {
|
|
|
163
163
|
SignUpFormValues,
|
|
164
164
|
} from './patterns/auth';
|
|
165
165
|
export { ForgotPasswordForm, OtpForm, SignInForm, SignUpForm } from './patterns/auth';
|
|
166
|
+
export type { ChatListAvatar, ChatListItemProps } from './patterns/chat-list-item';
|
|
167
|
+
export { ChatListItem } from './patterns/chat-list-item';
|
|
166
168
|
export type {
|
|
167
169
|
CollectionEditorProps,
|
|
168
170
|
CollectionEditorRenderItemProps,
|
|
@@ -201,6 +203,14 @@ export type {
|
|
|
201
203
|
ListSectionProps,
|
|
202
204
|
} from './patterns/list';
|
|
203
205
|
export { List, ListRow, ListSection } from './patterns/list';
|
|
206
|
+
export type {
|
|
207
|
+
MessageBubbleAuthor,
|
|
208
|
+
MessageBubbleAvatar,
|
|
209
|
+
MessageBubbleDirection,
|
|
210
|
+
MessageBubbleProps,
|
|
211
|
+
MessageBubbleStatus,
|
|
212
|
+
} from './patterns/message-bubble';
|
|
213
|
+
export { MessageBubble } from './patterns/message-bubble';
|
|
204
214
|
export type { NoticeProps } from './patterns/notice';
|
|
205
215
|
export { Notice } from './patterns/notice';
|
|
206
216
|
export type { PanelProps } from './patterns/panel';
|
|
@@ -141,6 +141,7 @@ describe('ZORA_COMPONENT_META invariants', () => {
|
|
|
141
141
|
'Text',
|
|
142
142
|
'Heading',
|
|
143
143
|
'Divider',
|
|
144
|
+
'ChatListItem',
|
|
144
145
|
]);
|
|
145
146
|
|
|
146
147
|
const expectedContainerNodes = new Set([
|
|
@@ -152,6 +153,7 @@ describe('ZORA_COMPONENT_META invariants', () => {
|
|
|
152
153
|
'Panel',
|
|
153
154
|
'Notice',
|
|
154
155
|
'PostCard',
|
|
156
|
+
'MessageBubble',
|
|
155
157
|
'Box',
|
|
156
158
|
'Stack',
|
|
157
159
|
'Grid',
|
|
@@ -43,6 +43,7 @@ import {
|
|
|
43
43
|
signInFormMeta,
|
|
44
44
|
signUpFormMeta,
|
|
45
45
|
} from '../patterns/auth/meta';
|
|
46
|
+
import { chatListItemMeta } from '../patterns/chat-list-item/meta';
|
|
46
47
|
import { collectionEditorMeta } from '../patterns/collection-editor/meta';
|
|
47
48
|
import { confirmDialogMeta } from '../patterns/confirm-dialog/meta';
|
|
48
49
|
import { disclosureSectionMeta } from '../patterns/disclosure-section/meta';
|
|
@@ -53,6 +54,7 @@ import { imagePreviewMeta } from '../patterns/image-preview/meta';
|
|
|
53
54
|
import { imageUploadFieldMeta } from '../patterns/image-upload-field/meta';
|
|
54
55
|
import { inspectorFieldMeta } from '../patterns/inspector-field/meta';
|
|
55
56
|
import { listMeta, listRowMeta, listSectionMeta } from '../patterns/list/meta';
|
|
57
|
+
import { messageBubbleMeta } from '../patterns/message-bubble/meta';
|
|
56
58
|
import { noticeMeta } from '../patterns/notice/meta';
|
|
57
59
|
import { panelMeta } from '../patterns/panel/meta';
|
|
58
60
|
import { postCardMeta } from '../patterns/post-card/meta';
|
|
@@ -119,6 +121,7 @@ export const ZORA_COMPONENT_META: ZoraComponentMetaRegistry = {
|
|
|
119
121
|
OtpForm: otpFormMeta,
|
|
120
122
|
SignInForm: signInFormMeta,
|
|
121
123
|
SignUpForm: signUpFormMeta,
|
|
124
|
+
ChatListItem: chatListItemMeta,
|
|
122
125
|
CollectionEditor: collectionEditorMeta,
|
|
123
126
|
ConfirmDialog: confirmDialogMeta,
|
|
124
127
|
DisclosureSection: disclosureSectionMeta,
|
|
@@ -131,6 +134,7 @@ export const ZORA_COMPONENT_META: ZoraComponentMetaRegistry = {
|
|
|
131
134
|
List: listMeta,
|
|
132
135
|
ListRow: listRowMeta,
|
|
133
136
|
ListSection: listSectionMeta,
|
|
137
|
+
MessageBubble: messageBubbleMeta,
|
|
134
138
|
Notice: noticeMeta,
|
|
135
139
|
Panel: panelMeta,
|
|
136
140
|
PostCard: postCardMeta,
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { describe, expect, test } from 'bun:test';
|
|
2
|
+
|
|
3
|
+
import { ZORA_COMPONENT_META } from '../../metadata';
|
|
4
|
+
|
|
5
|
+
describe('ChatListItem', () => {
|
|
6
|
+
test('is registered as a public ZORA pattern', () => {
|
|
7
|
+
expect(ZORA_COMPONENT_META.ChatListItem?.name).toBe('ChatListItem');
|
|
8
|
+
expect(ZORA_COMPONENT_META.ChatListItem?.category).toBe('pattern');
|
|
9
|
+
expect(ZORA_COMPONENT_META.ChatListItem?.directManifestNode).toBe(true);
|
|
10
|
+
});
|
|
11
|
+
});
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import { ButtonBase } from '@ankhorage/surface';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
|
|
4
|
+
import { Avatar } from '../../components/avatar';
|
|
5
|
+
import { Badge } from '../../components/badge';
|
|
6
|
+
import { Text } from '../../components/text';
|
|
7
|
+
import { Box, Inline, Stack } from '../../foundation';
|
|
8
|
+
import { useZoraTheme } from '../../theme/useZoraTheme';
|
|
9
|
+
import { withZoraThemeScope } from '../../theme/withZoraThemeScope';
|
|
10
|
+
import type { ChatListAvatar, ChatListItemProps } from './types';
|
|
11
|
+
|
|
12
|
+
function resolveAvatarName({
|
|
13
|
+
avatar,
|
|
14
|
+
title,
|
|
15
|
+
}: {
|
|
16
|
+
avatar: ChatListAvatar | undefined;
|
|
17
|
+
title: React.ReactNode;
|
|
18
|
+
}): string | undefined {
|
|
19
|
+
if (avatar?.name) {
|
|
20
|
+
return avatar.name;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return typeof title === 'string' ? title : undefined;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function resolvePadding(compact: boolean) {
|
|
27
|
+
return compact ? { px: 'm' as const, py: 's' as const } : { px: 'm' as const, py: 'm' as const };
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function resolveContainerStyles({
|
|
31
|
+
theme,
|
|
32
|
+
selected,
|
|
33
|
+
pressed,
|
|
34
|
+
hovered,
|
|
35
|
+
disabled,
|
|
36
|
+
}: {
|
|
37
|
+
theme: ReturnType<typeof useZoraTheme>['theme'];
|
|
38
|
+
selected: boolean;
|
|
39
|
+
pressed: boolean;
|
|
40
|
+
hovered: boolean;
|
|
41
|
+
disabled: boolean;
|
|
42
|
+
}) {
|
|
43
|
+
const borderColor = selected ? theme.semantics.border.focus : 'transparent';
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
bg: pressed
|
|
47
|
+
? theme.semantics.neutral.surfaceActive
|
|
48
|
+
: hovered
|
|
49
|
+
? theme.semantics.neutral.surfaceHover
|
|
50
|
+
: selected
|
|
51
|
+
? theme.semantics.neutral.surface
|
|
52
|
+
: 'transparent',
|
|
53
|
+
borderColor,
|
|
54
|
+
borderWidth: selected ? 1 : 0,
|
|
55
|
+
opacity: disabled ? 0.72 : 1,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function renderUnreadCount(unreadCount: React.ReactNode) {
|
|
60
|
+
if (unreadCount == null) {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return (
|
|
65
|
+
<Badge size="s" tone="primary">
|
|
66
|
+
{unreadCount}
|
|
67
|
+
</Badge>
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function ChatListItemInner({
|
|
72
|
+
themeId: _themeId,
|
|
73
|
+
mode: _mode,
|
|
74
|
+
testID,
|
|
75
|
+
title,
|
|
76
|
+
preview,
|
|
77
|
+
meta,
|
|
78
|
+
timestamp,
|
|
79
|
+
avatar,
|
|
80
|
+
leading,
|
|
81
|
+
trailing,
|
|
82
|
+
unread = false,
|
|
83
|
+
unreadCount,
|
|
84
|
+
selected = false,
|
|
85
|
+
disabled = false,
|
|
86
|
+
compact = false,
|
|
87
|
+
accessibilityLabel,
|
|
88
|
+
onPress,
|
|
89
|
+
}: ChatListItemProps) {
|
|
90
|
+
const { theme } = useZoraTheme();
|
|
91
|
+
const padding = resolvePadding(compact);
|
|
92
|
+
const avatarName = resolveAvatarName({ avatar, title });
|
|
93
|
+
const isInteractive = Boolean(onPress);
|
|
94
|
+
const hasTimestamp = timestamp != null;
|
|
95
|
+
const hasPreview = preview != null;
|
|
96
|
+
const hasMeta = meta != null;
|
|
97
|
+
const hasTrailing = trailing != null;
|
|
98
|
+
const hasUnreadCount = unreadCount != null;
|
|
99
|
+
const hasSecondaryRow = hasPreview || hasMeta || hasUnreadCount || hasTrailing;
|
|
100
|
+
|
|
101
|
+
const content = ({ pressed, hovered }: { pressed: boolean; hovered: boolean }) => {
|
|
102
|
+
const styles = resolveContainerStyles({
|
|
103
|
+
theme,
|
|
104
|
+
selected,
|
|
105
|
+
pressed,
|
|
106
|
+
hovered,
|
|
107
|
+
disabled,
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
return (
|
|
111
|
+
<Box
|
|
112
|
+
bg={styles.bg}
|
|
113
|
+
borderColor={styles.borderColor}
|
|
114
|
+
borderWidth={styles.borderWidth}
|
|
115
|
+
px={padding.px}
|
|
116
|
+
py={padding.py}
|
|
117
|
+
radius="m"
|
|
118
|
+
style={{ opacity: styles.opacity }}
|
|
119
|
+
>
|
|
120
|
+
<Inline align="center" gap="m" wrap="nowrap">
|
|
121
|
+
{leading ?? (
|
|
122
|
+
<Avatar
|
|
123
|
+
initials={avatar?.initials}
|
|
124
|
+
label={avatar?.label ?? avatarName}
|
|
125
|
+
name={avatarName}
|
|
126
|
+
shape={avatar?.shape}
|
|
127
|
+
size={avatar?.size ?? (compact ? 's' : 'm')}
|
|
128
|
+
source={avatar?.source}
|
|
129
|
+
tone={avatar?.tone}
|
|
130
|
+
/>
|
|
131
|
+
)}
|
|
132
|
+
|
|
133
|
+
<Box flex={1}>
|
|
134
|
+
<Stack gap="xxs">
|
|
135
|
+
<Inline align="center" gap="s" justify="space-between" wrap="nowrap">
|
|
136
|
+
<Box flex={1}>
|
|
137
|
+
<Text
|
|
138
|
+
numberOfLines={1}
|
|
139
|
+
tone={disabled ? 'muted' : 'default'}
|
|
140
|
+
variant="bodySmall"
|
|
141
|
+
weight={unread || selected ? 'semiBold' : 'medium'}
|
|
142
|
+
>
|
|
143
|
+
{title}
|
|
144
|
+
</Text>
|
|
145
|
+
</Box>
|
|
146
|
+
{hasTimestamp ? (
|
|
147
|
+
<Text
|
|
148
|
+
numberOfLines={1}
|
|
149
|
+
tone={unread ? 'primary' : 'subtle'}
|
|
150
|
+
variant="caption"
|
|
151
|
+
weight={unread ? 'semiBold' : 'regular'}
|
|
152
|
+
>
|
|
153
|
+
{timestamp}
|
|
154
|
+
</Text>
|
|
155
|
+
) : null}
|
|
156
|
+
</Inline>
|
|
157
|
+
|
|
158
|
+
{hasSecondaryRow ? (
|
|
159
|
+
<Inline align="center" gap="s" justify="space-between" wrap="nowrap">
|
|
160
|
+
<Box flex={1}>
|
|
161
|
+
<Stack gap="xxs">
|
|
162
|
+
{hasPreview ? (
|
|
163
|
+
<Text
|
|
164
|
+
numberOfLines={1}
|
|
165
|
+
tone={unread ? 'default' : 'muted'}
|
|
166
|
+
variant="bodySmall"
|
|
167
|
+
weight={unread ? 'medium' : 'regular'}
|
|
168
|
+
>
|
|
169
|
+
{preview}
|
|
170
|
+
</Text>
|
|
171
|
+
) : null}
|
|
172
|
+
{hasMeta ? (
|
|
173
|
+
<Text numberOfLines={1} tone="subtle" variant="caption">
|
|
174
|
+
{meta}
|
|
175
|
+
</Text>
|
|
176
|
+
) : null}
|
|
177
|
+
</Stack>
|
|
178
|
+
</Box>
|
|
179
|
+
|
|
180
|
+
{hasUnreadCount || hasTrailing ? (
|
|
181
|
+
<Inline align="center" gap="s" wrap="nowrap">
|
|
182
|
+
{renderUnreadCount(unreadCount)}
|
|
183
|
+
{trailing}
|
|
184
|
+
</Inline>
|
|
185
|
+
) : null}
|
|
186
|
+
</Inline>
|
|
187
|
+
) : null}
|
|
188
|
+
</Stack>
|
|
189
|
+
</Box>
|
|
190
|
+
</Inline>
|
|
191
|
+
</Box>
|
|
192
|
+
);
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
if (!isInteractive) {
|
|
196
|
+
return <Box testID={testID}>{content({ pressed: false, hovered: false })}</Box>;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
return (
|
|
200
|
+
<ButtonBase
|
|
201
|
+
accessibilityLabel={accessibilityLabel}
|
|
202
|
+
accessibilityRole="button"
|
|
203
|
+
accessibilityState={{ disabled, selected }}
|
|
204
|
+
disabled={disabled}
|
|
205
|
+
onPress={onPress}
|
|
206
|
+
radius="m"
|
|
207
|
+
testID={testID}
|
|
208
|
+
>
|
|
209
|
+
{(state) =>
|
|
210
|
+
content({
|
|
211
|
+
pressed: state.pressed,
|
|
212
|
+
hovered: state.hovered,
|
|
213
|
+
})
|
|
214
|
+
}
|
|
215
|
+
</ButtonBase>
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export const ChatListItem = withZoraThemeScope(ChatListItemInner);
|
|
@@ -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;
|