@campxdev/react-native-blueprint 0.1.20 → 0.1.24

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 (126) hide show
  1. package/global.css +3 -3
  2. package/lib/global.css +1 -1
  3. package/lib/module/assets/icons/Image.png +0 -0
  4. package/lib/module/components/DataDisplay/Avatar/Avatar.js +1 -1
  5. package/lib/module/components/DataDisplay/Avatar/Avatar.js.map +1 -1
  6. package/lib/module/components/DataDisplay/Banner/Banner.figma.js +17 -3
  7. package/lib/module/components/DataDisplay/Banner/Banner.figma.js.map +1 -1
  8. package/lib/module/components/DataDisplay/Banner/Banner.js +138 -34
  9. package/lib/module/components/DataDisplay/Banner/Banner.js.map +1 -1
  10. package/lib/module/components/DataDisplay/CalendarItem/CalendarItem.js +2 -2
  11. package/lib/module/components/DataDisplay/CalendarItem/CalendarItem.js.map +1 -1
  12. package/lib/module/components/DataDisplay/Card/Card.figma.js +11 -4
  13. package/lib/module/components/DataDisplay/Card/Card.figma.js.map +1 -1
  14. package/lib/module/components/DataDisplay/Card/Card.js +119 -65
  15. package/lib/module/components/DataDisplay/Card/Card.js.map +1 -1
  16. package/lib/module/components/DataDisplay/ChatBubble/ChatBubble.figma.js +54 -0
  17. package/lib/module/components/DataDisplay/ChatBubble/ChatBubble.figma.js.map +1 -0
  18. package/lib/module/components/DataDisplay/ChatBubble/ChatBubble.js +318 -0
  19. package/lib/module/components/DataDisplay/ChatBubble/ChatBubble.js.map +1 -0
  20. package/lib/module/components/DataDisplay/ChatBubble/index.js +4 -0
  21. package/lib/module/components/DataDisplay/ChatBubble/index.js.map +1 -0
  22. package/lib/module/components/DataDisplay/FeedCard/AttachmentDetails.js +69 -0
  23. package/lib/module/components/DataDisplay/FeedCard/AttachmentDetails.js.map +1 -0
  24. package/lib/module/components/DataDisplay/FeedCard/FeedCard.figma.js +19 -17
  25. package/lib/module/components/DataDisplay/FeedCard/FeedCard.figma.js.map +1 -1
  26. package/lib/module/components/DataDisplay/FeedCard/FeedCard.js +30 -19
  27. package/lib/module/components/DataDisplay/FeedCard/FeedCard.js.map +1 -1
  28. package/lib/module/components/DataDisplay/Greeting/Greeting.figma.js +5 -5
  29. package/lib/module/components/DataDisplay/Greeting/Greeting.figma.js.map +1 -1
  30. package/lib/module/components/DataDisplay/Greeting/Greeting.js +46 -70
  31. package/lib/module/components/DataDisplay/Greeting/Greeting.js.map +1 -1
  32. package/lib/module/components/DataDisplay/ProfileCard/ProfileCard.figma.js +16 -0
  33. package/lib/module/components/DataDisplay/ProfileCard/ProfileCard.figma.js.map +1 -0
  34. package/lib/module/components/DataDisplay/ProfileCard/ProfileCard.js +111 -0
  35. package/lib/module/components/DataDisplay/ProfileCard/ProfileCard.js.map +1 -0
  36. package/lib/module/components/DataDisplay/ProfileCard/index.js +4 -0
  37. package/lib/module/components/DataDisplay/ProfileCard/index.js.map +1 -0
  38. package/lib/module/components/Input/Button/Button.js +11 -9
  39. package/lib/module/components/Input/Button/Button.js.map +1 -1
  40. package/lib/module/components/Navigation/Appbar/AppBar.figma.js +18 -6
  41. package/lib/module/components/Navigation/Appbar/AppBar.figma.js.map +1 -1
  42. package/lib/module/components/Navigation/Appbar/AppBar.js +36 -9
  43. package/lib/module/components/Navigation/Appbar/AppBar.js.map +1 -1
  44. package/lib/module/components/Navigation/Popover/Popover.js +1 -1
  45. package/lib/module/components/Navigation/Popover/Popover.js.map +1 -1
  46. package/lib/module/components/ui/index.js +2 -0
  47. package/lib/module/components/ui/index.js.map +1 -1
  48. package/lib/module/lib/theme.js +2 -2
  49. package/lib/module/patterns/pattern-components/AccountPattern/AccountPattern.figma.js +196 -0
  50. package/lib/module/patterns/pattern-components/AccountPattern/AccountPattern.figma.js.map +1 -0
  51. package/lib/module/patterns/pattern-components/AccountPattern/AccountPattern.js +255 -0
  52. package/lib/module/patterns/pattern-components/AccountPattern/AccountPattern.js.map +1 -0
  53. package/lib/module/patterns/pattern-components/AccountPattern/index.js +4 -0
  54. package/lib/module/patterns/pattern-components/AccountPattern/index.js.map +1 -0
  55. package/lib/module/patterns/pattern-components/CalendarPattern/CalendarPattern.figma.js +1 -1
  56. package/lib/module/patterns/pattern-components/CardListPattern/CardListPattern.js +2 -4
  57. package/lib/module/patterns/pattern-components/CardListPattern/CardListPattern.js.map +1 -1
  58. package/lib/module/patterns/pattern-components/FeedPattern/FeedPattern.figma.js +144 -0
  59. package/lib/module/patterns/pattern-components/FeedPattern/FeedPattern.figma.js.map +1 -0
  60. package/lib/module/patterns/pattern-components/FeedPattern/FeedPattern.js +213 -0
  61. package/lib/module/patterns/pattern-components/FeedPattern/FeedPattern.js.map +1 -0
  62. package/lib/module/patterns/pattern-components/FeedPattern/index.js +4 -0
  63. package/lib/module/patterns/pattern-components/FeedPattern/index.js.map +1 -0
  64. package/lib/module/patterns/pattern-components/HomeFacultyPattern/HomeFacultyPattern.figma.js +70 -0
  65. package/lib/module/patterns/pattern-components/HomeFacultyPattern/HomeFacultyPattern.figma.js.map +1 -0
  66. package/lib/module/patterns/pattern-components/HomeFacultyPattern/HomeFacultyPattern.js +260 -0
  67. package/lib/module/patterns/pattern-components/HomeFacultyPattern/HomeFacultyPattern.js.map +1 -0
  68. package/lib/module/patterns/pattern-components/HomeFacultyPattern/index.js +4 -0
  69. package/lib/module/patterns/pattern-components/HomeFacultyPattern/index.js.map +1 -0
  70. package/lib/module/patterns/pattern-components/HomeParentPattern/HomeParentPattern.figma.js +82 -0
  71. package/lib/module/patterns/pattern-components/HomeParentPattern/HomeParentPattern.figma.js.map +1 -0
  72. package/lib/module/patterns/pattern-components/HomeParentPattern/HomeParentPattern.js +256 -0
  73. package/lib/module/patterns/pattern-components/HomeParentPattern/HomeParentPattern.js.map +1 -0
  74. package/lib/module/patterns/pattern-components/HomeParentPattern/index.js +4 -0
  75. package/lib/module/patterns/pattern-components/HomeParentPattern/index.js.map +1 -0
  76. package/lib/module/patterns/pattern-components/HomeStudentPattern/HomeStudentPattern.figma.js +73 -0
  77. package/lib/module/patterns/pattern-components/HomeStudentPattern/HomeStudentPattern.figma.js.map +1 -0
  78. package/lib/module/patterns/pattern-components/HomeStudentPattern/HomeStudentPattern.js +283 -0
  79. package/lib/module/patterns/pattern-components/HomeStudentPattern/HomeStudentPattern.js.map +1 -0
  80. package/lib/module/patterns/pattern-components/HomeStudentPattern/index.js +4 -0
  81. package/lib/module/patterns/pattern-components/HomeStudentPattern/index.js.map +1 -0
  82. package/lib/module/patterns/pattern-components/index.js +5 -0
  83. package/lib/module/patterns/pattern-components/index.js.map +1 -1
  84. package/package.json +27 -1
  85. package/src/assets/icons/Image.png +0 -0
  86. package/src/components/DataDisplay/Avatar/Avatar.tsx +24 -21
  87. package/src/components/DataDisplay/Banner/Banner.figma.tsx +18 -3
  88. package/src/components/DataDisplay/Banner/Banner.tsx +153 -26
  89. package/src/components/DataDisplay/CalendarItem/CalendarItem.tsx +2 -2
  90. package/src/components/DataDisplay/Card/Card.figma.tsx +7 -3
  91. package/src/components/DataDisplay/Card/Card.tsx +152 -101
  92. package/src/components/DataDisplay/ChatBubble/ChatBubble.figma.tsx +54 -0
  93. package/src/components/DataDisplay/ChatBubble/ChatBubble.tsx +404 -0
  94. package/src/components/DataDisplay/ChatBubble/index.ts +8 -0
  95. package/src/components/DataDisplay/FeedCard/AttachmentDetails.tsx +96 -0
  96. package/src/components/DataDisplay/FeedCard/FeedCard.figma.tsx +17 -15
  97. package/src/components/DataDisplay/FeedCard/FeedCard.tsx +66 -35
  98. package/src/components/DataDisplay/Greeting/Greeting.figma.tsx +5 -5
  99. package/src/components/DataDisplay/Greeting/Greeting.tsx +58 -96
  100. package/src/components/DataDisplay/ProfileCard/ProfileCard.figma.tsx +17 -0
  101. package/src/components/DataDisplay/ProfileCard/ProfileCard.tsx +173 -0
  102. package/src/components/DataDisplay/ProfileCard/index.ts +1 -0
  103. package/src/components/Input/Button/Button.tsx +18 -10
  104. package/src/components/Navigation/Appbar/AppBar.figma.tsx +18 -6
  105. package/src/components/Navigation/Appbar/AppBar.tsx +58 -13
  106. package/src/components/Navigation/Popover/Popover.tsx +3 -3
  107. package/src/components/ui/index.ts +2 -0
  108. package/src/lib/theme.ts +2 -2
  109. package/src/patterns/pattern-components/AccountPattern/AccountPattern.figma.tsx +193 -0
  110. package/src/patterns/pattern-components/AccountPattern/AccountPattern.tsx +301 -0
  111. package/src/patterns/pattern-components/AccountPattern/index.ts +1 -0
  112. package/src/patterns/pattern-components/CalendarPattern/CalendarPattern.figma.tsx +1 -1
  113. package/src/patterns/pattern-components/CardListPattern/CardListPattern.tsx +4 -9
  114. package/src/patterns/pattern-components/FeedPattern/FeedPattern.figma.tsx +146 -0
  115. package/src/patterns/pattern-components/FeedPattern/FeedPattern.tsx +264 -0
  116. package/src/patterns/pattern-components/FeedPattern/index.ts +2 -0
  117. package/src/patterns/pattern-components/HomeFacultyPattern/HomeFacultyPattern.figma.tsx +66 -0
  118. package/src/patterns/pattern-components/HomeFacultyPattern/HomeFacultyPattern.tsx +326 -0
  119. package/src/patterns/pattern-components/HomeFacultyPattern/index.ts +2 -0
  120. package/src/patterns/pattern-components/HomeParentPattern/HomeParentPattern.figma.tsx +75 -0
  121. package/src/patterns/pattern-components/HomeParentPattern/HomeParentPattern.tsx +328 -0
  122. package/src/patterns/pattern-components/HomeParentPattern/index.ts +2 -0
  123. package/src/patterns/pattern-components/HomeStudentPattern/HomeStudentPattern.figma.tsx +66 -0
  124. package/src/patterns/pattern-components/HomeStudentPattern/HomeStudentPattern.tsx +355 -0
  125. package/src/patterns/pattern-components/HomeStudentPattern/index.ts +2 -0
  126. package/src/patterns/pattern-components/index.ts +5 -0
