@linktr.ee/messaging-react 3.5.4-rc-1782919630 → 3.5.4-rc-1782920176
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-DjQ0O0ve.js → Card-BkToB7yL.js} +2 -2
- package/dist/{Card-DjQ0O0ve.js.map → Card-BkToB7yL.js.map} +1 -1
- package/dist/{Card-CylbFbg9.js → Card-CKV0d2i9.js} +3 -3
- package/dist/{Card-CylbFbg9.js.map → Card-CKV0d2i9.js.map} +1 -1
- package/dist/{Card-BaMPX4IJ.cjs → Card-Cvy-wtHk.cjs} +2 -2
- package/dist/{Card-BaMPX4IJ.cjs.map → Card-Cvy-wtHk.cjs.map} +1 -1
- package/dist/{Card-dRbnFA_A.cjs → Card-CxeRmW47.cjs} +2 -2
- package/dist/{Card-dRbnFA_A.cjs.map → Card-CxeRmW47.cjs.map} +1 -1
- package/dist/{Card-R_TPCRto.js → Card-DbdWoTwf.js} +2 -2
- package/dist/{Card-R_TPCRto.js.map → Card-DbdWoTwf.js.map} +1 -1
- package/dist/{Card-BGlzLvjX.cjs → Card-yGooZXB0.cjs} +2 -2
- package/dist/{Card-BGlzLvjX.cjs.map → Card-yGooZXB0.cjs.map} +1 -1
- package/dist/{LockedThumbnail-C5ahPvA3.cjs → LockedThumbnail-Dkr6-8Lw.cjs} +2 -2
- package/dist/{LockedThumbnail-C5ahPvA3.cjs.map → LockedThumbnail-Dkr6-8Lw.cjs.map} +1 -1
- package/dist/{LockedThumbnail-CCQ4wzdn.js → LockedThumbnail-PsO_A6dM.js} +3 -3
- package/dist/{LockedThumbnail-CCQ4wzdn.js.map → LockedThumbnail-PsO_A6dM.js.map} +1 -1
- package/dist/{index-BOzklqIY.js → index-B7fsmwKg.js} +7 -7
- package/dist/{index-BOzklqIY.js.map → index-B7fsmwKg.js.map} +1 -1
- package/dist/{index-BYS-61iP.cjs → index-CwyUGS68.cjs} +2 -2
- package/dist/{index-BYS-61iP.cjs.map → index-CwyUGS68.cjs.map} +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/package.json +2 -2
- package/src/components/AttachmentCard/index.tsx +1 -1
- package/src/components/CustomLinkPreviewList/CustomLinkPreviewCard.tsx +1 -1
- package/src/components/CustomMessage/MessageAttachmentConversations.stories.tsx +1 -1
- package/src/components/CustomMessage/MessageTag.stories.tsx +2 -2
- package/src/components/LinkAttachment/components/_shared/CardShell.tsx +1 -1
- package/src/components/LockedAttachment/components/_shared/LockedCardShell.tsx +1 -1
- package/src/components/MediaMessage/index.tsx +1 -1
- package/src/components/MessageAttachment/_shared/Bubble.tsx +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LockedThumbnail-C5ahPvA3.cjs","sources":["../src/components/LockedAttachment/components/_shared/CardBody.tsx","../src/components/LockedAttachment/components/_shared/GalleryThumbnail.tsx","../src/components/LockedAttachment/components/_shared/LockedCardShell.tsx","../src/components/LockedAttachment/components/_shared/LockBadge.tsx","../src/components/LockedAttachment/components/_shared/LockedThumbnail.tsx"],"sourcesContent":["import classNames from 'classnames'\nimport React from 'react'\n\nimport { renderTypeIcon } from '../../../AttachmentCard'\n\nimport type { LockedCardVariant } from './LockedCardShell'\n\nexport interface CardBodyProps {\n variant: LockedCardVariant\n title?: string\n placeholderTitle?: string\n mimeType: string\n detail?: string\n statusBadge?: React.ReactNode\n action?: React.ReactNode\n /** Overrides the auto-detected type icon (used by Gallery to swap in an `Images` icon). */\n icon?: React.ReactNode\n /** Optional control rendered on the right of the title/status block (e.g. Composer edit pencil). */\n trailingAction?: React.ReactNode\n}\n\n/**\n * Title + status row layout shared by Composer / Sent / Received cards.\n * Layout matches the Figma `Container > Labels` group (16px h-padding, 12px v-padding,\n * 4px gap between title and status row, 4px gap inside status row).\n */\nconst CardBody: React.FC<CardBodyProps> = ({\n variant,\n title,\n placeholderTitle = 'Attachment title',\n mimeType,\n detail,\n statusBadge,\n action,\n icon,\n trailingAction,\n}) => {\n const isDark = variant === 'dark'\n const displayTitle = isDark ? (title ?? placeholderTitle) : (title ?? '')\n const titleDimmed = isDark && !title\n\n const typeIcon =\n icon ??\n renderTypeIcon(mimeType, {\n className: classNames(\n 'size-5 shrink-0',\n isDark ? 'text-white/55' : 'text-black/55'\n ),\n weight: 'regular',\n })\n\n return (\n <div className=\"px-4 py-3\">\n <div className=\"flex items-end gap-3\">\n <div className=\"flex min-w-0 flex-1 flex-col gap-1\">\n {displayTitle.trim() !== '' && (\n <p\n className={classNames('truncate text-base font-medium leading-6', {\n 'text-black/90': !isDark,\n 'text-white/30': isDark && titleDimmed,\n 'text-white': isDark && !titleDimmed,\n })}\n >\n {displayTitle}\n </p>\n )}\n\n <div className=\"flex flex-wrap items-center gap-1\">\n {typeIcon}\n\n {detail != null && detail !== '' && (\n <span\n className={classNames(\n 'text-xs font-medium',\n isDark ? 'text-white/55' : 'text-black/55'\n )}\n >\n {detail}\n </span>\n )}\n\n {statusBadge}\n </div>\n </div>\n\n {trailingAction && <div className=\"shrink-0\">{trailingAction}</div>}\n </div>\n\n {action}\n </div>\n )\n}\n\nexport default CardBody\n","import {\n CaretLeftIcon,\n CaretRightIcon,\n LockOpenIcon,\n LockSimpleIcon,\n PlayIcon,\n} from '@phosphor-icons/react'\nimport classNames from 'classnames'\nimport React, { useState } from 'react'\n\nimport { AttachmentThumbnail, getSourceType } from '../../../AttachmentCard'\nimport type {\n LockedAttachmentGalleryItem,\n PaymentStatus,\n} from '../../types'\n\nimport type { LockedCardVariant } from './LockedCardShell'\n\nexport interface GalleryThumbnailProps {\n variant: LockedCardVariant\n gallery: LockedAttachmentGalleryItem[]\n title?: string\n /** When true, all items are shown blurred + the locked/play badge is overlaid. */\n showLocked: boolean\n paymentStatus?: PaymentStatus\n /** Top-right slot (e.g. dismiss X on Composer). Rendered inside the thumbnail. */\n topRight?: React.ReactNode\n}\n\nfunction isPlayableItem(item: LockedAttachmentGalleryItem): boolean {\n const sourceType = getSourceType(item.mimeType)\n return sourceType === 'video' || sourceType === 'audio'\n}\n\n/**\n * Mixed-media carousel used by every LockedAttachment card when its `gallery`\n * prop has 2+ items. Matches the \"Gallery\" frames in the Figma design system:\n * 337/386 aspect ratio, prev/next caret buttons, a counter pill, and a center\n * lock / play indicator that swaps based on the current item.\n */\nconst GalleryThumbnail: React.FC<GalleryThumbnailProps> = ({\n variant,\n gallery,\n title,\n showLocked,\n paymentStatus,\n topRight,\n}) => {\n const [index, setIndex] = useState(0)\n const total = gallery.length\n const safeIndex = Math.min(index, total - 1)\n const current = gallery[safeIndex]\n const isVideoItem = isPlayableItem(current)\n\n // Center badge: PLAY for video items, LOCK for non-video locked items.\n // Unlocked image items show no center badge — the image is the content.\n const centerBadge = (() => {\n if (isVideoItem) {\n return <PlayIcon className=\"size-6\" weight=\"fill\" />\n }\n if (showLocked) {\n return paymentStatus === 'paid' ? (\n <LockOpenIcon className=\"size-6\" weight=\"fill\" />\n ) : (\n <LockSimpleIcon className=\"size-6\" weight=\"fill\" />\n )\n }\n return null\n })()\n\n // Stop propagation so arrow taps don't bubble up to the outer preview-toggle\n // wrapper on ComposerCard / SentCard.\n const goPrev = (e: React.MouseEvent) => {\n e.stopPropagation()\n setIndex((i) => Math.max(0, i - 1))\n }\n const goNext = (e: React.MouseEvent) => {\n e.stopPropagation()\n setIndex((i) => Math.min(total - 1, i + 1))\n }\n const atStart = safeIndex === 0\n const atEnd = safeIndex === total - 1\n\n const isDark = variant === 'dark'\n\n // Locked + unlocked render entirely separate trees so the locked state\n // doesn't end up stacking a blurred `<img>` on top of an underlying\n // `AttachmentThumbnail` (whose `bg-white/10` poster shell otherwise\n // shows through as a visible horizontal seam at the 16:9 boundary\n // inside the taller 337/386 gallery aspect).\n //\n // The locked branch uses `filter: blur` on a single full-size `<img>`\n // — not `backdrop-filter` — so the rounded corners are clipped\n // normally without any clip-path workarounds (see LockedThumbnail).\n return (\n <div className=\"relative aspect-[337/386] overflow-hidden rounded-t-md\">\n {showLocked ? (\n <div\n className={classNames(\n 'absolute inset-0',\n isDark ? 'bg-white/10' : 'bg-black/5'\n )}\n >\n {current.thumbnailUrl && (\n <img\n src={current.thumbnailUrl}\n alt=\"\"\n aria-hidden\n draggable={false}\n // `scale-110` hides the fuzzy edge that `filter: blur` leaves\n // around the image bounds.\n className=\"absolute inset-0 h-full w-full scale-110 object-cover blur-[40px]\"\n />\n )}\n </div>\n ) : (\n <AttachmentThumbnail\n mimeType={current.mimeType}\n sourceUrl={current.sourceUrl}\n thumbnailUrl={current.thumbnailUrl}\n title={title}\n variant={variant}\n />\n )}\n\n {centerBadge && (\n <div className=\"pointer-events-none absolute inset-0 flex items-center justify-center\">\n <div className=\"flex size-12 items-center justify-center rounded-full bg-black/25 text-white\">\n {centerBadge}\n </div>\n </div>\n )}\n\n {total > 1 && (\n <React.Fragment>\n <button\n type=\"button\"\n onClick={goPrev}\n disabled={atStart}\n aria-label=\"Previous item\"\n className={classNames(\n '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',\n atStart ? 'opacity-40' : 'hover:bg-black/40'\n )}\n >\n <CaretLeftIcon className=\"size-5\" weight=\"bold\" />\n </button>\n <button\n type=\"button\"\n onClick={goNext}\n disabled={atEnd}\n aria-label=\"Next item\"\n className={classNames(\n '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',\n atEnd ? 'opacity-40' : 'hover:bg-black/40'\n )}\n >\n <CaretRightIcon className=\"size-5\" weight=\"bold\" />\n </button>\n\n <div className=\"pointer-events-none absolute bottom-5 left-1/2 -translate-x-1/2 rounded-lg bg-black/30 px-2 py-1\">\n <span className=\"text-xs font-medium leading-4 text-white\">\n {safeIndex + 1}/{total}\n </span>\n </div>\n </React.Fragment>\n )}\n\n {topRight && (\n <div className=\"pointer-events-auto absolute right-3 top-3 z-10\">\n {topRight}\n </div>\n )}\n </div>\n )\n}\n\nexport default GalleryThumbnail\n","import classNames from 'classnames'\nimport React from 'react'\n\nexport type LockedCardVariant = 'dark' | 'light'\n\nexport interface LockedCardShellProps {\n variant: LockedCardVariant\n children: React.ReactNode\n rootRef?: React.Ref<HTMLDivElement>\n 'data-testid'?: string\n}\n\n/**\n * Outer chrome for every LockedAttachment card.\n * Mirrors the `shadow-400` + 16px radius treatment from the Figma design system.\n */\nconst LockedCardShell: React.FC<LockedCardShellProps> = ({\n variant,\n children,\n rootRef,\n 'data-testid': dataTestId,\n}) => (\n <div\n ref={rootRef}\n data-testid={dataTestId}\n className={classNames(\n 'relative w-[280px] select-none overflow-hidden rounded-md',\n '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)]',\n variant === 'dark' ? 'bg-[#121110]' : 'bg-white'\n )}\n >\n {children}\n </div>\n)\n\nexport default LockedCardShell\n","import {\n LockOpenIcon,\n LockSimpleIcon,\n PlayIcon,\n} from '@phosphor-icons/react'\nimport React from 'react'\n\nimport { getSourceType } from '../../../AttachmentCard'\nimport type { PaymentStatus } from '../../types'\n\n/**\n * Centered 48x48 lock badge that overlays the thumbnail of any locked attachment.\n * Uses `bg-black/25` from the design system's `alpha-black-25` token.\n *\n * For playable media (video/audio), the badge shows a play icon instead of a\n * lock — matching the convention used by `GalleryThumbnail`.\n */\nexport const LockBadge: React.FC<{\n paymentStatus?: PaymentStatus\n mimeType?: string\n}> = ({ paymentStatus, mimeType }) => {\n const sourceType = mimeType ? getSourceType(mimeType) : undefined\n const isPlayable = sourceType === 'video' || sourceType === 'audio'\n\n const Icon = isPlayable\n ? PlayIcon\n : paymentStatus === 'paid'\n ? LockOpenIcon\n : LockSimpleIcon\n return (\n <div className=\"pointer-events-none absolute inset-0 flex items-center justify-center\">\n <div className=\"flex size-12 items-center justify-center rounded-full bg-black/25 text-white\">\n <Icon className=\"size-6\" weight=\"fill\" />\n </div>\n </div>\n )\n}\n\nexport default LockBadge\n","import classNames from 'classnames'\nimport React from 'react'\n\nimport {\n AttachmentThumbnail,\n renderTypeIcon,\n} from '../../../AttachmentCard'\nimport type { LockedAttachmentSource, PaymentStatus } from '../../types'\n\nimport { LockBadge } from './LockBadge'\nimport type { LockedCardVariant } from './LockedCardShell'\n\nexport interface LockedThumbnailProps {\n variant: LockedCardVariant\n mimeType: string\n thumbnailUrl?: string\n title?: string\n /**\n * When provided, the underlying source is shown unblurred (preview / unlocked state).\n * When undefined, the thumbnail is treated as locked: blurred with a central lock badge.\n */\n source?: LockedAttachmentSource\n /**\n * Forces the locked appearance even when a source is provided. Used for the\n * Composer card where the locked treatment is the default and the user toggles\n * a preview in place.\n */\n showLocked: boolean\n paymentStatus?: PaymentStatus\n /** Top-right overlay (e.g. dismiss X on Composer). Rendered inside the thumbnail. */\n topRight?: React.ReactNode\n /** When true, renders the unlocked image with aspect-video + object-contain. */\n containedImage?: boolean\n}\n\n/**\n * Renders the 180px-tall media area for a LockedAttachment card.\n * Handles three visual states:\n * - locked: blurred thumbnail + centered 48px lock badge\n * - preview/paid: clear thumbnail (the underlying source)\n * - empty: type-icon placeholder\n */\nconst LockedThumbnail: React.FC<LockedThumbnailProps> = ({\n variant,\n mimeType,\n thumbnailUrl,\n title,\n source,\n showLocked,\n paymentStatus,\n topRight,\n containedImage = false,\n}) => {\n const effectiveSourceUrl = showLocked ? undefined : source?.sourceUrl\n const effectiveThumbnailUrl = showLocked\n ? thumbnailUrl\n : (source?.thumbnailUrl ?? thumbnailUrl)\n\n const isDark = variant === 'dark'\n\n // Locked + unlocked render entirely separate trees so the locked state\n // doesn't end up stacking a blurred `<img>` on top of an underlying\n // `AttachmentThumbnail` (whose `bg-white/10` poster shell otherwise\n // shows through as a visible horizontal seam at the 16:9 boundary).\n //\n // The locked branch uses `filter: blur` on a single full-size `<img>`\n // — not `backdrop-filter` — because `backdrop-filter` paints in its\n // own compositing layer that escapes ancestor `overflow: hidden` on\n // Chrome/Safari and flattens the card's top corners. `filter` is\n // clipped normally, so the rounded corners stay round without any\n // clip-path workarounds.\n return (\n <div className=\"relative overflow-hidden rounded-t-md\">\n {showLocked ? (\n <div\n className={classNames(\n 'relative aspect-video overflow-hidden',\n isDark ? 'bg-white/10' : 'bg-black/5'\n )}\n >\n {effectiveThumbnailUrl ? (\n <img\n src={effectiveThumbnailUrl}\n alt=\"\"\n aria-hidden\n draggable={false}\n // `scale-110` hides the fuzzy semi-transparent edge that\n // `filter: blur` leaves around the image bounds.\n className=\"absolute inset-0 h-full w-full scale-110 object-cover blur-[40px]\"\n />\n ) : (\n <div className=\"absolute inset-0 flex items-center justify-center\">\n {renderTypeIcon(mimeType, {\n className: isDark\n ? 'size-12 text-white/20'\n : 'size-12 text-black/20',\n weight: 'regular',\n })}\n </div>\n )}\n <LockBadge paymentStatus={paymentStatus} mimeType={mimeType} />\n </div>\n ) : (\n <AttachmentThumbnail\n mimeType={mimeType}\n sourceUrl={effectiveSourceUrl}\n thumbnailUrl={effectiveThumbnailUrl}\n title={title}\n variant={variant}\n containedImage={containedImage}\n mediaPlayerProps={\n effectiveSourceUrl\n ? { autoPlay: true, loop: true, controls: true, muted: false }\n : undefined\n }\n />\n )}\n\n {topRight && (\n <div className=\"pointer-events-auto absolute right-3 top-3 z-10\">\n {topRight}\n </div>\n )}\n </div>\n )\n}\n\nexport default LockedThumbnail\n"],"names":["CardBody","variant","title","placeholderTitle","mimeType","detail","statusBadge","action","icon","trailingAction","isDark","displayTitle","titleDimmed","typeIcon","renderTypeIcon","classNames","jsxs","jsx","isPlayableItem","item","sourceType","getSourceType","GalleryThumbnail","gallery","showLocked","paymentStatus","topRight","index","setIndex","useState","total","safeIndex","current","isVideoItem","centerBadge","PlayIcon","LockOpenIcon","LockSimpleIcon","goPrev","e","i","goNext","atStart","atEnd","AttachmentThumbnail","React","CaretLeftIcon","CaretRightIcon","LockedCardShell","children","rootRef","dataTestId","LockBadge","Icon","LockedThumbnail","thumbnailUrl","source","containedImage","effectiveSourceUrl","effectiveThumbnailUrl"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"LockedThumbnail-Dkr6-8Lw.cjs","sources":["../src/components/LockedAttachment/components/_shared/CardBody.tsx","../src/components/LockedAttachment/components/_shared/GalleryThumbnail.tsx","../src/components/LockedAttachment/components/_shared/LockedCardShell.tsx","../src/components/LockedAttachment/components/_shared/LockBadge.tsx","../src/components/LockedAttachment/components/_shared/LockedThumbnail.tsx"],"sourcesContent":["import classNames from 'classnames'\nimport React from 'react'\n\nimport { renderTypeIcon } from '../../../AttachmentCard'\n\nimport type { LockedCardVariant } from './LockedCardShell'\n\nexport interface CardBodyProps {\n variant: LockedCardVariant\n title?: string\n placeholderTitle?: string\n mimeType: string\n detail?: string\n statusBadge?: React.ReactNode\n action?: React.ReactNode\n /** Overrides the auto-detected type icon (used by Gallery to swap in an `Images` icon). */\n icon?: React.ReactNode\n /** Optional control rendered on the right of the title/status block (e.g. Composer edit pencil). */\n trailingAction?: React.ReactNode\n}\n\n/**\n * Title + status row layout shared by Composer / Sent / Received cards.\n * Layout matches the Figma `Container > Labels` group (16px h-padding, 12px v-padding,\n * 4px gap between title and status row, 4px gap inside status row).\n */\nconst CardBody: React.FC<CardBodyProps> = ({\n variant,\n title,\n placeholderTitle = 'Attachment title',\n mimeType,\n detail,\n statusBadge,\n action,\n icon,\n trailingAction,\n}) => {\n const isDark = variant === 'dark'\n const displayTitle = isDark ? (title ?? placeholderTitle) : (title ?? '')\n const titleDimmed = isDark && !title\n\n const typeIcon =\n icon ??\n renderTypeIcon(mimeType, {\n className: classNames(\n 'size-5 shrink-0',\n isDark ? 'text-white/55' : 'text-black/55'\n ),\n weight: 'regular',\n })\n\n return (\n <div className=\"px-4 py-3\">\n <div className=\"flex items-end gap-3\">\n <div className=\"flex min-w-0 flex-1 flex-col gap-1\">\n {displayTitle.trim() !== '' && (\n <p\n className={classNames('truncate text-base font-medium leading-6', {\n 'text-black/90': !isDark,\n 'text-white/30': isDark && titleDimmed,\n 'text-white': isDark && !titleDimmed,\n })}\n >\n {displayTitle}\n </p>\n )}\n\n <div className=\"flex flex-wrap items-center gap-1\">\n {typeIcon}\n\n {detail != null && detail !== '' && (\n <span\n className={classNames(\n 'text-xs font-medium',\n isDark ? 'text-white/55' : 'text-black/55'\n )}\n >\n {detail}\n </span>\n )}\n\n {statusBadge}\n </div>\n </div>\n\n {trailingAction && <div className=\"shrink-0\">{trailingAction}</div>}\n </div>\n\n {action}\n </div>\n )\n}\n\nexport default CardBody\n","import {\n CaretLeftIcon,\n CaretRightIcon,\n LockOpenIcon,\n LockSimpleIcon,\n PlayIcon,\n} from '@phosphor-icons/react'\nimport classNames from 'classnames'\nimport React, { useState } from 'react'\n\nimport { AttachmentThumbnail, getSourceType } from '../../../AttachmentCard'\nimport type {\n LockedAttachmentGalleryItem,\n PaymentStatus,\n} from '../../types'\n\nimport type { LockedCardVariant } from './LockedCardShell'\n\nexport interface GalleryThumbnailProps {\n variant: LockedCardVariant\n gallery: LockedAttachmentGalleryItem[]\n title?: string\n /** When true, all items are shown blurred + the locked/play badge is overlaid. */\n showLocked: boolean\n paymentStatus?: PaymentStatus\n /** Top-right slot (e.g. dismiss X on Composer). Rendered inside the thumbnail. */\n topRight?: React.ReactNode\n}\n\nfunction isPlayableItem(item: LockedAttachmentGalleryItem): boolean {\n const sourceType = getSourceType(item.mimeType)\n return sourceType === 'video' || sourceType === 'audio'\n}\n\n/**\n * Mixed-media carousel used by every LockedAttachment card when its `gallery`\n * prop has 2+ items. Matches the \"Gallery\" frames in the Figma design system:\n * 337/386 aspect ratio, prev/next caret buttons, a counter pill, and a center\n * lock / play indicator that swaps based on the current item.\n */\nconst GalleryThumbnail: React.FC<GalleryThumbnailProps> = ({\n variant,\n gallery,\n title,\n showLocked,\n paymentStatus,\n topRight,\n}) => {\n const [index, setIndex] = useState(0)\n const total = gallery.length\n const safeIndex = Math.min(index, total - 1)\n const current = gallery[safeIndex]\n const isVideoItem = isPlayableItem(current)\n\n // Center badge: PLAY for video items, LOCK for non-video locked items.\n // Unlocked image items show no center badge — the image is the content.\n const centerBadge = (() => {\n if (isVideoItem) {\n return <PlayIcon className=\"size-6\" weight=\"fill\" />\n }\n if (showLocked) {\n return paymentStatus === 'paid' ? (\n <LockOpenIcon className=\"size-6\" weight=\"fill\" />\n ) : (\n <LockSimpleIcon className=\"size-6\" weight=\"fill\" />\n )\n }\n return null\n })()\n\n // Stop propagation so arrow taps don't bubble up to the outer preview-toggle\n // wrapper on ComposerCard / SentCard.\n const goPrev = (e: React.MouseEvent) => {\n e.stopPropagation()\n setIndex((i) => Math.max(0, i - 1))\n }\n const goNext = (e: React.MouseEvent) => {\n e.stopPropagation()\n setIndex((i) => Math.min(total - 1, i + 1))\n }\n const atStart = safeIndex === 0\n const atEnd = safeIndex === total - 1\n\n const isDark = variant === 'dark'\n\n // Locked + unlocked render entirely separate trees so the locked state\n // doesn't end up stacking a blurred `<img>` on top of an underlying\n // `AttachmentThumbnail` (whose `bg-white/10` poster shell otherwise\n // shows through as a visible horizontal seam at the 16:9 boundary\n // inside the taller 337/386 gallery aspect).\n //\n // The locked branch uses `filter: blur` on a single full-size `<img>`\n // — not `backdrop-filter` — so the rounded corners are clipped\n // normally without any clip-path workarounds (see LockedThumbnail).\n return (\n <div className=\"relative aspect-[337/386] overflow-hidden rounded-t-md\">\n {showLocked ? (\n <div\n className={classNames(\n 'absolute inset-0',\n isDark ? 'bg-white/10' : 'bg-black/5'\n )}\n >\n {current.thumbnailUrl && (\n <img\n src={current.thumbnailUrl}\n alt=\"\"\n aria-hidden\n draggable={false}\n // `scale-110` hides the fuzzy edge that `filter: blur` leaves\n // around the image bounds.\n className=\"absolute inset-0 h-full w-full scale-110 object-cover blur-[40px]\"\n />\n )}\n </div>\n ) : (\n <AttachmentThumbnail\n mimeType={current.mimeType}\n sourceUrl={current.sourceUrl}\n thumbnailUrl={current.thumbnailUrl}\n title={title}\n variant={variant}\n />\n )}\n\n {centerBadge && (\n <div className=\"pointer-events-none absolute inset-0 flex items-center justify-center\">\n <div className=\"flex size-12 items-center justify-center rounded-full bg-black/25 text-white\">\n {centerBadge}\n </div>\n </div>\n )}\n\n {total > 1 && (\n <React.Fragment>\n <button\n type=\"button\"\n onClick={goPrev}\n disabled={atStart}\n aria-label=\"Previous item\"\n className={classNames(\n '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',\n atStart ? 'opacity-40' : 'hover:bg-black/40'\n )}\n >\n <CaretLeftIcon className=\"size-5\" weight=\"bold\" />\n </button>\n <button\n type=\"button\"\n onClick={goNext}\n disabled={atEnd}\n aria-label=\"Next item\"\n className={classNames(\n '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',\n atEnd ? 'opacity-40' : 'hover:bg-black/40'\n )}\n >\n <CaretRightIcon className=\"size-5\" weight=\"bold\" />\n </button>\n\n <div className=\"pointer-events-none absolute bottom-5 left-1/2 -translate-x-1/2 rounded-lg bg-black/30 px-2 py-1\">\n <span className=\"text-xs font-medium leading-4 text-white\">\n {safeIndex + 1}/{total}\n </span>\n </div>\n </React.Fragment>\n )}\n\n {topRight && (\n <div className=\"pointer-events-auto absolute right-3 top-3 z-10\">\n {topRight}\n </div>\n )}\n </div>\n )\n}\n\nexport default GalleryThumbnail\n","import classNames from 'classnames'\nimport React from 'react'\n\nexport type LockedCardVariant = 'dark' | 'light'\n\nexport interface LockedCardShellProps {\n variant: LockedCardVariant\n children: React.ReactNode\n rootRef?: React.Ref<HTMLDivElement>\n 'data-testid'?: string\n}\n\n/**\n * Outer chrome for every LockedAttachment card.\n * Mirrors the `shadow-400` + 16px radius treatment from the Figma design system.\n */\nconst LockedCardShell: React.FC<LockedCardShellProps> = ({\n variant,\n children,\n rootRef,\n 'data-testid': dataTestId,\n}) => (\n <div\n ref={rootRef}\n data-testid={dataTestId}\n className={classNames(\n 'relative w-[280px] select-none overflow-hidden rounded-md',\n '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)]',\n variant === 'dark' ? 'bg-[#1e2330]' : 'bg-white'\n )}\n >\n {children}\n </div>\n)\n\nexport default LockedCardShell\n","import {\n LockOpenIcon,\n LockSimpleIcon,\n PlayIcon,\n} from '@phosphor-icons/react'\nimport React from 'react'\n\nimport { getSourceType } from '../../../AttachmentCard'\nimport type { PaymentStatus } from '../../types'\n\n/**\n * Centered 48x48 lock badge that overlays the thumbnail of any locked attachment.\n * Uses `bg-black/25` from the design system's `alpha-black-25` token.\n *\n * For playable media (video/audio), the badge shows a play icon instead of a\n * lock — matching the convention used by `GalleryThumbnail`.\n */\nexport const LockBadge: React.FC<{\n paymentStatus?: PaymentStatus\n mimeType?: string\n}> = ({ paymentStatus, mimeType }) => {\n const sourceType = mimeType ? getSourceType(mimeType) : undefined\n const isPlayable = sourceType === 'video' || sourceType === 'audio'\n\n const Icon = isPlayable\n ? PlayIcon\n : paymentStatus === 'paid'\n ? LockOpenIcon\n : LockSimpleIcon\n return (\n <div className=\"pointer-events-none absolute inset-0 flex items-center justify-center\">\n <div className=\"flex size-12 items-center justify-center rounded-full bg-black/25 text-white\">\n <Icon className=\"size-6\" weight=\"fill\" />\n </div>\n </div>\n )\n}\n\nexport default LockBadge\n","import classNames from 'classnames'\nimport React from 'react'\n\nimport {\n AttachmentThumbnail,\n renderTypeIcon,\n} from '../../../AttachmentCard'\nimport type { LockedAttachmentSource, PaymentStatus } from '../../types'\n\nimport { LockBadge } from './LockBadge'\nimport type { LockedCardVariant } from './LockedCardShell'\n\nexport interface LockedThumbnailProps {\n variant: LockedCardVariant\n mimeType: string\n thumbnailUrl?: string\n title?: string\n /**\n * When provided, the underlying source is shown unblurred (preview / unlocked state).\n * When undefined, the thumbnail is treated as locked: blurred with a central lock badge.\n */\n source?: LockedAttachmentSource\n /**\n * Forces the locked appearance even when a source is provided. Used for the\n * Composer card where the locked treatment is the default and the user toggles\n * a preview in place.\n */\n showLocked: boolean\n paymentStatus?: PaymentStatus\n /** Top-right overlay (e.g. dismiss X on Composer). Rendered inside the thumbnail. */\n topRight?: React.ReactNode\n /** When true, renders the unlocked image with aspect-video + object-contain. */\n containedImage?: boolean\n}\n\n/**\n * Renders the 180px-tall media area for a LockedAttachment card.\n * Handles three visual states:\n * - locked: blurred thumbnail + centered 48px lock badge\n * - preview/paid: clear thumbnail (the underlying source)\n * - empty: type-icon placeholder\n */\nconst LockedThumbnail: React.FC<LockedThumbnailProps> = ({\n variant,\n mimeType,\n thumbnailUrl,\n title,\n source,\n showLocked,\n paymentStatus,\n topRight,\n containedImage = false,\n}) => {\n const effectiveSourceUrl = showLocked ? undefined : source?.sourceUrl\n const effectiveThumbnailUrl = showLocked\n ? thumbnailUrl\n : (source?.thumbnailUrl ?? thumbnailUrl)\n\n const isDark = variant === 'dark'\n\n // Locked + unlocked render entirely separate trees so the locked state\n // doesn't end up stacking a blurred `<img>` on top of an underlying\n // `AttachmentThumbnail` (whose `bg-white/10` poster shell otherwise\n // shows through as a visible horizontal seam at the 16:9 boundary).\n //\n // The locked branch uses `filter: blur` on a single full-size `<img>`\n // — not `backdrop-filter` — because `backdrop-filter` paints in its\n // own compositing layer that escapes ancestor `overflow: hidden` on\n // Chrome/Safari and flattens the card's top corners. `filter` is\n // clipped normally, so the rounded corners stay round without any\n // clip-path workarounds.\n return (\n <div className=\"relative overflow-hidden rounded-t-md\">\n {showLocked ? (\n <div\n className={classNames(\n 'relative aspect-video overflow-hidden',\n isDark ? 'bg-white/10' : 'bg-black/5'\n )}\n >\n {effectiveThumbnailUrl ? (\n <img\n src={effectiveThumbnailUrl}\n alt=\"\"\n aria-hidden\n draggable={false}\n // `scale-110` hides the fuzzy semi-transparent edge that\n // `filter: blur` leaves around the image bounds.\n className=\"absolute inset-0 h-full w-full scale-110 object-cover blur-[40px]\"\n />\n ) : (\n <div className=\"absolute inset-0 flex items-center justify-center\">\n {renderTypeIcon(mimeType, {\n className: isDark\n ? 'size-12 text-white/20'\n : 'size-12 text-black/20',\n weight: 'regular',\n })}\n </div>\n )}\n <LockBadge paymentStatus={paymentStatus} mimeType={mimeType} />\n </div>\n ) : (\n <AttachmentThumbnail\n mimeType={mimeType}\n sourceUrl={effectiveSourceUrl}\n thumbnailUrl={effectiveThumbnailUrl}\n title={title}\n variant={variant}\n containedImage={containedImage}\n mediaPlayerProps={\n effectiveSourceUrl\n ? { autoPlay: true, loop: true, controls: true, muted: false }\n : undefined\n }\n />\n )}\n\n {topRight && (\n <div className=\"pointer-events-auto absolute right-3 top-3 z-10\">\n {topRight}\n </div>\n )}\n </div>\n )\n}\n\nexport default LockedThumbnail\n"],"names":["CardBody","variant","title","placeholderTitle","mimeType","detail","statusBadge","action","icon","trailingAction","isDark","displayTitle","titleDimmed","typeIcon","renderTypeIcon","classNames","jsxs","jsx","isPlayableItem","item","sourceType","getSourceType","GalleryThumbnail","gallery","showLocked","paymentStatus","topRight","index","setIndex","useState","total","safeIndex","current","isVideoItem","centerBadge","PlayIcon","LockOpenIcon","LockSimpleIcon","goPrev","e","i","goNext","atStart","atEnd","AttachmentThumbnail","React","CaretLeftIcon","CaretRightIcon","LockedCardShell","children","rootRef","dataTestId","LockBadge","Icon","LockedThumbnail","thumbnailUrl","source","containedImage","effectiveSourceUrl","effectiveThumbnailUrl"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsxs as o, jsx as e } from "react/jsx-runtime";
|
|
2
2
|
import m from "classnames";
|
|
3
|
-
import { r as N, A as y, g as w } from "./index-
|
|
3
|
+
import { r as N, A as y, g as w } from "./index-B7fsmwKg.js";
|
|
4
4
|
import U, { useState as _ } from "react";
|
|
5
5
|
import { CaretLeftIcon as T, CaretRightIcon as C, PlayIcon as k, LockOpenIcon as z, LockSimpleIcon as I } from "@phosphor-icons/react";
|
|
6
6
|
const F = ({
|
|
@@ -152,7 +152,7 @@ const O = ({
|
|
|
152
152
|
className: m(
|
|
153
153
|
"relative w-[280px] select-none overflow-hidden rounded-md",
|
|
154
154
|
"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)]",
|
|
155
|
-
l === "dark" ? "bg-[#
|
|
155
|
+
l === "dark" ? "bg-[#1e2330]" : "bg-white"
|
|
156
156
|
),
|
|
157
157
|
children: t
|
|
158
158
|
}
|
|
@@ -217,4 +217,4 @@ export {
|
|
|
217
217
|
V as L,
|
|
218
218
|
q as a
|
|
219
219
|
};
|
|
220
|
-
//# sourceMappingURL=LockedThumbnail-
|
|
220
|
+
//# sourceMappingURL=LockedThumbnail-PsO_A6dM.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LockedThumbnail-CCQ4wzdn.js","sources":["../src/components/LockedAttachment/components/_shared/CardBody.tsx","../src/components/LockedAttachment/components/_shared/GalleryThumbnail.tsx","../src/components/LockedAttachment/components/_shared/LockedCardShell.tsx","../src/components/LockedAttachment/components/_shared/LockBadge.tsx","../src/components/LockedAttachment/components/_shared/LockedThumbnail.tsx"],"sourcesContent":["import classNames from 'classnames'\nimport React from 'react'\n\nimport { renderTypeIcon } from '../../../AttachmentCard'\n\nimport type { LockedCardVariant } from './LockedCardShell'\n\nexport interface CardBodyProps {\n variant: LockedCardVariant\n title?: string\n placeholderTitle?: string\n mimeType: string\n detail?: string\n statusBadge?: React.ReactNode\n action?: React.ReactNode\n /** Overrides the auto-detected type icon (used by Gallery to swap in an `Images` icon). */\n icon?: React.ReactNode\n /** Optional control rendered on the right of the title/status block (e.g. Composer edit pencil). */\n trailingAction?: React.ReactNode\n}\n\n/**\n * Title + status row layout shared by Composer / Sent / Received cards.\n * Layout matches the Figma `Container > Labels` group (16px h-padding, 12px v-padding,\n * 4px gap between title and status row, 4px gap inside status row).\n */\nconst CardBody: React.FC<CardBodyProps> = ({\n variant,\n title,\n placeholderTitle = 'Attachment title',\n mimeType,\n detail,\n statusBadge,\n action,\n icon,\n trailingAction,\n}) => {\n const isDark = variant === 'dark'\n const displayTitle = isDark ? (title ?? placeholderTitle) : (title ?? '')\n const titleDimmed = isDark && !title\n\n const typeIcon =\n icon ??\n renderTypeIcon(mimeType, {\n className: classNames(\n 'size-5 shrink-0',\n isDark ? 'text-white/55' : 'text-black/55'\n ),\n weight: 'regular',\n })\n\n return (\n <div className=\"px-4 py-3\">\n <div className=\"flex items-end gap-3\">\n <div className=\"flex min-w-0 flex-1 flex-col gap-1\">\n {displayTitle.trim() !== '' && (\n <p\n className={classNames('truncate text-base font-medium leading-6', {\n 'text-black/90': !isDark,\n 'text-white/30': isDark && titleDimmed,\n 'text-white': isDark && !titleDimmed,\n })}\n >\n {displayTitle}\n </p>\n )}\n\n <div className=\"flex flex-wrap items-center gap-1\">\n {typeIcon}\n\n {detail != null && detail !== '' && (\n <span\n className={classNames(\n 'text-xs font-medium',\n isDark ? 'text-white/55' : 'text-black/55'\n )}\n >\n {detail}\n </span>\n )}\n\n {statusBadge}\n </div>\n </div>\n\n {trailingAction && <div className=\"shrink-0\">{trailingAction}</div>}\n </div>\n\n {action}\n </div>\n )\n}\n\nexport default CardBody\n","import {\n CaretLeftIcon,\n CaretRightIcon,\n LockOpenIcon,\n LockSimpleIcon,\n PlayIcon,\n} from '@phosphor-icons/react'\nimport classNames from 'classnames'\nimport React, { useState } from 'react'\n\nimport { AttachmentThumbnail, getSourceType } from '../../../AttachmentCard'\nimport type {\n LockedAttachmentGalleryItem,\n PaymentStatus,\n} from '../../types'\n\nimport type { LockedCardVariant } from './LockedCardShell'\n\nexport interface GalleryThumbnailProps {\n variant: LockedCardVariant\n gallery: LockedAttachmentGalleryItem[]\n title?: string\n /** When true, all items are shown blurred + the locked/play badge is overlaid. */\n showLocked: boolean\n paymentStatus?: PaymentStatus\n /** Top-right slot (e.g. dismiss X on Composer). Rendered inside the thumbnail. */\n topRight?: React.ReactNode\n}\n\nfunction isPlayableItem(item: LockedAttachmentGalleryItem): boolean {\n const sourceType = getSourceType(item.mimeType)\n return sourceType === 'video' || sourceType === 'audio'\n}\n\n/**\n * Mixed-media carousel used by every LockedAttachment card when its `gallery`\n * prop has 2+ items. Matches the \"Gallery\" frames in the Figma design system:\n * 337/386 aspect ratio, prev/next caret buttons, a counter pill, and a center\n * lock / play indicator that swaps based on the current item.\n */\nconst GalleryThumbnail: React.FC<GalleryThumbnailProps> = ({\n variant,\n gallery,\n title,\n showLocked,\n paymentStatus,\n topRight,\n}) => {\n const [index, setIndex] = useState(0)\n const total = gallery.length\n const safeIndex = Math.min(index, total - 1)\n const current = gallery[safeIndex]\n const isVideoItem = isPlayableItem(current)\n\n // Center badge: PLAY for video items, LOCK for non-video locked items.\n // Unlocked image items show no center badge — the image is the content.\n const centerBadge = (() => {\n if (isVideoItem) {\n return <PlayIcon className=\"size-6\" weight=\"fill\" />\n }\n if (showLocked) {\n return paymentStatus === 'paid' ? (\n <LockOpenIcon className=\"size-6\" weight=\"fill\" />\n ) : (\n <LockSimpleIcon className=\"size-6\" weight=\"fill\" />\n )\n }\n return null\n })()\n\n // Stop propagation so arrow taps don't bubble up to the outer preview-toggle\n // wrapper on ComposerCard / SentCard.\n const goPrev = (e: React.MouseEvent) => {\n e.stopPropagation()\n setIndex((i) => Math.max(0, i - 1))\n }\n const goNext = (e: React.MouseEvent) => {\n e.stopPropagation()\n setIndex((i) => Math.min(total - 1, i + 1))\n }\n const atStart = safeIndex === 0\n const atEnd = safeIndex === total - 1\n\n const isDark = variant === 'dark'\n\n // Locked + unlocked render entirely separate trees so the locked state\n // doesn't end up stacking a blurred `<img>` on top of an underlying\n // `AttachmentThumbnail` (whose `bg-white/10` poster shell otherwise\n // shows through as a visible horizontal seam at the 16:9 boundary\n // inside the taller 337/386 gallery aspect).\n //\n // The locked branch uses `filter: blur` on a single full-size `<img>`\n // — not `backdrop-filter` — so the rounded corners are clipped\n // normally without any clip-path workarounds (see LockedThumbnail).\n return (\n <div className=\"relative aspect-[337/386] overflow-hidden rounded-t-md\">\n {showLocked ? (\n <div\n className={classNames(\n 'absolute inset-0',\n isDark ? 'bg-white/10' : 'bg-black/5'\n )}\n >\n {current.thumbnailUrl && (\n <img\n src={current.thumbnailUrl}\n alt=\"\"\n aria-hidden\n draggable={false}\n // `scale-110` hides the fuzzy edge that `filter: blur` leaves\n // around the image bounds.\n className=\"absolute inset-0 h-full w-full scale-110 object-cover blur-[40px]\"\n />\n )}\n </div>\n ) : (\n <AttachmentThumbnail\n mimeType={current.mimeType}\n sourceUrl={current.sourceUrl}\n thumbnailUrl={current.thumbnailUrl}\n title={title}\n variant={variant}\n />\n )}\n\n {centerBadge && (\n <div className=\"pointer-events-none absolute inset-0 flex items-center justify-center\">\n <div className=\"flex size-12 items-center justify-center rounded-full bg-black/25 text-white\">\n {centerBadge}\n </div>\n </div>\n )}\n\n {total > 1 && (\n <React.Fragment>\n <button\n type=\"button\"\n onClick={goPrev}\n disabled={atStart}\n aria-label=\"Previous item\"\n className={classNames(\n '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',\n atStart ? 'opacity-40' : 'hover:bg-black/40'\n )}\n >\n <CaretLeftIcon className=\"size-5\" weight=\"bold\" />\n </button>\n <button\n type=\"button\"\n onClick={goNext}\n disabled={atEnd}\n aria-label=\"Next item\"\n className={classNames(\n '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',\n atEnd ? 'opacity-40' : 'hover:bg-black/40'\n )}\n >\n <CaretRightIcon className=\"size-5\" weight=\"bold\" />\n </button>\n\n <div className=\"pointer-events-none absolute bottom-5 left-1/2 -translate-x-1/2 rounded-lg bg-black/30 px-2 py-1\">\n <span className=\"text-xs font-medium leading-4 text-white\">\n {safeIndex + 1}/{total}\n </span>\n </div>\n </React.Fragment>\n )}\n\n {topRight && (\n <div className=\"pointer-events-auto absolute right-3 top-3 z-10\">\n {topRight}\n </div>\n )}\n </div>\n )\n}\n\nexport default GalleryThumbnail\n","import classNames from 'classnames'\nimport React from 'react'\n\nexport type LockedCardVariant = 'dark' | 'light'\n\nexport interface LockedCardShellProps {\n variant: LockedCardVariant\n children: React.ReactNode\n rootRef?: React.Ref<HTMLDivElement>\n 'data-testid'?: string\n}\n\n/**\n * Outer chrome for every LockedAttachment card.\n * Mirrors the `shadow-400` + 16px radius treatment from the Figma design system.\n */\nconst LockedCardShell: React.FC<LockedCardShellProps> = ({\n variant,\n children,\n rootRef,\n 'data-testid': dataTestId,\n}) => (\n <div\n ref={rootRef}\n data-testid={dataTestId}\n className={classNames(\n 'relative w-[280px] select-none overflow-hidden rounded-md',\n '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)]',\n variant === 'dark' ? 'bg-[#121110]' : 'bg-white'\n )}\n >\n {children}\n </div>\n)\n\nexport default LockedCardShell\n","import {\n LockOpenIcon,\n LockSimpleIcon,\n PlayIcon,\n} from '@phosphor-icons/react'\nimport React from 'react'\n\nimport { getSourceType } from '../../../AttachmentCard'\nimport type { PaymentStatus } from '../../types'\n\n/**\n * Centered 48x48 lock badge that overlays the thumbnail of any locked attachment.\n * Uses `bg-black/25` from the design system's `alpha-black-25` token.\n *\n * For playable media (video/audio), the badge shows a play icon instead of a\n * lock — matching the convention used by `GalleryThumbnail`.\n */\nexport const LockBadge: React.FC<{\n paymentStatus?: PaymentStatus\n mimeType?: string\n}> = ({ paymentStatus, mimeType }) => {\n const sourceType = mimeType ? getSourceType(mimeType) : undefined\n const isPlayable = sourceType === 'video' || sourceType === 'audio'\n\n const Icon = isPlayable\n ? PlayIcon\n : paymentStatus === 'paid'\n ? LockOpenIcon\n : LockSimpleIcon\n return (\n <div className=\"pointer-events-none absolute inset-0 flex items-center justify-center\">\n <div className=\"flex size-12 items-center justify-center rounded-full bg-black/25 text-white\">\n <Icon className=\"size-6\" weight=\"fill\" />\n </div>\n </div>\n )\n}\n\nexport default LockBadge\n","import classNames from 'classnames'\nimport React from 'react'\n\nimport {\n AttachmentThumbnail,\n renderTypeIcon,\n} from '../../../AttachmentCard'\nimport type { LockedAttachmentSource, PaymentStatus } from '../../types'\n\nimport { LockBadge } from './LockBadge'\nimport type { LockedCardVariant } from './LockedCardShell'\n\nexport interface LockedThumbnailProps {\n variant: LockedCardVariant\n mimeType: string\n thumbnailUrl?: string\n title?: string\n /**\n * When provided, the underlying source is shown unblurred (preview / unlocked state).\n * When undefined, the thumbnail is treated as locked: blurred with a central lock badge.\n */\n source?: LockedAttachmentSource\n /**\n * Forces the locked appearance even when a source is provided. Used for the\n * Composer card where the locked treatment is the default and the user toggles\n * a preview in place.\n */\n showLocked: boolean\n paymentStatus?: PaymentStatus\n /** Top-right overlay (e.g. dismiss X on Composer). Rendered inside the thumbnail. */\n topRight?: React.ReactNode\n /** When true, renders the unlocked image with aspect-video + object-contain. */\n containedImage?: boolean\n}\n\n/**\n * Renders the 180px-tall media area for a LockedAttachment card.\n * Handles three visual states:\n * - locked: blurred thumbnail + centered 48px lock badge\n * - preview/paid: clear thumbnail (the underlying source)\n * - empty: type-icon placeholder\n */\nconst LockedThumbnail: React.FC<LockedThumbnailProps> = ({\n variant,\n mimeType,\n thumbnailUrl,\n title,\n source,\n showLocked,\n paymentStatus,\n topRight,\n containedImage = false,\n}) => {\n const effectiveSourceUrl = showLocked ? undefined : source?.sourceUrl\n const effectiveThumbnailUrl = showLocked\n ? thumbnailUrl\n : (source?.thumbnailUrl ?? thumbnailUrl)\n\n const isDark = variant === 'dark'\n\n // Locked + unlocked render entirely separate trees so the locked state\n // doesn't end up stacking a blurred `<img>` on top of an underlying\n // `AttachmentThumbnail` (whose `bg-white/10` poster shell otherwise\n // shows through as a visible horizontal seam at the 16:9 boundary).\n //\n // The locked branch uses `filter: blur` on a single full-size `<img>`\n // — not `backdrop-filter` — because `backdrop-filter` paints in its\n // own compositing layer that escapes ancestor `overflow: hidden` on\n // Chrome/Safari and flattens the card's top corners. `filter` is\n // clipped normally, so the rounded corners stay round without any\n // clip-path workarounds.\n return (\n <div className=\"relative overflow-hidden rounded-t-md\">\n {showLocked ? (\n <div\n className={classNames(\n 'relative aspect-video overflow-hidden',\n isDark ? 'bg-white/10' : 'bg-black/5'\n )}\n >\n {effectiveThumbnailUrl ? (\n <img\n src={effectiveThumbnailUrl}\n alt=\"\"\n aria-hidden\n draggable={false}\n // `scale-110` hides the fuzzy semi-transparent edge that\n // `filter: blur` leaves around the image bounds.\n className=\"absolute inset-0 h-full w-full scale-110 object-cover blur-[40px]\"\n />\n ) : (\n <div className=\"absolute inset-0 flex items-center justify-center\">\n {renderTypeIcon(mimeType, {\n className: isDark\n ? 'size-12 text-white/20'\n : 'size-12 text-black/20',\n weight: 'regular',\n })}\n </div>\n )}\n <LockBadge paymentStatus={paymentStatus} mimeType={mimeType} />\n </div>\n ) : (\n <AttachmentThumbnail\n mimeType={mimeType}\n sourceUrl={effectiveSourceUrl}\n thumbnailUrl={effectiveThumbnailUrl}\n title={title}\n variant={variant}\n containedImage={containedImage}\n mediaPlayerProps={\n effectiveSourceUrl\n ? { autoPlay: true, loop: true, controls: true, muted: false }\n : undefined\n }\n />\n )}\n\n {topRight && (\n <div className=\"pointer-events-auto absolute right-3 top-3 z-10\">\n {topRight}\n </div>\n )}\n </div>\n )\n}\n\nexport default LockedThumbnail\n"],"names":["CardBody","variant","title","placeholderTitle","mimeType","detail","statusBadge","action","icon","trailingAction","isDark","displayTitle","titleDimmed","typeIcon","renderTypeIcon","classNames","jsxs","jsx","isPlayableItem","item","sourceType","getSourceType","GalleryThumbnail","gallery","showLocked","paymentStatus","topRight","index","setIndex","useState","total","safeIndex","current","isVideoItem","centerBadge","PlayIcon","LockOpenIcon","LockSimpleIcon","goPrev","e","i","goNext","atStart","atEnd","AttachmentThumbnail","React","CaretLeftIcon","CaretRightIcon","LockedCardShell","children","rootRef","dataTestId","LockBadge","LockedThumbnail","thumbnailUrl","source","containedImage","effectiveSourceUrl","effectiveThumbnailUrl"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"LockedThumbnail-PsO_A6dM.js","sources":["../src/components/LockedAttachment/components/_shared/CardBody.tsx","../src/components/LockedAttachment/components/_shared/GalleryThumbnail.tsx","../src/components/LockedAttachment/components/_shared/LockedCardShell.tsx","../src/components/LockedAttachment/components/_shared/LockBadge.tsx","../src/components/LockedAttachment/components/_shared/LockedThumbnail.tsx"],"sourcesContent":["import classNames from 'classnames'\nimport React from 'react'\n\nimport { renderTypeIcon } from '../../../AttachmentCard'\n\nimport type { LockedCardVariant } from './LockedCardShell'\n\nexport interface CardBodyProps {\n variant: LockedCardVariant\n title?: string\n placeholderTitle?: string\n mimeType: string\n detail?: string\n statusBadge?: React.ReactNode\n action?: React.ReactNode\n /** Overrides the auto-detected type icon (used by Gallery to swap in an `Images` icon). */\n icon?: React.ReactNode\n /** Optional control rendered on the right of the title/status block (e.g. Composer edit pencil). */\n trailingAction?: React.ReactNode\n}\n\n/**\n * Title + status row layout shared by Composer / Sent / Received cards.\n * Layout matches the Figma `Container > Labels` group (16px h-padding, 12px v-padding,\n * 4px gap between title and status row, 4px gap inside status row).\n */\nconst CardBody: React.FC<CardBodyProps> = ({\n variant,\n title,\n placeholderTitle = 'Attachment title',\n mimeType,\n detail,\n statusBadge,\n action,\n icon,\n trailingAction,\n}) => {\n const isDark = variant === 'dark'\n const displayTitle = isDark ? (title ?? placeholderTitle) : (title ?? '')\n const titleDimmed = isDark && !title\n\n const typeIcon =\n icon ??\n renderTypeIcon(mimeType, {\n className: classNames(\n 'size-5 shrink-0',\n isDark ? 'text-white/55' : 'text-black/55'\n ),\n weight: 'regular',\n })\n\n return (\n <div className=\"px-4 py-3\">\n <div className=\"flex items-end gap-3\">\n <div className=\"flex min-w-0 flex-1 flex-col gap-1\">\n {displayTitle.trim() !== '' && (\n <p\n className={classNames('truncate text-base font-medium leading-6', {\n 'text-black/90': !isDark,\n 'text-white/30': isDark && titleDimmed,\n 'text-white': isDark && !titleDimmed,\n })}\n >\n {displayTitle}\n </p>\n )}\n\n <div className=\"flex flex-wrap items-center gap-1\">\n {typeIcon}\n\n {detail != null && detail !== '' && (\n <span\n className={classNames(\n 'text-xs font-medium',\n isDark ? 'text-white/55' : 'text-black/55'\n )}\n >\n {detail}\n </span>\n )}\n\n {statusBadge}\n </div>\n </div>\n\n {trailingAction && <div className=\"shrink-0\">{trailingAction}</div>}\n </div>\n\n {action}\n </div>\n )\n}\n\nexport default CardBody\n","import {\n CaretLeftIcon,\n CaretRightIcon,\n LockOpenIcon,\n LockSimpleIcon,\n PlayIcon,\n} from '@phosphor-icons/react'\nimport classNames from 'classnames'\nimport React, { useState } from 'react'\n\nimport { AttachmentThumbnail, getSourceType } from '../../../AttachmentCard'\nimport type {\n LockedAttachmentGalleryItem,\n PaymentStatus,\n} from '../../types'\n\nimport type { LockedCardVariant } from './LockedCardShell'\n\nexport interface GalleryThumbnailProps {\n variant: LockedCardVariant\n gallery: LockedAttachmentGalleryItem[]\n title?: string\n /** When true, all items are shown blurred + the locked/play badge is overlaid. */\n showLocked: boolean\n paymentStatus?: PaymentStatus\n /** Top-right slot (e.g. dismiss X on Composer). Rendered inside the thumbnail. */\n topRight?: React.ReactNode\n}\n\nfunction isPlayableItem(item: LockedAttachmentGalleryItem): boolean {\n const sourceType = getSourceType(item.mimeType)\n return sourceType === 'video' || sourceType === 'audio'\n}\n\n/**\n * Mixed-media carousel used by every LockedAttachment card when its `gallery`\n * prop has 2+ items. Matches the \"Gallery\" frames in the Figma design system:\n * 337/386 aspect ratio, prev/next caret buttons, a counter pill, and a center\n * lock / play indicator that swaps based on the current item.\n */\nconst GalleryThumbnail: React.FC<GalleryThumbnailProps> = ({\n variant,\n gallery,\n title,\n showLocked,\n paymentStatus,\n topRight,\n}) => {\n const [index, setIndex] = useState(0)\n const total = gallery.length\n const safeIndex = Math.min(index, total - 1)\n const current = gallery[safeIndex]\n const isVideoItem = isPlayableItem(current)\n\n // Center badge: PLAY for video items, LOCK for non-video locked items.\n // Unlocked image items show no center badge — the image is the content.\n const centerBadge = (() => {\n if (isVideoItem) {\n return <PlayIcon className=\"size-6\" weight=\"fill\" />\n }\n if (showLocked) {\n return paymentStatus === 'paid' ? (\n <LockOpenIcon className=\"size-6\" weight=\"fill\" />\n ) : (\n <LockSimpleIcon className=\"size-6\" weight=\"fill\" />\n )\n }\n return null\n })()\n\n // Stop propagation so arrow taps don't bubble up to the outer preview-toggle\n // wrapper on ComposerCard / SentCard.\n const goPrev = (e: React.MouseEvent) => {\n e.stopPropagation()\n setIndex((i) => Math.max(0, i - 1))\n }\n const goNext = (e: React.MouseEvent) => {\n e.stopPropagation()\n setIndex((i) => Math.min(total - 1, i + 1))\n }\n const atStart = safeIndex === 0\n const atEnd = safeIndex === total - 1\n\n const isDark = variant === 'dark'\n\n // Locked + unlocked render entirely separate trees so the locked state\n // doesn't end up stacking a blurred `<img>` on top of an underlying\n // `AttachmentThumbnail` (whose `bg-white/10` poster shell otherwise\n // shows through as a visible horizontal seam at the 16:9 boundary\n // inside the taller 337/386 gallery aspect).\n //\n // The locked branch uses `filter: blur` on a single full-size `<img>`\n // — not `backdrop-filter` — so the rounded corners are clipped\n // normally without any clip-path workarounds (see LockedThumbnail).\n return (\n <div className=\"relative aspect-[337/386] overflow-hidden rounded-t-md\">\n {showLocked ? (\n <div\n className={classNames(\n 'absolute inset-0',\n isDark ? 'bg-white/10' : 'bg-black/5'\n )}\n >\n {current.thumbnailUrl && (\n <img\n src={current.thumbnailUrl}\n alt=\"\"\n aria-hidden\n draggable={false}\n // `scale-110` hides the fuzzy edge that `filter: blur` leaves\n // around the image bounds.\n className=\"absolute inset-0 h-full w-full scale-110 object-cover blur-[40px]\"\n />\n )}\n </div>\n ) : (\n <AttachmentThumbnail\n mimeType={current.mimeType}\n sourceUrl={current.sourceUrl}\n thumbnailUrl={current.thumbnailUrl}\n title={title}\n variant={variant}\n />\n )}\n\n {centerBadge && (\n <div className=\"pointer-events-none absolute inset-0 flex items-center justify-center\">\n <div className=\"flex size-12 items-center justify-center rounded-full bg-black/25 text-white\">\n {centerBadge}\n </div>\n </div>\n )}\n\n {total > 1 && (\n <React.Fragment>\n <button\n type=\"button\"\n onClick={goPrev}\n disabled={atStart}\n aria-label=\"Previous item\"\n className={classNames(\n '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',\n atStart ? 'opacity-40' : 'hover:bg-black/40'\n )}\n >\n <CaretLeftIcon className=\"size-5\" weight=\"bold\" />\n </button>\n <button\n type=\"button\"\n onClick={goNext}\n disabled={atEnd}\n aria-label=\"Next item\"\n className={classNames(\n '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',\n atEnd ? 'opacity-40' : 'hover:bg-black/40'\n )}\n >\n <CaretRightIcon className=\"size-5\" weight=\"bold\" />\n </button>\n\n <div className=\"pointer-events-none absolute bottom-5 left-1/2 -translate-x-1/2 rounded-lg bg-black/30 px-2 py-1\">\n <span className=\"text-xs font-medium leading-4 text-white\">\n {safeIndex + 1}/{total}\n </span>\n </div>\n </React.Fragment>\n )}\n\n {topRight && (\n <div className=\"pointer-events-auto absolute right-3 top-3 z-10\">\n {topRight}\n </div>\n )}\n </div>\n )\n}\n\nexport default GalleryThumbnail\n","import classNames from 'classnames'\nimport React from 'react'\n\nexport type LockedCardVariant = 'dark' | 'light'\n\nexport interface LockedCardShellProps {\n variant: LockedCardVariant\n children: React.ReactNode\n rootRef?: React.Ref<HTMLDivElement>\n 'data-testid'?: string\n}\n\n/**\n * Outer chrome for every LockedAttachment card.\n * Mirrors the `shadow-400` + 16px radius treatment from the Figma design system.\n */\nconst LockedCardShell: React.FC<LockedCardShellProps> = ({\n variant,\n children,\n rootRef,\n 'data-testid': dataTestId,\n}) => (\n <div\n ref={rootRef}\n data-testid={dataTestId}\n className={classNames(\n 'relative w-[280px] select-none overflow-hidden rounded-md',\n '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)]',\n variant === 'dark' ? 'bg-[#1e2330]' : 'bg-white'\n )}\n >\n {children}\n </div>\n)\n\nexport default LockedCardShell\n","import {\n LockOpenIcon,\n LockSimpleIcon,\n PlayIcon,\n} from '@phosphor-icons/react'\nimport React from 'react'\n\nimport { getSourceType } from '../../../AttachmentCard'\nimport type { PaymentStatus } from '../../types'\n\n/**\n * Centered 48x48 lock badge that overlays the thumbnail of any locked attachment.\n * Uses `bg-black/25` from the design system's `alpha-black-25` token.\n *\n * For playable media (video/audio), the badge shows a play icon instead of a\n * lock — matching the convention used by `GalleryThumbnail`.\n */\nexport const LockBadge: React.FC<{\n paymentStatus?: PaymentStatus\n mimeType?: string\n}> = ({ paymentStatus, mimeType }) => {\n const sourceType = mimeType ? getSourceType(mimeType) : undefined\n const isPlayable = sourceType === 'video' || sourceType === 'audio'\n\n const Icon = isPlayable\n ? PlayIcon\n : paymentStatus === 'paid'\n ? LockOpenIcon\n : LockSimpleIcon\n return (\n <div className=\"pointer-events-none absolute inset-0 flex items-center justify-center\">\n <div className=\"flex size-12 items-center justify-center rounded-full bg-black/25 text-white\">\n <Icon className=\"size-6\" weight=\"fill\" />\n </div>\n </div>\n )\n}\n\nexport default LockBadge\n","import classNames from 'classnames'\nimport React from 'react'\n\nimport {\n AttachmentThumbnail,\n renderTypeIcon,\n} from '../../../AttachmentCard'\nimport type { LockedAttachmentSource, PaymentStatus } from '../../types'\n\nimport { LockBadge } from './LockBadge'\nimport type { LockedCardVariant } from './LockedCardShell'\n\nexport interface LockedThumbnailProps {\n variant: LockedCardVariant\n mimeType: string\n thumbnailUrl?: string\n title?: string\n /**\n * When provided, the underlying source is shown unblurred (preview / unlocked state).\n * When undefined, the thumbnail is treated as locked: blurred with a central lock badge.\n */\n source?: LockedAttachmentSource\n /**\n * Forces the locked appearance even when a source is provided. Used for the\n * Composer card where the locked treatment is the default and the user toggles\n * a preview in place.\n */\n showLocked: boolean\n paymentStatus?: PaymentStatus\n /** Top-right overlay (e.g. dismiss X on Composer). Rendered inside the thumbnail. */\n topRight?: React.ReactNode\n /** When true, renders the unlocked image with aspect-video + object-contain. */\n containedImage?: boolean\n}\n\n/**\n * Renders the 180px-tall media area for a LockedAttachment card.\n * Handles three visual states:\n * - locked: blurred thumbnail + centered 48px lock badge\n * - preview/paid: clear thumbnail (the underlying source)\n * - empty: type-icon placeholder\n */\nconst LockedThumbnail: React.FC<LockedThumbnailProps> = ({\n variant,\n mimeType,\n thumbnailUrl,\n title,\n source,\n showLocked,\n paymentStatus,\n topRight,\n containedImage = false,\n}) => {\n const effectiveSourceUrl = showLocked ? undefined : source?.sourceUrl\n const effectiveThumbnailUrl = showLocked\n ? thumbnailUrl\n : (source?.thumbnailUrl ?? thumbnailUrl)\n\n const isDark = variant === 'dark'\n\n // Locked + unlocked render entirely separate trees so the locked state\n // doesn't end up stacking a blurred `<img>` on top of an underlying\n // `AttachmentThumbnail` (whose `bg-white/10` poster shell otherwise\n // shows through as a visible horizontal seam at the 16:9 boundary).\n //\n // The locked branch uses `filter: blur` on a single full-size `<img>`\n // — not `backdrop-filter` — because `backdrop-filter` paints in its\n // own compositing layer that escapes ancestor `overflow: hidden` on\n // Chrome/Safari and flattens the card's top corners. `filter` is\n // clipped normally, so the rounded corners stay round without any\n // clip-path workarounds.\n return (\n <div className=\"relative overflow-hidden rounded-t-md\">\n {showLocked ? (\n <div\n className={classNames(\n 'relative aspect-video overflow-hidden',\n isDark ? 'bg-white/10' : 'bg-black/5'\n )}\n >\n {effectiveThumbnailUrl ? (\n <img\n src={effectiveThumbnailUrl}\n alt=\"\"\n aria-hidden\n draggable={false}\n // `scale-110` hides the fuzzy semi-transparent edge that\n // `filter: blur` leaves around the image bounds.\n className=\"absolute inset-0 h-full w-full scale-110 object-cover blur-[40px]\"\n />\n ) : (\n <div className=\"absolute inset-0 flex items-center justify-center\">\n {renderTypeIcon(mimeType, {\n className: isDark\n ? 'size-12 text-white/20'\n : 'size-12 text-black/20',\n weight: 'regular',\n })}\n </div>\n )}\n <LockBadge paymentStatus={paymentStatus} mimeType={mimeType} />\n </div>\n ) : (\n <AttachmentThumbnail\n mimeType={mimeType}\n sourceUrl={effectiveSourceUrl}\n thumbnailUrl={effectiveThumbnailUrl}\n title={title}\n variant={variant}\n containedImage={containedImage}\n mediaPlayerProps={\n effectiveSourceUrl\n ? { autoPlay: true, loop: true, controls: true, muted: false }\n : undefined\n }\n />\n )}\n\n {topRight && (\n <div className=\"pointer-events-auto absolute right-3 top-3 z-10\">\n {topRight}\n </div>\n )}\n </div>\n )\n}\n\nexport default LockedThumbnail\n"],"names":["CardBody","variant","title","placeholderTitle","mimeType","detail","statusBadge","action","icon","trailingAction","isDark","displayTitle","titleDimmed","typeIcon","renderTypeIcon","classNames","jsxs","jsx","isPlayableItem","item","sourceType","getSourceType","GalleryThumbnail","gallery","showLocked","paymentStatus","topRight","index","setIndex","useState","total","safeIndex","current","isVideoItem","centerBadge","PlayIcon","LockOpenIcon","LockSimpleIcon","goPrev","e","i","goNext","atStart","atEnd","AttachmentThumbnail","React","CaretLeftIcon","CaretRightIcon","LockedCardShell","children","rootRef","dataTestId","LockBadge","LockedThumbnail","thumbnailUrl","source","containedImage","effectiveSourceUrl","effectiveThumbnailUrl"],"mappings":"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"}
|
|
@@ -638,7 +638,7 @@ function Qt({
|
|
|
638
638
|
const s = e == null ? void 0 : e.text, a = Xs(t);
|
|
639
639
|
return a ? ((r = e == null ? void 0 : e.i18n) == null ? void 0 : r[`${a}_text`]) ?? s : s;
|
|
640
640
|
}
|
|
641
|
-
const Ks = F.lazy(() => import("./Card-
|
|
641
|
+
const Ks = F.lazy(() => import("./Card-BkToB7yL.js")), Js = F.lazy(() => import("./Card-DbdWoTwf.js")), Zs = F.lazy(() => import("./Card-CKV0d2i9.js")), Qe = () => /* @__PURE__ */ n(
|
|
642
642
|
"div",
|
|
643
643
|
{
|
|
644
644
|
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)]",
|
|
@@ -1039,7 +1039,7 @@ const ia = (e) => {
|
|
|
1039
1039
|
"data-testid": m,
|
|
1040
1040
|
className: k(
|
|
1041
1041
|
"relative w-[280px] select-none overflow-hidden rounded-[24px] shadow-[0_0_0_1px_rgba(0,0,0,0.04),0_4px_8px_rgba(0,0,0,0.06)]",
|
|
1042
|
-
f ? "bg-[#
|
|
1042
|
+
f ? "bg-[#1e2330]" : "bg-white"
|
|
1043
1043
|
),
|
|
1044
1044
|
children: [
|
|
1045
1045
|
d ? /* @__PURE__ */ n("div", { className: "pointer-events-auto absolute left-3 top-3 z-50", children: d }) : null,
|
|
@@ -1087,7 +1087,7 @@ function rn(e) {
|
|
|
1087
1087
|
return e < 1024 ? `${e} B` : e < 1024 * 1024 ? `${(e / 1024).toFixed(1)} KB` : `${(e / (1024 * 1024)).toFixed(1)} MB`;
|
|
1088
1088
|
}
|
|
1089
1089
|
function et(e) {
|
|
1090
|
-
return `w-[280px] select-none overflow-hidden rounded-[24px] ${e ? "bg-[#
|
|
1090
|
+
return `w-[280px] select-none overflow-hidden rounded-[24px] ${e ? "bg-[#1e2330]" : "bg-[#F3F3F1]"} shadow-[0_0_0_1px_rgba(0,0,0,0.04),0_4px_8px_rgba(0,0,0,0.06)]`;
|
|
1091
1091
|
}
|
|
1092
1092
|
function ca(e) {
|
|
1093
1093
|
return e ? "bg-white/10" : "bg-black/5";
|
|
@@ -1692,7 +1692,7 @@ const _a = ({ size: e = 15 }) => /* @__PURE__ */ n(
|
|
|
1692
1692
|
href: s,
|
|
1693
1693
|
target: "_blank",
|
|
1694
1694
|
rel: "noopener noreferrer",
|
|
1695
|
-
className: "relative block w-full rounded-[24px] bg-[#
|
|
1695
|
+
className: "relative block w-full rounded-[24px] bg-[#1e2330] p-2 no-underline transition-opacity hover:opacity-90",
|
|
1696
1696
|
children: [
|
|
1697
1697
|
r && /* @__PURE__ */ n(
|
|
1698
1698
|
"img",
|
|
@@ -3105,7 +3105,7 @@ const ur = {
|
|
|
3105
3105
|
}) => {
|
|
3106
3106
|
const u = s != null || a != null, g = k(
|
|
3107
3107
|
pr,
|
|
3108
|
-
l ?? (e === "dark" ? "bg-[#
|
|
3108
|
+
l ?? (e === "dark" ? "bg-[#1e2330]" : "bg-white"),
|
|
3109
3109
|
// `focus-ring` is a design-system utility from the component-library
|
|
3110
3110
|
// tailwind preset — outline-none + a black 2px focus-visible ring
|
|
3111
3111
|
// with offset, so keyboard users can see the focused card.
|
|
@@ -3408,7 +3408,7 @@ const ur = {
|
|
|
3408
3408
|
Sent: Nr,
|
|
3409
3409
|
Received: wr
|
|
3410
3410
|
}, _r = {
|
|
3411
|
-
dark: "bg-[#
|
|
3411
|
+
dark: "bg-[#1e2330]",
|
|
3412
3412
|
light: "bg-[#e9eaed]"
|
|
3413
3413
|
}, yr = {
|
|
3414
3414
|
dark: "text-white",
|
|
@@ -4664,4 +4664,4 @@ export {
|
|
|
4664
4664
|
st as y,
|
|
4665
4665
|
Zt as z
|
|
4666
4666
|
};
|
|
4667
|
-
//# sourceMappingURL=index-
|
|
4667
|
+
//# sourceMappingURL=index-B7fsmwKg.js.map
|