@linktr.ee/messaging-react 3.10.0-rc-1783660962 → 3.10.0
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/dist/Card-B-L2MST4.js +107 -0
- package/dist/Card-B-L2MST4.js.map +1 -0
- package/dist/Card-B56QxJW3.cjs +2 -0
- package/dist/Card-B56QxJW3.cjs.map +1 -0
- package/dist/Card-Bqh-BQaX.js +132 -0
- package/dist/Card-Bqh-BQaX.js.map +1 -0
- package/dist/Card-ZCE6Lhfc.cjs +2 -0
- package/dist/Card-ZCE6Lhfc.cjs.map +1 -0
- package/dist/Card-g4JD-2ES.js +163 -0
- package/dist/Card-g4JD-2ES.js.map +1 -0
- package/dist/Card-wac6AMNc.cjs +2 -0
- package/dist/Card-wac6AMNc.cjs.map +1 -0
- package/dist/LockedThumbnail-BAQmoIff.js +220 -0
- package/dist/LockedThumbnail-BAQmoIff.js.map +1 -0
- package/dist/LockedThumbnail-Cr0Gqs3Y.cjs +2 -0
- package/dist/LockedThumbnail-Cr0Gqs3Y.cjs.map +1 -0
- package/dist/assets/index.css +1 -1
- package/dist/index-BPhZyaxT.cjs +2 -0
- package/dist/index-BPhZyaxT.cjs.map +1 -0
- package/dist/{index-DFZrAiLB.js → index-BxzzWK4K.js} +1249 -1276
- package/dist/index-BxzzWK4K.js.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +101 -164
- package/dist/index.js +1 -1
- package/dist/testing.d.ts +0 -1
- package/package.json +2 -2
- package/src/components/ChannelList/CustomChannelPreview.test.tsx +0 -95
- package/src/components/ChannelList/CustomChannelPreview.tsx +9 -21
- package/src/components/CustomMessage/CustomMessage.stories.tsx +1 -54
- package/src/components/CustomMessage/MessageTag.tsx +0 -8
- package/src/components/CustomMessage/context.tsx +1 -1
- package/src/components/CustomMessage/index.tsx +42 -76
- package/src/components/CustomMessageInput/CustomMessageInput.stories.tsx +3 -5
- package/src/components/LockedAttachment/LockedAttachment.stories.tsx +450 -0
- package/src/components/LockedAttachment/components/Composer/Card.tsx +221 -0
- package/src/components/LockedAttachment/components/Composer/index.ts +2 -0
- package/src/components/LockedAttachment/components/Received/Card.tsx +191 -0
- package/src/components/{CustomMessage/LockedAttachment/components/Media → LockedAttachment/components/Received}/CardActions.tsx +2 -9
- package/src/components/LockedAttachment/components/Received/index.ts +2 -0
- package/src/components/LockedAttachment/components/Sent/Card.tsx +177 -0
- package/src/components/LockedAttachment/components/Sent/index.ts +2 -0
- package/src/components/{CustomMessage/LockedAttachment → LockedAttachment}/components/_shared/CardBody.tsx +7 -8
- package/src/components/{CustomMessage/LockedAttachment → LockedAttachment}/components/_shared/GalleryThumbnail.tsx +39 -31
- package/src/components/LockedAttachment/components/_shared/LockBadge.tsx +39 -0
- package/src/components/{CustomMessage/LockedAttachment/components/_shared/MediaShell.tsx → LockedAttachment/components/_shared/LockedCardShell.tsx} +8 -8
- package/src/components/{CustomMessage/LockedAttachment/components/_shared/SingleThumbnail.tsx → LockedAttachment/components/_shared/LockedThumbnail.tsx} +7 -11
- package/src/components/LockedAttachment/index.tsx +63 -0
- package/src/components/LockedAttachment/types.ts +51 -0
- package/src/index.ts +8 -3
- package/src/stream-custom-data.ts +0 -1
- package/src/styles.css +0 -12
- package/src/types.ts +1 -1
- package/dist/Card-415OfRhw.cjs +0 -2
- package/dist/Card-415OfRhw.cjs.map +0 -1
- package/dist/Card-CyWdUMCB.cjs +0 -2
- package/dist/Card-CyWdUMCB.cjs.map +0 -1
- package/dist/Card-V5d6qhDT.js +0 -694
- package/dist/Card-V5d6qhDT.js.map +0 -1
- package/dist/Card-qS17qnN0.js +0 -103
- package/dist/Card-qS17qnN0.js.map +0 -1
- package/dist/LoadingDots-Ct3WmVlT.js +0 -59
- package/dist/LoadingDots-Ct3WmVlT.js.map +0 -1
- package/dist/LoadingDots-D9GGphgM.cjs +0 -2
- package/dist/LoadingDots-D9GGphgM.cjs.map +0 -1
- package/dist/index-Bx_zjNMR.cjs +0 -2
- package/dist/index-Bx_zjNMR.cjs.map +0 -1
- package/dist/index-DFZrAiLB.js.map +0 -1
- package/src/components/CustomMessage/LockedAttachment/LockedAttachment.stories.tsx +0 -541
- package/src/components/CustomMessage/LockedAttachment/LockedAttachment.test.tsx +0 -117
- package/src/components/CustomMessage/LockedAttachment/components/Media/Card.tsx +0 -358
- package/src/components/CustomMessage/LockedAttachment/components/Media/types.ts +0 -79
- package/src/components/CustomMessage/LockedAttachment/components/Text/Card.tsx +0 -153
- package/src/components/CustomMessage/LockedAttachment/components/Text/types.ts +0 -58
- package/src/components/CustomMessage/LockedAttachment/components/_shared/CardThumbnail.tsx +0 -92
- package/src/components/CustomMessage/LockedAttachment/components/_shared/LoadingDots.tsx +0 -36
- package/src/components/CustomMessage/LockedAttachment/components/_shared/LockBadge.tsx +0 -63
- package/src/components/CustomMessage/LockedAttachment/components/_shared/PreviewToggle.tsx +0 -58
- package/src/components/CustomMessage/LockedAttachment/components/_shared/PriceLockRow.tsx +0 -21
- package/src/components/CustomMessage/LockedAttachment/components/_shared/PurchaseStatusBadge.tsx +0 -74
- package/src/components/CustomMessage/LockedAttachment/components/_shared/SkeletonTextLines.tsx +0 -29
- package/src/components/CustomMessage/LockedAttachment/components/_shared/TextShell.tsx +0 -28
- package/src/components/CustomMessage/LockedAttachment/components/_shared/usePreviewToggle.test.ts +0 -67
- package/src/components/CustomMessage/LockedAttachment/components/_shared/usePreviewToggle.ts +0 -89
- package/src/components/CustomMessage/LockedAttachment/components/_shared/useReceivedSource.ts +0 -83
- package/src/components/CustomMessage/LockedAttachment/index.tsx +0 -105
- package/src/components/CustomMessage/LockedAttachment/types.ts +0 -44
|
@@ -1,541 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryFn } from '@storybook/react'
|
|
2
|
-
import React, { useState } from 'react'
|
|
3
|
-
import { MessageText } from 'stream-chat-react'
|
|
4
|
-
|
|
5
|
-
import type { LockedAttachmentGalleryItem } from './types'
|
|
6
|
-
|
|
7
|
-
import LockedAttachment from '.'
|
|
8
|
-
|
|
9
|
-
const meta: Meta = {
|
|
10
|
-
title: 'LockedAttachment',
|
|
11
|
-
parameters: { layout: 'fullscreen' },
|
|
12
|
-
}
|
|
13
|
-
export default meta
|
|
14
|
-
|
|
15
|
-
const MatrixTable: React.FC<{ children: React.ReactNode }> = ({ children }) => (
|
|
16
|
-
<div className="min-h-screen w-full bg-[#F9F7F4] p-12">
|
|
17
|
-
<table className="border-separate border-spacing-4">
|
|
18
|
-
<thead>
|
|
19
|
-
<tr>
|
|
20
|
-
<th className="w-8 pb-2" />
|
|
21
|
-
<th className="pb-2 text-left text-xs font-medium text-black/40">
|
|
22
|
-
Visitor
|
|
23
|
-
</th>
|
|
24
|
-
<th className="pb-2 text-left text-xs font-medium text-black/40">
|
|
25
|
-
Creator
|
|
26
|
-
</th>
|
|
27
|
-
</tr>
|
|
28
|
-
</thead>
|
|
29
|
-
<tbody>{children}</tbody>
|
|
30
|
-
</table>
|
|
31
|
-
</div>
|
|
32
|
-
)
|
|
33
|
-
|
|
34
|
-
const MatrixTableRow: React.FC<{
|
|
35
|
-
label: React.ReactNode
|
|
36
|
-
received: React.ReactNode
|
|
37
|
-
sent: React.ReactNode
|
|
38
|
-
}> = ({ label, received, sent }) => (
|
|
39
|
-
<tr>
|
|
40
|
-
<td className="whitespace-nowrap pr-4 align-top text-xs font-medium text-black/40">
|
|
41
|
-
{label}
|
|
42
|
-
</td>
|
|
43
|
-
<td className="align-top">
|
|
44
|
-
<MatrixTableCell isMine={false}>{received}</MatrixTableCell>
|
|
45
|
-
</td>
|
|
46
|
-
<td className="align-top">
|
|
47
|
-
<MatrixTableCell isMine>{sent}</MatrixTableCell>
|
|
48
|
-
</td>
|
|
49
|
-
</tr>
|
|
50
|
-
)
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Deliberately renders WITHOUT any `.str-chat` ancestor or
|
|
54
|
-
* `str-chat__message*` structure — the real Composer/preview surfaces this
|
|
55
|
-
* card renders in outside a message thread. If a card looks wrong here, it's
|
|
56
|
-
* leaning on ambient stream-chat-react CSS instead of its own explicit
|
|
57
|
-
* styling.
|
|
58
|
-
*/
|
|
59
|
-
const MatrixTableCell: React.FC<{
|
|
60
|
-
isMine: boolean
|
|
61
|
-
children: React.ReactNode
|
|
62
|
-
}> = ({ children }) => <div>{children}</div>
|
|
63
|
-
|
|
64
|
-
export const Text: StoryFn = () => {
|
|
65
|
-
const [isUnlocking, setUnlocking] = useState(false)
|
|
66
|
-
|
|
67
|
-
// Matches what `CustomMessage` passes `MessageText` for a revealed paid
|
|
68
|
-
// text attachment (`displayMessage`) — just enough of a `LocalMessage`
|
|
69
|
-
// shape to render the real `str-chat__message-text` markup/CSS.
|
|
70
|
-
const purchasedMessage = {
|
|
71
|
-
text: "Here's the address, see you Thursday at 7!",
|
|
72
|
-
type: 'regular',
|
|
73
|
-
} as Parameters<typeof MessageText>[0]['message']
|
|
74
|
-
|
|
75
|
-
return (
|
|
76
|
-
<MatrixTable>
|
|
77
|
-
<MatrixTableRow
|
|
78
|
-
label="Draft"
|
|
79
|
-
received={null}
|
|
80
|
-
sent={
|
|
81
|
-
<LockedAttachment
|
|
82
|
-
isDraft
|
|
83
|
-
contentType="text"
|
|
84
|
-
renderedText={purchasedMessage?.text}
|
|
85
|
-
amountText="AU$4.99"
|
|
86
|
-
onDismiss={() => alert('Removed')}
|
|
87
|
-
/>
|
|
88
|
-
}
|
|
89
|
-
/>
|
|
90
|
-
<MatrixTableRow
|
|
91
|
-
label="Preview"
|
|
92
|
-
received={null}
|
|
93
|
-
sent={
|
|
94
|
-
<LockedAttachment
|
|
95
|
-
isPreview
|
|
96
|
-
contentType="text"
|
|
97
|
-
placeholderAmountText="AU$0.00"
|
|
98
|
-
/>
|
|
99
|
-
}
|
|
100
|
-
/>
|
|
101
|
-
<MatrixTableRow
|
|
102
|
-
label="Idle"
|
|
103
|
-
received={
|
|
104
|
-
<LockedAttachment
|
|
105
|
-
isMine={false}
|
|
106
|
-
contentType="text"
|
|
107
|
-
amountText="AU$4.99"
|
|
108
|
-
isUnlocking={isUnlocking}
|
|
109
|
-
onUnlockClick={() => {
|
|
110
|
-
setUnlocking(true)
|
|
111
|
-
setTimeout(() => setUnlocking(false), 1500)
|
|
112
|
-
}}
|
|
113
|
-
/>
|
|
114
|
-
}
|
|
115
|
-
sent={
|
|
116
|
-
<LockedAttachment
|
|
117
|
-
isMine
|
|
118
|
-
contentType="text"
|
|
119
|
-
amountText="AU$4.99"
|
|
120
|
-
paymentStatus="pending"
|
|
121
|
-
/>
|
|
122
|
-
}
|
|
123
|
-
/>
|
|
124
|
-
<MatrixTableRow
|
|
125
|
-
label="Unlocking"
|
|
126
|
-
received={
|
|
127
|
-
<LockedAttachment
|
|
128
|
-
isMine={false}
|
|
129
|
-
contentType="text"
|
|
130
|
-
amountText="AU$4.99"
|
|
131
|
-
isUnlocking
|
|
132
|
-
/>
|
|
133
|
-
}
|
|
134
|
-
sent={null}
|
|
135
|
-
/>
|
|
136
|
-
<MatrixTableRow
|
|
137
|
-
label="Purchased"
|
|
138
|
-
received={
|
|
139
|
-
<LockedAttachment
|
|
140
|
-
isMine={false}
|
|
141
|
-
contentType="text"
|
|
142
|
-
amountText="AU$4.99"
|
|
143
|
-
paymentStatus="paid"
|
|
144
|
-
renderedText={<MessageText message={purchasedMessage} />}
|
|
145
|
-
/>
|
|
146
|
-
}
|
|
147
|
-
sent={
|
|
148
|
-
<LockedAttachment
|
|
149
|
-
isMine
|
|
150
|
-
contentType="text"
|
|
151
|
-
amountText="AU$4.99"
|
|
152
|
-
paymentStatus="paid"
|
|
153
|
-
renderedText={<MessageText message={purchasedMessage} />}
|
|
154
|
-
/>
|
|
155
|
-
}
|
|
156
|
-
/>
|
|
157
|
-
</MatrixTable>
|
|
158
|
-
)
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
const VIDEO_THUMBNAIL_BLURRED = '/video-thumbnail-blurred.jpg'
|
|
162
|
-
const VIDEO_THUMBNAIL = '/video-thumbnail.jpg'
|
|
163
|
-
const VIDEO_SOURCE = '/video-source.mp4'
|
|
164
|
-
|
|
165
|
-
const AUDIO_THUMBNAIL_BLURRED = '/audio-thumbnail-blurred.jpg'
|
|
166
|
-
const AUDIO_THUMBNAIL = '/audio-thumbnail.jpg'
|
|
167
|
-
const AUDIO_SOURCE = '/audio-source.mp3'
|
|
168
|
-
|
|
169
|
-
const IMAGE_THUMBNAIL_BLURRED = '/image-thumbnail-blurred.jpg'
|
|
170
|
-
const IMAGE_THUMBNAIL = '/image-thumbnail.jpg'
|
|
171
|
-
const IMAGE_SOURCE = '/image-source.jpg'
|
|
172
|
-
|
|
173
|
-
const DOCUMENT_THUMBNAIL_BLURRED = '/document-thumbnail-blurred.jpg'
|
|
174
|
-
const DOCUMENT_THUMBNAIL = '/document-thumbnail.jpg'
|
|
175
|
-
const DOCUMENT_SOURCE = '/document-source.pdf'
|
|
176
|
-
|
|
177
|
-
const VARIANTS = [
|
|
178
|
-
{
|
|
179
|
-
label: 'Video',
|
|
180
|
-
title: "Alicia's Workout Plan",
|
|
181
|
-
mimeType: 'video/mp4',
|
|
182
|
-
detail: '1:20',
|
|
183
|
-
thumbnailUrl: VIDEO_THUMBNAIL_BLURRED,
|
|
184
|
-
thumbnailUnlockedUrl: VIDEO_THUMBNAIL,
|
|
185
|
-
sourceUrl: VIDEO_SOURCE,
|
|
186
|
-
},
|
|
187
|
-
{
|
|
188
|
-
label: 'Audio',
|
|
189
|
-
title: 'Morning Meditation',
|
|
190
|
-
mimeType: 'audio/mpeg',
|
|
191
|
-
detail: '4:35',
|
|
192
|
-
thumbnailUrl: AUDIO_THUMBNAIL_BLURRED,
|
|
193
|
-
thumbnailUnlockedUrl: AUDIO_THUMBNAIL,
|
|
194
|
-
sourceUrl: AUDIO_SOURCE,
|
|
195
|
-
},
|
|
196
|
-
{
|
|
197
|
-
label: 'Image',
|
|
198
|
-
title: 'Picture of my cat',
|
|
199
|
-
mimeType: 'image/jpeg',
|
|
200
|
-
detail: '3.2 MB',
|
|
201
|
-
thumbnailUrl: IMAGE_THUMBNAIL_BLURRED,
|
|
202
|
-
thumbnailUnlockedUrl: IMAGE_THUMBNAIL,
|
|
203
|
-
sourceUrl: IMAGE_SOURCE,
|
|
204
|
-
},
|
|
205
|
-
{
|
|
206
|
-
label: 'Document',
|
|
207
|
-
title: 'Strength Training Guide',
|
|
208
|
-
mimeType: 'application/zip',
|
|
209
|
-
detail: '14 files',
|
|
210
|
-
thumbnailUrl: DOCUMENT_THUMBNAIL_BLURRED,
|
|
211
|
-
thumbnailUnlockedUrl: DOCUMENT_THUMBNAIL,
|
|
212
|
-
sourceUrl: DOCUMENT_SOURCE,
|
|
213
|
-
},
|
|
214
|
-
{
|
|
215
|
-
label: 'Unknown',
|
|
216
|
-
title: 'Unknown Attachment',
|
|
217
|
-
mimeType: 'application/octet-stream',
|
|
218
|
-
detail: '2.4 MB',
|
|
219
|
-
thumbnailUrl: undefined,
|
|
220
|
-
thumbnailUnlockedUrl: undefined,
|
|
221
|
-
sourceUrl: DOCUMENT_SOURCE,
|
|
222
|
-
},
|
|
223
|
-
]
|
|
224
|
-
|
|
225
|
-
/**
|
|
226
|
-
* A mixed-media collection (a video + 3 photos) used by the Gallery stories
|
|
227
|
-
* below. `LockedAttachment` accepts a `gallery` prop and renders a carousel
|
|
228
|
-
* of these items when 2+ items are provided.
|
|
229
|
-
*/
|
|
230
|
-
const GALLERY_ITEMS: LockedAttachmentGalleryItem[] = [
|
|
231
|
-
{
|
|
232
|
-
mimeType: 'video/mp4',
|
|
233
|
-
thumbnailUrl: VIDEO_THUMBNAIL,
|
|
234
|
-
sourceUrl: VIDEO_SOURCE,
|
|
235
|
-
},
|
|
236
|
-
{
|
|
237
|
-
mimeType: 'image/jpeg',
|
|
238
|
-
thumbnailUrl: IMAGE_THUMBNAIL,
|
|
239
|
-
sourceUrl: IMAGE_SOURCE,
|
|
240
|
-
},
|
|
241
|
-
{
|
|
242
|
-
mimeType: 'application/pdf',
|
|
243
|
-
thumbnailUrl: DOCUMENT_THUMBNAIL,
|
|
244
|
-
sourceUrl: DOCUMENT_SOURCE,
|
|
245
|
-
},
|
|
246
|
-
{
|
|
247
|
-
mimeType: 'audio/mpeg',
|
|
248
|
-
thumbnailUrl: AUDIO_THUMBNAIL,
|
|
249
|
-
sourceUrl: AUDIO_SOURCE,
|
|
250
|
-
},
|
|
251
|
-
]
|
|
252
|
-
|
|
253
|
-
const GALLERY_DETAIL = '4 items'
|
|
254
|
-
const GALLERY_TITLE = 'Workout Guide'
|
|
255
|
-
|
|
256
|
-
const MediaMatrix: React.FC<{ variant: (typeof VARIANTS)[number] }> = ({
|
|
257
|
-
variant,
|
|
258
|
-
}) => {
|
|
259
|
-
const [isPaid, setPaid] = useState(false)
|
|
260
|
-
const [isUnlocking, setUnlocking] = useState(false)
|
|
261
|
-
const {
|
|
262
|
-
title,
|
|
263
|
-
mimeType,
|
|
264
|
-
detail,
|
|
265
|
-
thumbnailUrl,
|
|
266
|
-
thumbnailUnlockedUrl,
|
|
267
|
-
sourceUrl,
|
|
268
|
-
} = variant
|
|
269
|
-
|
|
270
|
-
const fetchSource = async () => ({
|
|
271
|
-
sourceUrl,
|
|
272
|
-
thumbnailUrl: thumbnailUnlockedUrl,
|
|
273
|
-
})
|
|
274
|
-
|
|
275
|
-
return (
|
|
276
|
-
<MatrixTable>
|
|
277
|
-
<MatrixTableRow
|
|
278
|
-
label="Draft"
|
|
279
|
-
received={null}
|
|
280
|
-
sent={
|
|
281
|
-
<LockedAttachment
|
|
282
|
-
isDraft
|
|
283
|
-
title={title}
|
|
284
|
-
thumbnailUrl={thumbnailUrl}
|
|
285
|
-
contentType="media"
|
|
286
|
-
mimeType={mimeType}
|
|
287
|
-
detail={detail}
|
|
288
|
-
amountText="AU$9.99"
|
|
289
|
-
onDismiss={() => alert('Dismissed')}
|
|
290
|
-
/>
|
|
291
|
-
}
|
|
292
|
-
/>
|
|
293
|
-
<MatrixTableRow
|
|
294
|
-
label="Preview"
|
|
295
|
-
received={null}
|
|
296
|
-
sent={
|
|
297
|
-
<LockedAttachment
|
|
298
|
-
isPreview
|
|
299
|
-
placeholderTitle="Attachment title"
|
|
300
|
-
placeholderAmountText="AU$0.00"
|
|
301
|
-
thumbnailUrl={thumbnailUrl}
|
|
302
|
-
mimeType={mimeType}
|
|
303
|
-
contentType="media"
|
|
304
|
-
detail={detail}
|
|
305
|
-
/>
|
|
306
|
-
}
|
|
307
|
-
/>
|
|
308
|
-
<MatrixTableRow
|
|
309
|
-
label="Idle"
|
|
310
|
-
received={
|
|
311
|
-
<LockedAttachment
|
|
312
|
-
isMine={false}
|
|
313
|
-
title={title}
|
|
314
|
-
thumbnailUrl={thumbnailUrl}
|
|
315
|
-
mimeType={mimeType}
|
|
316
|
-
contentType="media"
|
|
317
|
-
detail={detail}
|
|
318
|
-
amountText="AU$9.99"
|
|
319
|
-
paymentStatus={isPaid ? 'paid' : undefined}
|
|
320
|
-
isUnlocking={isUnlocking}
|
|
321
|
-
onUnlockClick={() => {
|
|
322
|
-
setUnlocking(true)
|
|
323
|
-
setTimeout(() => {
|
|
324
|
-
setUnlocking(false)
|
|
325
|
-
setPaid(true)
|
|
326
|
-
}, 1500)
|
|
327
|
-
}}
|
|
328
|
-
onDownloadClick={() => alert('Download clicked')}
|
|
329
|
-
onFetchSource={fetchSource}
|
|
330
|
-
/>
|
|
331
|
-
}
|
|
332
|
-
sent={
|
|
333
|
-
<LockedAttachment
|
|
334
|
-
isMine
|
|
335
|
-
title={title}
|
|
336
|
-
thumbnailUrl={thumbnailUrl}
|
|
337
|
-
mimeType={mimeType}
|
|
338
|
-
contentType="media"
|
|
339
|
-
detail={detail}
|
|
340
|
-
amountText="AU$9.99"
|
|
341
|
-
onFetchSource={fetchSource}
|
|
342
|
-
/>
|
|
343
|
-
}
|
|
344
|
-
/>
|
|
345
|
-
<MatrixTableRow
|
|
346
|
-
label="Unlocking"
|
|
347
|
-
received={
|
|
348
|
-
<LockedAttachment
|
|
349
|
-
isMine={false}
|
|
350
|
-
title={title}
|
|
351
|
-
thumbnailUrl={thumbnailUrl}
|
|
352
|
-
mimeType={mimeType}
|
|
353
|
-
contentType="media"
|
|
354
|
-
detail={detail}
|
|
355
|
-
amountText="AU$9.99"
|
|
356
|
-
isUnlocking
|
|
357
|
-
onDownloadClick={() => alert('Download clicked')}
|
|
358
|
-
onFetchSource={fetchSource}
|
|
359
|
-
/>
|
|
360
|
-
}
|
|
361
|
-
// Sender never unlocks their own message — no distinct state to show.
|
|
362
|
-
sent={null}
|
|
363
|
-
/>
|
|
364
|
-
<MatrixTableRow
|
|
365
|
-
label="Purchased"
|
|
366
|
-
received={
|
|
367
|
-
<LockedAttachment
|
|
368
|
-
isMine={false}
|
|
369
|
-
title={title}
|
|
370
|
-
thumbnailUrl={thumbnailUrl}
|
|
371
|
-
mimeType={mimeType}
|
|
372
|
-
contentType="media"
|
|
373
|
-
detail={detail}
|
|
374
|
-
amountText="AU$9.99"
|
|
375
|
-
paymentStatus="paid"
|
|
376
|
-
onUnlockClick={() => alert('Unlock clicked')}
|
|
377
|
-
onDownloadClick={() => alert('Download clicked')}
|
|
378
|
-
onFetchSource={fetchSource}
|
|
379
|
-
/>
|
|
380
|
-
}
|
|
381
|
-
sent={
|
|
382
|
-
<LockedAttachment
|
|
383
|
-
isMine
|
|
384
|
-
title={title}
|
|
385
|
-
thumbnailUrl={thumbnailUrl}
|
|
386
|
-
mimeType={mimeType}
|
|
387
|
-
contentType="media"
|
|
388
|
-
detail={detail}
|
|
389
|
-
amountText="AU$9.99"
|
|
390
|
-
paymentStatus="paid"
|
|
391
|
-
onFetchSource={fetchSource}
|
|
392
|
-
/>
|
|
393
|
-
}
|
|
394
|
-
/>
|
|
395
|
-
</MatrixTable>
|
|
396
|
-
)
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
const variantByLabel = (label: string) =>
|
|
400
|
-
VARIANTS.find((v) => v.label === label)!
|
|
401
|
-
|
|
402
|
-
export const Video: StoryFn = () => (
|
|
403
|
-
<MediaMatrix variant={variantByLabel('Video')} />
|
|
404
|
-
)
|
|
405
|
-
// LockedAttachment (contentType="media", !isMine) autoplays the video preview once paid; even with
|
|
406
|
-
// our SMIL/CSS animation freeze the <video> element advances frames
|
|
407
|
-
// independently and produces a non-deterministic snapshot. Skip in Chromatic.
|
|
408
|
-
Video.parameters = { chromatic: { disableSnapshot: true } }
|
|
409
|
-
|
|
410
|
-
export const Audio: StoryFn = () => (
|
|
411
|
-
<MediaMatrix variant={variantByLabel('Audio')} />
|
|
412
|
-
)
|
|
413
|
-
|
|
414
|
-
export const Image: StoryFn = () => (
|
|
415
|
-
<MediaMatrix variant={variantByLabel('Image')} />
|
|
416
|
-
)
|
|
417
|
-
|
|
418
|
-
export const Document: StoryFn = () => (
|
|
419
|
-
<MediaMatrix variant={variantByLabel('Document')} />
|
|
420
|
-
)
|
|
421
|
-
|
|
422
|
-
export const Unknown: StoryFn = () => (
|
|
423
|
-
<MediaMatrix variant={variantByLabel('Unknown')} />
|
|
424
|
-
)
|
|
425
|
-
|
|
426
|
-
export const Gallery: StoryFn = () => {
|
|
427
|
-
const [isPaid, setPaid] = useState(false)
|
|
428
|
-
const [isUnlocking, setUnlocking] = useState(false)
|
|
429
|
-
|
|
430
|
-
return (
|
|
431
|
-
<MatrixTable>
|
|
432
|
-
<MatrixTableRow
|
|
433
|
-
label="Draft"
|
|
434
|
-
received={null}
|
|
435
|
-
sent={
|
|
436
|
-
<LockedAttachment
|
|
437
|
-
isDraft
|
|
438
|
-
contentType="media"
|
|
439
|
-
title={GALLERY_TITLE}
|
|
440
|
-
detail={GALLERY_DETAIL}
|
|
441
|
-
amountText="AU$50.00"
|
|
442
|
-
gallery={GALLERY_ITEMS}
|
|
443
|
-
onDismiss={() => alert('Dismissed gallery')}
|
|
444
|
-
onEditClick={() => alert('Edit gallery')}
|
|
445
|
-
/>
|
|
446
|
-
}
|
|
447
|
-
/>
|
|
448
|
-
<MatrixTableRow
|
|
449
|
-
label="Preview"
|
|
450
|
-
received={null}
|
|
451
|
-
sent={
|
|
452
|
-
<LockedAttachment
|
|
453
|
-
isPreview
|
|
454
|
-
contentType="media"
|
|
455
|
-
placeholderTitle="Attachment title"
|
|
456
|
-
detail={GALLERY_DETAIL}
|
|
457
|
-
placeholderAmountText="AU$0.00"
|
|
458
|
-
gallery={GALLERY_ITEMS}
|
|
459
|
-
/>
|
|
460
|
-
}
|
|
461
|
-
/>
|
|
462
|
-
<MatrixTableRow
|
|
463
|
-
label="Idle"
|
|
464
|
-
received={
|
|
465
|
-
<LockedAttachment
|
|
466
|
-
isMine={false}
|
|
467
|
-
contentType="media"
|
|
468
|
-
title={GALLERY_TITLE}
|
|
469
|
-
detail={GALLERY_DETAIL}
|
|
470
|
-
amountText="AU$50.00"
|
|
471
|
-
gallery={GALLERY_ITEMS}
|
|
472
|
-
paymentStatus={isPaid ? 'paid' : undefined}
|
|
473
|
-
isUnlocking={isUnlocking}
|
|
474
|
-
onUnlockClick={() => {
|
|
475
|
-
setUnlocking(true)
|
|
476
|
-
setTimeout(() => {
|
|
477
|
-
setUnlocking(false)
|
|
478
|
-
setPaid(true)
|
|
479
|
-
}, 1500)
|
|
480
|
-
}}
|
|
481
|
-
onDownloadClick={() => alert('Download gallery')}
|
|
482
|
-
/>
|
|
483
|
-
}
|
|
484
|
-
sent={
|
|
485
|
-
<LockedAttachment
|
|
486
|
-
isMine
|
|
487
|
-
contentType="media"
|
|
488
|
-
title={GALLERY_TITLE}
|
|
489
|
-
detail={GALLERY_DETAIL}
|
|
490
|
-
amountText="AU$50.00"
|
|
491
|
-
gallery={GALLERY_ITEMS}
|
|
492
|
-
/>
|
|
493
|
-
}
|
|
494
|
-
/>
|
|
495
|
-
<MatrixTableRow
|
|
496
|
-
label="Unlocking"
|
|
497
|
-
received={
|
|
498
|
-
<LockedAttachment
|
|
499
|
-
isMine={false}
|
|
500
|
-
contentType="media"
|
|
501
|
-
title={GALLERY_TITLE}
|
|
502
|
-
detail={GALLERY_DETAIL}
|
|
503
|
-
amountText="AU$50.00"
|
|
504
|
-
gallery={GALLERY_ITEMS}
|
|
505
|
-
isUnlocking
|
|
506
|
-
onDownloadClick={() => alert('Download gallery')}
|
|
507
|
-
/>
|
|
508
|
-
}
|
|
509
|
-
// Sender never unlocks their own message — no distinct state to show.
|
|
510
|
-
sent={null}
|
|
511
|
-
/>
|
|
512
|
-
<MatrixTableRow
|
|
513
|
-
label="Purchased"
|
|
514
|
-
received={
|
|
515
|
-
<LockedAttachment
|
|
516
|
-
isMine={false}
|
|
517
|
-
contentType="media"
|
|
518
|
-
title={GALLERY_TITLE}
|
|
519
|
-
detail={GALLERY_DETAIL}
|
|
520
|
-
amountText="AU$50.00"
|
|
521
|
-
paymentStatus="paid"
|
|
522
|
-
gallery={GALLERY_ITEMS}
|
|
523
|
-
onUnlockClick={() => alert('Unlock clicked')}
|
|
524
|
-
onDownloadClick={() => alert('Download gallery')}
|
|
525
|
-
/>
|
|
526
|
-
}
|
|
527
|
-
sent={
|
|
528
|
-
<LockedAttachment
|
|
529
|
-
isMine
|
|
530
|
-
contentType="media"
|
|
531
|
-
title={GALLERY_TITLE}
|
|
532
|
-
detail={GALLERY_DETAIL}
|
|
533
|
-
amountText="AU$50.00"
|
|
534
|
-
paymentStatus="paid"
|
|
535
|
-
gallery={GALLERY_ITEMS}
|
|
536
|
-
/>
|
|
537
|
-
}
|
|
538
|
-
/>
|
|
539
|
-
</MatrixTable>
|
|
540
|
-
)
|
|
541
|
-
}
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi } from 'vitest'
|
|
2
|
-
|
|
3
|
-
import { renderWithProviders, screen } from '../../../test/utils'
|
|
4
|
-
|
|
5
|
-
import MediaCard from './components/Media/Card'
|
|
6
|
-
import TextCard from './components/Text/Card'
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Characterization tests — the safety net for the LockedAttachment
|
|
10
|
-
* separate-concerns refactor. They assert stable, user-visible facts only
|
|
11
|
-
* (lock affordances, CTAs, amount/status text, the preview toggle), never
|
|
12
|
-
* DOM structure or class names — exactly the things the refactor moves
|
|
13
|
-
* around. Storybook remains the pixel-level visual oracle.
|
|
14
|
-
*/
|
|
15
|
-
describe('LockedAttachment (characterization)', () => {
|
|
16
|
-
describe('Draft', () => {
|
|
17
|
-
it('media mode: shows the placeholder title when locked with no title', () => {
|
|
18
|
-
renderWithProviders(<MediaCard isDraft />)
|
|
19
|
-
expect(screen.getByText('Attachment title')).toBeInTheDocument()
|
|
20
|
-
})
|
|
21
|
-
|
|
22
|
-
it('media mode: renders a preview toggle when a source fetcher is wired', () => {
|
|
23
|
-
renderWithProviders(
|
|
24
|
-
<MediaCard isDraft onFetchSource={vi.fn().mockResolvedValue(undefined)} />
|
|
25
|
-
)
|
|
26
|
-
expect(
|
|
27
|
-
screen.getByRole('button', { name: 'Toggle preview' })
|
|
28
|
-
).toBeInTheDocument()
|
|
29
|
-
})
|
|
30
|
-
|
|
31
|
-
it('media mode: renders a dismiss control when onDismiss is provided', () => {
|
|
32
|
-
renderWithProviders(<MediaCard isDraft onDismiss={vi.fn()} />)
|
|
33
|
-
expect(
|
|
34
|
-
screen.getByRole('button', { name: 'Dismiss attachment' })
|
|
35
|
-
).toBeInTheDocument()
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
it('text mode: shows the draft text and amount', () => {
|
|
39
|
-
renderWithProviders(
|
|
40
|
-
<TextCard isDraft amountText="$5" renderedText="Secret draft" />
|
|
41
|
-
)
|
|
42
|
-
expect(screen.getByText('Secret draft')).toBeInTheDocument()
|
|
43
|
-
expect(screen.getByText('$5')).toBeInTheDocument()
|
|
44
|
-
})
|
|
45
|
-
})
|
|
46
|
-
|
|
47
|
-
describe('Preview', () => {
|
|
48
|
-
it('media mode: shows the placeholder title when locked with no title', () => {
|
|
49
|
-
renderWithProviders(<MediaCard isPreview amountText="$5" />)
|
|
50
|
-
expect(screen.getByText('Attachment title')).toBeInTheDocument()
|
|
51
|
-
expect(screen.getByText('$5')).toBeInTheDocument()
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
it('text mode: never shows real text, only the amount', () => {
|
|
55
|
-
renderWithProviders(<TextCard isPreview amountText="$5" />)
|
|
56
|
-
expect(screen.queryByText('Secret draft')).not.toBeInTheDocument()
|
|
57
|
-
expect(screen.getByText('$5')).toBeInTheDocument()
|
|
58
|
-
})
|
|
59
|
-
})
|
|
60
|
-
|
|
61
|
-
describe('Media (isMine)', () => {
|
|
62
|
-
it('shows the amount in the status badge', () => {
|
|
63
|
-
renderWithProviders(<MediaCard isMine amountText="$5" />)
|
|
64
|
-
expect(screen.getByText('$5')).toBeInTheDocument()
|
|
65
|
-
})
|
|
66
|
-
})
|
|
67
|
-
|
|
68
|
-
describe('Text (isMine)', () => {
|
|
69
|
-
it('pending: shows the amount with no status label', () => {
|
|
70
|
-
renderWithProviders(
|
|
71
|
-
<TextCard isMine amountText="$5" paymentStatus="pending" />
|
|
72
|
-
)
|
|
73
|
-
expect(screen.queryByText('Sent')).not.toBeInTheDocument()
|
|
74
|
-
expect(screen.getByText('$5')).toBeInTheDocument()
|
|
75
|
-
})
|
|
76
|
-
|
|
77
|
-
it('paid: shows the Sold label', () => {
|
|
78
|
-
renderWithProviders(
|
|
79
|
-
<TextCard isMine amountText="$5" paymentStatus="paid" />
|
|
80
|
-
)
|
|
81
|
-
expect(screen.getByText('Sold')).toBeInTheDocument()
|
|
82
|
-
})
|
|
83
|
-
})
|
|
84
|
-
|
|
85
|
-
describe('Media (!isMine)', () => {
|
|
86
|
-
it('renders the locked-attachment root and an Unlock CTA when locked', () => {
|
|
87
|
-
renderWithProviders(
|
|
88
|
-
<MediaCard isMine={false} amountText="$5" onUnlockClick={vi.fn()} />
|
|
89
|
-
)
|
|
90
|
-
expect(screen.getByTestId('locked-attachment')).toBeInTheDocument()
|
|
91
|
-
expect(
|
|
92
|
-
screen.getByRole('button', { name: 'Unlock' })
|
|
93
|
-
).toBeInTheDocument()
|
|
94
|
-
})
|
|
95
|
-
})
|
|
96
|
-
|
|
97
|
-
describe('Text (!isMine)', () => {
|
|
98
|
-
it('shows an Unlock control and the amount', () => {
|
|
99
|
-
renderWithProviders(
|
|
100
|
-
<TextCard isMine={false} amountText="$5" onUnlockClick={vi.fn()} />
|
|
101
|
-
)
|
|
102
|
-
expect(
|
|
103
|
-
screen.getByRole('button', { name: 'Unlock message' })
|
|
104
|
-
).toBeInTheDocument()
|
|
105
|
-
expect(screen.getByText('$5')).toBeInTheDocument()
|
|
106
|
-
})
|
|
107
|
-
|
|
108
|
-
it('unlocking: marks the Unlock control busy', () => {
|
|
109
|
-
renderWithProviders(
|
|
110
|
-
<TextCard isMine={false} isUnlocking onUnlockClick={vi.fn()} />
|
|
111
|
-
)
|
|
112
|
-
const button = screen.getByRole('button', { name: 'Unlocking message' })
|
|
113
|
-
expect(button).toBeDisabled()
|
|
114
|
-
expect(button).toHaveAttribute('aria-busy', 'true')
|
|
115
|
-
})
|
|
116
|
-
})
|
|
117
|
-
})
|