@@ -0,0 +1,404 @@
1
+ // @ts-nocheck
2
+ import React from 'react';
3
+ import {
4
+ View,
5
+ Text as RNText,
6
+ Image as RNImage,
7
+ Pressable,
8
+ type StyleProp,
9
+ type ViewStyle,
10
+ type ImageSourcePropType,
11
+ } from 'react-native';
12
+ import { cssInterop } from 'nativewind';
13
+
14
+ import { Avatar } from '../Avatar/Avatar';
15
+ import { Badge } from '../Badge/Badge';
16
+
17
+ cssInterop(View, { className: 'style' });
18
+ cssInterop(RNText, { className: 'style' });
19
+ cssInterop(RNImage, { className: 'style' });
20
+ cssInterop(Pressable, { className: 'style' });
21
+
22
+ const View_ = View as any;
23
+ const Text = RNText as any;
24
+ const Image = RNImage as any;
25
+
26
+ /* ============================================================================
27
+ * Types
28
+ * ============================================================================ */
29
+
30
+ export type ChatBubbleType = 'incoming' | 'outgoing';
31
+ export type ChatBubbleVariant = 'default' | 'ai';
32
+
33
+ export interface ChatBubbleQuotedMessage {
34
+ author: string;
35
+ text: string;
36
+ }
37
+
38
+ export interface ChatBubbleAttachment {
39
+ type: 'image' | 'link';
40
+ uri?: string;
41
+ title?: string;
42
+ description?: string;
43
+ url?: string;
44
+ }
45
+
46
+ export interface ChatBubbleProps {
47
+ type?: ChatBubbleType;
48
+ variant?: ChatBubbleVariant;
49
+ message?: string;
50
+ userName?: string;
51
+ userAvatar?: ImageSourcePropType;
52
+ timestamp?: string;
53
+ showUser?: boolean;
54
+ showMessage?: boolean;
55
+ showEditedIndication?: boolean;
56
+ showQuotedReply?: boolean;
57
+ quotedMessage?: ChatBubbleQuotedMessage;
58
+ showMessageAttachment?: boolean;
59
+ attachment?: ChatBubbleAttachment;
60
+ showReactions?: boolean;
61
+ reactions?: string[];
62
+ showActions?: boolean;
63
+ onCopy?: () => void;
64
+ onLike?: () => void;
65
+ onDislike?: () => void;
66
+ onRegenerate?: () => void;
67
+ style?: StyleProp<ViewStyle>;
68
+ testID?: string;
69
+ }
70
+
71
+ /* ============================================================================
72
+ * Component
73
+ * ============================================================================ */
74
+
75
+ /**
76
+ * ChatBubble Component
77
+ *
78
+ * A comprehensive chat message bubble component for chat interfaces.
79
+ * Supports incoming/outgoing messages with default and AI variants.
80
+ *
81
+ * @example
82
+ * ```tsx
83
+ * <ChatBubble
84
+ * type="incoming"
85
+ * variant="default"
86
+ * message="Hello!"
87
+ * userName="John"
88
+ * timestamp="09:10 PM"
89
+ * />
90
+ * ```
91
+ */
92
+ export function ChatBubble({
93
+ type = 'incoming',
94
+ variant = 'default',
95
+ message = 'This is the Message bubble content. This will have truncated content and we can fix the width as 300px.',
96
+ userName = 'User Name',
97
+ _userAvatar,
98
+ timestamp = '09:10 PM',
99
+ showUser = true,
100
+ showMessage = true,
101
+ showEditedIndication = true,
102
+ showQuotedReply = true,
103
+ quotedMessage = {
104
+ author: 'John Doe',
105
+ text: 'This is a quoted reply section',
106
+ },
107
+ showMessageAttachment = true,
108
+ attachment,
109
+ showReactions = true,
110
+ reactions = ['👍', '❤️'],
111
+ showActions = true,
112
+ onCopy,
113
+ onLike,
114
+ onDislike,
115
+ onRegenerate,
116
+ style,
117
+ testID,
118
+ }: ChatBubbleProps) {
119
+ const isIncoming = type === 'incoming';
120
+ const isOutgoing = type === 'outgoing';
121
+ const isAi = variant === 'ai';
122
+ const isDefault = variant === 'default';
123
+
124
+ if (isIncoming && isDefault) {
125
+ return (
126
+ <View_
127
+ testID={testID ?? 'chat-bubble'}
128
+ style={style}
129
+ className="flex-row gap-2 px-5 py-2 items-end"
130
+ >
131
+ {/* Avatar */}
132
+ {showUser && (
133
+ <Avatar
134
+ size="sm"
135
+ type="initials"
136
+ initials={userName?.slice(0, 2).toUpperCase() ?? 'AK'}
137
+ showRing={true}
138
+ />
139
+ )}
140
+
141
+ {/* Content */}
142
+ <View_ className="flex-1 gap-1">
143
+ {/* Meta */}
144
+ <View_ className="flex-row items-center justify-between px-4">
145
+ <Text className="text-xs font-medium text-text-secondary">
146
+ {userName}
147
+ </Text>
148
+ <View_ className="flex-row items-center gap-1">
149
+ {showEditedIndication && (
150
+ <>
151
+ <Text className="text-xs font-medium text-text-secondary">
152
+ Edited
153
+ </Text>
154
+ <View_ className="w-0.5 h-0.5 rounded-full bg-text-secondary" />
155
+ </>
156
+ )}
157
+ <Text className="text-xs font-medium text-text-secondary">
158
+ {timestamp}
159
+ </Text>
160
+ </View_>
161
+ </View_>
162
+
163
+ {/* Bubble */}
164
+ <View_ className="rounded-3xl rounded-bl-none bg-white px-4 py-3 gap-3">
165
+ {/* Quoted Reply */}
166
+ {showQuotedReply && quotedMessage && (
167
+ <View_ className="bg-white rounded-xl border-l-4 border-l-highlight-purple px-3 py-2 gap-0.5">
168
+ <Text className="text-xs font-semibold text-text-primary">
169
+ {quotedMessage.author}
170
+ </Text>
171
+ <Text className="text-xs font-medium text-text-secondary">
172
+ {quotedMessage.text}
173
+ </Text>
174
+ </View_>
175
+ )}
176
+
177
+ {/* Message */}
178
+ {showMessage && (
179
+ <Text className="text-sm font-medium text-text-primary leading-5">
180
+ {message}
181
+ </Text>
182
+ )}
183
+
184
+ {/* Image */}
185
+ {showMessageAttachment &&
186
+ attachment?.type === 'image' &&
187
+ attachment.uri && (
188
+ <Image
189
+ source={{ uri: attachment.uri }}
190
+ style={{
191
+ width: '100%',
192
+ height: 160,
193
+ borderRadius: 16,
194
+ }}
195
+ resizeMode="cover"
196
+ />
197
+ )}
198
+ </View_>
199
+
200
+ {/* Reactions */}
201
+ {showReactions && reactions && reactions.length > 0 && (
202
+ <View_ className="flex-row gap-1 px-4 pt-1">
203
+ {reactions.map((reaction, idx) => (
204
+ <Badge
205
+ key={idx}
206
+ variant="default"
207
+ size="sm"
208
+ className="rounded-full"
209
+ >
210
+ <Text className="text-sm">{reaction}</Text>
211
+ </Badge>
212
+ ))}
213
+ </View_>
214
+ )}
215
+ </View_>
216
+ </View_>
217
+ );
218
+ }
219
+
220
+ if (isOutgoing && isDefault) {
221
+ return (
222
+ <View_
223
+ testID={testID ?? 'chat-bubble'}
224
+ style={style}
225
+ className="flex-row-reverse gap-2 px-5 py-2 items-end"
226
+ >
227
+ {/* Avatar */}
228
+ {showUser && (
229
+ <Avatar
230
+ size="sm"
231
+ type="image"
232
+ initials={userName?.slice(0, 2).toUpperCase() ?? 'AK'}
233
+ showRing={true}
234
+ />
235
+ )}
236
+
237
+ {/* Content */}
238
+ <View_ className="flex-1 gap-1">
239
+ {/* Meta */}
240
+ <View_ className="flex-row items-center justify-between px-4">
241
+ <View_ className="flex-row items-center gap-1">
242
+ <Text className="text-xs font-medium text-text-secondary">
243
+ {timestamp}
244
+ </Text>
245
+ {showEditedIndication && (
246
+ <>
247
+ <View_ className="w-0.5 h-0.5 rounded-full bg-text-secondary" />
248
+ <Text className="text-xs font-medium text-text-secondary">
249
+ Edited
250
+ </Text>
251
+ </>
252
+ )}
253
+ </View_>
254
+ <Text className="text-xs font-medium text-text-secondary">You</Text>
255
+ </View_>
256
+
257
+ {/* Bubble */}
258
+ <View_ className="rounded-3xl rounded-br-none bg-surface-subtle px-4 py-3 gap-3">
259
+ {/* Quoted Reply */}
260
+ {showQuotedReply && quotedMessage && (
261
+ <View_ className="bg-surface-default rounded-xl border-l-4 border-l-white px-3 py-2 gap-0.5">
262
+ <Text className="text-xs font-semibold text-text-primary">
263
+ {quotedMessage.author}
264
+ </Text>
265
+ <Text className="text-xs font-medium text-text-secondary">
266
+ {quotedMessage.text}
267
+ </Text>
268
+ </View_>
269
+ )}
270
+
271
+ {/* Message */}
272
+ {showMessage && (
273
+ <Text className="text-sm font-medium text-text-primary leading-5">
274
+ {message}
275
+ </Text>
276
+ )}
277
+
278
+ {/* Link Attachment */}
279
+ {showMessageAttachment && attachment?.type === 'link' && (
280
+ <View_ className="gap-2">
281
+ <View_ className="bg-white rounded-2xl px-3 py-2 gap-1">
282
+ <Text className="text-xs font-semibold text-text-primary">
283
+ {attachment.title}
284
+ </Text>
285
+ <Text className="text-xs font-medium text-text-muted">
286
+ {attachment.description}
287
+ </Text>
288
+ <Text className="text-xs font-medium text-text-secondary">
289
+ {attachment.url}
290
+ </Text>
291
+ </View_>
292
+ <Pressable>
293
+ <Text className="text-xs font-medium text-highlight-purple underline">
294
+ {attachment.url && `https://${attachment.url}/home`}
295
+ </Text>
296
+ </Pressable>
297
+ </View_>
298
+ )}
299
+ </View_>
300
+
301
+ {/* Footer */}
302
+ <View_ className="flex-row items-center justify-between px-4 pt-1">
303
+ {showReactions && reactions && reactions.length > 0 && (
304
+ <View_ className="flex-row gap-1">
305
+ {reactions.map((reaction, idx) => (
306
+ <Badge
307
+ key={idx}
308
+ variant="default"
309
+ size="sm"
310
+ className="rounded-full"
311
+ >
312
+ <Text className="text-sm">{reaction}</Text>
313
+ </Badge>
314
+ ))}
315
+ </View_>
316
+ )}
317
+
318
+ <View_ className="flex-row items-center gap-1">
319
+ <View_ className="w-3 h-3 rounded-full bg-text-muted" />
320
+ <Text className="text-xs font-medium text-text-muted">Sent</Text>
321
+ </View_>
322
+ </View_>
323
+ </View_>
324
+ </View_>
325
+ );
326
+ }
327
+
328
+ if (isIncoming && isAi) {
329
+ return (
330
+ <View_
331
+ testID={testID ?? 'chat-bubble'}
332
+ style={style}
333
+ className="flex-row gap-2 px-5 py-2 items-end"
334
+ >
335
+ {/* Avatar */}
336
+ {showUser && (
337
+ <Avatar size="sm" type="icon" initials="AI" showRing={true} />
338
+ )}
339
+
340
+ {/* Content */}
341
+ <View_ className="flex-1 gap-1">
342
+ {/* Meta */}
343
+ <View_ className="flex-row items-center justify-between px-4">
344
+ <Text className="text-lg">✨</Text>
345
+ <Text className="text-xs font-medium text-text-secondary">
346
+ {timestamp}
347
+ </Text>
348
+ </View_>
349
+
350
+ {/* Bubble */}
351
+ <View_ className="rounded-3xl rounded-bl-none bg-white px-4 py-3 gap-3">
352
+ {/* Message */}
353
+ {showMessage && (
354
+ <Text className="text-sm font-medium text-text-primary leading-5">
355
+ {message}
356
+ </Text>
357
+ )}
358
+
359
+ {/* Image */}
360
+ {showMessageAttachment &&
361
+ attachment?.type === 'image' &&
362
+ attachment.uri && (
363
+ <Image
364
+ source={{ uri: attachment.uri }}
365
+ style={{
366
+ width: '100%',
367
+ height: 160,
368
+ borderRadius: 16,
369
+ }}
370
+ resizeMode="cover"
371
+ />
372
+ )}
373
+ </View_>
374
+
375
+ {/* Actions */}
376
+ <View_ className="flex-row items-center gap-5 px-4 pt-2">
377
+ {showActions && (
378
+ <>
379
+ <Pressable onPress={onCopy}>
380
+ <Text className="text-base">📋</Text>
381
+ </Pressable>
382
+ <Pressable onPress={onLike}>
383
+ <Text className="text-base">👍</Text>
384
+ </Pressable>
385
+ <Pressable onPress={onDislike}>
386
+ <Text className="text-base">👎</Text>
387
+ </Pressable>
388
+ <Pressable onPress={onRegenerate}>
389
+ <Text className="text-base">🔄</Text>
390
+ </Pressable>
391
+ </>
392
+ )}
393
+ </View_>
394
+ </View_>
395
+ </View_>
396
+ );
397
+ }
398
+
399
+ return null;
400
+ }
401
+
402
+ ChatBubble.displayName = 'ChatBubble';
403
+
404
+ export type { ChatBubbleProps };
@@ -0,0 +1,8 @@
1
+ export { ChatBubble } from './ChatBubble';
2
+ export type {
3
+ ChatBubbleProps,
4
+ ChatBubbleType,
5
+ ChatBubbleVariant,
6
+ ChatBubbleQuotedMessage,
7
+ ChatBubbleAttachment,
8
+ } from './ChatBubble';
@@ -0,0 +1,96 @@
1
+ // @ts-nocheck
2
+ import {
3
+ View as RNView,
4
+ Text as RNTextBase,
5
+ type StyleProp,
6
+ type ViewStyle,
7
+ } from 'react-native';
8
+ import { cssInterop } from 'nativewind';
9
+
10
+ // NativeWind interop (className -> style)
11
+ const View = cssInterop(RNView, { className: 'style' });
12
+ const RNText = cssInterop(RNTextBase, { className: 'style' });
13
+
14
+ export type AttachmentDetailsProps = {
15
+ /** File name */
16
+ fileName?: string;
17
+
18
+ /** Number of pages */
19
+ pages?: number;
20
+
21
+ /** File size in MB */
22
+ sizeMB?: number;
23
+
24
+ /** File type (e.g., PDF, DOC) */
25
+ fileType?: string;
26
+
27
+ /** Styling */
28
+ style?: StyleProp<ViewStyle>;
29
+ testID?: string;
30
+ className?: never;
31
+ };
32
+
33
+ /**
34
+ * AttachmentDetails - Displays file attachment metadata
35
+ *
36
+ * Shows file name, pages, size, and file type in a compact card format
37
+ *
38
+ * @component
39
+ * @example
40
+ * ```tsx
41
+ * <AttachmentDetails
42
+ * fileName="Document"
43
+ * pages={27}
44
+ * sizeMB={3}
45
+ * fileType="PDF"
46
+ * />
47
+ * ```
48
+ */
49
+ export function AttachmentDetails({
50
+ fileName = 'File Name',
51
+ pages = 27,
52
+ sizeMB = 3,
53
+ fileType = 'Pdf',
54
+ style,
55
+ testID,
56
+ }: AttachmentDetailsProps) {
57
+ return (
58
+ <View
59
+ testID={testID ?? 'attachment-details'}
60
+ className="bg-surface-subtle rounded-lg px-4 py-3 flex-col gap-1 w-full"
61
+ style={style}
62
+ >
63
+ {/* File Name */}
64
+ <RNText
65
+ testID="attachment-file-name"
66
+ numberOfLines={1}
67
+ className="text-sm font-semibold text-text-primary"
68
+ >
69
+ {fileName}
70
+ </RNText>
71
+
72
+ {/* Meta Information */}
73
+ <View testID="attachment-meta" className="flex-row items-center gap-2">
74
+ <RNText className="text-xs font-medium text-text-secondary">
75
+ {pages} Pages
76
+ </RNText>
77
+
78
+ {/* Divider dot */}
79
+ <View className="w-1 h-1 rounded-full bg-text-secondary" />
80
+
81
+ <RNText className="text-xs font-medium text-text-secondary">
82
+ {sizeMB} MB
83
+ </RNText>
84
+
85
+ {/* Divider dot */}
86
+ <View className="w-1 h-1 rounded-full bg-text-secondary" />
87
+
88
+ <RNText className="text-xs font-medium text-text-secondary">
89
+ {fileType}
90
+ </RNText>
91
+ </View>
92
+ </View>
93
+ );
94
+ }
95
+
96
+ AttachmentDetails.displayName = 'AttachmentDetails';
@@ -10,34 +10,36 @@ figma.connect(FeedCard, FIGMA_URL, {
10
10
  post: 'post',
11
11
  announcement: 'announcement',
12
12
  }),
