@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,18 +1,23 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
CaretLeftIcon,
|
|
3
|
+
CaretRightIcon,
|
|
4
|
+
LockOpenIcon,
|
|
5
|
+
LockSimpleIcon,
|
|
6
|
+
PlayIcon,
|
|
7
|
+
} from '@phosphor-icons/react'
|
|
2
8
|
import classNames from 'classnames'
|
|
3
9
|
import React, { useState } from 'react'
|
|
4
10
|
|
|
5
|
-
import { AttachmentThumbnail, getSourceType } from '
|
|
11
|
+
import { AttachmentThumbnail, getSourceType } from '../../../AttachmentCard'
|
|
6
12
|
import type {
|
|
7
13
|
LockedAttachmentGalleryItem,
|
|
8
14
|
PaymentStatus,
|
|
9
15
|
} from '../../types'
|
|
10
16
|
|
|
11
|
-
import {
|
|
12
|
-
import type { CardVariant } from './MediaShell'
|
|
17
|
+
import type { LockedCardVariant } from './LockedCardShell'
|
|
13
18
|
|
|
14
19
|
export interface GalleryThumbnailProps {
|
|
15
|
-
variant:
|
|
20
|
+
variant: LockedCardVariant
|
|
16
21
|
gallery: LockedAttachmentGalleryItem[]
|
|
17
22
|
title?: string
|
|
18
23
|
/** When true, all items are shown blurred + the locked/play badge is overlaid. */
|
|
@@ -47,8 +52,24 @@ const GalleryThumbnail: React.FC<GalleryThumbnailProps> = ({
|
|
|
47
52
|
const current = gallery[safeIndex]
|
|
48
53
|
const isVideoItem = isPlayableItem(current)
|
|
49
54
|
|
|
55
|
+
// Center badge: PLAY for video items, LOCK for non-video locked items.
|
|
56
|
+
// Unlocked image items show no center badge — the image is the content.
|
|
57
|
+
const centerBadge = (() => {
|
|
58
|
+
if (isVideoItem) {
|
|
59
|
+
return <PlayIcon className="size-6" weight="fill" />
|
|
60
|
+
}
|
|
61
|
+
if (showLocked) {
|
|
62
|
+
return paymentStatus === 'paid' ? (
|
|
63
|
+
<LockOpenIcon className="size-6" weight="fill" />
|
|
64
|
+
) : (
|
|
65
|
+
<LockSimpleIcon className="size-6" weight="fill" />
|
|
66
|
+
)
|
|
67
|
+
}
|
|
68
|
+
return null
|
|
69
|
+
})()
|
|
70
|
+
|
|
50
71
|
// Stop propagation so arrow taps don't bubble up to the outer preview-toggle
|
|
51
|
-
// wrapper on
|
|
72
|
+
// wrapper on ComposerCard / SentCard.
|
|
52
73
|
const goPrev = (e: React.MouseEvent) => {
|
|
53
74
|
e.stopPropagation()
|
|
54
75
|
setIndex((i) => Math.max(0, i - 1))
|
|
@@ -65,22 +86,14 @@ const GalleryThumbnail: React.FC<GalleryThumbnailProps> = ({
|
|
|
65
86
|
// Locked + unlocked render entirely separate trees so the locked state
|
|
66
87
|
// doesn't end up stacking a blurred `<img>` on top of an underlying
|
|
67
88
|
// `AttachmentThumbnail` (whose `bg-white/10` poster shell otherwise
|
|
68
|
-
// shows through as a visible horizontal seam
|
|
69
|
-
//
|
|
70
|
-
// The locked placeholder is absolutely positioned, so it needs the fixed
|
|
71
|
-
// 337/386 box for height; unlocked content (video, natural-sized image)
|
|
72
|
-
// manages its own height and can expand/shrink per item.
|
|
89
|
+
// shows through as a visible horizontal seam at the 16:9 boundary
|
|
90
|
+
// inside the taller 337/386 gallery aspect).
|
|
73
91
|
//
|
|
74
92
|
// The locked branch uses `filter: blur` on a single full-size `<img>`
|
|
75
93
|
// — not `backdrop-filter` — so the rounded corners are clipped
|
|
76
|
-
// normally without any clip-path workarounds (see
|
|
94
|
+
// normally without any clip-path workarounds (see LockedThumbnail).
|
|
77
95
|
return (
|
|
78
|
-
<div
|
|
79
|
-
className={classNames(
|
|
80
|
-
'group relative overflow-hidden rounded-t-md',
|
|
81
|
-
showLocked ? 'aspect-[337/386]' : undefined
|
|
82
|
-
)}
|
|
83
|
-
>
|
|
96
|
+
<div className="relative aspect-[337/386] overflow-hidden rounded-t-md">
|
|
84
97
|
{showLocked ? (
|
|
85
98
|
<div
|
|
86
99
|
className={classNames(
|
|
@@ -102,25 +115,20 @@ const GalleryThumbnail: React.FC<GalleryThumbnailProps> = ({
|
|
|
102
115
|
</div>
|
|
103
116
|
) : (
|
|
104
117
|
<AttachmentThumbnail
|
|
105
|
-
key={safeIndex}
|
|
106
118
|
mimeType={current.mimeType}
|
|
107
119
|
sourceUrl={current.sourceUrl}
|
|
108
120
|
thumbnailUrl={current.thumbnailUrl}
|
|
109
121
|
title={title}
|
|
110
122
|
variant={variant}
|
|
111
|
-
mediaPlayerProps={{ autoPlay: true }}
|
|
112
123
|
/>
|
|
113
124
|
)}
|
|
114
125
|
|
|
115
|
-
{
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
isPlayable={isVideoItem}
|
|
122
|
-
isLocked={showLocked}
|
|
123
|
-
/>
|
|
126
|
+
{centerBadge && (
|
|
127
|
+
<div className="pointer-events-none absolute inset-0 flex items-center justify-center">
|
|
128
|
+
<div className="flex size-12 items-center justify-center rounded-full bg-black/25 text-white">
|
|
129
|
+
{centerBadge}
|
|
130
|
+
</div>
|
|
131
|
+
</div>
|
|
124
132
|
)}
|
|
125
133
|
|
|
126
134
|
{total > 1 && (
|
|
@@ -150,8 +158,8 @@ const GalleryThumbnail: React.FC<GalleryThumbnailProps> = ({
|
|
|
150
158
|
<CaretRightIcon className="size-5" weight="bold" />
|
|
151
159
|
</button>
|
|
152
160
|
|
|
153
|
-
<div className="pointer-events-none absolute bottom-
|
|
154
|
-
<span className="text-xs font-medium leading-
|
|
161
|
+
<div className="pointer-events-none absolute bottom-5 left-1/2 -translate-x-1/2 rounded-lg bg-black/30 px-2 py-1">
|
|
162
|
+
<span className="text-xs font-medium leading-4 text-white">
|
|
155
163
|
{safeIndex + 1}/{total}
|
|
156
164
|
</span>
|
|
157
165
|
</div>
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import {
|
|
2
|
+
LockOpenIcon,
|
|
3
|
+
LockSimpleIcon,
|
|
4
|
+
PlayIcon,
|
|
5
|
+
} from '@phosphor-icons/react'
|
|
6
|
+
import React from 'react'
|
|
7
|
+
|
|
8
|
+
import { getSourceType } from '../../../AttachmentCard'
|
|
9
|
+
import type { PaymentStatus } from '../../types'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Centered 48x48 lock badge that overlays the thumbnail of any locked attachment.
|
|
13
|
+
* Uses `bg-black/25` from the design system's `alpha-black-25` token.
|
|
14
|
+
*
|
|
15
|
+
* For playable media (video/audio), the badge shows a play icon instead of a
|
|
16
|
+
* lock — matching the convention used by `GalleryThumbnail`.
|
|
17
|
+
*/
|
|
18
|
+
export const LockBadge: React.FC<{
|
|
19
|
+
paymentStatus?: PaymentStatus
|
|
20
|
+
mimeType?: string
|
|
21
|
+
}> = ({ paymentStatus, mimeType }) => {
|
|
22
|
+
const sourceType = mimeType ? getSourceType(mimeType) : undefined
|
|
23
|
+
const isPlayable = sourceType === 'video' || sourceType === 'audio'
|
|
24
|
+
|
|
25
|
+
const Icon = isPlayable
|
|
26
|
+
? PlayIcon
|
|
27
|
+
: paymentStatus === 'paid'
|
|
28
|
+
? LockOpenIcon
|
|
29
|
+
: LockSimpleIcon
|
|
30
|
+
return (
|
|
31
|
+
<div className="pointer-events-none absolute inset-0 flex items-center justify-center">
|
|
32
|
+
<div className="flex size-12 items-center justify-center rounded-full bg-black/25 text-white">
|
|
33
|
+
<Icon className="size-6" weight="fill" />
|
|
34
|
+
</div>
|
|
35
|
+
</div>
|
|
36
|
+
)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export default LockBadge
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import classNames from 'classnames'
|
|
2
2
|
import React from 'react'
|
|
3
3
|
|
|
4
|
-
export type
|
|
4
|
+
export type LockedCardVariant = 'dark' | 'light'
|
|
5
5
|
|
|
6
|
-
export interface
|
|
7
|
-
variant:
|
|
6
|
+
export interface LockedCardShellProps {
|
|
7
|
+
variant: LockedCardVariant
|
|
8
8
|
children: React.ReactNode
|
|
9
9
|
rootRef?: React.Ref<HTMLDivElement>
|
|
10
10
|
'data-testid'?: string
|
|
@@ -12,9 +12,9 @@ export interface MediaShellProps {
|
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Outer chrome for every LockedAttachment card.
|
|
15
|
-
* Mirrors the 16px radius treatment from the Figma design system.
|
|
15
|
+
* Mirrors the `shadow-400` + 16px radius treatment from the Figma design system.
|
|
16
16
|
*/
|
|
17
|
-
const
|
|
17
|
+
const LockedCardShell: React.FC<LockedCardShellProps> = ({
|
|
18
18
|
variant,
|
|
19
19
|
children,
|
|
20
20
|
rootRef,
|
|
@@ -25,12 +25,12 @@ const MediaShell: React.FC<MediaShellProps> = ({
|
|
|
25
25
|
data-testid={dataTestId}
|
|
26
26
|
className={classNames(
|
|
27
27
|
'relative w-[280px] select-none overflow-hidden rounded-md',
|
|
28
|
-
|
|
29
|
-
'
|
|
28
|
+
'shadow-[0_0_0_1px_rgba(0,0,0,0.04),0_1px_2px_rgba(0,0,0,0.04),0_8px_32px_rgba(0,0,0,0.1)]',
|
|
29
|
+
variant === 'dark' ? 'bg-[#1e2330]' : 'bg-white'
|
|
30
30
|
)}
|
|
31
31
|
>
|
|
32
32
|
{children}
|
|
33
33
|
</div>
|
|
34
34
|
)
|
|
35
35
|
|
|
36
|
-
export default
|
|
36
|
+
export default LockedCardShell
|
|
@@ -4,14 +4,14 @@ import React from 'react'
|
|
|
4
4
|
import {
|
|
5
5
|
AttachmentThumbnail,
|
|
6
6
|
renderTypeIcon,
|
|
7
|
-
} from '
|
|
7
|
+
} from '../../../AttachmentCard'
|
|
8
8
|
import type { LockedAttachmentSource, PaymentStatus } from '../../types'
|
|
9
9
|
|
|
10
10
|
import { LockBadge } from './LockBadge'
|
|
11
|
-
import type {
|
|
11
|
+
import type { LockedCardVariant } from './LockedCardShell'
|
|
12
12
|
|
|
13
|
-
export interface
|
|
14
|
-
variant:
|
|
13
|
+
export interface LockedThumbnailProps {
|
|
14
|
+
variant: LockedCardVariant
|
|
15
15
|
mimeType: string
|
|
16
16
|
thumbnailUrl?: string
|
|
17
17
|
title?: string
|
|
@@ -40,7 +40,7 @@ export interface SingleThumbnailProps {
|
|
|
40
40
|
* - preview/paid: clear thumbnail (the underlying source)
|
|
41
41
|
* - empty: type-icon placeholder
|
|
42
42
|
*/
|
|
43
|
-
const
|
|
43
|
+
const LockedThumbnail: React.FC<LockedThumbnailProps> = ({
|
|
44
44
|
variant,
|
|
45
45
|
mimeType,
|
|
46
46
|
thumbnailUrl,
|
|
@@ -98,11 +98,7 @@ const SingleThumbnail: React.FC<SingleThumbnailProps> = ({
|
|
|
98
98
|
})}
|
|
99
99
|
</div>
|
|
100
100
|
)}
|
|
101
|
-
<LockBadge
|
|
102
|
-
paymentStatus={paymentStatus}
|
|
103
|
-
mimeType={mimeType}
|
|
104
|
-
isLocked={showLocked}
|
|
105
|
-
/>
|
|
101
|
+
<LockBadge paymentStatus={paymentStatus} mimeType={mimeType} />
|
|
106
102
|
</div>
|
|
107
103
|
) : (
|
|
108
104
|
<AttachmentThumbnail
|
|
@@ -129,4 +125,4 @@ const SingleThumbnail: React.FC<SingleThumbnailProps> = ({
|
|
|
129
125
|
)
|
|
130
126
|
}
|
|
131
127
|
|
|
132
|
-
export default
|
|
128
|
+
export default LockedThumbnail
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import React, { Suspense } from 'react'
|
|
2
|
+
|
|
3
|
+
import type { ComposerCardProps } from './components/Composer/Card'
|
|
4
|
+
import type { ReceivedCardProps } from './components/Received/Card'
|
|
5
|
+
import type { SentCardProps } from './components/Sent/Card'
|
|
6
|
+
|
|
7
|
+
const ComposerCardLazy = React.lazy(() => import('./components/Composer/Card'))
|
|
8
|
+
const SentCardLazy = React.lazy(() => import('./components/Sent/Card'))
|
|
9
|
+
const ReceivedCardLazy = React.lazy(() => import('./components/Received/Card'))
|
|
10
|
+
|
|
11
|
+
const LockedAttachmentFallback = () => (
|
|
12
|
+
<div
|
|
13
|
+
className="w-[280px] min-h-[200px] animate-pulse rounded-md bg-black/[0.06] shadow-[0_0_0_1px_rgba(0,0,0,0.04),0_1px_2px_rgba(0,0,0,0.04),0_8px_32px_rgba(0,0,0,0.1)]"
|
|
14
|
+
aria-hidden
|
|
15
|
+
/>
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
const Composer = (props: ComposerCardProps) => (
|
|
19
|
+
<Suspense fallback={<LockedAttachmentFallback />}>
|
|
20
|
+
<ComposerCardLazy {...props} />
|
|
21
|
+
</Suspense>
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
const Sent = (props: SentCardProps) => (
|
|
25
|
+
<Suspense fallback={<LockedAttachmentFallback />}>
|
|
26
|
+
<SentCardLazy {...props} />
|
|
27
|
+
</Suspense>
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
const Received = (props: ReceivedCardProps) => (
|
|
31
|
+
<Suspense fallback={<LockedAttachmentFallback />}>
|
|
32
|
+
<ReceivedCardLazy {...props} />
|
|
33
|
+
</Suspense>
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @deprecated Renamed to `LockedAttachment.Sent` (post-send sender card) or
|
|
38
|
+
* `LockedAttachment.Composer` (drafting state). This alias maps to `Sent`
|
|
39
|
+
* because that matches the previous in-thread usage; pre-send / drafting
|
|
40
|
+
* usages (e.g. with `onDismiss`) should migrate to `LockedAttachment.Composer`.
|
|
41
|
+
*/
|
|
42
|
+
const Creator = Sent
|
|
43
|
+
|
|
44
|
+
/** @deprecated Renamed to `LockedAttachment.Received`. */
|
|
45
|
+
const Visitor = Received
|
|
46
|
+
|
|
47
|
+
const LockedAttachment = { Composer, Sent, Received, Creator, Visitor }
|
|
48
|
+
|
|
49
|
+
export default LockedAttachment
|
|
50
|
+
export type { ComposerCardProps, SentCardProps, ReceivedCardProps }
|
|
51
|
+
/**
|
|
52
|
+
* @deprecated Renamed to `SentCardProps`. Drafting usages (with `onDismiss`)
|
|
53
|
+
* should migrate to `ComposerCardProps`.
|
|
54
|
+
*/
|
|
55
|
+
export type CreatorCardProps = SentCardProps
|
|
56
|
+
/** @deprecated Renamed to `ReceivedCardProps`. */
|
|
57
|
+
export type VisitorCardProps = ReceivedCardProps
|
|
58
|
+
export type {
|
|
59
|
+
PaymentStatus,
|
|
60
|
+
LockedAttachmentSource,
|
|
61
|
+
LockedAttachmentGalleryItem,
|
|
62
|
+
LockedAttachmentContextValue,
|
|
63
|
+
} from './types'
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { Channel, LocalMessage } from 'stream-chat'
|
|
2
|
+
|
|
3
|
+
import type { PaymentStatus } from '../../stream-custom-data'
|
|
4
|
+
|
|
5
|
+
export interface LockedAttachmentBaseProps {
|
|
6
|
+
title?: string
|
|
7
|
+
mimeType?: string
|
|
8
|
+
thumbnailUrl?: string
|
|
9
|
+
detail?: string
|
|
10
|
+
amountText?: string
|
|
11
|
+
paymentStatus?: PaymentStatus
|
|
12
|
+
/**
|
|
13
|
+
* When provided with 2+ items, the card renders as a mixed-media carousel
|
|
14
|
+
* (e.g. a couple of photos + a video) instead of a single thumbnail. Each
|
|
15
|
+
* item brings its own thumbnail and optional source so that
|
|
16
|
+
* `LockedAttachment.Composer` / `.Sent` / `.Received` can all share the
|
|
17
|
+
* same carousel chrome.
|
|
18
|
+
*/
|
|
19
|
+
gallery?: LockedAttachmentGalleryItem[]
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface LockedAttachmentGalleryItem {
|
|
23
|
+
/** MIME type of this carousel item — drives the per-item play / lock affordance. */
|
|
24
|
+
mimeType: string
|
|
25
|
+
/** Poster image used for both the locked (blurred) and unlocked preview state. */
|
|
26
|
+
thumbnailUrl?: string
|
|
27
|
+
/** Underlying source (image or video URL) — shown only when unlocked. */
|
|
28
|
+
sourceUrl?: string
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface LockedAttachmentSource {
|
|
32
|
+
/** Proxied URL used by the media player for in-app playback. */
|
|
33
|
+
sourceUrl: string
|
|
34
|
+
/** URL opened when the visitor clicks Download — may be a file or a web destination. */
|
|
35
|
+
redeemUrl?: string
|
|
36
|
+
/** Thumbnail URL from the fetched asset — overrides the metadata thumbnail when present. */
|
|
37
|
+
thumbnailUrl?: string
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export type { PaymentStatus }
|
|
41
|
+
|
|
42
|
+
export interface LockedAttachmentContextValue {
|
|
43
|
+
isUnlocking: (id: string) => boolean
|
|
44
|
+
onUnlockClick?: (message: LocalMessage, channel: Channel) => void
|
|
45
|
+
onDownloadClick?: (message: LocalMessage, channel: Channel) => void
|
|
46
|
+
onFetchSource?: (message: LocalMessage, channel: Channel) => Promise<LockedAttachmentSource | void>
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export const defaultLockedAttachmentContextValue: LockedAttachmentContextValue = {
|
|
50
|
+
isUnlocking: () => false,
|
|
51
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -6,7 +6,7 @@ export { MessagingShell } from './components/MessagingShell'
|
|
|
6
6
|
export { ChannelList } from './components/ChannelList'
|
|
7
7
|
export { ChannelView } from './components/ChannelView'
|
|
8
8
|
export { default as ActionButton } from './components/ActionButton'
|
|
9
|
-
export { default as LockedAttachment } from './components/
|
|
9
|
+
export { default as LockedAttachment } from './components/LockedAttachment'
|
|
10
10
|
export { default as LinkAttachment } from './components/LinkAttachment'
|
|
11
11
|
export { default as MessageAttachment } from './components/MessageAttachment'
|
|
12
12
|
export { Avatar } from './components/Avatar'
|
|
@@ -76,10 +76,15 @@ export type {
|
|
|
76
76
|
} from './components/MessageBubble'
|
|
77
77
|
export type { ActionButtonProps } from './components/ActionButton'
|
|
78
78
|
export type {
|
|
79
|
-
|
|
79
|
+
ComposerCardProps,
|
|
80
|
+
SentCardProps,
|
|
81
|
+
ReceivedCardProps,
|
|
80
82
|
LockedAttachmentGalleryItem,
|
|
81
83
|
LockedAttachmentContextValue,
|
|
82
|
-
|
|
84
|
+
// Deprecated aliases preserved for backwards compatibility:
|
|
85
|
+
CreatorCardProps,
|
|
86
|
+
VisitorCardProps,
|
|
87
|
+
} from './components/LockedAttachment'
|
|
83
88
|
export type {
|
|
84
89
|
ComposerCardProps as LinkAttachmentComposerCardProps,
|
|
85
90
|
SentCardProps as LinkAttachmentSentCardProps,
|
|
@@ -41,7 +41,6 @@ export interface MessageMetadata {
|
|
|
41
41
|
amount_text?: string
|
|
42
42
|
payment_status?: PaymentStatus
|
|
43
43
|
attachment_title?: string
|
|
44
|
-
attachment_content_type?: 'text' | 'media'
|
|
45
44
|
attachment_mime_type?: string
|
|
46
45
|
attachment_thumbnail?: string
|
|
47
46
|
attachment_detail?: string
|
package/src/styles.css
CHANGED
|
@@ -831,15 +831,3 @@
|
|
|
831
831
|
color: #016e1a;
|
|
832
832
|
background-color: #dbf0e0;
|
|
833
833
|
}
|
|
834
|
-
|
|
835
|
-
/** Remove padding from the text inside the locked attachment text shell,
|
|
836
|
-
and inherit TextShell's explicit colour — stream-chat-react's own
|
|
837
|
-
`MessageText` sets its own (black) colour that only gets overridden by
|
|
838
|
-
`.str-chat`'s CSS vars, which the Composer preview doesn't have. */
|
|
839
|
-
.message-locked-attachment-text .str-chat__message-text {
|
|
840
|
-
padding: 0rem !important;
|
|
841
|
-
}
|
|
842
|
-
|
|
843
|
-
.message-locked-attachment-text .str-chat__message-text-inner {
|
|
844
|
-
color: inherit;
|
|
845
|
-
}
|
package/src/types.ts
CHANGED
|
@@ -20,7 +20,7 @@ import type {
|
|
|
20
20
|
|
|
21
21
|
import type { MessageMetadata } from './stream-custom-data'
|
|
22
22
|
|
|
23
|
-
export type { LockedAttachmentSource } from './components/
|
|
23
|
+
export type { LockedAttachmentSource } from './components/LockedAttachment'
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
26
|
* Callback invoked when a user clicks a link inside the channel view.
|
package/dist/Card-415OfRhw.cjs
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),h=require("@phosphor-icons/react"),d=require("./LoadingDots-D9GGphgM.cjs"),x=require("classnames"),r=({children:s})=>e.jsxs("div",{className:"flex items-center gap-1 text-xs font-medium",children:[e.jsx(h.LockSimpleIcon,{className:"size-3.5 shrink-0 opacity-55",weight:"fill","aria-hidden":!0}),s]}),c=({variant:s="dark"})=>{const a=s==="dark"?"bg-white/25":"bg-black/15";return e.jsxs("div",{className:"flex flex-col gap-2 str-chat__message-text my-1 animate-pulse","aria-hidden":!0,children:[e.jsx("div",{className:x("h-3 w-40 rounded-full",a)}),e.jsx("div",{className:x("h-3 w-24 rounded-full",a)})]})},n=({isMine:s,children:a,className:i})=>e.jsx("div",{className:x("message-locked-attachment-text","relative flex min-w-[225px] max-w-[280px] flex-col gap-1 rounded-[1.5rem] px-4 py-3","text-[0.875rem] leading-[1.3125rem] tracking-[0.14px]",s?"bg-[#1e2330] text-white":"bg-[#f2f1ef] text-black","shadow-[0_1px_2px_rgba(0,0,0,0.08)]",i),children:a}),u=({renderedText:s,amountText:a,placeholderAmountText:i,onDismiss:t})=>e.jsxs(n,{isMine:!0,className:"pr-8",children:[s||e.jsx(c,{variant:"dark"}),e.jsx(r,{children:e.jsx("span",{className:a?"text-white/55":"text-white/30",children:a||i})}),t&&e.jsx("button",{type:"button",onClick:t,className:"absolute right-3 top-3 flex size-6 shrink-0 items-center justify-center rounded-full bg-white/10 text-white hover:bg-white/15","aria-label":"Dismiss attachment",children:e.jsx(h.XIcon,{className:"size-3",weight:"bold"})})]}),j=({amountText:s,placeholderAmountText:a})=>e.jsxs(n,{isMine:!1,children:[e.jsx(c,{variant:"light"}),e.jsx(r,{children:e.jsx("span",{className:"opacity-55",children:s||a})})]}),m=({renderedText:s,amountText:a,paymentStatus:i="pending"})=>{const t=i==="paid";return e.jsxs(n,{isMine:!0,children:[t&&s?s:e.jsx(c,{variant:"dark"}),e.jsxs(r,{children:[a&&e.jsx("span",{className:"text-white/55",children:a}),e.jsx(d.PurchaseStatusBadge,{isMine:!0,paymentStatus:i})]})]})},f=({renderedText:s,amountText:a,paymentStatus:i,onUnlockClick:t,isUnlocking:l=!1})=>{if(i==="paid"&&s)return e.jsxs(n,{isMine:!1,children:[s,e.jsxs(r,{children:[a!=null&&e.jsx("span",{className:"opacity-55",children:a}),e.jsx(d.PurchaseStatusBadge,{isMine:!1,paymentStatus:"paid"})]})]});const o=l?"Unlocking message.":"Unlock this message.";return e.jsx(n,{isMine:!1,children:e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsxs("div",{className:"flex flex-1 flex-col gap-2",children:[e.jsx(c,{variant:"light"}),e.jsx("span",{className:"sr-only","aria-live":"polite",children:o}),e.jsx(r,{children:a!=null&&e.jsx("span",{className:"opacity-55",children:a})})]}),e.jsx("button",{type:"button",onClick:t,disabled:l,"aria-label":l?"Unlocking message":"Unlock message","aria-busy":l,title:l?"Unlocking message":"Unlock message",className:"flex size-10 shrink-0 items-center justify-center rounded-full bg-[#121110] text-white hover:bg-[#2a2928]",children:l?e.jsx(d.LoadingDots,{}):e.jsx(h.LockSimpleIcon,{className:"size-4",weight:"fill","aria-hidden":!0})})]})})},g=s=>s.isDraft?e.jsx(u,{...s}):s.isPreview?e.jsx(j,{...s}):s.isMine?e.jsx(m,{...s}):e.jsx(f,{...s});exports.default=g;
|
|
2
|
-
//# sourceMappingURL=Card-415OfRhw.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Card-415OfRhw.cjs","sources":["../src/components/CustomMessage/LockedAttachment/components/_shared/PriceLockRow.tsx","../src/components/CustomMessage/LockedAttachment/components/_shared/SkeletonTextLines.tsx","../src/components/CustomMessage/LockedAttachment/components/_shared/TextShell.tsx","../src/components/CustomMessage/LockedAttachment/components/Text/Card.tsx"],"sourcesContent":["import { LockSimpleIcon } from '@phosphor-icons/react'\nimport type React from 'react'\n\n/**\n * The lock-icon + amount/status row shared by every LockedAttachment text-mode\n * card. Only the wrapper and the leading lock icon are shared — the amount and\n * any trailing status live in `children`, since they genuinely differ per card\n * (placeholder fallback vs. paid badge vs. bare amount).\n */\nconst PriceLockRow: React.FC<React.PropsWithChildren> = ({ children }) => (\n <div className=\"flex items-center gap-1 text-xs font-medium\">\n <LockSimpleIcon\n className=\"size-3.5 shrink-0 opacity-55\"\n weight=\"fill\"\n aria-hidden\n />\n {children}\n </div>\n)\n\nexport default PriceLockRow\n","import classNames from 'classnames'\nimport React from 'react'\n\nexport interface SkeletonTextLinesProps {\n /** Matches the bubble it sits in — \"dark\" for the sender's own bubble. */\n variant: 'light' | 'dark'\n}\n\n/**\n * Two skeleton bars standing in for the redacted text of a paid text-only\n * message — the real content is never sent to the client until purchase, so\n * there's nothing to render yet.\n *\n * Uses explicit black/white (not `bg-current`) because Tailwind doesn't\n * support opacity modifiers on the `current` color — `bg-current/30` silently\n * produces no CSS rule at all.\n */\nconst SkeletonTextLines: React.FC<SkeletonTextLinesProps> = ({ variant = 'dark' }) => {\n const colour = variant === 'dark' ? 'bg-white/25' : 'bg-black/15'\n\n return (\n <div className=\"flex flex-col gap-2 str-chat__message-text my-1 animate-pulse\" aria-hidden>\n <div className={classNames('h-3 w-40 rounded-full', colour)} />\n <div className={classNames('h-3 w-24 rounded-full', colour)} />\n </div>\n )\n}\n\nexport default SkeletonTextLines\n","import classNames from 'classnames'\nimport React from 'react'\n\n/**\n * Chat-bubble chrome for a paid text-only message/preview. Deliberately\n * doesn't lean on `.str-chat`'s CSS variables (`--str-chat__message-bubble-*`)\n * — this renders in the Composer preview too, which sits outside any\n * `.str-chat` ancestor, so every value here (radius, colour, type scale) is\n * hardcoded to match the Figma spec directly.\n */\nconst TextShell: React.FC<\n React.PropsWithChildren<{ isMine: boolean; className?: string }>\n> = ({ isMine, children, className }) => (\n <div\n className={classNames(\n 'message-locked-attachment-text',\n 'relative flex min-w-[225px] max-w-[280px] flex-col gap-1 rounded-[1.5rem] px-4 py-3',\n 'text-[0.875rem] leading-[1.3125rem] tracking-[0.14px]',\n isMine ? 'bg-[#1e2330] text-white' : 'bg-[#f2f1ef] text-black',\n 'shadow-[0_1px_2px_rgba(0,0,0,0.08)]',\n className\n )}\n >\n {children}\n </div>\n)\n\nexport default TextShell\n","import { LockSimpleIcon, XIcon } from '@phosphor-icons/react'\nimport type React from 'react'\n\nimport LoadingDots from '../_shared/LoadingDots'\nimport PriceLockRow from '../_shared/PriceLockRow'\nimport PurchaseStatusBadge from '../_shared/PurchaseStatusBadge'\nimport SkeletonTextLines from '../_shared/SkeletonTextLines'\nimport TextShell from '../_shared/TextShell'\n\nimport type {\n TextCardDraftProps,\n TextCardOtherProps,\n TextCardOwnProps,\n TextCardPreviewProps,\n TextCardProps,\n} from './types'\n\nexport type { TextCardProps } from './types'\n\nconst DraftTextCard: React.FC<TextCardDraftProps> = ({\n renderedText,\n amountText,\n placeholderAmountText,\n onDismiss,\n}) => (\n <TextShell isMine className=\"pr-8\">\n {renderedText || <SkeletonTextLines variant=\"dark\" />}\n <PriceLockRow>\n <span className={amountText ? 'text-white/55' : 'text-white/30'}>\n {amountText || placeholderAmountText}\n </span>\n </PriceLockRow>\n {onDismiss && (\n <button\n type=\"button\"\n onClick={onDismiss}\n className=\"absolute right-3 top-3 flex size-6 shrink-0 items-center justify-center rounded-full bg-white/10 text-white hover:bg-white/15\"\n aria-label=\"Dismiss attachment\"\n >\n <XIcon className=\"size-3\" weight=\"bold\" />\n </button>\n )}\n </TextShell>\n)\n\nconst PreviewTextCard: React.FC<TextCardPreviewProps> = ({\n amountText,\n placeholderAmountText,\n}) => (\n <TextShell isMine={false}>\n <SkeletonTextLines variant=\"light\" />\n <PriceLockRow>\n <span className=\"opacity-55\">{amountText || placeholderAmountText}</span>\n </PriceLockRow>\n </TextShell>\n)\n\nconst OwnTextCard: React.FC<TextCardOwnProps> = ({\n renderedText,\n amountText,\n paymentStatus = 'pending',\n}) => {\n const isPaid = paymentStatus === 'paid'\n\n return (\n <TextShell isMine>\n {isPaid && renderedText ? (\n renderedText\n ) : (\n <SkeletonTextLines variant=\"dark\" />\n )}\n <PriceLockRow>\n {amountText && <span className=\"text-white/55\">{amountText}</span>}\n <PurchaseStatusBadge isMine paymentStatus={paymentStatus} />\n </PriceLockRow>\n </TextShell>\n )\n}\n\nconst OtherTextCard: React.FC<TextCardOtherProps> = ({\n renderedText,\n amountText,\n paymentStatus,\n onUnlockClick,\n isUnlocking = false,\n}) => {\n const isPaid = paymentStatus === 'paid'\n\n if (isPaid && renderedText) {\n return (\n <TextShell isMine={false}>\n {renderedText}\n <PriceLockRow>\n {amountText != null && (\n <span className=\"opacity-55\">{amountText}</span>\n )}\n <PurchaseStatusBadge isMine={false} paymentStatus=\"paid\" />\n </PriceLockRow>\n </TextShell>\n )\n }\n\n const ariaLabel = isUnlocking\n ? 'Unlocking message.'\n : 'Unlock this message.'\n\n return (\n <TextShell isMine={false}>\n <div className=\"flex items-center gap-3\">\n <div className=\"flex flex-1 flex-col gap-2\">\n <SkeletonTextLines variant=\"light\" />\n <span className=\"sr-only\" aria-live=\"polite\">\n {ariaLabel}\n </span>\n <PriceLockRow>\n {amountText != null && (\n <span className=\"opacity-55\">{amountText}</span>\n )}\n </PriceLockRow>\n </div>\n <button\n type=\"button\"\n onClick={onUnlockClick}\n disabled={isUnlocking}\n aria-label={isUnlocking ? 'Unlocking message' : 'Unlock message'}\n aria-busy={isUnlocking}\n title={isUnlocking ? 'Unlocking message' : 'Unlock message'}\n className=\"flex size-10 shrink-0 items-center justify-center rounded-full bg-[#121110] text-white hover:bg-[#2a2928]\"\n >\n {isUnlocking ? (\n <LoadingDots />\n ) : (\n <LockSimpleIcon className=\"size-4\" weight=\"fill\" aria-hidden />\n )}\n </button>\n </div>\n </TextShell>\n )\n}\n\nconst TextCard: React.FC<TextCardProps> = (props) => {\n if (props.isDraft) {\n return <DraftTextCard {...props} />\n } else if (props.isPreview) {\n return <PreviewTextCard {...props} />\n } else if (props.isMine) {\n return <OwnTextCard {...props} />\n } else {\n return <OtherTextCard {...props} />\n }\n}\n\nexport default TextCard\n"],"names":["PriceLockRow","children","jsxs","jsx","LockSimpleIcon","SkeletonTextLines","variant","colour","classNames","TextShell","isMine","className","DraftTextCard","renderedText","amountText","placeholderAmountText","onDismiss","XIcon","PreviewTextCard","OwnTextCard","paymentStatus","isPaid","PurchaseStatusBadge","OtherTextCard","onUnlockClick","isUnlocking","ariaLabel","LoadingDots","TextCard","props"],"mappings":"wNASMA,EAAkD,CAAC,CAAE,SAAAC,KACzDC,EAAAA,KAAC,MAAA,CAAI,UAAU,8CACb,SAAA,CAAAC,EAAAA,IAACC,EAAAA,eAAA,CACC,UAAU,+BACV,OAAO,OACP,cAAW,EAAA,CAAA,EAEZH,CAAA,EACH,ECAII,EAAsD,CAAC,CAAE,QAAAC,EAAU,UAAa,CACpF,MAAMC,EAASD,IAAY,OAAS,cAAgB,cAEpD,OACEJ,EAAAA,KAAC,MAAA,CAAI,UAAU,gEAAgE,cAAW,GACxF,SAAA,CAAAC,EAAAA,IAAC,MAAA,CAAI,UAAWK,EAAW,wBAAyBD,CAAM,EAAG,QAC5D,MAAA,CAAI,UAAWC,EAAW,wBAAyBD,CAAM,CAAA,CAAG,CAAA,EAC/D,CAEJ,EChBME,EAEF,CAAC,CAAE,OAAAC,EAAQ,SAAAT,EAAU,UAAAU,KACvBR,EAAAA,IAAC,MAAA,CACC,UAAWK,EACT,iCACA,sFACA,wDACAE,EAAS,0BAA4B,0BACrC,sCACAC,CAAA,EAGD,SAAAV,CAAA,CACH,ECLIW,EAA8C,CAAC,CACnD,aAAAC,EACA,WAAAC,EACA,sBAAAC,EACA,UAAAC,CACF,IACEd,EAAAA,KAACO,EAAA,CAAU,OAAM,GAAC,UAAU,OACvB,SAAA,CAAAI,GAAgBV,EAAAA,IAACE,EAAA,CAAkB,QAAQ,MAAA,CAAO,EACrDF,EAAAA,IAACH,EAAA,CACC,SAAAG,EAAAA,IAAC,OAAA,CAAK,UAAWW,EAAa,gBAAkB,gBAC7C,SAAAA,GAAcC,CAAA,CACjB,CAAA,CACF,EACCC,GACCb,EAAAA,IAAC,SAAA,CACC,KAAK,SACL,QAASa,EACT,UAAU,gIACV,aAAW,qBAEX,SAAAb,EAAAA,IAACc,QAAA,CAAM,UAAU,SAAS,OAAO,MAAA,CAAO,CAAA,CAAA,CAC1C,EAEJ,EAGIC,EAAkD,CAAC,CACvD,WAAAJ,EACA,sBAAAC,CACF,IACEb,EAAAA,KAACO,EAAA,CAAU,OAAQ,GACjB,SAAA,CAAAN,EAAAA,IAACE,EAAA,CAAkB,QAAQ,OAAA,CAAQ,EACnCF,EAAAA,IAACH,GACC,SAAAG,EAAAA,IAAC,OAAA,CAAK,UAAU,aAAc,SAAAW,GAAcC,EAAsB,CAAA,CACpE,CAAA,EACF,EAGII,EAA0C,CAAC,CAC/C,aAAAN,EACA,WAAAC,EACA,cAAAM,EAAgB,SAClB,IAAM,CACJ,MAAMC,EAASD,IAAkB,OAEjC,OACElB,EAAAA,KAACO,EAAA,CAAU,OAAM,GACd,SAAA,CAAAY,GAAUR,EACTA,EAEAV,EAAAA,IAACE,EAAA,CAAkB,QAAQ,OAAO,SAEnCL,EAAA,CACE,SAAA,CAAAc,GAAcX,EAAAA,IAAC,OAAA,CAAK,UAAU,gBAAiB,SAAAW,EAAW,EAC3DX,EAAAA,IAACmB,EAAAA,oBAAA,CAAoB,OAAM,GAAC,cAAAF,CAAA,CAA8B,CAAA,CAAA,CAC5D,CAAA,EACF,CAEJ,EAEMG,EAA8C,CAAC,CACnD,aAAAV,EACA,WAAAC,EACA,cAAAM,EACA,cAAAI,EACA,YAAAC,EAAc,EAChB,IAAM,CAGJ,GAFeL,IAAkB,QAEnBP,EACZ,OACEX,EAAAA,KAACO,EAAA,CAAU,OAAQ,GAChB,SAAA,CAAAI,SACAb,EAAA,CACE,SAAA,CAAAc,GAAc,MACbX,EAAAA,IAAC,OAAA,CAAK,UAAU,aAAc,SAAAW,EAAW,EAE3CX,EAAAA,IAACmB,EAAAA,oBAAA,CAAoB,OAAQ,GAAO,cAAc,MAAA,CAAO,CAAA,CAAA,CAC3D,CAAA,EACF,EAIJ,MAAMI,EAAYD,EACd,qBACA,uBAEJ,aACGhB,EAAA,CAAU,OAAQ,GACjB,SAAAP,EAAAA,KAAC,MAAA,CAAI,UAAU,0BACb,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,6BACb,SAAA,CAAAC,EAAAA,IAACE,EAAA,CAAkB,QAAQ,OAAA,CAAQ,QAClC,OAAA,CAAK,UAAU,UAAU,YAAU,SACjC,SAAAqB,EACH,EACAvB,EAAAA,IAACH,GACE,SAAAc,GAAc,YACZ,OAAA,CAAK,UAAU,aAAc,SAAAA,CAAA,CAAW,CAAA,CAE7C,CAAA,EACF,EACAX,EAAAA,IAAC,SAAA,CACC,KAAK,SACL,QAASqB,EACT,SAAUC,EACV,aAAYA,EAAc,oBAAsB,iBAChD,YAAWA,EACX,MAAOA,EAAc,oBAAsB,iBAC3C,UAAU,4GAET,SAAAA,EACCtB,EAAAA,IAACwB,EAAAA,YAAA,CAAA,CAAY,EAEbxB,EAAAA,IAACC,EAAAA,eAAA,CAAe,UAAU,SAAS,OAAO,OAAO,cAAW,EAAA,CAAC,CAAA,CAAA,CAEjE,CAAA,CACF,CAAA,CACF,CAEJ,EAEMwB,EAAqCC,GACrCA,EAAM,QACD1B,MAACS,EAAA,CAAe,GAAGiB,CAAA,CAAO,EACxBA,EAAM,UACR1B,MAACe,EAAA,CAAiB,GAAGW,CAAA,CAAO,EAC1BA,EAAM,OACR1B,MAACgB,EAAA,CAAa,GAAGU,CAAA,CAAO,EAExB1B,MAACoB,EAAA,CAAe,GAAGM,CAAA,CAAO"}
|
package/dist/Card-CyWdUMCB.cjs
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),b=require("@phosphor-icons/react"),h=require("react"),v=require("classnames"),k=require("./index-Bx_zjNMR.cjs"),T=require("./LoadingDots-D9GGphgM.cjs"),P=({variant:t,title:s,placeholderTitle:n="Attachment title",mimeType:i,detail:a,statusBadge:r,action:c,icon:u,trailingAction:d})=>{const l=t==="dark",o=s||n,x=!s,f=u??k.renderTypeIcon(i,{className:v("size-5 shrink-0",l?"text-white/55":"text-black/55"),weight:"regular"});return e.jsxs("div",{className:"px-4 py-3",children:[e.jsxs("div",{className:"flex items-end gap-3",children:[e.jsxs("div",{className:"flex min-w-0 flex-1 flex-col gap-1",children:[o.trim()!==""&&e.jsx("p",{className:v("truncate text-base font-medium leading-6",{"text-black/90":!l&&!x,"text-black/30":!l&&x,"text-white/30":l&&x,"text-white":l&&!x}),children:o}),e.jsxs("div",{className:"flex flex-wrap items-center gap-1",children:[f,a!=null&&a!==""&&e.jsx("span",{className:v("text-xs font-medium",l?"text-white/55":"text-black/55"),children:a}),r]})]}),d&&e.jsx("div",{className:"shrink-0",children:d})]}),c]})},M=({paymentStatus:t,mimeType:s,isPlayable:n,isLocked:i})=>{const a=s?k.getSourceType(s):void 0,c=(n??(a==="video"||a==="audio"))&&!i?b.PlayIcon:t==="paid"?b.LockOpenIcon:b.LockSimpleIcon;return e.jsx("div",{className:"pointer-events-none absolute inset-0 flex items-center justify-center",children:e.jsx("div",{className:v("flex size-12 items-center justify-center rounded-full bg-black/30 text-white",c===b.PlayIcon&&"group-hover:bg-black/40"),children:e.jsx(c,{className:"size-6",weight:"fill"})})})};function q(t){const s=k.getSourceType(t.mimeType);return s==="video"||s==="audio"}const O=({variant:t,gallery:s,title:n,showLocked:i,paymentStatus:a,topRight:r})=>{const[c,u]=h.useState(0),d=s.length,l=Math.min(c,d-1),o=s[l],x=q(o),f=g=>{g.stopPropagation(),u(N=>Math.max(0,N-1))},w=g=>{g.stopPropagation(),u(N=>Math.min(d-1,N+1))},j=l===0,m=l===d-1,p=t==="dark";return e.jsxs("div",{className:v("group relative overflow-hidden rounded-t-md",i?"aspect-[337/386]":void 0),children:[i?e.jsx("div",{className:v("absolute inset-0",p?"bg-white/10":"bg-black/5"),children:o.thumbnailUrl&&e.jsx("img",{src:o.thumbnailUrl,alt:"","aria-hidden":!0,draggable:!1,className:"absolute inset-0 h-full w-full scale-110 object-cover blur-[40px]"})}):e.jsx(k.AttachmentThumbnail,{mimeType:o.mimeType,sourceUrl:o.sourceUrl,thumbnailUrl:o.thumbnailUrl,title:n,variant:t,mediaPlayerProps:{autoPlay:!0}},l),i&&e.jsx(M,{paymentStatus:a,isPlayable:x,isLocked:i}),d>1&&e.jsxs(h.Fragment,{children:[e.jsx("button",{type:"button",onClick:f,disabled:j,"aria-label":"Previous item",className:v("absolute left-3 top-1/2 -translate-y-1/2 flex size-7 items-center justify-center rounded-full bg-black/30 text-white transition-opacity",j?"opacity-40":"hover:bg-black/40"),children:e.jsx(b.CaretLeftIcon,{className:"size-5",weight:"bold"})}),e.jsx("button",{type:"button",onClick:w,disabled:m,"aria-label":"Next item",className:v("absolute right-3 top-1/2 -translate-y-1/2 flex size-7 items-center justify-center rounded-full bg-black/30 text-white transition-opacity",m?"opacity-40":"hover:bg-black/40"),children:e.jsx(b.CaretRightIcon,{className:"size-5",weight:"bold"})}),e.jsx("div",{className:"pointer-events-none absolute bottom-10 left-1/2 flex size-8 -translate-x-1/2 items-center justify-center rounded-full bg-black/30",children:e.jsxs("span",{className:"text-xs font-medium leading-none text-white",children:[l+1,"/",d]})})]}),r&&e.jsx("div",{className:"pointer-events-auto absolute right-3 top-3 z-10",children:r})]})},A=({variant:t,mimeType:s,thumbnailUrl:n,title:i,source:a,showLocked:r,paymentStatus:c,topRight:u,containedImage:d=!1})=>{const l=r||a==null?void 0:a.sourceUrl,o=r?n:(a==null?void 0:a.thumbnailUrl)??n,x=t==="dark";return e.jsxs("div",{className:"relative overflow-hidden rounded-t-md",children:[r?e.jsxs("div",{className:v("relative aspect-video overflow-hidden",x?"bg-white/10":"bg-black/5"),children:[o?e.jsx("img",{src:o,alt:"","aria-hidden":!0,draggable:!1,className:"absolute inset-0 h-full w-full scale-110 object-cover blur-[40px]"}):e.jsx("div",{className:"absolute inset-0 flex items-center justify-center",children:k.renderTypeIcon(s,{className:x?"size-12 text-white/20":"size-12 text-black/20",weight:"regular"})}),e.jsx(M,{paymentStatus:c,mimeType:s,isLocked:r})]}):e.jsx(k.AttachmentThumbnail,{mimeType:s,sourceUrl:l,thumbnailUrl:o,title:i,variant:t,containedImage:d,mediaPlayerProps:l?{autoPlay:!0,loop:!0,controls:!0,muted:!1}:void 0}),u&&e.jsx("div",{className:"pointer-events-auto absolute right-3 top-3 z-10",children:u})]})},y=t=>t.length>=2,I=t=>e.jsx(b.ImagesIcon,{className:t==="dark"?"size-5 shrink-0 text-white/55":"size-5 shrink-0 text-black/55"}),z=({variant:t,gallery:s,title:n,showLocked:i,paymentStatus:a,mimeType:r,thumbnailUrl:c,source:u,containedImage:d,topRight:l})=>y(s)?e.jsx(O,{variant:t,gallery:s,title:n,showLocked:i,paymentStatus:a,topRight:l}):e.jsx(A,{variant:t,mimeType:r,thumbnailUrl:c,title:n,source:u,showLocked:i,paymentStatus:a,topRight:l,containedImage:d}),U=({variant:t,children:s,rootRef:n,"data-testid":i})=>e.jsx("div",{ref:n,"data-testid":i,className:v("relative w-[280px] select-none overflow-hidden rounded-md",t==="dark"?"bg-[#1e2330]":"bg-white","shadow-[0_1px_2px_rgba(0,0,0,0.08)]"),children:s}),C=({onToggle:t,isBusy:s,isPreviewVisible:n,children:i})=>t?e.jsx("div",{role:"button",tabIndex:s?-1:0,"aria-label":"Toggle preview","aria-busy":s,"aria-pressed":n,"aria-disabled":s||void 0,onClick:s?void 0:t,onKeyDown:a=>{s||a.target===a.currentTarget&&(a.key==="Enter"||a.key===" ")&&(a.preventDefault(),t())},className:s?"block w-full text-left":"block w-full cursor-pointer text-left",children:i}):e.jsx(h.Fragment,{children:i});function R({isGallery:t,onFetchSource:s,onPreviewClick:n}){const[i,a]=h.useState(),[r,c]=h.useState(!1),[u,d]=h.useState(!1),l=h.useRef(!1),o=h.useCallback(async()=>{if(n==null||n(),r){c(!1);return}if(t){c(!0);return}if(i){c(!0);return}if(s&&!l.current){l.current=!0,d(!0);try{const f=await s();f&&(a(f),c(!0))}finally{l.current=!1,d(!1)}}},[r,t,i,n,s]),x=t||s!=null||n!=null?o:void 0;return{source:i,isPreviewVisible:r,isLoadingPreview:u,handleToggle:o,togglePreview:x}}function G({paymentStatus:t,onFetchSource:s,onUnlockClick:n}){const[i,a]=h.useState(),r=h.useRef(null),c=h.useRef(!1),u=h.useRef(s);u.current=s;const d=h.useCallback(async()=>{var o;if(!c.current){c.current=!0;try{const x=await((o=u.current)==null?void 0:o.call(u));x&&a(x)}finally{c.current=!1}}},[]),l=h.useCallback(()=>{t==="paid"?d():n==null||n()},[t,d,n]);return h.useEffect(()=>{if(!r.current||t!=="paid"||i!==void 0)return;const o=new IntersectionObserver(([x])=>{x.isIntersecting&&(d(),o.disconnect())},{threshold:1});return o.observe(r.current),()=>o.disconnect()},[t,i,d]),{source:i,cardRef:r,handleUnlockClick:l}}const S="mt-3 inline-flex h-10 w-full items-center justify-center gap-2 rounded-full bg-[#121110] px-4 text-sm font-medium leading-none text-white hover:bg-[#2a2928]",_=({isLocked:t,sourceUrl:s,redeemUrl:n,onUnlockClicked:i,onDownloadClicked:a,isUnlocking:r=!1})=>{if(t&&i!=null)return e.jsx("button",{type:"button",onClick:i,disabled:r,"aria-label":r?"Unlocking":"Unlock","aria-busy":r,title:r?"Unlocking":"Unlock",className:S,children:r?e.jsx(T.LoadingDots,{}):e.jsxs(h.Fragment,{children:[e.jsx(b.LockSimpleIcon,{className:"size-4",weight:"fill"}),"Unlock"]})});if(!t&&a!=null){const c=n??s;return c!=null?e.jsxs("a",{href:c,"aria-label":"Download",target:"_blank",rel:"noopener noreferrer",onClick:a,className:`${S} !text-white`,children:[e.jsx(b.DownloadSimpleIcon,{className:"size-4",weight:"bold"}),"Download"]}):e.jsxs("button",{type:"button",onClick:a,"aria-label":"Download",className:S,children:[e.jsx(b.DownloadSimpleIcon,{className:"size-4",weight:"bold"}),"Download"]})}return null},E=({title:t,mimeType:s="application/octet-stream",thumbnailUrl:n,detail:i,amountText:a,placeholderTitle:r,placeholderAmountText:c,gallery:u=[],onDismiss:d,onPreviewClick:l,onFetchSource:o,onEditClick:x})=>{const f=y(u),{source:w,isPreviewVisible:j,isLoadingPreview:m,togglePreview:p}=R({isGallery:f,onFetchSource:o,onPreviewClick:l}),g=!j,N=m,D=e.jsxs(h.Fragment,{children:[e.jsx("span",{className:"text-xs font-medium text-white/55",children:"•"}),e.jsx("span",{className:a?"text-xs font-medium text-white/55":"text-xs font-medium text-white/30",children:a||c})]}),L=d?e.jsx("button",{type:"button",onClick:V=>{V.stopPropagation(),d()},className:"flex size-6 items-center justify-center rounded-full bg-[#121110] text-white","aria-label":"Dismiss attachment",children:e.jsx(b.XIcon,{className:"size-3",weight:"bold"})}):void 0,B=x?e.jsx("button",{type:"button",onClick:x,"aria-label":"Edit attachment",className:"flex size-10 items-center justify-center rounded-full bg-white/10 text-white hover:bg-white/15",children:e.jsx(b.PencilSimpleIcon,{className:"size-5",weight:"regular"})}):void 0;return e.jsxs(U,{variant:"dark",children:[e.jsx(C,{onToggle:p,isBusy:N,isPreviewVisible:!g,children:e.jsx(z,{variant:"dark",gallery:u,title:t,showLocked:g,mimeType:s,thumbnailUrl:n,source:w,topRight:L})}),e.jsx(P,{variant:"dark",title:t,placeholderTitle:r,mimeType:s,detail:i,statusBadge:D,icon:f?I("dark"):void 0,trailingAction:B})]})},$=({title:t,mimeType:s="application/octet-stream",thumbnailUrl:n,detail:i,amountText:a,placeholderTitle:r,placeholderAmountText:c,gallery:u=[]})=>{const d=y(u),l=e.jsxs(h.Fragment,{children:[e.jsx("span",{className:"text-xs font-medium text-black/55",children:"•"}),e.jsx("span",{className:a?"text-xs font-medium text-black/55":"text-xs font-medium text-black/30",children:a||c})]});return e.jsxs(U,{variant:"light",children:[e.jsx(z,{variant:"light",gallery:u,title:t,showLocked:!0,mimeType:s,thumbnailUrl:n}),e.jsx(P,{variant:"light",title:t,placeholderTitle:r,mimeType:s,detail:i,statusBadge:l,icon:d?I("light"):void 0})]})},K=({title:t,mimeType:s="application/octet-stream",thumbnailUrl:n,detail:i,amountText:a,placeholderTitle:r,paymentStatus:c="pending",gallery:u=[],onPreviewClick:d,onFetchSource:l})=>{const o=y(u),{source:x,isPreviewVisible:f,isLoadingPreview:w,togglePreview:j}=R({isGallery:o,onFetchSource:l,onPreviewClick:d}),m=!f,p=w;return e.jsxs(U,{variant:"dark",children:[e.jsx(C,{onToggle:j,isBusy:p,isPreviewVisible:!m,children:e.jsx(z,{variant:"dark",gallery:u,title:t,showLocked:m,paymentStatus:c,mimeType:s,thumbnailUrl:n,source:x})}),e.jsx(P,{variant:"dark",title:t,placeholderTitle:r,mimeType:s,detail:i,statusBadge:e.jsx(T.PurchaseStatusBadge,{isMine:!0,paymentStatus:c,amountText:a}),icon:o?I("dark"):void 0})]})},X=({title:t,amountText:s,thumbnailUrl:n,mimeType:i="application/octet-stream",detail:a,gallery:r=[],onUnlockClick:c,onFetchSource:u,onDownloadClick:d,paymentStatus:l,isUnlocking:o=!1})=>{const x=y(r),{source:f,cardRef:w,handleUnlockClick:j}=G({paymentStatus:l,onFetchSource:u,onUnlockClick:c}),m=f==null?void 0:f.sourceUrl,p=f==null?void 0:f.redeemUrl,g=x?l!=="paid":m===void 0,N=k.getSourceType(i),D=x?void 0:m;return e.jsxs(U,{variant:"light",rootRef:w,"data-testid":"locked-attachment",children:[e.jsx(z,{variant:"light",gallery:r,title:t,showLocked:g,paymentStatus:l,mimeType:i,thumbnailUrl:n,source:f,containedImage:!g&&N==="document"}),e.jsx(P,{variant:"light",title:t,mimeType:i,detail:a,statusBadge:e.jsx(T.PurchaseStatusBadge,{isMine:!1,paymentStatus:l,amountText:s}),icon:x?I("light"):void 0,action:e.jsx(_,{isLocked:g,isUnlocking:o,sourceUrl:D,redeemUrl:p,onUnlockClicked:j,onDownloadClicked:d})})]})},F=t=>t.isDraft?e.jsx(E,{...t}):t.isPreview?e.jsx($,{...t}):t.isMine?e.jsx(K,{...t}):e.jsx(X,{...t});exports.default=F;
|
|
2
|
-
//# sourceMappingURL=Card-CyWdUMCB.cjs.map
|