@linktr.ee/messaging-react 1.25.1 → 1.26.1-rc-1776055454
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/Preview-DqAv16NS.js +87 -0
- package/dist/Preview-DqAv16NS.js.map +1 -0
- package/dist/dash.all.min-Duv4lvGS.js +18858 -0
- package/dist/dash.all.min-Duv4lvGS.js.map +1 -0
- package/dist/hls-Bogc7CBn.js +21710 -0
- package/dist/hls-Bogc7CBn.js.map +1 -0
- package/dist/index-Da-xN4Yq.js +16142 -0
- package/dist/index-Da-xN4Yq.js.map +1 -0
- package/dist/index-Dj9rqWcU.js +69 -0
- package/dist/index-Dj9rqWcU.js.map +1 -0
- package/dist/index.d.ts +85 -9
- package/dist/index.js +1745 -1156
- package/dist/index.js.map +1 -1
- package/dist/mixin-B6jYfIcp.js +808 -0
- package/dist/mixin-B6jYfIcp.js.map +1 -0
- package/dist/react-BxlQMOfz.js +419 -0
- package/dist/react-BxlQMOfz.js.map +1 -0
- package/dist/react-COAP-MIW.js +377 -0
- package/dist/react-COAP-MIW.js.map +1 -0
- package/dist/react-Cn4WlMcl.js +3108 -0
- package/dist/react-Cn4WlMcl.js.map +1 -0
- package/dist/react-CwTJArKY.js +459 -0
- package/dist/react-CwTJArKY.js.map +1 -0
- package/dist/react-DkfS_atT.js +373 -0
- package/dist/react-DkfS_atT.js.map +1 -0
- package/dist/react-Pea5fum1.js +286 -0
- package/dist/react-Pea5fum1.js.map +1 -0
- package/dist/react-RiBbsUDd.js +534 -0
- package/dist/react-RiBbsUDd.js.map +1 -0
- package/dist/react-dS1WBxxz.js +238 -0
- package/dist/react-dS1WBxxz.js.map +1 -0
- package/package.json +2 -1
- package/src/components/ChannelList/index.test.tsx +18 -0
- package/src/components/ChannelList/index.tsx +2 -0
- package/src/components/ChannelView.test.tsx +50 -1
- package/src/components/ChannelView.tsx +13 -3
- package/src/components/CustomMessage/CustomMessage.stories.tsx +61 -2
- package/src/components/CustomMessage/MessageTag.tsx +5 -0
- package/src/components/CustomMessage/index.tsx +46 -4
- package/src/components/LockedAttachmentCard/LockedAttachmentCard.stories.tsx +351 -0
- package/src/components/LockedAttachmentCard/index.tsx +378 -0
- package/src/components/LockedAttachmentCard/mimeType.test.ts +97 -0
- package/src/components/LockedAttachmentCard/mimeType.ts +35 -0
- package/src/components/MessagingShell/index.tsx +2 -0
- package/src/index.ts +4 -0
- package/src/stream-custom-data.ts +10 -3
- package/src/types.ts +41 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import classNames from 'classnames'
|
|
2
2
|
import React, { useMemo, useState } from 'react'
|
|
3
|
+
import { type Channel, type LocalMessage } from 'stream-chat'
|
|
3
4
|
import {
|
|
4
5
|
Attachment as DefaultAttachment,
|
|
5
6
|
EditMessageModal as DefaultEditMessageModal,
|
|
@@ -20,6 +21,7 @@ import {
|
|
|
20
21
|
isMessageBounced,
|
|
21
22
|
messageHasAttachments,
|
|
22
23
|
messageHasReactions,
|
|
24
|
+
useChannelStateContext,
|
|
23
25
|
useComponentContext,
|
|
24
26
|
useChatContext,
|
|
25
27
|
useMessageContext,
|
|
@@ -30,18 +32,23 @@ import {
|
|
|
30
32
|
|
|
31
33
|
import { useMessageVote } from '../../hooks/useMessageVote'
|
|
32
34
|
import { Avatar } from '../Avatar'
|
|
35
|
+
import LockedAttachmentCard from '../LockedAttachmentCard'
|
|
33
36
|
|
|
34
|
-
import { MessageTag, isChatbotMessage, isTipOnlyMessage } from './MessageTag'
|
|
37
|
+
import { MessageTag, isAttachmentMessage, isChatbotMessage, isTipOnlyMessage } from './MessageTag'
|
|
35
38
|
import { MessageVoteButtons } from './MessageVoteButtons'
|
|
36
39
|
|
|
37
40
|
type CustomMessageWithContextProps = MessageContextValue & {
|
|
38
41
|
chatbotVotingEnabled?: boolean
|
|
42
|
+
onAttachmentUnlock?: (message: LocalMessage, channel: Channel) => Promise<string>
|
|
43
|
+
onAttachmentDownload?: (message: LocalMessage, channel: Channel) => void
|
|
39
44
|
}
|
|
40
45
|
|
|
41
46
|
const CustomMessageWithContext = (props: CustomMessageWithContextProps) => {
|
|
42
47
|
const {
|
|
43
48
|
additionalMessageInputProps,
|
|
44
49
|
chatbotVotingEnabled,
|
|
50
|
+
onAttachmentUnlock,
|
|
51
|
+
onAttachmentDownload,
|
|
45
52
|
editing,
|
|
46
53
|
endOfGroup,
|
|
47
54
|
firstOfGroup,
|
|
@@ -58,7 +65,10 @@ const CustomMessageWithContext = (props: CustomMessageWithContextProps) => {
|
|
|
58
65
|
} = props
|
|
59
66
|
|
|
60
67
|
const { client } = useChatContext('CustomMessage')
|
|
68
|
+
const { channel } = useChannelStateContext('CustomMessage')
|
|
61
69
|
const [isBounceDialogOpen, setIsBounceDialogOpen] = useState(false)
|
|
70
|
+
const [unlocking, setUnlocking] = useState(false)
|
|
71
|
+
const [attachmentSource, setAttachmentSource] = useState<string | undefined>(undefined)
|
|
62
72
|
const reminder = useMessageReminder(message.id)
|
|
63
73
|
const { selected: voteState, voteUp, voteDown } = useMessageVote(message)
|
|
64
74
|
|
|
@@ -144,6 +154,7 @@ const CustomMessageWithContext = (props: CustomMessageWithContextProps) => {
|
|
|
144
154
|
const poll = message.poll_id && client.polls.fromState(message.poll_id)
|
|
145
155
|
const isTipOnly = isTipOnlyMessage(message)
|
|
146
156
|
const isChatbot = isChatbotMessage(message)
|
|
157
|
+
const isAttachment = isAttachmentMessage(message)
|
|
147
158
|
const hasRenderableAttachments = !!(
|
|
148
159
|
finalAttachments?.length && !message.quoted_message
|
|
149
160
|
)
|
|
@@ -192,7 +203,29 @@ const CustomMessageWithContext = (props: CustomMessageWithContextProps) => {
|
|
|
192
203
|
marginInlineStart: 0,
|
|
193
204
|
}}
|
|
194
205
|
>
|
|
195
|
-
{
|
|
206
|
+
{isAttachment ? (
|
|
207
|
+
<div className="flex flex-col gap-1">
|
|
208
|
+
<LockedAttachmentCard
|
|
209
|
+
title={message.metadata?.attachment_title ?? ''}
|
|
210
|
+
mimeType={message.metadata?.attachment_mime_type ?? 'application/octet-stream'}
|
|
211
|
+
thumbnail={message.metadata?.attachment_thumbnail}
|
|
212
|
+
amountText={message.metadata?.amount_text}
|
|
213
|
+
detail={message.metadata?.attachment_detail}
|
|
214
|
+
source={attachmentSource}
|
|
215
|
+
isPurchased={message.metadata?.payment_status === 'paid'}
|
|
216
|
+
loading={unlocking}
|
|
217
|
+
onUnlock={onAttachmentUnlock ? async () => { setUnlocking(true); try { setAttachmentSource(await onAttachmentUnlock(message, channel)) } catch { /* caller handles errors (e.g. payment cancellation) */ } finally { setUnlocking(false) } } : undefined}
|
|
218
|
+
onDownload={attachmentSource && onAttachmentDownload ? () => onAttachmentDownload(message, channel) : undefined}
|
|
219
|
+
/>
|
|
220
|
+
{message.text && (
|
|
221
|
+
<div className="str-chat__message-bubble-wrapper">
|
|
222
|
+
<div className="str-chat__message-bubble">
|
|
223
|
+
<MessageText message={message} renderText={renderText} />
|
|
224
|
+
</div>
|
|
225
|
+
</div>
|
|
226
|
+
)}
|
|
227
|
+
</div>
|
|
228
|
+
) : isTipOnly ? (
|
|
196
229
|
/* Tip-only messages render as a standalone bubble */
|
|
197
230
|
<MessageTag message={message} standalone />
|
|
198
231
|
) : (
|
|
@@ -256,11 +289,20 @@ const CustomMessageWithContext = (props: CustomMessageWithContextProps) => {
|
|
|
256
289
|
|
|
257
290
|
const MemoizedCustomMessage = React.memo(
|
|
258
291
|
CustomMessageWithContext,
|
|
259
|
-
|
|
292
|
+
(prev, next) => {
|
|
293
|
+
if (prev.chatbotVotingEnabled !== next.chatbotVotingEnabled) return false
|
|
294
|
+
if (prev.onAttachmentUnlock !== next.onAttachmentUnlock) return false
|
|
295
|
+
if (prev.onAttachmentDownload !== next.onAttachmentDownload) return false
|
|
296
|
+
return areMessageUIPropsEqual(prev, next)
|
|
297
|
+
}
|
|
260
298
|
) as typeof CustomMessageWithContext
|
|
261
299
|
|
|
262
300
|
export const CustomMessage = (
|
|
263
|
-
props: MessageUIComponentProps & {
|
|
301
|
+
props: MessageUIComponentProps & {
|
|
302
|
+
chatbotVotingEnabled?: boolean
|
|
303
|
+
onAttachmentUnlock?: (message: LocalMessage, channel: Channel) => Promise<string>
|
|
304
|
+
onAttachmentDownload?: (message: LocalMessage, channel: Channel) => void
|
|
305
|
+
}
|
|
264
306
|
) => {
|
|
265
307
|
const messageContext = useMessageContext('CustomMessage')
|
|
266
308
|
return <MemoizedCustomMessage {...messageContext} {...props} />
|
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
import type { Meta, StoryFn } from '@storybook/react'
|
|
2
|
+
import React, { useState } from 'react'
|
|
3
|
+
|
|
4
|
+
import LockedAttachmentCard, { type LockedAttachmentCardProps } from '.'
|
|
5
|
+
|
|
6
|
+
const VIDEO_THUMBNAIL = '/video-thumbnail.jpg'
|
|
7
|
+
const VIDEO_THUMBNAIL_BLURRED = '/video-thumbnail-blurred.jpg'
|
|
8
|
+
const VIDEO_SOURCE = '/video-source.mp4'
|
|
9
|
+
|
|
10
|
+
const IMAGE_THUMBNAIL = '/image-thumbnail.jpg'
|
|
11
|
+
const IMAGE_THUMBNAIL_BLURRED = '/image-thumbnail-blurred.jpg'
|
|
12
|
+
const IMAGE_SOURCE = '/image-source.jpg'
|
|
13
|
+
|
|
14
|
+
const DOCUMENT_THUMBNAIL = '/document-thumbnail.jpg'
|
|
15
|
+
const DOCUMENT_THUMBNAIL_BLURRED = '/document-thumbnail-blurred.jpg'
|
|
16
|
+
const DOCUMENT_SOURCE = '/document-source.pdf'
|
|
17
|
+
|
|
18
|
+
const AUDIO_THUMBNAIL = '/audio-thumbnail.jpg'
|
|
19
|
+
const AUDIO_THUMBNAIL_BLURRED = '/audio-thumbnail-blurred.jpg'
|
|
20
|
+
const AUDIO_SOURCE = '/audio-source.mp3'
|
|
21
|
+
|
|
22
|
+
const meta: Meta = {
|
|
23
|
+
title: 'LockedAttachmentCard',
|
|
24
|
+
component: LockedAttachmentCard,
|
|
25
|
+
parameters: { layout: 'centered' },
|
|
26
|
+
}
|
|
27
|
+
export default meta
|
|
28
|
+
|
|
29
|
+
const Labeled = ({ label, children }: { label: string; children: React.ReactNode }) => (
|
|
30
|
+
<div className="flex flex-col gap-2">
|
|
31
|
+
{children}
|
|
32
|
+
<span className="text-center text-xs text-black/40">{label}</span>
|
|
33
|
+
</div>
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
type InteractiveProps = Omit<LockedAttachmentCardProps, 'onUnlock' | 'onDownload'> & {
|
|
37
|
+
unlockedSource: string
|
|
38
|
+
unlockedThumbnail?: string
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const Interactive = ({ unlockedSource, unlockedThumbnail, ...props }: InteractiveProps) => {
|
|
42
|
+
const [source, setSource] = useState<string | undefined>(undefined)
|
|
43
|
+
const [thumbnail, setThumbnail] = useState(props.thumbnail)
|
|
44
|
+
const [loading, setLoading] = useState(false)
|
|
45
|
+
|
|
46
|
+
const handleUnlock = async () => {
|
|
47
|
+
setLoading(true)
|
|
48
|
+
await new Promise(resolve => setTimeout(resolve, 1000))
|
|
49
|
+
const res = await fetch(unlockedSource)
|
|
50
|
+
const blob = await res.blob()
|
|
51
|
+
setSource(URL.createObjectURL(blob))
|
|
52
|
+
if (unlockedThumbnail) setThumbnail(unlockedThumbnail)
|
|
53
|
+
setLoading(false)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return (
|
|
57
|
+
<LockedAttachmentCard
|
|
58
|
+
{...props}
|
|
59
|
+
thumbnail={thumbnail}
|
|
60
|
+
source={source}
|
|
61
|
+
loading={loading}
|
|
62
|
+
onUnlock={source ? undefined : handleUnlock}
|
|
63
|
+
onDownload={source ? () => {} : undefined}
|
|
64
|
+
/>
|
|
65
|
+
)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export const Video: StoryFn = () => (
|
|
69
|
+
<div className="flex items-start gap-4 p-12">
|
|
70
|
+
<Labeled label="Locked">
|
|
71
|
+
<Interactive
|
|
72
|
+
title="Alicia's Workout Plan"
|
|
73
|
+
amountText="AU$9.99"
|
|
74
|
+
thumbnail={VIDEO_THUMBNAIL_BLURRED}
|
|
75
|
+
unlockedThumbnail={VIDEO_THUMBNAIL}
|
|
76
|
+
mimeType="video/mp4"
|
|
77
|
+
detail="1:20"
|
|
78
|
+
unlockedSource={VIDEO_SOURCE}
|
|
79
|
+
/>
|
|
80
|
+
</Labeled>
|
|
81
|
+
<Labeled label="Purchased">
|
|
82
|
+
<Interactive
|
|
83
|
+
title="Alicia's Workout Plan"
|
|
84
|
+
amountText="AU$9.99"
|
|
85
|
+
thumbnail={VIDEO_THUMBNAIL_BLURRED}
|
|
86
|
+
unlockedThumbnail={VIDEO_THUMBNAIL}
|
|
87
|
+
mimeType="video/mp4"
|
|
88
|
+
detail="1:20"
|
|
89
|
+
unlockedSource={VIDEO_SOURCE}
|
|
90
|
+
isPurchased
|
|
91
|
+
/>
|
|
92
|
+
</Labeled>
|
|
93
|
+
<Labeled label="Unlocked">
|
|
94
|
+
<LockedAttachmentCard
|
|
95
|
+
title="Alicia's Workout Plan"
|
|
96
|
+
thumbnail={VIDEO_THUMBNAIL}
|
|
97
|
+
source={VIDEO_SOURCE}
|
|
98
|
+
mimeType="video/mp4"
|
|
99
|
+
detail="1:20"
|
|
100
|
+
onDownload={() => {}}
|
|
101
|
+
/>
|
|
102
|
+
</Labeled>
|
|
103
|
+
</div>
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
export const Audio: StoryFn = () => (
|
|
107
|
+
<div className="flex items-start gap-4 p-12">
|
|
108
|
+
<Labeled label="Locked">
|
|
109
|
+
<Interactive
|
|
110
|
+
title="Morning Meditation"
|
|
111
|
+
amountText="AU$4.99"
|
|
112
|
+
thumbnail={AUDIO_THUMBNAIL_BLURRED}
|
|
113
|
+
unlockedThumbnail={AUDIO_THUMBNAIL}
|
|
114
|
+
mimeType="audio/mpeg"
|
|
115
|
+
detail="4:35"
|
|
116
|
+
unlockedSource={AUDIO_SOURCE}
|
|
117
|
+
/>
|
|
118
|
+
</Labeled>
|
|
119
|
+
<Labeled label="Purchased">
|
|
120
|
+
<Interactive
|
|
121
|
+
title="Morning Meditation"
|
|
122
|
+
amountText="AU$4.99"
|
|
123
|
+
thumbnail={AUDIO_THUMBNAIL_BLURRED}
|
|
124
|
+
unlockedThumbnail={AUDIO_THUMBNAIL}
|
|
125
|
+
mimeType="audio/mpeg"
|
|
126
|
+
detail="4:35"
|
|
127
|
+
unlockedSource={AUDIO_SOURCE}
|
|
128
|
+
isPurchased
|
|
129
|
+
/>
|
|
130
|
+
</Labeled>
|
|
131
|
+
<Labeled label="Unlocked">
|
|
132
|
+
<LockedAttachmentCard
|
|
133
|
+
title="Morning Meditation"
|
|
134
|
+
thumbnail={AUDIO_THUMBNAIL}
|
|
135
|
+
source={AUDIO_SOURCE}
|
|
136
|
+
mimeType="audio/mpeg"
|
|
137
|
+
detail="4:35"
|
|
138
|
+
onDownload={() => {}}
|
|
139
|
+
/>
|
|
140
|
+
</Labeled>
|
|
141
|
+
</div>
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
export const Image: StoryFn = () => (
|
|
145
|
+
<div className="flex items-start gap-4 p-12">
|
|
146
|
+
<Labeled label="Locked">
|
|
147
|
+
<Interactive
|
|
148
|
+
title="Picture of my cat"
|
|
149
|
+
amountText="AU$2.99"
|
|
150
|
+
thumbnail={IMAGE_THUMBNAIL_BLURRED}
|
|
151
|
+
unlockedThumbnail={IMAGE_THUMBNAIL}
|
|
152
|
+
mimeType="image/jpeg"
|
|
153
|
+
detail="3.2 MB"
|
|
154
|
+
unlockedSource={IMAGE_SOURCE}
|
|
155
|
+
/>
|
|
156
|
+
</Labeled>
|
|
157
|
+
<Labeled label="Purchased">
|
|
158
|
+
<Interactive
|
|
159
|
+
title="Picture of my cat"
|
|
160
|
+
amountText="AU$2.99"
|
|
161
|
+
thumbnail={IMAGE_THUMBNAIL_BLURRED}
|
|
162
|
+
unlockedThumbnail={IMAGE_THUMBNAIL}
|
|
163
|
+
mimeType="image/jpeg"
|
|
164
|
+
detail="3.2 MB"
|
|
165
|
+
unlockedSource={IMAGE_SOURCE}
|
|
166
|
+
isPurchased
|
|
167
|
+
/>
|
|
168
|
+
</Labeled>
|
|
169
|
+
<Labeled label="Unlocked">
|
|
170
|
+
<LockedAttachmentCard
|
|
171
|
+
title="Picture of my cat"
|
|
172
|
+
thumbnail={IMAGE_THUMBNAIL}
|
|
173
|
+
source={IMAGE_SOURCE}
|
|
174
|
+
mimeType="image/jpeg"
|
|
175
|
+
detail="3.2 MB"
|
|
176
|
+
onDownload={() => {}}
|
|
177
|
+
/>
|
|
178
|
+
</Labeled>
|
|
179
|
+
</div>
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
export const Document: StoryFn = () => (
|
|
183
|
+
<div className="flex items-start gap-4 p-12">
|
|
184
|
+
<Labeled label="Locked">
|
|
185
|
+
<Interactive
|
|
186
|
+
title="Strength Training Guide"
|
|
187
|
+
amountText="AU$4.99"
|
|
188
|
+
thumbnail={DOCUMENT_THUMBNAIL_BLURRED}
|
|
189
|
+
unlockedThumbnail={DOCUMENT_THUMBNAIL}
|
|
190
|
+
mimeType="application/zip"
|
|
191
|
+
detail="14 files"
|
|
192
|
+
unlockedSource={DOCUMENT_SOURCE}
|
|
193
|
+
/>
|
|
194
|
+
</Labeled>
|
|
195
|
+
<Labeled label="Purchased">
|
|
196
|
+
<Interactive
|
|
197
|
+
title="Strength Training Guide"
|
|
198
|
+
amountText="AU$4.99"
|
|
199
|
+
thumbnail={DOCUMENT_THUMBNAIL_BLURRED}
|
|
200
|
+
unlockedThumbnail={DOCUMENT_THUMBNAIL}
|
|
201
|
+
mimeType="application/zip"
|
|
202
|
+
detail="14 files"
|
|
203
|
+
unlockedSource={DOCUMENT_SOURCE}
|
|
204
|
+
isPurchased
|
|
205
|
+
/>
|
|
206
|
+
</Labeled>
|
|
207
|
+
<Labeled label="Unlocked">
|
|
208
|
+
<LockedAttachmentCard
|
|
209
|
+
title="Strength Training Guide"
|
|
210
|
+
thumbnail={DOCUMENT_THUMBNAIL}
|
|
211
|
+
source={DOCUMENT_SOURCE}
|
|
212
|
+
mimeType="application/zip"
|
|
213
|
+
detail="14 files"
|
|
214
|
+
onDownload={() => {}}
|
|
215
|
+
/>
|
|
216
|
+
</Labeled>
|
|
217
|
+
</div>
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
const VARIANTS = [
|
|
221
|
+
{ label: 'Video', title: "Alicia's Workout Plan", mimeType: 'video/mp4', detail: '1:20', thumbnail: VIDEO_THUMBNAIL, thumbnailBlurred: VIDEO_THUMBNAIL_BLURRED, source: VIDEO_SOURCE },
|
|
222
|
+
{ label: 'Audio', title: 'Morning Meditation', mimeType: 'audio/mpeg', detail: '4:35', thumbnail: AUDIO_THUMBNAIL, thumbnailBlurred: AUDIO_THUMBNAIL_BLURRED, source: AUDIO_SOURCE },
|
|
223
|
+
{ label: 'Image', title: 'Picture of my cat', mimeType: 'image/jpeg', detail: '3.2 MB', thumbnail: IMAGE_THUMBNAIL, thumbnailBlurred: IMAGE_THUMBNAIL_BLURRED, source: IMAGE_SOURCE },
|
|
224
|
+
{ label: 'Document', title: 'Strength Training Guide', mimeType: 'application/zip', detail: '14 files', thumbnail: DOCUMENT_THUMBNAIL, thumbnailBlurred: DOCUMENT_THUMBNAIL_BLURRED, source: DOCUMENT_SOURCE },
|
|
225
|
+
]
|
|
226
|
+
|
|
227
|
+
export const Fallback: StoryFn = () => (
|
|
228
|
+
<div className="flex items-start gap-4 p-12">
|
|
229
|
+
<Labeled label="Locked">
|
|
230
|
+
<Interactive
|
|
231
|
+
title="Unknown Attachment"
|
|
232
|
+
amountText="AU$9.99"
|
|
233
|
+
mimeType="application/octet-stream"
|
|
234
|
+
unlockedSource={DOCUMENT_SOURCE}
|
|
235
|
+
/>
|
|
236
|
+
</Labeled>
|
|
237
|
+
<Labeled label="Purchased">
|
|
238
|
+
<Interactive
|
|
239
|
+
title="Unknown Attachment"
|
|
240
|
+
amountText="AU$9.99"
|
|
241
|
+
mimeType="application/octet-stream"
|
|
242
|
+
unlockedSource={DOCUMENT_SOURCE}
|
|
243
|
+
isPurchased
|
|
244
|
+
/>
|
|
245
|
+
</Labeled>
|
|
246
|
+
<Labeled label="Unlocked">
|
|
247
|
+
<LockedAttachmentCard
|
|
248
|
+
title="Unknown Attachment"
|
|
249
|
+
source={DOCUMENT_SOURCE}
|
|
250
|
+
mimeType="application/octet-stream"
|
|
251
|
+
onDownload={() => {}}
|
|
252
|
+
/>
|
|
253
|
+
</Labeled>
|
|
254
|
+
</div>
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
const NO_POSTER_VARIANTS = [
|
|
258
|
+
{ label: 'Video', title: "Alicia's Workout Plan", mimeType: 'video/mp4', detail: '1:20', source: VIDEO_SOURCE },
|
|
259
|
+
{ label: 'Audio', title: 'Morning Meditation', mimeType: 'audio/mpeg', detail: '4:35', source: AUDIO_SOURCE },
|
|
260
|
+
{ label: 'Image', title: 'Picture of my cat', mimeType: 'image/jpeg', detail: '3.2 MB', source: IMAGE_SOURCE },
|
|
261
|
+
{ label: 'Document', title: 'Strength Training Guide', mimeType: 'application/zip', detail: '14 files', source: DOCUMENT_SOURCE },
|
|
262
|
+
]
|
|
263
|
+
|
|
264
|
+
export const NoPoster: StoryFn = () => (
|
|
265
|
+
<div className="p-12">
|
|
266
|
+
<table className="border-separate border-spacing-4">
|
|
267
|
+
<thead>
|
|
268
|
+
<tr>
|
|
269
|
+
<th className="text-left text-xs font-medium text-black/40 pb-2" />
|
|
270
|
+
{NO_POSTER_VARIANTS.map(({ label, mimeType }) => (
|
|
271
|
+
<th key={mimeType} className="text-left text-xs font-medium text-black/40 pb-2">{label}</th>
|
|
272
|
+
))}
|
|
273
|
+
</tr>
|
|
274
|
+
</thead>
|
|
275
|
+
<tbody>
|
|
276
|
+
{(['Locked', 'Unlocked'] as const).map(state => (
|
|
277
|
+
<tr key={state}>
|
|
278
|
+
<td className="text-xs font-medium text-black/40 pr-4 align-top pt-2">{state}</td>
|
|
279
|
+
{NO_POSTER_VARIANTS.map(({ title, mimeType, detail, source }) => (
|
|
280
|
+
<td key={mimeType} className="align-top">
|
|
281
|
+
{state === 'Locked' ? (
|
|
282
|
+
<Interactive
|
|
283
|
+
title={title}
|
|
284
|
+
amountText="AU$9.99"
|
|
285
|
+
mimeType={mimeType}
|
|
286
|
+
detail={detail}
|
|
287
|
+
unlockedSource={source}
|
|
288
|
+
/>
|
|
289
|
+
) : (
|
|
290
|
+
<LockedAttachmentCard
|
|
291
|
+
title={title}
|
|
292
|
+
source={source}
|
|
293
|
+
mimeType={mimeType}
|
|
294
|
+
detail={detail}
|
|
295
|
+
onDownload={() => {}}
|
|
296
|
+
/>
|
|
297
|
+
)}
|
|
298
|
+
</td>
|
|
299
|
+
))}
|
|
300
|
+
</tr>
|
|
301
|
+
))}
|
|
302
|
+
</tbody>
|
|
303
|
+
</table>
|
|
304
|
+
</div>
|
|
305
|
+
)
|
|
306
|
+
|
|
307
|
+
export const CreatorView: StoryFn = () => (
|
|
308
|
+
<div className="p-12">
|
|
309
|
+
<table className="border-separate border-spacing-4">
|
|
310
|
+
<thead>
|
|
311
|
+
<tr>
|
|
312
|
+
<th className="text-left text-xs font-medium text-black/40 pb-2" />
|
|
313
|
+
{VARIANTS.map(({ label, mimeType }) => (
|
|
314
|
+
<th key={mimeType} className="text-left text-xs font-medium text-black/40 pb-2">{label}</th>
|
|
315
|
+
))}
|
|
316
|
+
</tr>
|
|
317
|
+
</thead>
|
|
318
|
+
<tbody>
|
|
319
|
+
<tr>
|
|
320
|
+
<td className="text-xs font-medium text-black/40 pr-4 align-top pt-2">Unsold</td>
|
|
321
|
+
{VARIANTS.map(({ title, mimeType, detail, thumbnailBlurred }) => (
|
|
322
|
+
<td key={mimeType} className="align-top">
|
|
323
|
+
<LockedAttachmentCard
|
|
324
|
+
title={title}
|
|
325
|
+
thumbnail={thumbnailBlurred}
|
|
326
|
+
mimeType={mimeType}
|
|
327
|
+
detail={detail}
|
|
328
|
+
amountText="AU$9.99"
|
|
329
|
+
/>
|
|
330
|
+
</td>
|
|
331
|
+
))}
|
|
332
|
+
</tr>
|
|
333
|
+
<tr>
|
|
334
|
+
<td className="text-xs font-medium text-black/40 pr-4 align-top pt-2">Sold</td>
|
|
335
|
+
{VARIANTS.map(({ title, mimeType, detail, thumbnailBlurred }) => (
|
|
336
|
+
<td key={mimeType} className="align-top">
|
|
337
|
+
<LockedAttachmentCard
|
|
338
|
+
title={title}
|
|
339
|
+
thumbnail={thumbnailBlurred}
|
|
340
|
+
mimeType={mimeType}
|
|
341
|
+
detail={detail}
|
|
342
|
+
amountText="AU$9.99"
|
|
343
|
+
isPurchased
|
|
344
|
+
/>
|
|
345
|
+
</td>
|
|
346
|
+
))}
|
|
347
|
+
</tr>
|
|
348
|
+
</tbody>
|
|
349
|
+
</table>
|
|
350
|
+
</div>
|
|
351
|
+
)
|