@linktr.ee/messaging-react 1.29.1-rc-1776408377 → 1.29.1

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.
@@ -90,7 +90,7 @@ const x = (s) => s === "paid" ? C : y, z = (s) => {
90
90
  {
91
91
  href: a,
92
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]",
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
94
  children: [
95
95
  /* @__PURE__ */ e(P, { className: "size-4", weight: "bold" }),
96
96
  "Download"
@@ -193,4 +193,4 @@ const x = (s) => s === "paid" ? C : y, z = (s) => {
193
193
  export {
194
194
  B as default
195
195
  };
196
- //# sourceMappingURL=Visitor-BcyrCpuF.js.map
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.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-BcyrCpuF.js")), Je = () => /* @__PURE__ */ e(
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.1-rc-1776408377",
3
+ "version": "1.29.1",
4
4
  "description": "React messaging components built on messaging-core for web applications",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -213,7 +213,7 @@ const CardActions: React.FC<CardActionsProps> = (props) => {
213
213
  <a
214
214
  href={source}
215
215
  onClick={onDownload}
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]"
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]"
217
217
  >
218
218
  <DownloadSimpleIcon className="size-4" weight="bold" />
219
219
  Download
@@ -1 +0,0 @@
1
- {"version":3,"file":"Visitor-BcyrCpuF.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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"}