@linktr.ee/messaging-react 1.29.0 → 1.29.1-rc-1776411492
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/Visitor-CB5mQ20A.js +196 -0
- package/dist/Visitor-CB5mQ20A.js.map +1 -0
- package/dist/index.d.ts +2 -5
- package/dist/index.js +1 -1
- package/package.json +5 -5
- package/src/components/LockedAttachment/LockedAttachment.stories.tsx +1 -1
- package/src/components/LockedAttachment/components/Visitor.tsx +21 -71
- package/dist/Visitor-C4WqnN8H.js +0 -218
- package/dist/Visitor-C4WqnN8H.js.map +0 -1
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import { jsxs as l, jsx as e, Fragment as p } from "react/jsx-runtime";
|
|
2
|
+
import { CheckCircleIcon as T, LockSimpleIcon as y, DownloadSimpleIcon as P, LockOpenIcon as C } from "@phosphor-icons/react";
|
|
3
|
+
import { useState as b, useEffect as L } from "react";
|
|
4
|
+
import { g as D, r as g, M as U } from "./MediaPlayer-Bf-xPB8Z.js";
|
|
5
|
+
const x = (s) => s === "paid" ? C : y, z = (s) => {
|
|
6
|
+
const { icon: t } = s;
|
|
7
|
+
return /* @__PURE__ */ e("div", { className: "absolute inset-0 bg-black/30", children: /* @__PURE__ */ e("div", { className: "absolute left-3 top-3 flex size-8 items-center justify-center rounded-full bg-black/60", children: /* @__PURE__ */ e(t, { className: "size-4 text-white", weight: "fill" }) }) });
|
|
8
|
+
}, I = (s) => {
|
|
9
|
+
const { thumbnail: t, mimeType: n, LockIcon: a } = s;
|
|
10
|
+
return /* @__PURE__ */ l("div", { className: "relative aspect-video overflow-hidden bg-black/5", children: [
|
|
11
|
+
t ? /* @__PURE__ */ e(
|
|
12
|
+
"img",
|
|
13
|
+
{
|
|
14
|
+
src: t,
|
|
15
|
+
alt: "",
|
|
16
|
+
className: "absolute inset-0 h-full w-full object-cover"
|
|
17
|
+
}
|
|
18
|
+
) : /* @__PURE__ */ e("div", { className: "absolute inset-0 flex items-center justify-center", children: g(n, {
|
|
19
|
+
className: "size-12 text-black/20",
|
|
20
|
+
weight: "regular"
|
|
21
|
+
}) }),
|
|
22
|
+
/* @__PURE__ */ e(z, { icon: a })
|
|
23
|
+
] });
|
|
24
|
+
}, M = (s) => {
|
|
25
|
+
const { source: t, thumbnail: n, mimeType: a, title: c, paymentStatus: i, isLocked: r } = s, [o, d] = b(!1);
|
|
26
|
+
return L(() => {
|
|
27
|
+
d(!1);
|
|
28
|
+
}, [t]), r ? /* @__PURE__ */ e(
|
|
29
|
+
I,
|
|
30
|
+
{
|
|
31
|
+
thumbnail: n,
|
|
32
|
+
mimeType: a,
|
|
33
|
+
LockIcon: x(i)
|
|
34
|
+
}
|
|
35
|
+
) : /* @__PURE__ */ e("div", { className: "relative overflow-hidden bg-black/5", children: /* @__PURE__ */ e(
|
|
36
|
+
"img",
|
|
37
|
+
{
|
|
38
|
+
src: t,
|
|
39
|
+
alt: c,
|
|
40
|
+
className: `block w-full transition-opacity duration-300 ${o ? "opacity-100" : "opacity-0"}`,
|
|
41
|
+
onLoad: () => d(!0)
|
|
42
|
+
}
|
|
43
|
+
) });
|
|
44
|
+
}, O = (s) => {
|
|
45
|
+
const { thumbnail: t, mimeType: n, paymentStatus: a, isLocked: c } = s;
|
|
46
|
+
return /* @__PURE__ */ l("div", { className: "relative aspect-video overflow-hidden bg-black/5", children: [
|
|
47
|
+
t ? /* @__PURE__ */ e(
|
|
48
|
+
"img",
|
|
49
|
+
{
|
|
50
|
+
src: t,
|
|
51
|
+
alt: "",
|
|
52
|
+
className: "absolute inset-0 h-full w-full object-cover"
|
|
53
|
+
}
|
|
54
|
+
) : /* @__PURE__ */ e("div", { className: "absolute inset-0 flex items-center justify-center", children: g(n, {
|
|
55
|
+
className: "size-12 text-black/20",
|
|
56
|
+
weight: "regular"
|
|
57
|
+
}) }),
|
|
58
|
+
c && /* @__PURE__ */ e(z, { icon: x(a) })
|
|
59
|
+
] });
|
|
60
|
+
}, R = (s) => {
|
|
61
|
+
const { source: t, thumbnail: n, mimeType: a, paymentStatus: c, isLocked: i } = s;
|
|
62
|
+
return i ? /* @__PURE__ */ e(
|
|
63
|
+
I,
|
|
64
|
+
{
|
|
65
|
+
thumbnail: n,
|
|
66
|
+
mimeType: a,
|
|
67
|
+
LockIcon: x(c)
|
|
68
|
+
}
|
|
69
|
+
) : /* @__PURE__ */ e(U, { source: t, mimeType: a, poster: n });
|
|
70
|
+
}, A = () => /* @__PURE__ */ l("span", { className: "flex items-center gap-1", children: [
|
|
71
|
+
/* @__PURE__ */ e("span", { className: "size-1 rounded-full bg-white animate-bounce [animation-delay:-0.3s]" }),
|
|
72
|
+
/* @__PURE__ */ e("span", { className: "size-1 rounded-full bg-white animate-bounce [animation-delay:-0.15s]" }),
|
|
73
|
+
/* @__PURE__ */ e("span", { className: "size-1 rounded-full bg-white animate-bounce" })
|
|
74
|
+
] }), E = (s) => {
|
|
75
|
+
const { isLocked: t, unlockLoading: n, source: a, onUnlock: c, onDownload: i } = s;
|
|
76
|
+
return t && c ? /* @__PURE__ */ e(
|
|
77
|
+
"button",
|
|
78
|
+
{
|
|
79
|
+
type: "button",
|
|
80
|
+
onClick: c,
|
|
81
|
+
disabled: n,
|
|
82
|
+
className: "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] disabled:opacity-70",
|
|
83
|
+
children: n ? /* @__PURE__ */ e(A, {}) : /* @__PURE__ */ l(p, { children: [
|
|
84
|
+
/* @__PURE__ */ e(y, { className: "size-4", weight: "fill" }),
|
|
85
|
+
"Unlock"
|
|
86
|
+
] })
|
|
87
|
+
}
|
|
88
|
+
) : !t && i && a ? /* @__PURE__ */ l(
|
|
89
|
+
"a",
|
|
90
|
+
{
|
|
91
|
+
href: a,
|
|
92
|
+
onClick: i,
|
|
93
|
+
className: "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]",
|
|
94
|
+
children: [
|
|
95
|
+
/* @__PURE__ */ e(P, { className: "size-4", weight: "bold" }),
|
|
96
|
+
"Download"
|
|
97
|
+
]
|
|
98
|
+
}
|
|
99
|
+
) : null;
|
|
100
|
+
}, B = (s) => {
|
|
101
|
+
const {
|
|
102
|
+
title: t,
|
|
103
|
+
amountText: n,
|
|
104
|
+
thumbnail: a,
|
|
105
|
+
source: c,
|
|
106
|
+
mimeType: i = "application/octet-stream",
|
|
107
|
+
detail: r,
|
|
108
|
+
onUnlock: o,
|
|
109
|
+
onDownload: d,
|
|
110
|
+
paymentStatus: m
|
|
111
|
+
} = s, [u, k] = b(c), [S, w] = b(!1);
|
|
112
|
+
L(() => {
|
|
113
|
+
c !== void 0 && k(c);
|
|
114
|
+
}, [c]);
|
|
115
|
+
const f = u === void 0, v = D(i), j = async () => {
|
|
116
|
+
if (o) {
|
|
117
|
+
w(!0);
|
|
118
|
+
try {
|
|
119
|
+
const N = await o();
|
|
120
|
+
k(N.source);
|
|
121
|
+
} catch {
|
|
122
|
+
} finally {
|
|
123
|
+
w(!1);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
let h;
|
|
128
|
+
return v === "image" ? h = /* @__PURE__ */ e(
|
|
129
|
+
M,
|
|
130
|
+
{
|
|
131
|
+
source: u,
|
|
132
|
+
thumbnail: a,
|
|
133
|
+
mimeType: i,
|
|
134
|
+
title: t,
|
|
135
|
+
paymentStatus: m,
|
|
136
|
+
isLocked: f
|
|
137
|
+
}
|
|
138
|
+
) : v === "document" ? h = /* @__PURE__ */ e(
|
|
139
|
+
O,
|
|
140
|
+
{
|
|
141
|
+
thumbnail: a,
|
|
142
|
+
mimeType: i,
|
|
143
|
+
paymentStatus: m,
|
|
144
|
+
isLocked: f
|
|
145
|
+
}
|
|
146
|
+
) : h = /* @__PURE__ */ e(
|
|
147
|
+
R,
|
|
148
|
+
{
|
|
149
|
+
source: u,
|
|
150
|
+
thumbnail: a,
|
|
151
|
+
mimeType: i,
|
|
152
|
+
paymentStatus: m,
|
|
153
|
+
isLocked: f
|
|
154
|
+
}
|
|
155
|
+
), /* @__PURE__ */ l("div", { className: "w-[280px] select-none overflow-hidden rounded-3xl bg-white shadow-card", children: [
|
|
156
|
+
h,
|
|
157
|
+
/* @__PURE__ */ l("div", { className: "px-4 pb-3 pt-3", children: [
|
|
158
|
+
/* @__PURE__ */ e("p", { className: "mb-1.5 truncate text-base font-medium text-black", children: t }),
|
|
159
|
+
/* @__PURE__ */ l("div", { className: "flex items-center gap-1", children: [
|
|
160
|
+
g(i, {
|
|
161
|
+
className: "size-5 shrink-0 text-black/55",
|
|
162
|
+
weight: "regular"
|
|
163
|
+
}),
|
|
164
|
+
r && /* @__PURE__ */ e("span", { className: "text-xs font-medium text-black/55", children: r }),
|
|
165
|
+
m === "paid" ? /* @__PURE__ */ l(p, { children: [
|
|
166
|
+
/* @__PURE__ */ e("span", { className: "text-xs font-medium text-black/55", children: "•" }),
|
|
167
|
+
/* @__PURE__ */ e("span", { className: "text-xs font-medium text-[#008236]", children: "Purchased" }),
|
|
168
|
+
/* @__PURE__ */ e(
|
|
169
|
+
T,
|
|
170
|
+
{
|
|
171
|
+
className: "size-4 text-[#008236]",
|
|
172
|
+
weight: "bold"
|
|
173
|
+
}
|
|
174
|
+
)
|
|
175
|
+
] }) : n && /* @__PURE__ */ l(p, { children: [
|
|
176
|
+
/* @__PURE__ */ e("span", { className: "text-xs font-medium text-black/55", children: "•" }),
|
|
177
|
+
/* @__PURE__ */ e("span", { className: "text-xs font-medium text-black/55", children: n })
|
|
178
|
+
] })
|
|
179
|
+
] }),
|
|
180
|
+
/* @__PURE__ */ e(
|
|
181
|
+
E,
|
|
182
|
+
{
|
|
183
|
+
isLocked: f,
|
|
184
|
+
unlockLoading: S,
|
|
185
|
+
source: u,
|
|
186
|
+
onUnlock: o ? j : void 0,
|
|
187
|
+
onDownload: d
|
|
188
|
+
}
|
|
189
|
+
)
|
|
190
|
+
] })
|
|
191
|
+
] });
|
|
192
|
+
};
|
|
193
|
+
export {
|
|
194
|
+
B as default
|
|
195
|
+
};
|
|
196
|
+
//# sourceMappingURL=Visitor-CB5mQ20A.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Visitor-CB5mQ20A.js","sources":["../src/components/LockedAttachment/components/Visitor.tsx"],"sourcesContent":["import {\n CheckCircleIcon,\n DownloadSimpleIcon,\n LockOpenIcon,\n LockSimpleIcon,\n} from '@phosphor-icons/react'\nimport React, { useEffect, useState } from 'react'\n\nimport { isDevBuild } from '../../../utils/isDevBuild'\nimport type {\n LockedAttachmentBaseProps,\n LockedAttachmentSource,\n PaymentStatus,\n} from '../types'\nimport { renderTypeIcon } from '../utils/icons'\nimport { getSourceType } from '../utils/mimeType'\n\nimport MediaPlayer from './MediaPlayer'\n\nexport interface VisitorCardProps extends LockedAttachmentBaseProps {\n /**\n * Called when the visitor clicks Unlock. Return the resolved source URL.\n * The component manages loading state and sets source internally on resolution.\n * Omit to hide the Unlock button.\n */\n onUnlock?: () => Promise<LockedAttachmentSource>\n /** Called when the visitor clicks Download on an unlocked card. */\n onDownload?: () => void \n}\n\nconst getLockIcon = (paymentStatus?: PaymentStatus): React.ElementType =>\n paymentStatus === 'paid' ? LockOpenIcon : LockSimpleIcon\n\n\ninterface LockOverlayProps {\n icon: React.ElementType\n}\n\nconst LockOverlay: React.FC<LockOverlayProps> = (props) => {\n const { icon: Icon } = props\n return (\n <div className=\"absolute inset-0 bg-black/30\">\n <div className=\"absolute left-3 top-3 flex size-8 items-center justify-center rounded-full bg-black/60\">\n <Icon className=\"size-4 text-white\" weight=\"fill\" />\n </div>\n </div>\n )\n}\n\ninterface LockedPreviewProps {\n thumbnail?: string\n mimeType: string\n LockIcon: React.ElementType\n}\n\nconst LockedPreview: React.FC<LockedPreviewProps> = (props) => {\n const { thumbnail, mimeType, LockIcon } = props\n return (\n <div className=\"relative aspect-video overflow-hidden bg-black/5\">\n {thumbnail ? (\n <img\n src={thumbnail}\n alt=\"\"\n className=\"absolute inset-0 h-full w-full object-cover\"\n />\n ) : (\n <div className=\"absolute inset-0 flex items-center justify-center\">\n {renderTypeIcon(mimeType, {\n className: 'size-12 text-black/20',\n weight: 'regular',\n })}\n </div>\n )}\n <LockOverlay icon={LockIcon} />\n </div>\n )\n}\n\n\ninterface ImagePreviewProps {\n source?: string\n thumbnail?: string\n mimeType: string\n title?: string\n paymentStatus?: PaymentStatus\n isLocked: boolean\n}\n\nconst ImagePreview: React.FC<ImagePreviewProps> = (props) => {\n const { source, thumbnail, mimeType, title, paymentStatus, isLocked } = props\n const [sourceReady, setSourceReady] = useState(false)\n\n useEffect(() => {\n setSourceReady(false)\n }, [source])\n\n if (isLocked) {\n return (\n <LockedPreview\n thumbnail={thumbnail}\n mimeType={mimeType}\n LockIcon={getLockIcon(paymentStatus)}\n />\n )\n }\n\n return (\n <div className=\"relative overflow-hidden bg-black/5\">\n <img\n src={source}\n alt={title}\n className={`block w-full transition-opacity duration-300 ${sourceReady ? 'opacity-100' : 'opacity-0'}`}\n onLoad={() => setSourceReady(true)}\n />\n </div>\n )\n}\n\ninterface DocumentPreviewProps {\n thumbnail?: string\n mimeType: string\n paymentStatus?: PaymentStatus\n isLocked: boolean\n}\n\nconst DocumentPreview: React.FC<DocumentPreviewProps> = (props) => {\n const { thumbnail, mimeType, paymentStatus, isLocked } = props\n return (\n <div className=\"relative aspect-video overflow-hidden bg-black/5\">\n {thumbnail ? (\n <img\n src={thumbnail}\n alt=\"\"\n className=\"absolute inset-0 h-full w-full object-cover\"\n />\n ) : (\n <div className=\"absolute inset-0 flex items-center justify-center\">\n {renderTypeIcon(mimeType, {\n className: 'size-12 text-black/20',\n weight: 'regular',\n })}\n </div>\n )}\n {isLocked && <LockOverlay icon={getLockIcon(paymentStatus)} />}\n </div>\n )\n}\n\ninterface MediaPreviewProps {\n source?: string\n thumbnail?: string\n mimeType: string\n paymentStatus?: PaymentStatus\n isLocked: boolean\n}\n\nconst MediaPreview: React.FC<MediaPreviewProps> = (props) => {\n const { source, thumbnail, mimeType, paymentStatus, isLocked } = props\n if (isLocked) {\n return (\n <LockedPreview\n thumbnail={thumbnail}\n mimeType={mimeType}\n LockIcon={getLockIcon(paymentStatus)}\n />\n )\n }\n return <MediaPlayer source={source!} mimeType={mimeType} poster={thumbnail} />\n}\n\n\nconst LoadingDots = () => (\n <span className=\"flex items-center gap-1\">\n <span className=\"size-1 rounded-full bg-white animate-bounce [animation-delay:-0.3s]\" />\n <span className=\"size-1 rounded-full bg-white animate-bounce [animation-delay:-0.15s]\" />\n <span className=\"size-1 rounded-full bg-white animate-bounce\" />\n </span>\n)\n\ninterface CardActionsProps {\n isLocked: boolean\n unlockLoading: boolean\n source?: string\n onUnlock?: () => void\n onDownload?: () => void\n}\n\nconst CardActions: React.FC<CardActionsProps> = (props) => {\n const { isLocked, unlockLoading, source, onUnlock, onDownload } = props\n\n if (isLocked && onUnlock) {\n return (\n <button\n type=\"button\"\n onClick={onUnlock}\n disabled={unlockLoading}\n className=\"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] disabled:opacity-70\"\n >\n {unlockLoading ? (\n <LoadingDots />\n ) : (\n <>\n <LockSimpleIcon className=\"size-4\" weight=\"fill\" />\n Unlock\n </>\n )}\n </button>\n )\n }\n\n if (!isLocked && onDownload && source) {\n return (\n <a\n href={source}\n onClick={onDownload}\n className=\"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]\"\n >\n <DownloadSimpleIcon className=\"size-4\" weight=\"bold\" />\n Download\n </a>\n )\n }\n\n return null\n}\n\n\nconst VisitorCard: React.FC<VisitorCardProps> = (props) => {\n const {\n title,\n amountText,\n thumbnail,\n source: sourceProp,\n mimeType = 'application/octet-stream',\n detail,\n onUnlock,\n onDownload,\n paymentStatus,\n } = props\n const [source, setSource] = useState(sourceProp)\n const [unlockLoading, setUnlockLoading] = useState(false)\n\n useEffect(() => {\n if (sourceProp !== undefined) setSource(sourceProp)\n }, [sourceProp])\n\n const isLocked = source === undefined\n const sourceType = getSourceType(mimeType)\n\n const handleUnlock = async () => {\n if (!onUnlock) return\n setUnlockLoading(true)\n try {\n const result = await onUnlock()\n setSource(result.source)\n } catch (err) {\n if (isDevBuild()) console.debug('[LockedAttachment] onUnlock failed', err)\n } finally {\n setUnlockLoading(false)\n }\n }\n\n let mediaPreview: React.ReactNode\n if (sourceType === 'image') {\n mediaPreview = (\n <ImagePreview\n source={source}\n thumbnail={thumbnail}\n mimeType={mimeType}\n title={title}\n paymentStatus={paymentStatus}\n isLocked={isLocked}\n />\n )\n } else if (sourceType === 'document') {\n mediaPreview = (\n <DocumentPreview\n thumbnail={thumbnail}\n mimeType={mimeType}\n paymentStatus={paymentStatus}\n isLocked={isLocked}\n />\n )\n } else {\n mediaPreview = (\n <MediaPreview\n source={source}\n thumbnail={thumbnail}\n mimeType={mimeType}\n paymentStatus={paymentStatus}\n isLocked={isLocked}\n />\n )\n }\n\n return (\n <div className=\"w-[280px] select-none overflow-hidden rounded-3xl bg-white shadow-card\">\n {mediaPreview}\n <div className=\"px-4 pb-3 pt-3\">\n <p className=\"mb-1.5 truncate text-base font-medium text-black\">\n {title}\n </p>\n <div className=\"flex items-center gap-1\">\n {renderTypeIcon(mimeType, {\n className: 'size-5 shrink-0 text-black/55',\n weight: 'regular',\n })}\n {detail && (\n <span className=\"text-xs font-medium text-black/55\">{detail}</span>\n )}\n {paymentStatus === 'paid' ? (\n <>\n <span className=\"text-xs font-medium text-black/55\">•</span>\n <span className=\"text-xs font-medium text-[#008236]\">\n Purchased\n </span>\n <CheckCircleIcon\n className=\"size-4 text-[#008236]\"\n weight=\"bold\"\n />\n </>\n ) : (\n amountText && (\n <>\n <span className=\"text-xs font-medium text-black/55\">•</span>\n <span className=\"text-xs font-medium text-black/55\">\n {amountText}\n </span>\n </>\n )\n )}\n </div>\n <CardActions\n isLocked={isLocked}\n unlockLoading={unlockLoading}\n source={source}\n onUnlock={onUnlock ? handleUnlock : undefined}\n onDownload={onDownload}\n />\n </div>\n </div>\n )\n}\n\nexport default VisitorCard\n"],"names":["getLockIcon","paymentStatus","LockOpenIcon","LockSimpleIcon","LockOverlay","props","Icon","jsx","LockedPreview","thumbnail","mimeType","LockIcon","jsxs","ImagePreview","source","title","isLocked","sourceReady","setSourceReady","useState","useEffect","DocumentPreview","MediaPreview","MediaPlayer","LoadingDots","CardActions","unlockLoading","onUnlock","onDownload","Fragment","DownloadSimpleIcon","VisitorCard","amountText","sourceProp","detail","setSource","setUnlockLoading","sourceType","getSourceType","handleUnlock","result","mediaPreview","renderTypeIcon","CheckCircleIcon"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -524,11 +524,8 @@ declare interface VisitorCardProps extends LockedAttachmentBaseProps {
|
|
|
524
524
|
* Omit to hide the Unlock button.
|
|
525
525
|
*/
|
|
526
526
|
onUnlock?: () => Promise<LockedAttachmentSource>;
|
|
527
|
-
/**
|
|
528
|
-
|
|
529
|
-
* May return a Promise — if so, the component shows a loader until it resolves.
|
|
530
|
-
*/
|
|
531
|
-
onDownload?: () => void | Promise<void>;
|
|
527
|
+
/** Called when the visitor clicks Download on an unlocked card. */
|
|
528
|
+
onDownload?: () => void;
|
|
532
529
|
}
|
|
533
530
|
|
|
534
531
|
export declare type VoteSelection = 'up' | 'down' | null;
|
package/dist/index.js
CHANGED
|
@@ -835,7 +835,7 @@ function ws(t) {
|
|
|
835
835
|
}, [s, n == null ? void 0 : n.userID, t.id, o]);
|
|
836
836
|
return { selected: o, voteUp: l, voteDown: d };
|
|
837
837
|
}
|
|
838
|
-
const _s = F.lazy(() => import("./Creator-VyMyIk2b.js")), Es = F.lazy(() => import("./Visitor-
|
|
838
|
+
const _s = F.lazy(() => import("./Creator-VyMyIk2b.js")), Es = F.lazy(() => import("./Visitor-CB5mQ20A.js")), Je = () => /* @__PURE__ */ e(
|
|
839
839
|
"div",
|
|
840
840
|
{
|
|
841
841
|
className: "w-[280px] min-h-[200px] animate-pulse rounded-3xl bg-black/[0.06] shadow-[0px_0px_0px_1px_rgba(0,0,0,0.04),0px_1px_2px_0px_rgba(0,0,0,0.04)]",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@linktr.ee/messaging-react",
|
|
3
|
-
"version": "1.29.
|
|
3
|
+
"version": "1.29.1-rc-1776411492",
|
|
4
4
|
"description": "React messaging components built on messaging-core for web applications",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -33,10 +33,9 @@
|
|
|
33
33
|
"storybook:build": "storybook build"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@linktr.ee/component-library": "
|
|
37
|
-
"@linktr.ee/messaging-core": "^1.
|
|
38
|
-
"@phosphor-icons/react": "^2.1.
|
|
39
|
-
"stream-chat-react": "^13.12.0"
|
|
36
|
+
"@linktr.ee/component-library": "12.1.4",
|
|
37
|
+
"@linktr.ee/messaging-core": "^1.7.1",
|
|
38
|
+
"@phosphor-icons/react": "^2.1.10"
|
|
40
39
|
},
|
|
41
40
|
"devDependencies": {
|
|
42
41
|
"@storybook/addon-essentials": "^8.5.0",
|
|
@@ -62,6 +61,7 @@
|
|
|
62
61
|
"react-dom": "^18.3.1",
|
|
63
62
|
"storybook": "^8.5.0",
|
|
64
63
|
"stream-chat": "^9.26.0",
|
|
64
|
+
"stream-chat-react": "^13.12.0",
|
|
65
65
|
"tailwindcss": "^3.4.17",
|
|
66
66
|
"tailwindcss-animate": "^1.0.7",
|
|
67
67
|
"typescript": "5.9.2",
|
|
@@ -24,11 +24,8 @@ export interface VisitorCardProps extends LockedAttachmentBaseProps {
|
|
|
24
24
|
* Omit to hide the Unlock button.
|
|
25
25
|
*/
|
|
26
26
|
onUnlock?: () => Promise<LockedAttachmentSource>
|
|
27
|
-
/**
|
|
28
|
-
|
|
29
|
-
* May return a Promise — if so, the component shows a loader until it resolves.
|
|
30
|
-
*/
|
|
31
|
-
onDownload?: () => void | Promise<void>
|
|
27
|
+
/** Called when the visitor clicks Download on an unlocked card. */
|
|
28
|
+
onDownload?: () => void
|
|
32
29
|
}
|
|
33
30
|
|
|
34
31
|
const getLockIcon = (paymentStatus?: PaymentStatus): React.ElementType =>
|
|
@@ -37,23 +34,14 @@ const getLockIcon = (paymentStatus?: PaymentStatus): React.ElementType =>
|
|
|
37
34
|
|
|
38
35
|
interface LockOverlayProps {
|
|
39
36
|
icon: React.ElementType
|
|
40
|
-
loading?: boolean
|
|
41
37
|
}
|
|
42
38
|
|
|
43
39
|
const LockOverlay: React.FC<LockOverlayProps> = (props) => {
|
|
44
|
-
const { icon: Icon
|
|
40
|
+
const { icon: Icon } = props
|
|
45
41
|
return (
|
|
46
42
|
<div className="absolute inset-0 bg-black/30">
|
|
47
43
|
<div className="absolute left-3 top-3 flex size-8 items-center justify-center rounded-full bg-black/60">
|
|
48
|
-
|
|
49
|
-
<span className="flex items-center gap-[2px]">
|
|
50
|
-
<span className="size-1 rounded-full bg-white animate-bounce [animation-delay:-0.3s]" />
|
|
51
|
-
<span className="size-1 rounded-full bg-white animate-bounce [animation-delay:-0.15s]" />
|
|
52
|
-
<span className="size-1 rounded-full bg-white animate-bounce" />
|
|
53
|
-
</span>
|
|
54
|
-
) : (
|
|
55
|
-
<Icon className="size-4 text-white" weight="fill" />
|
|
56
|
-
)}
|
|
44
|
+
<Icon className="size-4 text-white" weight="fill" />
|
|
57
45
|
</div>
|
|
58
46
|
</div>
|
|
59
47
|
)
|
|
@@ -63,11 +51,10 @@ interface LockedPreviewProps {
|
|
|
63
51
|
thumbnail?: string
|
|
64
52
|
mimeType: string
|
|
65
53
|
LockIcon: React.ElementType
|
|
66
|
-
loading?: boolean
|
|
67
54
|
}
|
|
68
55
|
|
|
69
56
|
const LockedPreview: React.FC<LockedPreviewProps> = (props) => {
|
|
70
|
-
const { thumbnail, mimeType, LockIcon
|
|
57
|
+
const { thumbnail, mimeType, LockIcon } = props
|
|
71
58
|
return (
|
|
72
59
|
<div className="relative aspect-video overflow-hidden bg-black/5">
|
|
73
60
|
{thumbnail ? (
|
|
@@ -84,7 +71,7 @@ const LockedPreview: React.FC<LockedPreviewProps> = (props) => {
|
|
|
84
71
|
})}
|
|
85
72
|
</div>
|
|
86
73
|
)}
|
|
87
|
-
<LockOverlay icon={LockIcon}
|
|
74
|
+
<LockOverlay icon={LockIcon} />
|
|
88
75
|
</div>
|
|
89
76
|
)
|
|
90
77
|
}
|
|
@@ -97,11 +84,10 @@ interface ImagePreviewProps {
|
|
|
97
84
|
title?: string
|
|
98
85
|
paymentStatus?: PaymentStatus
|
|
99
86
|
isLocked: boolean
|
|
100
|
-
loading?: boolean
|
|
101
87
|
}
|
|
102
88
|
|
|
103
89
|
const ImagePreview: React.FC<ImagePreviewProps> = (props) => {
|
|
104
|
-
const { source, thumbnail, mimeType, title, paymentStatus, isLocked
|
|
90
|
+
const { source, thumbnail, mimeType, title, paymentStatus, isLocked } = props
|
|
105
91
|
const [sourceReady, setSourceReady] = useState(false)
|
|
106
92
|
|
|
107
93
|
useEffect(() => {
|
|
@@ -114,7 +100,6 @@ const ImagePreview: React.FC<ImagePreviewProps> = (props) => {
|
|
|
114
100
|
thumbnail={thumbnail}
|
|
115
101
|
mimeType={mimeType}
|
|
116
102
|
LockIcon={getLockIcon(paymentStatus)}
|
|
117
|
-
loading={loading}
|
|
118
103
|
/>
|
|
119
104
|
)
|
|
120
105
|
}
|
|
@@ -136,11 +121,10 @@ interface DocumentPreviewProps {
|
|
|
136
121
|
mimeType: string
|
|
137
122
|
paymentStatus?: PaymentStatus
|
|
138
123
|
isLocked: boolean
|
|
139
|
-
loading?: boolean
|
|
140
124
|
}
|
|
141
125
|
|
|
142
126
|
const DocumentPreview: React.FC<DocumentPreviewProps> = (props) => {
|
|
143
|
-
const { thumbnail, mimeType, paymentStatus, isLocked
|
|
127
|
+
const { thumbnail, mimeType, paymentStatus, isLocked } = props
|
|
144
128
|
return (
|
|
145
129
|
<div className="relative aspect-video overflow-hidden bg-black/5">
|
|
146
130
|
{thumbnail ? (
|
|
@@ -157,7 +141,7 @@ const DocumentPreview: React.FC<DocumentPreviewProps> = (props) => {
|
|
|
157
141
|
})}
|
|
158
142
|
</div>
|
|
159
143
|
)}
|
|
160
|
-
{isLocked && <LockOverlay icon={getLockIcon(paymentStatus)}
|
|
144
|
+
{isLocked && <LockOverlay icon={getLockIcon(paymentStatus)} />}
|
|
161
145
|
</div>
|
|
162
146
|
)
|
|
163
147
|
}
|
|
@@ -168,18 +152,16 @@ interface MediaPreviewProps {
|
|
|
168
152
|
mimeType: string
|
|
169
153
|
paymentStatus?: PaymentStatus
|
|
170
154
|
isLocked: boolean
|
|
171
|
-
loading?: boolean
|
|
172
155
|
}
|
|
173
156
|
|
|
174
157
|
const MediaPreview: React.FC<MediaPreviewProps> = (props) => {
|
|
175
|
-
const { source, thumbnail, mimeType, paymentStatus, isLocked
|
|
158
|
+
const { source, thumbnail, mimeType, paymentStatus, isLocked } = props
|
|
176
159
|
if (isLocked) {
|
|
177
160
|
return (
|
|
178
161
|
<LockedPreview
|
|
179
162
|
thumbnail={thumbnail}
|
|
180
163
|
mimeType={mimeType}
|
|
181
164
|
LockIcon={getLockIcon(paymentStatus)}
|
|
182
|
-
loading={loading}
|
|
183
165
|
/>
|
|
184
166
|
)
|
|
185
167
|
}
|
|
@@ -198,16 +180,13 @@ const LoadingDots = () => (
|
|
|
198
180
|
interface CardActionsProps {
|
|
199
181
|
isLocked: boolean
|
|
200
182
|
unlockLoading: boolean
|
|
201
|
-
downloadLoading: boolean
|
|
202
|
-
paymentStatus?: PaymentStatus
|
|
203
183
|
source?: string
|
|
204
184
|
onUnlock?: () => void
|
|
205
185
|
onDownload?: () => void
|
|
206
186
|
}
|
|
207
187
|
|
|
208
188
|
const CardActions: React.FC<CardActionsProps> = (props) => {
|
|
209
|
-
const { isLocked, unlockLoading,
|
|
210
|
-
const LockIcon = getLockIcon(paymentStatus)
|
|
189
|
+
const { isLocked, unlockLoading, source, onUnlock, onDownload } = props
|
|
211
190
|
|
|
212
191
|
if (isLocked && onUnlock) {
|
|
213
192
|
return (
|
|
@@ -215,18 +194,14 @@ const CardActions: React.FC<CardActionsProps> = (props) => {
|
|
|
215
194
|
type="button"
|
|
216
195
|
onClick={onUnlock}
|
|
217
196
|
disabled={unlockLoading}
|
|
218
|
-
className="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 disabled:opacity-70"
|
|
197
|
+
className="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] disabled:opacity-70"
|
|
219
198
|
>
|
|
220
199
|
{unlockLoading ? (
|
|
221
200
|
<LoadingDots />
|
|
222
201
|
) : (
|
|
223
202
|
<>
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
) : (
|
|
227
|
-
<LockIcon className="size-4" weight="fill" />
|
|
228
|
-
)}
|
|
229
|
-
{paymentStatus === 'paid' ? 'Open' : 'Unlock'}
|
|
203
|
+
<LockSimpleIcon className="size-4" weight="fill" />
|
|
204
|
+
Unlock
|
|
230
205
|
</>
|
|
231
206
|
)}
|
|
232
207
|
</button>
|
|
@@ -235,21 +210,14 @@ const CardActions: React.FC<CardActionsProps> = (props) => {
|
|
|
235
210
|
|
|
236
211
|
if (!isLocked && onDownload && source) {
|
|
237
212
|
return (
|
|
238
|
-
<
|
|
239
|
-
|
|
213
|
+
<a
|
|
214
|
+
href={source}
|
|
240
215
|
onClick={onDownload}
|
|
241
|
-
|
|
242
|
-
className="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 disabled:opacity-70"
|
|
216
|
+
className="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]"
|
|
243
217
|
>
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
<>
|
|
248
|
-
<DownloadSimpleIcon className="size-4" weight="bold" />
|
|
249
|
-
Download
|
|
250
|
-
</>
|
|
251
|
-
)}
|
|
252
|
-
</button>
|
|
218
|
+
<DownloadSimpleIcon className="size-4" weight="bold" />
|
|
219
|
+
Download
|
|
220
|
+
</a>
|
|
253
221
|
)
|
|
254
222
|
}
|
|
255
223
|
|
|
@@ -271,7 +239,6 @@ const VisitorCard: React.FC<VisitorCardProps> = (props) => {
|
|
|
271
239
|
} = props
|
|
272
240
|
const [source, setSource] = useState(sourceProp)
|
|
273
241
|
const [unlockLoading, setUnlockLoading] = useState(false)
|
|
274
|
-
const [downloadLoading, setDownloadLoading] = useState(false)
|
|
275
242
|
|
|
276
243
|
useEffect(() => {
|
|
277
244
|
if (sourceProp !== undefined) setSource(sourceProp)
|
|
@@ -293,18 +260,6 @@ const VisitorCard: React.FC<VisitorCardProps> = (props) => {
|
|
|
293
260
|
}
|
|
294
261
|
}
|
|
295
262
|
|
|
296
|
-
const handleDownload = async () => {
|
|
297
|
-
if (!onDownload) return
|
|
298
|
-
setDownloadLoading(true)
|
|
299
|
-
try {
|
|
300
|
-
await onDownload()
|
|
301
|
-
} catch (err) {
|
|
302
|
-
if (isDevBuild()) console.debug('[LockedAttachment] onDownload failed', err)
|
|
303
|
-
} finally {
|
|
304
|
-
setDownloadLoading(false)
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
|
|
308
263
|
let mediaPreview: React.ReactNode
|
|
309
264
|
if (sourceType === 'image') {
|
|
310
265
|
mediaPreview = (
|
|
@@ -315,7 +270,6 @@ const VisitorCard: React.FC<VisitorCardProps> = (props) => {
|
|
|
315
270
|
title={title}
|
|
316
271
|
paymentStatus={paymentStatus}
|
|
317
272
|
isLocked={isLocked}
|
|
318
|
-
loading={unlockLoading}
|
|
319
273
|
/>
|
|
320
274
|
)
|
|
321
275
|
} else if (sourceType === 'document') {
|
|
@@ -325,7 +279,6 @@ const VisitorCard: React.FC<VisitorCardProps> = (props) => {
|
|
|
325
279
|
mimeType={mimeType}
|
|
326
280
|
paymentStatus={paymentStatus}
|
|
327
281
|
isLocked={isLocked}
|
|
328
|
-
loading={unlockLoading}
|
|
329
282
|
/>
|
|
330
283
|
)
|
|
331
284
|
} else {
|
|
@@ -336,7 +289,6 @@ const VisitorCard: React.FC<VisitorCardProps> = (props) => {
|
|
|
336
289
|
mimeType={mimeType}
|
|
337
290
|
paymentStatus={paymentStatus}
|
|
338
291
|
isLocked={isLocked}
|
|
339
|
-
loading={unlockLoading}
|
|
340
292
|
/>
|
|
341
293
|
)
|
|
342
294
|
}
|
|
@@ -381,11 +333,9 @@ const VisitorCard: React.FC<VisitorCardProps> = (props) => {
|
|
|
381
333
|
<CardActions
|
|
382
334
|
isLocked={isLocked}
|
|
383
335
|
unlockLoading={unlockLoading}
|
|
384
|
-
downloadLoading={downloadLoading}
|
|
385
|
-
paymentStatus={paymentStatus}
|
|
386
336
|
source={source}
|
|
387
337
|
onUnlock={onUnlock ? handleUnlock : undefined}
|
|
388
|
-
onDownload={onDownload
|
|
338
|
+
onDownload={onDownload}
|
|
389
339
|
/>
|
|
390
340
|
</div>
|
|
391
341
|
</div>
|
package/dist/Visitor-C4WqnN8H.js
DELETED
|
@@ -1,218 +0,0 @@
|
|
|
1
|
-
import { jsxs as o, jsx as e, Fragment as g } from "react/jsx-runtime";
|
|
2
|
-
import { CheckCircleIcon as U, LockOpenIcon as I, DownloadSimpleIcon as M, LockSimpleIcon as O } from "@phosphor-icons/react";
|
|
3
|
-
import { useState as b, useEffect as S } from "react";
|
|
4
|
-
import { g as R, r as k, M as A } from "./MediaPlayer-Bf-xPB8Z.js";
|
|
5
|
-
const w = (s) => s === "paid" ? I : O, j = (s) => {
|
|
6
|
-
const { icon: t, loading: a } = s;
|
|
7
|
-
return /* @__PURE__ */ e("div", { className: "absolute inset-0 bg-black/30", children: /* @__PURE__ */ e("div", { className: "absolute left-3 top-3 flex size-8 items-center justify-center rounded-full bg-black/60", children: a ? /* @__PURE__ */ o("span", { className: "flex items-center gap-[2px]", children: [
|
|
8
|
-
/* @__PURE__ */ e("span", { className: "size-1 rounded-full bg-white animate-bounce [animation-delay:-0.3s]" }),
|
|
9
|
-
/* @__PURE__ */ e("span", { className: "size-1 rounded-full bg-white animate-bounce [animation-delay:-0.15s]" }),
|
|
10
|
-
/* @__PURE__ */ e("span", { className: "size-1 rounded-full bg-white animate-bounce" })
|
|
11
|
-
] }) : /* @__PURE__ */ e(t, { className: "size-4 text-white", weight: "fill" }) }) });
|
|
12
|
-
}, D = (s) => {
|
|
13
|
-
const { thumbnail: t, mimeType: a, LockIcon: i, loading: n } = s;
|
|
14
|
-
return /* @__PURE__ */ o("div", { className: "relative aspect-video overflow-hidden bg-black/5", children: [
|
|
15
|
-
t ? /* @__PURE__ */ e(
|
|
16
|
-
"img",
|
|
17
|
-
{
|
|
18
|
-
src: t,
|
|
19
|
-
alt: "",
|
|
20
|
-
className: "absolute inset-0 h-full w-full object-cover"
|
|
21
|
-
}
|
|
22
|
-
) : /* @__PURE__ */ e("div", { className: "absolute inset-0 flex items-center justify-center", children: k(a, {
|
|
23
|
-
className: "size-12 text-black/20",
|
|
24
|
-
weight: "regular"
|
|
25
|
-
}) }),
|
|
26
|
-
/* @__PURE__ */ e(j, { icon: i, loading: n })
|
|
27
|
-
] });
|
|
28
|
-
}, E = (s) => {
|
|
29
|
-
const { source: t, thumbnail: a, mimeType: i, title: n, paymentStatus: l, isLocked: c, loading: d } = s, [m, r] = b(!1);
|
|
30
|
-
return S(() => {
|
|
31
|
-
r(!1);
|
|
32
|
-
}, [t]), c ? /* @__PURE__ */ e(
|
|
33
|
-
D,
|
|
34
|
-
{
|
|
35
|
-
thumbnail: a,
|
|
36
|
-
mimeType: i,
|
|
37
|
-
LockIcon: w(l),
|
|
38
|
-
loading: d
|
|
39
|
-
}
|
|
40
|
-
) : /* @__PURE__ */ e("div", { className: "relative overflow-hidden bg-black/5", children: /* @__PURE__ */ e(
|
|
41
|
-
"img",
|
|
42
|
-
{
|
|
43
|
-
src: t,
|
|
44
|
-
alt: n,
|
|
45
|
-
className: `block w-full transition-opacity duration-300 ${m ? "opacity-100" : "opacity-0"}`,
|
|
46
|
-
onLoad: () => r(!0)
|
|
47
|
-
}
|
|
48
|
-
) });
|
|
49
|
-
}, F = (s) => {
|
|
50
|
-
const { thumbnail: t, mimeType: a, paymentStatus: i, isLocked: n, loading: l } = s;
|
|
51
|
-
return /* @__PURE__ */ o("div", { className: "relative aspect-video overflow-hidden bg-black/5", children: [
|
|
52
|
-
t ? /* @__PURE__ */ e(
|
|
53
|
-
"img",
|
|
54
|
-
{
|
|
55
|
-
src: t,
|
|
56
|
-
alt: "",
|
|
57
|
-
className: "absolute inset-0 h-full w-full object-cover"
|
|
58
|
-
}
|
|
59
|
-
) : /* @__PURE__ */ e("div", { className: "absolute inset-0 flex items-center justify-center", children: k(a, {
|
|
60
|
-
className: "size-12 text-black/20",
|
|
61
|
-
weight: "regular"
|
|
62
|
-
}) }),
|
|
63
|
-
n && /* @__PURE__ */ e(j, { icon: w(i), loading: l })
|
|
64
|
-
] });
|
|
65
|
-
}, V = (s) => {
|
|
66
|
-
const { source: t, thumbnail: a, mimeType: i, paymentStatus: n, isLocked: l, loading: c } = s;
|
|
67
|
-
return l ? /* @__PURE__ */ e(
|
|
68
|
-
D,
|
|
69
|
-
{
|
|
70
|
-
thumbnail: a,
|
|
71
|
-
mimeType: i,
|
|
72
|
-
LockIcon: w(n),
|
|
73
|
-
loading: c
|
|
74
|
-
}
|
|
75
|
-
) : /* @__PURE__ */ e(A, { source: t, mimeType: i, poster: a });
|
|
76
|
-
}, z = () => /* @__PURE__ */ o("span", { className: "flex items-center gap-1", children: [
|
|
77
|
-
/* @__PURE__ */ e("span", { className: "size-1 rounded-full bg-white animate-bounce [animation-delay:-0.3s]" }),
|
|
78
|
-
/* @__PURE__ */ e("span", { className: "size-1 rounded-full bg-white animate-bounce [animation-delay:-0.15s]" }),
|
|
79
|
-
/* @__PURE__ */ e("span", { className: "size-1 rounded-full bg-white animate-bounce" })
|
|
80
|
-
] }), $ = (s) => {
|
|
81
|
-
const { isLocked: t, unlockLoading: a, downloadLoading: i, paymentStatus: n, source: l, onUnlock: c, onDownload: d } = s, m = w(n);
|
|
82
|
-
return t && c ? /* @__PURE__ */ e(
|
|
83
|
-
"button",
|
|
84
|
-
{
|
|
85
|
-
type: "button",
|
|
86
|
-
onClick: c,
|
|
87
|
-
disabled: a,
|
|
88
|
-
className: "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 disabled:opacity-70",
|
|
89
|
-
children: a ? /* @__PURE__ */ e(z, {}) : /* @__PURE__ */ o(g, { children: [
|
|
90
|
-
n === "paid" ? /* @__PURE__ */ e(I, { className: "size-4", weight: "fill" }) : /* @__PURE__ */ e(m, { className: "size-4", weight: "fill" }),
|
|
91
|
-
n === "paid" ? "Open" : "Unlock"
|
|
92
|
-
] })
|
|
93
|
-
}
|
|
94
|
-
) : !t && d && l ? /* @__PURE__ */ e(
|
|
95
|
-
"button",
|
|
96
|
-
{
|
|
97
|
-
type: "button",
|
|
98
|
-
onClick: d,
|
|
99
|
-
disabled: i,
|
|
100
|
-
className: "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 disabled:opacity-70",
|
|
101
|
-
children: i ? /* @__PURE__ */ e(z, {}) : /* @__PURE__ */ o(g, { children: [
|
|
102
|
-
/* @__PURE__ */ e(M, { className: "size-4", weight: "bold" }),
|
|
103
|
-
"Download"
|
|
104
|
-
] })
|
|
105
|
-
}
|
|
106
|
-
) : null;
|
|
107
|
-
}, J = (s) => {
|
|
108
|
-
const {
|
|
109
|
-
title: t,
|
|
110
|
-
amountText: a,
|
|
111
|
-
thumbnail: i,
|
|
112
|
-
source: n,
|
|
113
|
-
mimeType: l = "application/octet-stream",
|
|
114
|
-
detail: c,
|
|
115
|
-
onUnlock: d,
|
|
116
|
-
onDownload: m,
|
|
117
|
-
paymentStatus: r
|
|
118
|
-
} = s, [u, y] = b(n), [f, N] = b(!1), [T, v] = b(!1);
|
|
119
|
-
S(() => {
|
|
120
|
-
n !== void 0 && y(n);
|
|
121
|
-
}, [n]);
|
|
122
|
-
const p = u === void 0, L = R(l), P = async () => {
|
|
123
|
-
if (d) {
|
|
124
|
-
N(!0);
|
|
125
|
-
try {
|
|
126
|
-
const x = await d();
|
|
127
|
-
y(x.source);
|
|
128
|
-
} catch {
|
|
129
|
-
} finally {
|
|
130
|
-
N(!1);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
}, C = async () => {
|
|
134
|
-
if (m) {
|
|
135
|
-
v(!0);
|
|
136
|
-
try {
|
|
137
|
-
await m();
|
|
138
|
-
} catch {
|
|
139
|
-
} finally {
|
|
140
|
-
v(!1);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
};
|
|
144
|
-
let h;
|
|
145
|
-
return L === "image" ? h = /* @__PURE__ */ e(
|
|
146
|
-
E,
|
|
147
|
-
{
|
|
148
|
-
source: u,
|
|
149
|
-
thumbnail: i,
|
|
150
|
-
mimeType: l,
|
|
151
|
-
title: t,
|
|
152
|
-
paymentStatus: r,
|
|
153
|
-
isLocked: p,
|
|
154
|
-
loading: f
|
|
155
|
-
}
|
|
156
|
-
) : L === "document" ? h = /* @__PURE__ */ e(
|
|
157
|
-
F,
|
|
158
|
-
{
|
|
159
|
-
thumbnail: i,
|
|
160
|
-
mimeType: l,
|
|
161
|
-
paymentStatus: r,
|
|
162
|
-
isLocked: p,
|
|
163
|
-
loading: f
|
|
164
|
-
}
|
|
165
|
-
) : h = /* @__PURE__ */ e(
|
|
166
|
-
V,
|
|
167
|
-
{
|
|
168
|
-
source: u,
|
|
169
|
-
thumbnail: i,
|
|
170
|
-
mimeType: l,
|
|
171
|
-
paymentStatus: r,
|
|
172
|
-
isLocked: p,
|
|
173
|
-
loading: f
|
|
174
|
-
}
|
|
175
|
-
), /* @__PURE__ */ o("div", { className: "w-[280px] select-none overflow-hidden rounded-3xl bg-white shadow-card", children: [
|
|
176
|
-
h,
|
|
177
|
-
/* @__PURE__ */ o("div", { className: "px-4 pb-3 pt-3", children: [
|
|
178
|
-
/* @__PURE__ */ e("p", { className: "mb-1.5 truncate text-base font-medium text-black", children: t }),
|
|
179
|
-
/* @__PURE__ */ o("div", { className: "flex items-center gap-1", children: [
|
|
180
|
-
k(l, {
|
|
181
|
-
className: "size-5 shrink-0 text-black/55",
|
|
182
|
-
weight: "regular"
|
|
183
|
-
}),
|
|
184
|
-
c && /* @__PURE__ */ e("span", { className: "text-xs font-medium text-black/55", children: c }),
|
|
185
|
-
r === "paid" ? /* @__PURE__ */ o(g, { children: [
|
|
186
|
-
/* @__PURE__ */ e("span", { className: "text-xs font-medium text-black/55", children: "•" }),
|
|
187
|
-
/* @__PURE__ */ e("span", { className: "text-xs font-medium text-[#008236]", children: "Purchased" }),
|
|
188
|
-
/* @__PURE__ */ e(
|
|
189
|
-
U,
|
|
190
|
-
{
|
|
191
|
-
className: "size-4 text-[#008236]",
|
|
192
|
-
weight: "bold"
|
|
193
|
-
}
|
|
194
|
-
)
|
|
195
|
-
] }) : a && /* @__PURE__ */ o(g, { children: [
|
|
196
|
-
/* @__PURE__ */ e("span", { className: "text-xs font-medium text-black/55", children: "•" }),
|
|
197
|
-
/* @__PURE__ */ e("span", { className: "text-xs font-medium text-black/55", children: a })
|
|
198
|
-
] })
|
|
199
|
-
] }),
|
|
200
|
-
/* @__PURE__ */ e(
|
|
201
|
-
$,
|
|
202
|
-
{
|
|
203
|
-
isLocked: p,
|
|
204
|
-
unlockLoading: f,
|
|
205
|
-
downloadLoading: T,
|
|
206
|
-
paymentStatus: r,
|
|
207
|
-
source: u,
|
|
208
|
-
onUnlock: d ? P : void 0,
|
|
209
|
-
onDownload: m ? C : void 0
|
|
210
|
-
}
|
|
211
|
-
)
|
|
212
|
-
] })
|
|
213
|
-
] });
|
|
214
|
-
};
|
|
215
|
-
export {
|
|
216
|
-
J as default
|
|
217
|
-
};
|
|
218
|
-
//# sourceMappingURL=Visitor-C4WqnN8H.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Visitor-C4WqnN8H.js","sources":["../src/components/LockedAttachment/components/Visitor.tsx"],"sourcesContent":["import {\n CheckCircleIcon,\n DownloadSimpleIcon,\n LockOpenIcon,\n LockSimpleIcon,\n} from '@phosphor-icons/react'\nimport React, { useEffect, useState } from 'react'\n\nimport { isDevBuild } from '../../../utils/isDevBuild'\nimport type {\n LockedAttachmentBaseProps,\n LockedAttachmentSource,\n PaymentStatus,\n} from '../types'\nimport { renderTypeIcon } from '../utils/icons'\nimport { getSourceType } from '../utils/mimeType'\n\nimport MediaPlayer from './MediaPlayer'\n\nexport interface VisitorCardProps extends LockedAttachmentBaseProps {\n /**\n * Called when the visitor clicks Unlock. Return the resolved source URL.\n * The component manages loading state and sets source internally on resolution.\n * Omit to hide the Unlock button.\n */\n onUnlock?: () => Promise<LockedAttachmentSource>\n /**\n * Called when the visitor clicks Download on an unlocked card.\n * May return a Promise — if so, the component shows a loader until it resolves.\n */\n onDownload?: () => void | Promise<void>\n}\n\nconst getLockIcon = (paymentStatus?: PaymentStatus): React.ElementType =>\n paymentStatus === 'paid' ? LockOpenIcon : LockSimpleIcon\n\n\ninterface LockOverlayProps {\n icon: React.ElementType\n loading?: boolean\n}\n\nconst LockOverlay: React.FC<LockOverlayProps> = (props) => {\n const { icon: Icon, loading } = props\n return (\n <div className=\"absolute inset-0 bg-black/30\">\n <div className=\"absolute left-3 top-3 flex size-8 items-center justify-center rounded-full bg-black/60\">\n {loading ? (\n <span className=\"flex items-center gap-[2px]\">\n <span className=\"size-1 rounded-full bg-white animate-bounce [animation-delay:-0.3s]\" />\n <span className=\"size-1 rounded-full bg-white animate-bounce [animation-delay:-0.15s]\" />\n <span className=\"size-1 rounded-full bg-white animate-bounce\" />\n </span>\n ) : (\n <Icon className=\"size-4 text-white\" weight=\"fill\" />\n )}\n </div>\n </div>\n )\n}\n\ninterface LockedPreviewProps {\n thumbnail?: string\n mimeType: string\n LockIcon: React.ElementType\n loading?: boolean\n}\n\nconst LockedPreview: React.FC<LockedPreviewProps> = (props) => {\n const { thumbnail, mimeType, LockIcon, loading } = props\n return (\n <div className=\"relative aspect-video overflow-hidden bg-black/5\">\n {thumbnail ? (\n <img\n src={thumbnail}\n alt=\"\"\n className=\"absolute inset-0 h-full w-full object-cover\"\n />\n ) : (\n <div className=\"absolute inset-0 flex items-center justify-center\">\n {renderTypeIcon(mimeType, {\n className: 'size-12 text-black/20',\n weight: 'regular',\n })}\n </div>\n )}\n <LockOverlay icon={LockIcon} loading={loading} />\n </div>\n )\n}\n\n\ninterface ImagePreviewProps {\n source?: string\n thumbnail?: string\n mimeType: string\n title?: string\n paymentStatus?: PaymentStatus\n isLocked: boolean\n loading?: boolean\n}\n\nconst ImagePreview: React.FC<ImagePreviewProps> = (props) => {\n const { source, thumbnail, mimeType, title, paymentStatus, isLocked, loading } = props\n const [sourceReady, setSourceReady] = useState(false)\n\n useEffect(() => {\n setSourceReady(false)\n }, [source])\n\n if (isLocked) {\n return (\n <LockedPreview\n thumbnail={thumbnail}\n mimeType={mimeType}\n LockIcon={getLockIcon(paymentStatus)}\n loading={loading}\n />\n )\n }\n\n return (\n <div className=\"relative overflow-hidden bg-black/5\">\n <img\n src={source}\n alt={title}\n className={`block w-full transition-opacity duration-300 ${sourceReady ? 'opacity-100' : 'opacity-0'}`}\n onLoad={() => setSourceReady(true)}\n />\n </div>\n )\n}\n\ninterface DocumentPreviewProps {\n thumbnail?: string\n mimeType: string\n paymentStatus?: PaymentStatus\n isLocked: boolean\n loading?: boolean\n}\n\nconst DocumentPreview: React.FC<DocumentPreviewProps> = (props) => {\n const { thumbnail, mimeType, paymentStatus, isLocked, loading } = props\n return (\n <div className=\"relative aspect-video overflow-hidden bg-black/5\">\n {thumbnail ? (\n <img\n src={thumbnail}\n alt=\"\"\n className=\"absolute inset-0 h-full w-full object-cover\"\n />\n ) : (\n <div className=\"absolute inset-0 flex items-center justify-center\">\n {renderTypeIcon(mimeType, {\n className: 'size-12 text-black/20',\n weight: 'regular',\n })}\n </div>\n )}\n {isLocked && <LockOverlay icon={getLockIcon(paymentStatus)} loading={loading} />}\n </div>\n )\n}\n\ninterface MediaPreviewProps {\n source?: string\n thumbnail?: string\n mimeType: string\n paymentStatus?: PaymentStatus\n isLocked: boolean\n loading?: boolean\n}\n\nconst MediaPreview: React.FC<MediaPreviewProps> = (props) => {\n const { source, thumbnail, mimeType, paymentStatus, isLocked, loading } = props\n if (isLocked) {\n return (\n <LockedPreview\n thumbnail={thumbnail}\n mimeType={mimeType}\n LockIcon={getLockIcon(paymentStatus)}\n loading={loading}\n />\n )\n }\n return <MediaPlayer source={source!} mimeType={mimeType} poster={thumbnail} />\n}\n\n\nconst LoadingDots = () => (\n <span className=\"flex items-center gap-1\">\n <span className=\"size-1 rounded-full bg-white animate-bounce [animation-delay:-0.3s]\" />\n <span className=\"size-1 rounded-full bg-white animate-bounce [animation-delay:-0.15s]\" />\n <span className=\"size-1 rounded-full bg-white animate-bounce\" />\n </span>\n)\n\ninterface CardActionsProps {\n isLocked: boolean\n unlockLoading: boolean\n downloadLoading: boolean\n paymentStatus?: PaymentStatus\n source?: string\n onUnlock?: () => void\n onDownload?: () => void\n}\n\nconst CardActions: React.FC<CardActionsProps> = (props) => {\n const { isLocked, unlockLoading, downloadLoading, paymentStatus, source, onUnlock, onDownload } = props\n const LockIcon = getLockIcon(paymentStatus)\n\n if (isLocked && onUnlock) {\n return (\n <button\n type=\"button\"\n onClick={onUnlock}\n disabled={unlockLoading}\n className=\"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 disabled:opacity-70\"\n >\n {unlockLoading ? (\n <LoadingDots />\n ) : (\n <>\n {paymentStatus === 'paid' ? (\n <LockOpenIcon className=\"size-4\" weight=\"fill\" />\n ) : (\n <LockIcon className=\"size-4\" weight=\"fill\" />\n )}\n {paymentStatus === 'paid' ? 'Open' : 'Unlock'}\n </>\n )}\n </button>\n )\n }\n\n if (!isLocked && onDownload && source) {\n return (\n <button\n type=\"button\"\n onClick={onDownload}\n disabled={downloadLoading}\n className=\"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 disabled:opacity-70\"\n >\n {downloadLoading ? (\n <LoadingDots />\n ) : (\n <>\n <DownloadSimpleIcon className=\"size-4\" weight=\"bold\" />\n Download\n </>\n )}\n </button>\n )\n }\n\n return null\n}\n\n\nconst VisitorCard: React.FC<VisitorCardProps> = (props) => {\n const {\n title,\n amountText,\n thumbnail,\n source: sourceProp,\n mimeType = 'application/octet-stream',\n detail,\n onUnlock,\n onDownload,\n paymentStatus,\n } = props\n const [source, setSource] = useState(sourceProp)\n const [unlockLoading, setUnlockLoading] = useState(false)\n const [downloadLoading, setDownloadLoading] = useState(false)\n\n useEffect(() => {\n if (sourceProp !== undefined) setSource(sourceProp)\n }, [sourceProp])\n\n const isLocked = source === undefined\n const sourceType = getSourceType(mimeType)\n\n const handleUnlock = async () => {\n if (!onUnlock) return\n setUnlockLoading(true)\n try {\n const result = await onUnlock()\n setSource(result.source)\n } catch (err) {\n if (isDevBuild()) console.debug('[LockedAttachment] onUnlock failed', err)\n } finally {\n setUnlockLoading(false)\n }\n }\n\n const handleDownload = async () => {\n if (!onDownload) return\n setDownloadLoading(true)\n try {\n await onDownload()\n } catch (err) {\n if (isDevBuild()) console.debug('[LockedAttachment] onDownload failed', err)\n } finally {\n setDownloadLoading(false)\n }\n }\n\n let mediaPreview: React.ReactNode\n if (sourceType === 'image') {\n mediaPreview = (\n <ImagePreview\n source={source}\n thumbnail={thumbnail}\n mimeType={mimeType}\n title={title}\n paymentStatus={paymentStatus}\n isLocked={isLocked}\n loading={unlockLoading}\n />\n )\n } else if (sourceType === 'document') {\n mediaPreview = (\n <DocumentPreview\n thumbnail={thumbnail}\n mimeType={mimeType}\n paymentStatus={paymentStatus}\n isLocked={isLocked}\n loading={unlockLoading}\n />\n )\n } else {\n mediaPreview = (\n <MediaPreview\n source={source}\n thumbnail={thumbnail}\n mimeType={mimeType}\n paymentStatus={paymentStatus}\n isLocked={isLocked}\n loading={unlockLoading}\n />\n )\n }\n\n return (\n <div className=\"w-[280px] select-none overflow-hidden rounded-3xl bg-white shadow-card\">\n {mediaPreview}\n <div className=\"px-4 pb-3 pt-3\">\n <p className=\"mb-1.5 truncate text-base font-medium text-black\">\n {title}\n </p>\n <div className=\"flex items-center gap-1\">\n {renderTypeIcon(mimeType, {\n className: 'size-5 shrink-0 text-black/55',\n weight: 'regular',\n })}\n {detail && (\n <span className=\"text-xs font-medium text-black/55\">{detail}</span>\n )}\n {paymentStatus === 'paid' ? (\n <>\n <span className=\"text-xs font-medium text-black/55\">•</span>\n <span className=\"text-xs font-medium text-[#008236]\">\n Purchased\n </span>\n <CheckCircleIcon\n className=\"size-4 text-[#008236]\"\n weight=\"bold\"\n />\n </>\n ) : (\n amountText && (\n <>\n <span className=\"text-xs font-medium text-black/55\">•</span>\n <span className=\"text-xs font-medium text-black/55\">\n {amountText}\n </span>\n </>\n )\n )}\n </div>\n <CardActions\n isLocked={isLocked}\n unlockLoading={unlockLoading}\n downloadLoading={downloadLoading}\n paymentStatus={paymentStatus}\n source={source}\n onUnlock={onUnlock ? handleUnlock : undefined}\n onDownload={onDownload ? handleDownload : undefined}\n />\n </div>\n </div>\n )\n}\n\nexport default VisitorCard\n"],"names":["getLockIcon","paymentStatus","LockOpenIcon","LockSimpleIcon","LockOverlay","props","Icon","loading","jsx","jsxs","LockedPreview","thumbnail","mimeType","LockIcon","ImagePreview","source","title","isLocked","sourceReady","setSourceReady","useState","useEffect","DocumentPreview","MediaPreview","MediaPlayer","LoadingDots","CardActions","unlockLoading","downloadLoading","onUnlock","onDownload","Fragment","DownloadSimpleIcon","VisitorCard","amountText","sourceProp","detail","setSource","setUnlockLoading","setDownloadLoading","sourceType","getSourceType","handleUnlock","result","handleDownload","mediaPreview","renderTypeIcon","CheckCircleIcon"],"mappings":"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"}
|