13
- authorName: figma.string('authorName'),
14
- postTitle: figma.string('postTitle'),
15
- subtitle: figma.string('subtitle'),
16
- postContent: figma.string('postContent'),
17
- showHeader: figma.boolean('Show Header'),
18
- showLeading: figma.boolean('Show Leading'),
19
13
  showMedia: figma.boolean('Show Media'),
20
- showPostContent: figma.boolean('Show PostContent'),
21
- showSubtitle: figma.boolean('Show Subtitle'),
14
+ showHeader: figma.boolean('Show Header'),
15
+ showPostContent: figma.boolean('Show Post Content'),
16
+ showBody: figma.boolean('Show Body'),
22
17
  showBadges: figma.boolean('Show Badges'),
23
18
  showFooterActions: figma.boolean('Show FooterActions'),
19
+ showLeading: figma.boolean('Show Leading'),
20
+ showSubtitle: figma.boolean('Show Subtitle'),
24
21
  showSecondaryButton: figma.boolean('Show SecondaryButton'),
22
+ authorName: figma.string('Author Name'),
23
+ postTitle: figma.string('Post Title'),
24
+ subtitle: figma.string('Subtitle'),
25
+ postContent: figma.string('Post Content'),
25
26
  },
26
27
  example: (props) => (
27
28
  <FeedCard
28
29
  type={props.type}
29
- authorName={props.authorName}
30
- postTitle={props.postTitle}
31
- subtitle={props.subtitle}
32
- postContent={props.postContent}
33
- showHeader={props.showHeader}
34
- showLeading={props.showLeading}
35
30
  showMedia={props.showMedia}
31
+ showHeader={props.showHeader}
36
32
  showPostContent={props.showPostContent}
37
- showSubtitle={props.showSubtitle}
33
+ showBody={props.showBody}
38
34
  showBadges={props.showBadges}
39
35
  showFooterActions={props.showFooterActions}
36
+ showLeading={props.showLeading}
37
+ showSubtitle={props.showSubtitle}
40
38
  showSecondaryButton={props.showSecondaryButton}
39
+ authorName={props.authorName}
40
+ postTitle={props.postTitle}
41
+ subtitle={props.subtitle}
42
+ postContent={props.postContent}
41
43
  />
42
44
  ),
43
45
  });