@medialane/ui 0.310.0 → 0.312.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/activity-card.cjs +2 -2
- package/dist/components/activity-card.cjs.map +1 -1
- package/dist/components/activity-card.js +2 -2
- package/dist/components/activity-card.js.map +1 -1
- package/dist/components/animated-token-media.cjs +2 -2
- package/dist/components/animated-token-media.cjs.map +1 -1
- package/dist/components/animated-token-media.js +2 -2
- package/dist/components/animated-token-media.js.map +1 -1
- package/dist/components/asset-card.cjs +1 -1
- package/dist/components/asset-card.cjs.map +1 -1
- package/dist/components/asset-card.js +1 -1
- package/dist/components/asset-card.js.map +1 -1
- package/dist/components/badge.d.cts +1 -1
- package/dist/components/badge.d.ts +1 -1
- package/dist/components/button.d.cts +1 -1
- package/dist/components/button.d.ts +1 -1
- package/dist/components/collection-card.cjs +1 -1
- package/dist/components/collection-card.cjs.map +1 -1
- package/dist/components/collection-card.js +1 -1
- package/dist/components/collection-card.js.map +1 -1
- package/dist/components/creators-page.cjs +2 -2
- package/dist/components/creators-page.cjs.map +1 -1
- package/dist/components/creators-page.js +2 -2
- package/dist/components/creators-page.js.map +1 -1
- package/dist/components/drop/drop-card.cjs +1 -1
- package/dist/components/drop/drop-card.cjs.map +1 -1
- package/dist/components/drop/drop-card.js +1 -1
- package/dist/components/drop/drop-card.js.map +1 -1
- package/dist/components/editions-page.cjs +1 -1
- package/dist/components/editions-page.cjs.map +1 -1
- package/dist/components/editions-page.js +1 -1
- package/dist/components/editions-page.js.map +1 -1
- package/dist/components/launchpad/edition-mint-schema.d.cts +19 -19
- package/dist/components/launchpad/edition-mint-schema.d.ts +19 -19
- package/dist/components/launchpad/pop-create-schema.d.cts +10 -10
- package/dist/components/launchpad/pop-create-schema.d.ts +10 -10
- package/dist/components/listing-card.cjs +4 -4
- package/dist/components/listing-card.cjs.map +1 -1
- package/dist/components/listing-card.js +4 -4
- package/dist/components/listing-card.js.map +1 -1
- package/dist/components/media-wallet/media-wallet-send.cjs +2 -5
- package/dist/components/media-wallet/media-wallet-send.cjs.map +1 -1
- package/dist/components/media-wallet/media-wallet-send.js +2 -5
- package/dist/components/media-wallet/media-wallet-send.js.map +1 -1
- package/dist/components/media-wallet/nft-strip.cjs +1 -1
- package/dist/components/media-wallet/nft-strip.cjs.map +1 -1
- package/dist/components/media-wallet/nft-strip.js +1 -1
- package/dist/components/media-wallet/nft-strip.js.map +1 -1
- package/dist/components/remix-browse-page.cjs +1 -1
- package/dist/components/remix-browse-page.cjs.map +1 -1
- package/dist/components/remix-browse-page.js +1 -1
- package/dist/components/remix-browse-page.js.map +1 -1
- package/dist/components/token-card.cjs +1 -1
- package/dist/components/token-card.cjs.map +1 -1
- package/dist/components/token-card.js +1 -1
- package/dist/components/token-card.js.map +1 -1
- package/dist/components/transfer-collection-ownership.cjs +1 -1
- package/dist/components/transfer-collection-ownership.cjs.map +1 -1
- package/dist/components/transfer-collection-ownership.js +1 -1
- package/dist/components/transfer-collection-ownership.js.map +1 -1
- package/dist/index.d.cts +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/medialane.css +7 -0
- package/dist/utils/send-token.cjs +40 -0
- package/dist/utils/send-token.cjs.map +1 -0
- package/dist/utils/send-token.d.cts +19 -0
- package/dist/utils/send-token.d.ts +19 -0
- package/dist/utils/send-token.js +16 -0
- package/dist/utils/send-token.js.map +1 -0
- package/dist/utils/use-collection-settings.d.cts +19 -19
- package/dist/utils/use-collection-settings.d.ts +19 -19
- package/dist/utils/use-collections.d.cts +212 -205
- package/dist/utils/use-collections.d.ts +212 -205
- package/dist/utils/use-orders.d.cts +299 -299
- package/dist/utils/use-orders.d.ts +299 -299
- package/dist/utils/use-pop.d.cts +57 -55
- package/dist/utils/use-pop.d.ts +57 -55
- package/dist/utils/use-tiers.d.cts +76 -73
- package/dist/utils/use-tiers.d.ts +76 -73
- package/dist/utils/use-tokens-by-ip-type.d.cts +78 -77
- package/dist/utils/use-tokens-by-ip-type.d.ts +78 -77
- package/dist/utils/use-tokens.d.cts +234 -229
- package/dist/utils/use-tokens.d.ts +234 -229
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/remix-browse-page.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport Link from \"./link.js\";\nimport Image from \"./image.js\";\nimport { ServiceHeader } from \"./service-header.js\";\nimport { BackButton } from \"./back-button.js\";\nimport { FadeIn, Stagger, StaggerItem } from \"./motion-primitives.js\";\nimport { Skeleton } from \"./skeleton.js\";\nimport { Button } from \"./button.js\";\nimport { useMedialaneClient } from \"../utils/use-medialane-client.js\";\nimport { useImageUrl } from \"../utils/use-image-url.js\";\nimport type { ApiToken } from \"@medialane/sdk\";\nimport { GitBranch, ImageIcon, Inbox } from \"lucide-react\";\n\nconst PAGE_SIZE = 24;\n\nfunction useRemixableTokens() {\n const client = useMedialaneClient();\n const [tokens, setTokens] = useState<ApiToken[]>([]);\n const [page, setPage] = useState(1);\n const [isLoading, setIsLoading] = useState(true);\n const [hasMore, setHasMore] = useState(false);\n const [error, setError] = useState(false);\n\n useEffect(() => {\n let cancelled = false;\n setIsLoading(true);\n client.api.tokens.list({ derivatives: \"allowed\", limit: PAGE_SIZE, page })\n .then((json) => {\n if (cancelled) return;\n setTokens((prev) => (page === 1 ? json.data : [...prev, ...json.data]));\n setHasMore(page * PAGE_SIZE < (json.meta?.total ?? 0));\n })\n .catch(() => { if (!cancelled) setError(true); })\n .finally(() => { if (!cancelled) setIsLoading(false); });\n return () => { cancelled = true; };\n }, [client, page]);\n\n return { tokens, isLoading, hasMore, error, loadMore: () => setPage((p) => p + 1) };\n}\n\nfunction RemixableCard({ token }: { token: ApiToken }) {\n const [imgError, setImgError] = useState(false);\n const imageUrl = useImageUrl()(token.metadata?.image, { width: 480 });\n const showImage = imageUrl && !imgError;\n const name = token.metadata?.name ?? `#${token.tokenId}`;\n\n return (\n <Link\n href={`/create/remix/${token.contractAddress}/${token.tokenId}`}\n className=\"group flex flex-col rounded-2xl border border-border/60 bg-card overflow-hidden transition-colors sm:hover:border-brand-blue/50 active:scale-[0.99] motion-reduce:transform-none\"\n >\n <div className=\"relative aspect-square bg-muted overflow-hidden\">\n {showImage ? (\n <Image\n src={imageUrl}\n alt={name}\n fill\n className=\"object-cover\"\n onError={() => setImgError(true)}\n unoptimized\n />\n ) : (\n <div className=\"absolute inset-0 flex items-center justify-center\">\n <ImageIcon className=\"h-8 w-8 text-muted-foreground/30\" />\n </div>\n )}\n </div>\n <div className=\"p-4 space-y-1\">\n <p className=\"font-semibold text-sm leading-tight truncate\">{name}</p>\n <p className=\"text-xs text-muted-foreground\">\n Derivatives: Allowed\n </p>\n <p className=\"text-xs font-semibold pt-1 inline-flex items-center gap-1.5\">\n <GitBranch className=\"h-3 w-3\" />\n Remix this work\n </p>\n </div>\n </Link>\n );\n}\n\nfunction RemixableCardSkeleton() {\n return (\n <div className=\"rounded-2xl border border-border/40 overflow-hidden\">\n <Skeleton className=\"aspect-square rounded-none\" />\n <div className=\"p-4 space-y-2\">\n <Skeleton className=\"h-4 w-32\" />\n <Skeleton className=\"h-3 w-24\" />\n </div>\n </div>\n );\n}\n\nexport function RemixBrowsePage() {\n const { tokens, isLoading, hasMore, error, loadMore } = useRemixableTokens();\n\n return (\n <div className=\"pb-16\">\n <section className=\"px-4 pt-10 max-w-5xl mx-auto\">\n <BackButton />\n <FadeIn>\n <div className=\"mt-6\">\n <ServiceHeader\n plain\n icon={<GitBranch className=\"h-4 w-4 text-white\" />}\n title=\"Remix\"\n subtitle=\"Pick a work that is open to remixing. Attribution and royalties flow back to the original creator.\"\n />\n </div>\n </FadeIn>\n </section>\n\n <section className=\"px-4 pt-8 max-w-5xl mx-auto space-y-6\">\n {isLoading && tokens.length === 0 ? (\n <div className=\"grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-4\">\n {Array.from({ length: 8 }).map((_, i) => (\n <RemixableCardSkeleton key={i} />\n ))}\n </div>\n ) : error && tokens.length === 0 ? (\n <div className=\"bento-cell p-10 flex flex-col items-center gap-3 text-center\">\n <p className=\"font-semibold\">Could not load works</p>\n <p className=\"text-sm text-muted-foreground\">Check your connection and try again.</p>\n <Button variant=\"outline\" size=\"sm\" onClick={() => location.reload()}>Retry</Button>\n </div>\n ) : tokens.length === 0 ? (\n <FadeIn>\n <div className=\"bento-cell p-10 flex flex-col items-center gap-4 text-center\">\n <Inbox className=\"h-10 w-10 text-muted-foreground/30\" />\n <div>\n <p className=\"font-semibold\">No works open to remixing yet</p>\n <p className=\"text-sm text-muted-foreground mt-1 max-w-sm\">\n Works appear here when their creator sets the license to allow derivatives.\n </p>\n </div>\n </div>\n </FadeIn>\n ) : (\n <>\n <Stagger className=\"grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-4\">\n {tokens.map((t) => (\n <StaggerItem key={`${t.contractAddress}-${t.tokenId}`}>\n <RemixableCard token={t} />\n </StaggerItem>\n ))}\n </Stagger>\n {hasMore && (\n <div className=\"flex justify-center\">\n <Button variant=\"outline\" onClick={loadMore} disabled={isLoading}>\n {isLoading ? \"Loading…\" : \"Load more\"}\n </Button>\n </div>\n )}\n </>\n )}\n </section>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/components/remix-browse-page.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport Link from \"./link.js\";\nimport Image from \"./image.js\";\nimport { ServiceHeader } from \"./service-header.js\";\nimport { BackButton } from \"./back-button.js\";\nimport { FadeIn, Stagger, StaggerItem } from \"./motion-primitives.js\";\nimport { Skeleton } from \"./skeleton.js\";\nimport { Button } from \"./button.js\";\nimport { useMedialaneClient } from \"../utils/use-medialane-client.js\";\nimport { useImageUrl } from \"../utils/use-image-url.js\";\nimport type { ApiToken } from \"@medialane/sdk\";\nimport { GitBranch, ImageIcon, Inbox } from \"lucide-react\";\n\nconst PAGE_SIZE = 24;\n\nfunction useRemixableTokens() {\n const client = useMedialaneClient();\n const [tokens, setTokens] = useState<ApiToken[]>([]);\n const [page, setPage] = useState(1);\n const [isLoading, setIsLoading] = useState(true);\n const [hasMore, setHasMore] = useState(false);\n const [error, setError] = useState(false);\n\n useEffect(() => {\n let cancelled = false;\n setIsLoading(true);\n client.api.tokens.list({ derivatives: \"allowed\", limit: PAGE_SIZE, page })\n .then((json) => {\n if (cancelled) return;\n setTokens((prev) => (page === 1 ? json.data : [...prev, ...json.data]));\n setHasMore(page * PAGE_SIZE < (json.meta?.total ?? 0));\n })\n .catch(() => { if (!cancelled) setError(true); })\n .finally(() => { if (!cancelled) setIsLoading(false); });\n return () => { cancelled = true; };\n }, [client, page]);\n\n return { tokens, isLoading, hasMore, error, loadMore: () => setPage((p) => p + 1) };\n}\n\nfunction RemixableCard({ token }: { token: ApiToken }) {\n const [imgError, setImgError] = useState(false);\n const imageUrl = useImageUrl()(token.metadata?.image, { width: 480 });\n const showImage = imageUrl && !imgError;\n const name = token.metadata?.name ?? `#${token.tokenId}`;\n\n return (\n <Link\n href={`/create/remix/${token.contractAddress}/${token.tokenId}`}\n className=\"group flex flex-col rounded-2xl border border-border/60 bg-card overflow-hidden transition-colors sm:hover:border-brand-blue/50 active:scale-[0.99] motion-reduce:transform-none\"\n >\n <div className=\"relative aspect-square bg-muted overflow-hidden\">\n {showImage ? (\n <Image\n src={imageUrl}\n alt={name}\n fill\n className=\"object-cover card-media\"\n onError={() => setImgError(true)}\n unoptimized\n />\n ) : (\n <div className=\"absolute inset-0 flex items-center justify-center\">\n <ImageIcon className=\"h-8 w-8 text-muted-foreground/30\" />\n </div>\n )}\n </div>\n <div className=\"p-4 space-y-1\">\n <p className=\"font-semibold text-sm leading-tight truncate\">{name}</p>\n <p className=\"text-xs text-muted-foreground\">\n Derivatives: Allowed\n </p>\n <p className=\"text-xs font-semibold pt-1 inline-flex items-center gap-1.5\">\n <GitBranch className=\"h-3 w-3\" />\n Remix this work\n </p>\n </div>\n </Link>\n );\n}\n\nfunction RemixableCardSkeleton() {\n return (\n <div className=\"rounded-2xl border border-border/40 overflow-hidden\">\n <Skeleton className=\"aspect-square rounded-none\" />\n <div className=\"p-4 space-y-2\">\n <Skeleton className=\"h-4 w-32\" />\n <Skeleton className=\"h-3 w-24\" />\n </div>\n </div>\n );\n}\n\nexport function RemixBrowsePage() {\n const { tokens, isLoading, hasMore, error, loadMore } = useRemixableTokens();\n\n return (\n <div className=\"pb-16\">\n <section className=\"px-4 pt-10 max-w-5xl mx-auto\">\n <BackButton />\n <FadeIn>\n <div className=\"mt-6\">\n <ServiceHeader\n plain\n icon={<GitBranch className=\"h-4 w-4 text-white\" />}\n title=\"Remix\"\n subtitle=\"Pick a work that is open to remixing. Attribution and royalties flow back to the original creator.\"\n />\n </div>\n </FadeIn>\n </section>\n\n <section className=\"px-4 pt-8 max-w-5xl mx-auto space-y-6\">\n {isLoading && tokens.length === 0 ? (\n <div className=\"grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-4\">\n {Array.from({ length: 8 }).map((_, i) => (\n <RemixableCardSkeleton key={i} />\n ))}\n </div>\n ) : error && tokens.length === 0 ? (\n <div className=\"bento-cell p-10 flex flex-col items-center gap-3 text-center\">\n <p className=\"font-semibold\">Could not load works</p>\n <p className=\"text-sm text-muted-foreground\">Check your connection and try again.</p>\n <Button variant=\"outline\" size=\"sm\" onClick={() => location.reload()}>Retry</Button>\n </div>\n ) : tokens.length === 0 ? (\n <FadeIn>\n <div className=\"bento-cell p-10 flex flex-col items-center gap-4 text-center\">\n <Inbox className=\"h-10 w-10 text-muted-foreground/30\" />\n <div>\n <p className=\"font-semibold\">No works open to remixing yet</p>\n <p className=\"text-sm text-muted-foreground mt-1 max-w-sm\">\n Works appear here when their creator sets the license to allow derivatives.\n </p>\n </div>\n </div>\n </FadeIn>\n ) : (\n <>\n <Stagger className=\"grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-4\">\n {tokens.map((t) => (\n <StaggerItem key={`${t.contractAddress}-${t.tokenId}`}>\n <RemixableCard token={t} />\n </StaggerItem>\n ))}\n </Stagger>\n {hasMore && (\n <div className=\"flex justify-center\">\n <Button variant=\"outline\" onClick={loadMore} disabled={isLoading}>\n {isLoading ? \"Loading…\" : \"Load more\"}\n </Button>\n </div>\n )}\n </>\n )}\n </section>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -85,7 +85,7 @@ function TokenCard({
|
|
|
85
85
|
e.stopPropagation();
|
|
86
86
|
onOffer?.(token);
|
|
87
87
|
};
|
|
88
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "card-base relative overflow-hidden flex flex-col w-full", children: [
|
|
88
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "card-base group relative overflow-hidden flex flex-col w-full", children: [
|
|
89
89
|
ipType && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "absolute top-2 right-2 z-10", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ip_type_badge.IpTypeBadge, { ipType, size: "sm" }) }),
|
|
90
90
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_link.default, { href: assetHref, className: "flex flex-col flex-1", children: [
|
|
91
91
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "relative aspect-square bg-muted overflow-hidden shrink-0", children: [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/token-card.tsx"],"sourcesContent":["\"use client\";\n\nimport Link from \"./link.js\";\nimport {\n Loader2, ArrowUpRight, MoreHorizontal, Zap, HandCoins, Tag,\n Layers, GitBranch, Flag, UserCircle2, ArrowRightLeft, XCircle,\n} from \"lucide-react\";\nimport {\n DropdownMenu, DropdownMenuContent, DropdownMenuItem,\n DropdownMenuSeparator, DropdownMenuTrigger,\n} from \"./dropdown-menu.js\";\nimport { cn } from \"../utils/cn.js\";\nimport { formatDisplayPrice } from \"../utils/format.js\";\nimport { CurrencyIcon } from \"./currency-icon.js\";\nimport { PriceChipContent } from \"./dual-price.js\";\nimport { IpTypeBadge } from \"./ip-type-badge.js\";\nimport { AnimatedTokenMedia } from \"./animated-token-media.js\";\nimport { isLivingRenderCollection } from \"../data/living-render-collections.js\";\nimport { assetHref as buildAssetHref, collectionHref as buildCollectionHref } from \"@medialane/sdk\";\nimport type { ApiToken, Chain } from \"@medialane/sdk\";\nimport { tokenProfileLink } from \"../utils/token-profile-link.js\";\nimport { useImageUrl } from \"../utils/use-image-url.js\";\n\n\nconst BTN_BASE = \"h-8 rounded-[9px] flex items-center justify-center gap-1.5 text-xs font-semibold transition-all active:scale-[0.98] shadow-none border-0\";\nconst BTN_OUTLINE = cn(BTN_BASE, \"border border-border/60 text-foreground hover:bg-muted/60\");\n\nexport interface TokenCardProps {\n token: ApiToken;\n isOwner?: boolean;\n onList?: (token: ApiToken) => void;\n onTransfer?: (token: ApiToken) => void;\n onCancel?: (token: ApiToken) => void;\n onBuy?: (token: ApiToken) => void;\n onOffer?: (token: ApiToken) => void;\n onReport?: (token: ApiToken) => void;\n\n usdValue?: string | null;\n}\n\nexport function TokenCard({\n token,\n isOwner = false,\n onList,\n onTransfer,\n onCancel,\n onBuy,\n onOffer,\n onReport,\n usdValue,\n}: TokenCardProps) {\n const resolveImage = useImageUrl();\n const name = token.metadata?.name || `Token #${token.tokenId}`;\n const image = resolveImage(token.metadata?.image, { width: 480 });\n const animationUrl = token.metadata?.animationUrl ?? null;\n const ipType = token.metadata?.ipType;\n\n const listingOrder = token.activeOrders?.find(\n (o) => o.offer.itemType === \"ERC721\" || o.offer.itemType === \"ERC1155\"\n );\n\n const profileLink = tokenProfileLink(token);\n const hasPrimaryAction = isOwner ? !listingOrder : listingOrder ? !!onBuy : !!onOffer;\n\n const chain = token.chain.toUpperCase() as Chain;\n const live = isLivingRenderCollection(chain, token.contractAddress);\n const assetHref = buildAssetHref(chain, token.contractAddress, token.tokenId);\n const collectionHref = buildCollectionHref(chain, token.contractAddress);\n const remixHref = `/create/remix/${token.contractAddress}/${token.tokenId}`;\n\n const handleBuy = (e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n onBuy?.(token);\n };\n\n const handleOffer = (e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n onOffer?.(token);\n };\n\n return (\n <div className=\"card-base relative overflow-hidden flex flex-col w-full\">\n {ipType && (\n <div className=\"absolute top-2 right-2 z-10\">\n <IpTypeBadge ipType={ipType as any} size=\"sm\" />\n </div>\n )}\n\n <Link href={assetHref} className=\"flex flex-col flex-1\">\n\n <div className=\"relative aspect-square bg-muted overflow-hidden shrink-0\">\n <AnimatedTokenMedia\n image={image}\n animationUrl={animationUrl}\n live={live}\n alt={name}\n mode=\"fill\"\n sizes=\"(max-width: 640px) 50vw, (max-width: 1024px) 33vw, 22vw\"\n className=\"object-cover\"\n fallback={\n <div className=\"absolute inset-0 bg-gradient-to-br from-brand-purple/15 to-brand-blue/15\" />\n }\n />\n\n {listingOrder && (\n <div className=\"absolute bottom-2 right-2 z-10\">\n <span className=\"inline-flex items-center gap-1.5 px-2.5 py-1.5 rounded-full text-sm font-bold bg-background/90 backdrop-blur-sm border border-border/40 shadow-sm tabular-nums\">\n <PriceChipContent\n amountFormatted={listingOrder.price.formatted}\n currency={listingOrder.price.currency}\n usdValue={usdValue}\n tone=\"card\"\n />\n </span>\n </div>\n )}\n\n {(token.metadataStatus === \"PENDING\" || token.metadataStatus === \"FETCHING\") && (\n <div className=\"absolute bottom-0 inset-x-0 flex items-center justify-center gap-1.5 bg-black/50 backdrop-blur-sm py-1.5\">\n <Loader2 className=\"h-3 w-3 animate-spin text-white/70\" />\n <span className=\"text-2xs text-white/70\">Indexing…</span>\n </div>\n )}\n </div>\n\n <div className=\"px-3 pt-2.5 pb-4 flex-1\">\n <p className=\"text-base font-bold line-clamp-2 leading-snug\">{name}</p>\n </div>\n </Link>\n\n <div className=\"px-3 pb-3 flex items-center gap-1.5\">\n\n <Link href={assetHref} className={cn(BTN_OUTLINE, \"px-2.5\", hasPrimaryAction ? \"shrink-0\" : \"flex-1\")}>\n <ArrowUpRight className=\"h-3.5 w-3.5\" />\n View\n </Link>\n\n {isOwner ? (\n !listingOrder ? (\n <button\n className={cn(BTN_OUTLINE, \"flex-1 text-brand-purple border-brand-purple/30 hover:bg-brand-purple/10 hover:text-brand-purple\")}\n onClick={(e) => { e.preventDefault(); e.stopPropagation(); onList?.(token); }}\n >\n <Tag className=\"h-3.5 w-3.5 mr-1.5\" />\n List\n </button>\n ) : null\n ) : listingOrder && onBuy ? (\n <div className=\"btn-border-animated p-[1.5px] rounded-[10px] flex-1 h-8\">\n <button\n className=\"w-full h-full rounded-[9px] bg-background flex items-center justify-center gap-1.5 text-xs font-semibold text-foreground hover:bg-muted/60 transition-all active:scale-[0.98]\"\n onClick={handleBuy}\n >\n <Zap className=\"h-3.5 w-3.5 shrink-0\" />\n Buy\n </button>\n </div>\n ) : !listingOrder && onOffer ? (\n <button\n className={cn(BTN_OUTLINE, \"flex-1 text-brand-orange border-brand-orange/30 hover:bg-brand-orange/10 hover:text-brand-orange\")}\n onClick={handleOffer}\n >\n <HandCoins className=\"h-3.5 w-3.5 mr-1.5\" />\n Offer\n </button>\n ) : null}\n\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <button\n className={cn(BTN_OUTLINE, \"w-8 p-0 shrink-0\")}\n aria-label=\"More actions\"\n >\n <MoreHorizontal className=\"h-3.5 w-3.5\" />\n </button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"w-52\">\n\n <DropdownMenuItem asChild>\n <Link href={assetHref} className=\"flex items-center gap-2\">\n <ArrowUpRight className=\"h-3.5 w-3.5 text-muted-foreground\" />\n View asset\n </Link>\n </DropdownMenuItem>\n\n <DropdownMenuSeparator />\n\n {isOwner ? (\n <>\n {!listingOrder && onList && (\n <DropdownMenuItem\n className=\"flex items-center gap-2 text-brand-purple focus:text-brand-purple\"\n onClick={() => onList(token)}\n >\n <Tag className=\"h-3.5 w-3.5\" />\n List\n </DropdownMenuItem>\n )}\n {onTransfer && (\n <DropdownMenuItem\n className=\"flex items-center gap-2\"\n onClick={() => onTransfer(token)}\n >\n <ArrowRightLeft className=\"h-3.5 w-3.5 text-muted-foreground\" />\n Transfer\n </DropdownMenuItem>\n )}\n {listingOrder && onCancel && (\n <DropdownMenuItem\n className=\"flex items-center gap-2 text-brand-orange focus:text-brand-orange\"\n onClick={() => onCancel(token)}\n >\n <XCircle className=\"h-3.5 w-3.5\" />\n Cancel listing\n </DropdownMenuItem>\n )}\n </>\n ) : (\n <>\n {listingOrder && onBuy && (\n <DropdownMenuItem\n className=\"flex items-center gap-2 text-brand-blue focus:text-brand-blue\"\n onClick={handleBuy}\n >\n <Zap className=\"h-3.5 w-3.5\" />\n <span className=\"flex items-center gap-1\">\n Buy —\n <CurrencyIcon symbol={listingOrder.price.currency} size={12} />\n {formatDisplayPrice(listingOrder.price.formatted)}\n </span>\n </DropdownMenuItem>\n )}\n {onOffer && (\n <DropdownMenuItem\n className=\"flex items-center gap-2 text-brand-orange focus:text-brand-orange\"\n onClick={handleOffer}\n >\n <HandCoins className=\"h-3.5 w-3.5\" />\n Make offer\n </DropdownMenuItem>\n )}\n </>\n )}\n\n <DropdownMenuItem asChild>\n <Link href={remixHref} className=\"flex items-center gap-2 text-brand-purple focus:text-brand-purple\">\n <GitBranch className=\"h-3.5 w-3.5\" />\n Remix\n </Link>\n </DropdownMenuItem>\n\n <DropdownMenuSeparator />\n\n <DropdownMenuItem asChild>\n <Link href={collectionHref} className=\"flex items-center gap-2\">\n <Layers className=\"h-3.5 w-3.5 text-muted-foreground\" />\n View collection\n </Link>\n </DropdownMenuItem>\n\n {profileLink && (\n <DropdownMenuItem asChild>\n <Link href={profileLink.href} className=\"flex items-center gap-2\">\n <UserCircle2 className=\"h-3.5 w-3.5 text-muted-foreground\" />\n {profileLink.label}\n </Link>\n </DropdownMenuItem>\n )}\n\n {onReport && (\n <>\n <DropdownMenuSeparator />\n <DropdownMenuItem\n className=\"flex items-center gap-2 text-muted-foreground focus:text-muted-foreground\"\n onClick={() => onReport(token)}\n >\n <Flag className=\"h-3.5 w-3.5\" />\n Report\n </DropdownMenuItem>\n </>\n )}\n\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n </div>\n );\n}\n\nexport function TokenCardSkeleton() {\n return (\n <div className=\"card-base overflow-hidden\">\n <div className=\"aspect-square w-full animate-pulse bg-muted\" />\n <div className=\"px-3 pt-2.5 pb-3 space-y-1.5\">\n <div className=\"h-4 w-3/4 rounded-md animate-pulse bg-muted\" />\n </div>\n <div className=\"px-3 pb-3 flex gap-1.5\">\n <div className=\"h-8 w-8 rounded-[9px] animate-pulse bg-muted shrink-0\" />\n <div className=\"h-8 flex-1 rounded-[9px] animate-pulse bg-muted\" />\n <div className=\"h-8 w-8 rounded-[9px] animate-pulse bg-muted shrink-0\" />\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":["buildAssetHref","buildCollectionHref","Link"]}
|
|
1
|
+
{"version":3,"sources":["../../src/components/token-card.tsx"],"sourcesContent":["\"use client\";\n\nimport Link from \"./link.js\";\nimport {\n Loader2, ArrowUpRight, MoreHorizontal, Zap, HandCoins, Tag,\n Layers, GitBranch, Flag, UserCircle2, ArrowRightLeft, XCircle,\n} from \"lucide-react\";\nimport {\n DropdownMenu, DropdownMenuContent, DropdownMenuItem,\n DropdownMenuSeparator, DropdownMenuTrigger,\n} from \"./dropdown-menu.js\";\nimport { cn } from \"../utils/cn.js\";\nimport { formatDisplayPrice } from \"../utils/format.js\";\nimport { CurrencyIcon } from \"./currency-icon.js\";\nimport { PriceChipContent } from \"./dual-price.js\";\nimport { IpTypeBadge } from \"./ip-type-badge.js\";\nimport { AnimatedTokenMedia } from \"./animated-token-media.js\";\nimport { isLivingRenderCollection } from \"../data/living-render-collections.js\";\nimport { assetHref as buildAssetHref, collectionHref as buildCollectionHref } from \"@medialane/sdk\";\nimport type { ApiToken, Chain } from \"@medialane/sdk\";\nimport { tokenProfileLink } from \"../utils/token-profile-link.js\";\nimport { useImageUrl } from \"../utils/use-image-url.js\";\n\n\nconst BTN_BASE = \"h-8 rounded-[9px] flex items-center justify-center gap-1.5 text-xs font-semibold transition-all active:scale-[0.98] shadow-none border-0\";\nconst BTN_OUTLINE = cn(BTN_BASE, \"border border-border/60 text-foreground hover:bg-muted/60\");\n\nexport interface TokenCardProps {\n token: ApiToken;\n isOwner?: boolean;\n onList?: (token: ApiToken) => void;\n onTransfer?: (token: ApiToken) => void;\n onCancel?: (token: ApiToken) => void;\n onBuy?: (token: ApiToken) => void;\n onOffer?: (token: ApiToken) => void;\n onReport?: (token: ApiToken) => void;\n\n usdValue?: string | null;\n}\n\nexport function TokenCard({\n token,\n isOwner = false,\n onList,\n onTransfer,\n onCancel,\n onBuy,\n onOffer,\n onReport,\n usdValue,\n}: TokenCardProps) {\n const resolveImage = useImageUrl();\n const name = token.metadata?.name || `Token #${token.tokenId}`;\n const image = resolveImage(token.metadata?.image, { width: 480 });\n const animationUrl = token.metadata?.animationUrl ?? null;\n const ipType = token.metadata?.ipType;\n\n const listingOrder = token.activeOrders?.find(\n (o) => o.offer.itemType === \"ERC721\" || o.offer.itemType === \"ERC1155\"\n );\n\n const profileLink = tokenProfileLink(token);\n const hasPrimaryAction = isOwner ? !listingOrder : listingOrder ? !!onBuy : !!onOffer;\n\n const chain = token.chain.toUpperCase() as Chain;\n const live = isLivingRenderCollection(chain, token.contractAddress);\n const assetHref = buildAssetHref(chain, token.contractAddress, token.tokenId);\n const collectionHref = buildCollectionHref(chain, token.contractAddress);\n const remixHref = `/create/remix/${token.contractAddress}/${token.tokenId}`;\n\n const handleBuy = (e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n onBuy?.(token);\n };\n\n const handleOffer = (e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n onOffer?.(token);\n };\n\n return (\n <div className=\"card-base group relative overflow-hidden flex flex-col w-full\">\n {ipType && (\n <div className=\"absolute top-2 right-2 z-10\">\n <IpTypeBadge ipType={ipType as any} size=\"sm\" />\n </div>\n )}\n\n <Link href={assetHref} className=\"flex flex-col flex-1\">\n\n <div className=\"relative aspect-square bg-muted overflow-hidden shrink-0\">\n <AnimatedTokenMedia\n image={image}\n animationUrl={animationUrl}\n live={live}\n alt={name}\n mode=\"fill\"\n sizes=\"(max-width: 640px) 50vw, (max-width: 1024px) 33vw, 22vw\"\n className=\"object-cover\"\n fallback={\n <div className=\"absolute inset-0 bg-gradient-to-br from-brand-purple/15 to-brand-blue/15\" />\n }\n />\n\n {listingOrder && (\n <div className=\"absolute bottom-2 right-2 z-10\">\n <span className=\"inline-flex items-center gap-1.5 px-2.5 py-1.5 rounded-full text-sm font-bold bg-background/90 backdrop-blur-sm border border-border/40 shadow-sm tabular-nums\">\n <PriceChipContent\n amountFormatted={listingOrder.price.formatted}\n currency={listingOrder.price.currency}\n usdValue={usdValue}\n tone=\"card\"\n />\n </span>\n </div>\n )}\n\n {(token.metadataStatus === \"PENDING\" || token.metadataStatus === \"FETCHING\") && (\n <div className=\"absolute bottom-0 inset-x-0 flex items-center justify-center gap-1.5 bg-black/50 backdrop-blur-sm py-1.5\">\n <Loader2 className=\"h-3 w-3 animate-spin text-white/70\" />\n <span className=\"text-2xs text-white/70\">Indexing…</span>\n </div>\n )}\n </div>\n\n <div className=\"px-3 pt-2.5 pb-4 flex-1\">\n <p className=\"text-base font-bold line-clamp-2 leading-snug\">{name}</p>\n </div>\n </Link>\n\n <div className=\"px-3 pb-3 flex items-center gap-1.5\">\n\n <Link href={assetHref} className={cn(BTN_OUTLINE, \"px-2.5\", hasPrimaryAction ? \"shrink-0\" : \"flex-1\")}>\n <ArrowUpRight className=\"h-3.5 w-3.5\" />\n View\n </Link>\n\n {isOwner ? (\n !listingOrder ? (\n <button\n className={cn(BTN_OUTLINE, \"flex-1 text-brand-purple border-brand-purple/30 hover:bg-brand-purple/10 hover:text-brand-purple\")}\n onClick={(e) => { e.preventDefault(); e.stopPropagation(); onList?.(token); }}\n >\n <Tag className=\"h-3.5 w-3.5 mr-1.5\" />\n List\n </button>\n ) : null\n ) : listingOrder && onBuy ? (\n <div className=\"btn-border-animated p-[1.5px] rounded-[10px] flex-1 h-8\">\n <button\n className=\"w-full h-full rounded-[9px] bg-background flex items-center justify-center gap-1.5 text-xs font-semibold text-foreground hover:bg-muted/60 transition-all active:scale-[0.98]\"\n onClick={handleBuy}\n >\n <Zap className=\"h-3.5 w-3.5 shrink-0\" />\n Buy\n </button>\n </div>\n ) : !listingOrder && onOffer ? (\n <button\n className={cn(BTN_OUTLINE, \"flex-1 text-brand-orange border-brand-orange/30 hover:bg-brand-orange/10 hover:text-brand-orange\")}\n onClick={handleOffer}\n >\n <HandCoins className=\"h-3.5 w-3.5 mr-1.5\" />\n Offer\n </button>\n ) : null}\n\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <button\n className={cn(BTN_OUTLINE, \"w-8 p-0 shrink-0\")}\n aria-label=\"More actions\"\n >\n <MoreHorizontal className=\"h-3.5 w-3.5\" />\n </button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"w-52\">\n\n <DropdownMenuItem asChild>\n <Link href={assetHref} className=\"flex items-center gap-2\">\n <ArrowUpRight className=\"h-3.5 w-3.5 text-muted-foreground\" />\n View asset\n </Link>\n </DropdownMenuItem>\n\n <DropdownMenuSeparator />\n\n {isOwner ? (\n <>\n {!listingOrder && onList && (\n <DropdownMenuItem\n className=\"flex items-center gap-2 text-brand-purple focus:text-brand-purple\"\n onClick={() => onList(token)}\n >\n <Tag className=\"h-3.5 w-3.5\" />\n List\n </DropdownMenuItem>\n )}\n {onTransfer && (\n <DropdownMenuItem\n className=\"flex items-center gap-2\"\n onClick={() => onTransfer(token)}\n >\n <ArrowRightLeft className=\"h-3.5 w-3.5 text-muted-foreground\" />\n Transfer\n </DropdownMenuItem>\n )}\n {listingOrder && onCancel && (\n <DropdownMenuItem\n className=\"flex items-center gap-2 text-brand-orange focus:text-brand-orange\"\n onClick={() => onCancel(token)}\n >\n <XCircle className=\"h-3.5 w-3.5\" />\n Cancel listing\n </DropdownMenuItem>\n )}\n </>\n ) : (\n <>\n {listingOrder && onBuy && (\n <DropdownMenuItem\n className=\"flex items-center gap-2 text-brand-blue focus:text-brand-blue\"\n onClick={handleBuy}\n >\n <Zap className=\"h-3.5 w-3.5\" />\n <span className=\"flex items-center gap-1\">\n Buy —\n <CurrencyIcon symbol={listingOrder.price.currency} size={12} />\n {formatDisplayPrice(listingOrder.price.formatted)}\n </span>\n </DropdownMenuItem>\n )}\n {onOffer && (\n <DropdownMenuItem\n className=\"flex items-center gap-2 text-brand-orange focus:text-brand-orange\"\n onClick={handleOffer}\n >\n <HandCoins className=\"h-3.5 w-3.5\" />\n Make offer\n </DropdownMenuItem>\n )}\n </>\n )}\n\n <DropdownMenuItem asChild>\n <Link href={remixHref} className=\"flex items-center gap-2 text-brand-purple focus:text-brand-purple\">\n <GitBranch className=\"h-3.5 w-3.5\" />\n Remix\n </Link>\n </DropdownMenuItem>\n\n <DropdownMenuSeparator />\n\n <DropdownMenuItem asChild>\n <Link href={collectionHref} className=\"flex items-center gap-2\">\n <Layers className=\"h-3.5 w-3.5 text-muted-foreground\" />\n View collection\n </Link>\n </DropdownMenuItem>\n\n {profileLink && (\n <DropdownMenuItem asChild>\n <Link href={profileLink.href} className=\"flex items-center gap-2\">\n <UserCircle2 className=\"h-3.5 w-3.5 text-muted-foreground\" />\n {profileLink.label}\n </Link>\n </DropdownMenuItem>\n )}\n\n {onReport && (\n <>\n <DropdownMenuSeparator />\n <DropdownMenuItem\n className=\"flex items-center gap-2 text-muted-foreground focus:text-muted-foreground\"\n onClick={() => onReport(token)}\n >\n <Flag className=\"h-3.5 w-3.5\" />\n Report\n </DropdownMenuItem>\n </>\n )}\n\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n </div>\n );\n}\n\nexport function TokenCardSkeleton() {\n return (\n <div className=\"card-base overflow-hidden\">\n <div className=\"aspect-square w-full animate-pulse bg-muted\" />\n <div className=\"px-3 pt-2.5 pb-3 space-y-1.5\">\n <div className=\"h-4 w-3/4 rounded-md animate-pulse bg-muted\" />\n </div>\n <div className=\"px-3 pb-3 flex gap-1.5\">\n <div className=\"h-8 w-8 rounded-[9px] animate-pulse bg-muted shrink-0\" />\n <div className=\"h-8 flex-1 rounded-[9px] animate-pulse bg-muted\" />\n <div className=\"h-8 w-8 rounded-[9px] animate-pulse bg-muted shrink-0\" />\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":["buildAssetHref","buildCollectionHref","Link"]}
|
|
@@ -70,7 +70,7 @@ function TokenCard({
|
|
|
70
70
|
e.stopPropagation();
|
|
71
71
|
onOffer?.(token);
|
|
72
72
|
};
|
|
73
|
-
return /* @__PURE__ */ jsxs("div", { className: "card-base relative overflow-hidden flex flex-col w-full", children: [
|
|
73
|
+
return /* @__PURE__ */ jsxs("div", { className: "card-base group relative overflow-hidden flex flex-col w-full", children: [
|
|
74
74
|
ipType && /* @__PURE__ */ jsx("div", { className: "absolute top-2 right-2 z-10", children: /* @__PURE__ */ jsx(IpTypeBadge, { ipType, size: "sm" }) }),
|
|
75
75
|
/* @__PURE__ */ jsxs(Link, { href: assetHref, className: "flex flex-col flex-1", children: [
|
|
76
76
|
/* @__PURE__ */ jsxs("div", { className: "relative aspect-square bg-muted overflow-hidden shrink-0", children: [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/token-card.tsx"],"sourcesContent":["\"use client\";\n\nimport Link from \"./link.js\";\nimport {\n Loader2, ArrowUpRight, MoreHorizontal, Zap, HandCoins, Tag,\n Layers, GitBranch, Flag, UserCircle2, ArrowRightLeft, XCircle,\n} from \"lucide-react\";\nimport {\n DropdownMenu, DropdownMenuContent, DropdownMenuItem,\n DropdownMenuSeparator, DropdownMenuTrigger,\n} from \"./dropdown-menu.js\";\nimport { cn } from \"../utils/cn.js\";\nimport { formatDisplayPrice } from \"../utils/format.js\";\nimport { CurrencyIcon } from \"./currency-icon.js\";\nimport { PriceChipContent } from \"./dual-price.js\";\nimport { IpTypeBadge } from \"./ip-type-badge.js\";\nimport { AnimatedTokenMedia } from \"./animated-token-media.js\";\nimport { isLivingRenderCollection } from \"../data/living-render-collections.js\";\nimport { assetHref as buildAssetHref, collectionHref as buildCollectionHref } from \"@medialane/sdk\";\nimport type { ApiToken, Chain } from \"@medialane/sdk\";\nimport { tokenProfileLink } from \"../utils/token-profile-link.js\";\nimport { useImageUrl } from \"../utils/use-image-url.js\";\n\n\nconst BTN_BASE = \"h-8 rounded-[9px] flex items-center justify-center gap-1.5 text-xs font-semibold transition-all active:scale-[0.98] shadow-none border-0\";\nconst BTN_OUTLINE = cn(BTN_BASE, \"border border-border/60 text-foreground hover:bg-muted/60\");\n\nexport interface TokenCardProps {\n token: ApiToken;\n isOwner?: boolean;\n onList?: (token: ApiToken) => void;\n onTransfer?: (token: ApiToken) => void;\n onCancel?: (token: ApiToken) => void;\n onBuy?: (token: ApiToken) => void;\n onOffer?: (token: ApiToken) => void;\n onReport?: (token: ApiToken) => void;\n\n usdValue?: string | null;\n}\n\nexport function TokenCard({\n token,\n isOwner = false,\n onList,\n onTransfer,\n onCancel,\n onBuy,\n onOffer,\n onReport,\n usdValue,\n}: TokenCardProps) {\n const resolveImage = useImageUrl();\n const name = token.metadata?.name || `Token #${token.tokenId}`;\n const image = resolveImage(token.metadata?.image, { width: 480 });\n const animationUrl = token.metadata?.animationUrl ?? null;\n const ipType = token.metadata?.ipType;\n\n const listingOrder = token.activeOrders?.find(\n (o) => o.offer.itemType === \"ERC721\" || o.offer.itemType === \"ERC1155\"\n );\n\n const profileLink = tokenProfileLink(token);\n const hasPrimaryAction = isOwner ? !listingOrder : listingOrder ? !!onBuy : !!onOffer;\n\n const chain = token.chain.toUpperCase() as Chain;\n const live = isLivingRenderCollection(chain, token.contractAddress);\n const assetHref = buildAssetHref(chain, token.contractAddress, token.tokenId);\n const collectionHref = buildCollectionHref(chain, token.contractAddress);\n const remixHref = `/create/remix/${token.contractAddress}/${token.tokenId}`;\n\n const handleBuy = (e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n onBuy?.(token);\n };\n\n const handleOffer = (e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n onOffer?.(token);\n };\n\n return (\n <div className=\"card-base relative overflow-hidden flex flex-col w-full\">\n {ipType && (\n <div className=\"absolute top-2 right-2 z-10\">\n <IpTypeBadge ipType={ipType as any} size=\"sm\" />\n </div>\n )}\n\n <Link href={assetHref} className=\"flex flex-col flex-1\">\n\n <div className=\"relative aspect-square bg-muted overflow-hidden shrink-0\">\n <AnimatedTokenMedia\n image={image}\n animationUrl={animationUrl}\n live={live}\n alt={name}\n mode=\"fill\"\n sizes=\"(max-width: 640px) 50vw, (max-width: 1024px) 33vw, 22vw\"\n className=\"object-cover\"\n fallback={\n <div className=\"absolute inset-0 bg-gradient-to-br from-brand-purple/15 to-brand-blue/15\" />\n }\n />\n\n {listingOrder && (\n <div className=\"absolute bottom-2 right-2 z-10\">\n <span className=\"inline-flex items-center gap-1.5 px-2.5 py-1.5 rounded-full text-sm font-bold bg-background/90 backdrop-blur-sm border border-border/40 shadow-sm tabular-nums\">\n <PriceChipContent\n amountFormatted={listingOrder.price.formatted}\n currency={listingOrder.price.currency}\n usdValue={usdValue}\n tone=\"card\"\n />\n </span>\n </div>\n )}\n\n {(token.metadataStatus === \"PENDING\" || token.metadataStatus === \"FETCHING\") && (\n <div className=\"absolute bottom-0 inset-x-0 flex items-center justify-center gap-1.5 bg-black/50 backdrop-blur-sm py-1.5\">\n <Loader2 className=\"h-3 w-3 animate-spin text-white/70\" />\n <span className=\"text-2xs text-white/70\">Indexing…</span>\n </div>\n )}\n </div>\n\n <div className=\"px-3 pt-2.5 pb-4 flex-1\">\n <p className=\"text-base font-bold line-clamp-2 leading-snug\">{name}</p>\n </div>\n </Link>\n\n <div className=\"px-3 pb-3 flex items-center gap-1.5\">\n\n <Link href={assetHref} className={cn(BTN_OUTLINE, \"px-2.5\", hasPrimaryAction ? \"shrink-0\" : \"flex-1\")}>\n <ArrowUpRight className=\"h-3.5 w-3.5\" />\n View\n </Link>\n\n {isOwner ? (\n !listingOrder ? (\n <button\n className={cn(BTN_OUTLINE, \"flex-1 text-brand-purple border-brand-purple/30 hover:bg-brand-purple/10 hover:text-brand-purple\")}\n onClick={(e) => { e.preventDefault(); e.stopPropagation(); onList?.(token); }}\n >\n <Tag className=\"h-3.5 w-3.5 mr-1.5\" />\n List\n </button>\n ) : null\n ) : listingOrder && onBuy ? (\n <div className=\"btn-border-animated p-[1.5px] rounded-[10px] flex-1 h-8\">\n <button\n className=\"w-full h-full rounded-[9px] bg-background flex items-center justify-center gap-1.5 text-xs font-semibold text-foreground hover:bg-muted/60 transition-all active:scale-[0.98]\"\n onClick={handleBuy}\n >\n <Zap className=\"h-3.5 w-3.5 shrink-0\" />\n Buy\n </button>\n </div>\n ) : !listingOrder && onOffer ? (\n <button\n className={cn(BTN_OUTLINE, \"flex-1 text-brand-orange border-brand-orange/30 hover:bg-brand-orange/10 hover:text-brand-orange\")}\n onClick={handleOffer}\n >\n <HandCoins className=\"h-3.5 w-3.5 mr-1.5\" />\n Offer\n </button>\n ) : null}\n\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <button\n className={cn(BTN_OUTLINE, \"w-8 p-0 shrink-0\")}\n aria-label=\"More actions\"\n >\n <MoreHorizontal className=\"h-3.5 w-3.5\" />\n </button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"w-52\">\n\n <DropdownMenuItem asChild>\n <Link href={assetHref} className=\"flex items-center gap-2\">\n <ArrowUpRight className=\"h-3.5 w-3.5 text-muted-foreground\" />\n View asset\n </Link>\n </DropdownMenuItem>\n\n <DropdownMenuSeparator />\n\n {isOwner ? (\n <>\n {!listingOrder && onList && (\n <DropdownMenuItem\n className=\"flex items-center gap-2 text-brand-purple focus:text-brand-purple\"\n onClick={() => onList(token)}\n >\n <Tag className=\"h-3.5 w-3.5\" />\n List\n </DropdownMenuItem>\n )}\n {onTransfer && (\n <DropdownMenuItem\n className=\"flex items-center gap-2\"\n onClick={() => onTransfer(token)}\n >\n <ArrowRightLeft className=\"h-3.5 w-3.5 text-muted-foreground\" />\n Transfer\n </DropdownMenuItem>\n )}\n {listingOrder && onCancel && (\n <DropdownMenuItem\n className=\"flex items-center gap-2 text-brand-orange focus:text-brand-orange\"\n onClick={() => onCancel(token)}\n >\n <XCircle className=\"h-3.5 w-3.5\" />\n Cancel listing\n </DropdownMenuItem>\n )}\n </>\n ) : (\n <>\n {listingOrder && onBuy && (\n <DropdownMenuItem\n className=\"flex items-center gap-2 text-brand-blue focus:text-brand-blue\"\n onClick={handleBuy}\n >\n <Zap className=\"h-3.5 w-3.5\" />\n <span className=\"flex items-center gap-1\">\n Buy —\n <CurrencyIcon symbol={listingOrder.price.currency} size={12} />\n {formatDisplayPrice(listingOrder.price.formatted)}\n </span>\n </DropdownMenuItem>\n )}\n {onOffer && (\n <DropdownMenuItem\n className=\"flex items-center gap-2 text-brand-orange focus:text-brand-orange\"\n onClick={handleOffer}\n >\n <HandCoins className=\"h-3.5 w-3.5\" />\n Make offer\n </DropdownMenuItem>\n )}\n </>\n )}\n\n <DropdownMenuItem asChild>\n <Link href={remixHref} className=\"flex items-center gap-2 text-brand-purple focus:text-brand-purple\">\n <GitBranch className=\"h-3.5 w-3.5\" />\n Remix\n </Link>\n </DropdownMenuItem>\n\n <DropdownMenuSeparator />\n\n <DropdownMenuItem asChild>\n <Link href={collectionHref} className=\"flex items-center gap-2\">\n <Layers className=\"h-3.5 w-3.5 text-muted-foreground\" />\n View collection\n </Link>\n </DropdownMenuItem>\n\n {profileLink && (\n <DropdownMenuItem asChild>\n <Link href={profileLink.href} className=\"flex items-center gap-2\">\n <UserCircle2 className=\"h-3.5 w-3.5 text-muted-foreground\" />\n {profileLink.label}\n </Link>\n </DropdownMenuItem>\n )}\n\n {onReport && (\n <>\n <DropdownMenuSeparator />\n <DropdownMenuItem\n className=\"flex items-center gap-2 text-muted-foreground focus:text-muted-foreground\"\n onClick={() => onReport(token)}\n >\n <Flag className=\"h-3.5 w-3.5\" />\n Report\n </DropdownMenuItem>\n </>\n )}\n\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n </div>\n );\n}\n\nexport function TokenCardSkeleton() {\n return (\n <div className=\"card-base overflow-hidden\">\n <div className=\"aspect-square w-full animate-pulse bg-muted\" />\n <div className=\"px-3 pt-2.5 pb-3 space-y-1.5\">\n <div className=\"h-4 w-3/4 rounded-md animate-pulse bg-muted\" />\n </div>\n <div className=\"px-3 pb-3 flex gap-1.5\">\n <div className=\"h-8 w-8 rounded-[9px] animate-pulse bg-muted shrink-0\" />\n <div className=\"h-8 flex-1 rounded-[9px] animate-pulse bg-muted\" />\n <div className=\"h-8 w-8 rounded-[9px] animate-pulse bg-muted shrink-0\" />\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/components/token-card.tsx"],"sourcesContent":["\"use client\";\n\nimport Link from \"./link.js\";\nimport {\n Loader2, ArrowUpRight, MoreHorizontal, Zap, HandCoins, Tag,\n Layers, GitBranch, Flag, UserCircle2, ArrowRightLeft, XCircle,\n} from \"lucide-react\";\nimport {\n DropdownMenu, DropdownMenuContent, DropdownMenuItem,\n DropdownMenuSeparator, DropdownMenuTrigger,\n} from \"./dropdown-menu.js\";\nimport { cn } from \"../utils/cn.js\";\nimport { formatDisplayPrice } from \"../utils/format.js\";\nimport { CurrencyIcon } from \"./currency-icon.js\";\nimport { PriceChipContent } from \"./dual-price.js\";\nimport { IpTypeBadge } from \"./ip-type-badge.js\";\nimport { AnimatedTokenMedia } from \"./animated-token-media.js\";\nimport { isLivingRenderCollection } from \"../data/living-render-collections.js\";\nimport { assetHref as buildAssetHref, collectionHref as buildCollectionHref } from \"@medialane/sdk\";\nimport type { ApiToken, Chain } from \"@medialane/sdk\";\nimport { tokenProfileLink } from \"../utils/token-profile-link.js\";\nimport { useImageUrl } from \"../utils/use-image-url.js\";\n\n\nconst BTN_BASE = \"h-8 rounded-[9px] flex items-center justify-center gap-1.5 text-xs font-semibold transition-all active:scale-[0.98] shadow-none border-0\";\nconst BTN_OUTLINE = cn(BTN_BASE, \"border border-border/60 text-foreground hover:bg-muted/60\");\n\nexport interface TokenCardProps {\n token: ApiToken;\n isOwner?: boolean;\n onList?: (token: ApiToken) => void;\n onTransfer?: (token: ApiToken) => void;\n onCancel?: (token: ApiToken) => void;\n onBuy?: (token: ApiToken) => void;\n onOffer?: (token: ApiToken) => void;\n onReport?: (token: ApiToken) => void;\n\n usdValue?: string | null;\n}\n\nexport function TokenCard({\n token,\n isOwner = false,\n onList,\n onTransfer,\n onCancel,\n onBuy,\n onOffer,\n onReport,\n usdValue,\n}: TokenCardProps) {\n const resolveImage = useImageUrl();\n const name = token.metadata?.name || `Token #${token.tokenId}`;\n const image = resolveImage(token.metadata?.image, { width: 480 });\n const animationUrl = token.metadata?.animationUrl ?? null;\n const ipType = token.metadata?.ipType;\n\n const listingOrder = token.activeOrders?.find(\n (o) => o.offer.itemType === \"ERC721\" || o.offer.itemType === \"ERC1155\"\n );\n\n const profileLink = tokenProfileLink(token);\n const hasPrimaryAction = isOwner ? !listingOrder : listingOrder ? !!onBuy : !!onOffer;\n\n const chain = token.chain.toUpperCase() as Chain;\n const live = isLivingRenderCollection(chain, token.contractAddress);\n const assetHref = buildAssetHref(chain, token.contractAddress, token.tokenId);\n const collectionHref = buildCollectionHref(chain, token.contractAddress);\n const remixHref = `/create/remix/${token.contractAddress}/${token.tokenId}`;\n\n const handleBuy = (e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n onBuy?.(token);\n };\n\n const handleOffer = (e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n onOffer?.(token);\n };\n\n return (\n <div className=\"card-base group relative overflow-hidden flex flex-col w-full\">\n {ipType && (\n <div className=\"absolute top-2 right-2 z-10\">\n <IpTypeBadge ipType={ipType as any} size=\"sm\" />\n </div>\n )}\n\n <Link href={assetHref} className=\"flex flex-col flex-1\">\n\n <div className=\"relative aspect-square bg-muted overflow-hidden shrink-0\">\n <AnimatedTokenMedia\n image={image}\n animationUrl={animationUrl}\n live={live}\n alt={name}\n mode=\"fill\"\n sizes=\"(max-width: 640px) 50vw, (max-width: 1024px) 33vw, 22vw\"\n className=\"object-cover\"\n fallback={\n <div className=\"absolute inset-0 bg-gradient-to-br from-brand-purple/15 to-brand-blue/15\" />\n }\n />\n\n {listingOrder && (\n <div className=\"absolute bottom-2 right-2 z-10\">\n <span className=\"inline-flex items-center gap-1.5 px-2.5 py-1.5 rounded-full text-sm font-bold bg-background/90 backdrop-blur-sm border border-border/40 shadow-sm tabular-nums\">\n <PriceChipContent\n amountFormatted={listingOrder.price.formatted}\n currency={listingOrder.price.currency}\n usdValue={usdValue}\n tone=\"card\"\n />\n </span>\n </div>\n )}\n\n {(token.metadataStatus === \"PENDING\" || token.metadataStatus === \"FETCHING\") && (\n <div className=\"absolute bottom-0 inset-x-0 flex items-center justify-center gap-1.5 bg-black/50 backdrop-blur-sm py-1.5\">\n <Loader2 className=\"h-3 w-3 animate-spin text-white/70\" />\n <span className=\"text-2xs text-white/70\">Indexing…</span>\n </div>\n )}\n </div>\n\n <div className=\"px-3 pt-2.5 pb-4 flex-1\">\n <p className=\"text-base font-bold line-clamp-2 leading-snug\">{name}</p>\n </div>\n </Link>\n\n <div className=\"px-3 pb-3 flex items-center gap-1.5\">\n\n <Link href={assetHref} className={cn(BTN_OUTLINE, \"px-2.5\", hasPrimaryAction ? \"shrink-0\" : \"flex-1\")}>\n <ArrowUpRight className=\"h-3.5 w-3.5\" />\n View\n </Link>\n\n {isOwner ? (\n !listingOrder ? (\n <button\n className={cn(BTN_OUTLINE, \"flex-1 text-brand-purple border-brand-purple/30 hover:bg-brand-purple/10 hover:text-brand-purple\")}\n onClick={(e) => { e.preventDefault(); e.stopPropagation(); onList?.(token); }}\n >\n <Tag className=\"h-3.5 w-3.5 mr-1.5\" />\n List\n </button>\n ) : null\n ) : listingOrder && onBuy ? (\n <div className=\"btn-border-animated p-[1.5px] rounded-[10px] flex-1 h-8\">\n <button\n className=\"w-full h-full rounded-[9px] bg-background flex items-center justify-center gap-1.5 text-xs font-semibold text-foreground hover:bg-muted/60 transition-all active:scale-[0.98]\"\n onClick={handleBuy}\n >\n <Zap className=\"h-3.5 w-3.5 shrink-0\" />\n Buy\n </button>\n </div>\n ) : !listingOrder && onOffer ? (\n <button\n className={cn(BTN_OUTLINE, \"flex-1 text-brand-orange border-brand-orange/30 hover:bg-brand-orange/10 hover:text-brand-orange\")}\n onClick={handleOffer}\n >\n <HandCoins className=\"h-3.5 w-3.5 mr-1.5\" />\n Offer\n </button>\n ) : null}\n\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <button\n className={cn(BTN_OUTLINE, \"w-8 p-0 shrink-0\")}\n aria-label=\"More actions\"\n >\n <MoreHorizontal className=\"h-3.5 w-3.5\" />\n </button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"w-52\">\n\n <DropdownMenuItem asChild>\n <Link href={assetHref} className=\"flex items-center gap-2\">\n <ArrowUpRight className=\"h-3.5 w-3.5 text-muted-foreground\" />\n View asset\n </Link>\n </DropdownMenuItem>\n\n <DropdownMenuSeparator />\n\n {isOwner ? (\n <>\n {!listingOrder && onList && (\n <DropdownMenuItem\n className=\"flex items-center gap-2 text-brand-purple focus:text-brand-purple\"\n onClick={() => onList(token)}\n >\n <Tag className=\"h-3.5 w-3.5\" />\n List\n </DropdownMenuItem>\n )}\n {onTransfer && (\n <DropdownMenuItem\n className=\"flex items-center gap-2\"\n onClick={() => onTransfer(token)}\n >\n <ArrowRightLeft className=\"h-3.5 w-3.5 text-muted-foreground\" />\n Transfer\n </DropdownMenuItem>\n )}\n {listingOrder && onCancel && (\n <DropdownMenuItem\n className=\"flex items-center gap-2 text-brand-orange focus:text-brand-orange\"\n onClick={() => onCancel(token)}\n >\n <XCircle className=\"h-3.5 w-3.5\" />\n Cancel listing\n </DropdownMenuItem>\n )}\n </>\n ) : (\n <>\n {listingOrder && onBuy && (\n <DropdownMenuItem\n className=\"flex items-center gap-2 text-brand-blue focus:text-brand-blue\"\n onClick={handleBuy}\n >\n <Zap className=\"h-3.5 w-3.5\" />\n <span className=\"flex items-center gap-1\">\n Buy —\n <CurrencyIcon symbol={listingOrder.price.currency} size={12} />\n {formatDisplayPrice(listingOrder.price.formatted)}\n </span>\n </DropdownMenuItem>\n )}\n {onOffer && (\n <DropdownMenuItem\n className=\"flex items-center gap-2 text-brand-orange focus:text-brand-orange\"\n onClick={handleOffer}\n >\n <HandCoins className=\"h-3.5 w-3.5\" />\n Make offer\n </DropdownMenuItem>\n )}\n </>\n )}\n\n <DropdownMenuItem asChild>\n <Link href={remixHref} className=\"flex items-center gap-2 text-brand-purple focus:text-brand-purple\">\n <GitBranch className=\"h-3.5 w-3.5\" />\n Remix\n </Link>\n </DropdownMenuItem>\n\n <DropdownMenuSeparator />\n\n <DropdownMenuItem asChild>\n <Link href={collectionHref} className=\"flex items-center gap-2\">\n <Layers className=\"h-3.5 w-3.5 text-muted-foreground\" />\n View collection\n </Link>\n </DropdownMenuItem>\n\n {profileLink && (\n <DropdownMenuItem asChild>\n <Link href={profileLink.href} className=\"flex items-center gap-2\">\n <UserCircle2 className=\"h-3.5 w-3.5 text-muted-foreground\" />\n {profileLink.label}\n </Link>\n </DropdownMenuItem>\n )}\n\n {onReport && (\n <>\n <DropdownMenuSeparator />\n <DropdownMenuItem\n className=\"flex items-center gap-2 text-muted-foreground focus:text-muted-foreground\"\n onClick={() => onReport(token)}\n >\n <Flag className=\"h-3.5 w-3.5\" />\n Report\n </DropdownMenuItem>\n </>\n )}\n\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n </div>\n );\n}\n\nexport function TokenCardSkeleton() {\n return (\n <div className=\"card-base overflow-hidden\">\n <div className=\"aspect-square w-full animate-pulse bg-muted\" />\n <div className=\"px-3 pt-2.5 pb-3 space-y-1.5\">\n <div className=\"h-4 w-3/4 rounded-md animate-pulse bg-muted\" />\n </div>\n <div className=\"px-3 pb-3 flex gap-1.5\">\n <div className=\"h-8 w-8 rounded-[9px] animate-pulse bg-muted shrink-0\" />\n <div className=\"h-8 flex-1 rounded-[9px] animate-pulse bg-muted\" />\n <div className=\"h-8 w-8 rounded-[9px] animate-pulse bg-muted shrink-0\" />\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -56,7 +56,7 @@ function TransferCollectionOwnership({ collectionId, currentOwner, collectionNam
|
|
|
56
56
|
void tx.run(async (signer) => {
|
|
57
57
|
await (0, import_run_intent_calls.runIntentCalls)(
|
|
58
58
|
signer,
|
|
59
|
-
() => app.getClient().
|
|
59
|
+
() => app.getClient().createIntent("transfer-collection-ownership", { owner: signer.address, collectionId: String(collectionId), newOwner: trimmed })
|
|
60
60
|
);
|
|
61
61
|
}).then((ok) => {
|
|
62
62
|
if (ok) onTransferred?.();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/transfer-collection-ownership.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport { UserRoundCog } from \"lucide-react\";\nimport { normalizeAddress } from \"@medialane/sdk\";\nimport { Button } from \"./button.js\";\nimport { Dialog, DialogContent, DialogDescription, DialogTitle } from \"./dialog.js\";\nimport { Input } from \"./input.js\";\nimport { Label } from \"./label.js\";\nimport { MarketplaceConfirmStep } from \"./marketplace-dialog-primitives.js\";\nimport { useMedialaneApp } from \"./medialane-app.js\";\nimport { TransactionDialog } from \"./transaction-dialog.js\";\nimport { TransactionSuccess } from \"./transaction-success.js\";\nimport { shortenAddress } from \"../utils/address.js\";\nimport { runIntentCalls } from \"../utils/run-intent-calls.js\";\nimport { successMessages } from \"../utils/success-messages.js\";\nimport { useTransaction } from \"../utils/use-transaction.js\";\n\nexport interface TransferCollectionOwnershipProps {\n collectionId: string;\n currentOwner: string;\n collectionName?: string | null;\n onTransferred?: () => void;\n}\n\nexport function TransferCollectionOwnership({ collectionId, currentOwner, collectionName, onTransferred }: TransferCollectionOwnershipProps) {\n const app = useMedialaneApp();\n const tx = useTransaction();\n const [open, setOpen] = useState(false);\n const [confirming, setConfirming] = useState(false);\n const [newOwner, setNewOwner] = useState(\"\");\n\n const trimmed = newOwner.trim();\n const isValid = /^0x[0-9a-fA-F]{1,64}$/.test(trimmed);\n const wouldNoop = isValid && normalizeAddress(\"STARKNET\", trimmed) === normalizeAddress(\"STARKNET\", currentOwner);\n\n const close = () => {\n setOpen(false);\n setConfirming(false);\n };\n\n const transfer = () => {\n close();\n void tx\n .run(async (signer) => {\n await runIntentCalls(signer, () =>\n app.getClient().
|
|
1
|
+
{"version":3,"sources":["../../src/components/transfer-collection-ownership.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport { UserRoundCog } from \"lucide-react\";\nimport { normalizeAddress } from \"@medialane/sdk\";\nimport { Button } from \"./button.js\";\nimport { Dialog, DialogContent, DialogDescription, DialogTitle } from \"./dialog.js\";\nimport { Input } from \"./input.js\";\nimport { Label } from \"./label.js\";\nimport { MarketplaceConfirmStep } from \"./marketplace-dialog-primitives.js\";\nimport { useMedialaneApp } from \"./medialane-app.js\";\nimport { TransactionDialog } from \"./transaction-dialog.js\";\nimport { TransactionSuccess } from \"./transaction-success.js\";\nimport { shortenAddress } from \"../utils/address.js\";\nimport { runIntentCalls } from \"../utils/run-intent-calls.js\";\nimport { successMessages } from \"../utils/success-messages.js\";\nimport { useTransaction } from \"../utils/use-transaction.js\";\n\nexport interface TransferCollectionOwnershipProps {\n collectionId: string;\n currentOwner: string;\n collectionName?: string | null;\n onTransferred?: () => void;\n}\n\nexport function TransferCollectionOwnership({ collectionId, currentOwner, collectionName, onTransferred }: TransferCollectionOwnershipProps) {\n const app = useMedialaneApp();\n const tx = useTransaction();\n const [open, setOpen] = useState(false);\n const [confirming, setConfirming] = useState(false);\n const [newOwner, setNewOwner] = useState(\"\");\n\n const trimmed = newOwner.trim();\n const isValid = /^0x[0-9a-fA-F]{1,64}$/.test(trimmed);\n const wouldNoop = isValid && normalizeAddress(\"STARKNET\", trimmed) === normalizeAddress(\"STARKNET\", currentOwner);\n\n const close = () => {\n setOpen(false);\n setConfirming(false);\n };\n\n const transfer = () => {\n close();\n void tx\n .run(async (signer) => {\n await runIntentCalls(signer, () =>\n app.getClient().createIntent(\"transfer-collection-ownership\", { owner: signer.address, collectionId: String(collectionId), newOwner: trimmed }),\n );\n })\n .then((ok) => {\n if (ok) onTransferred?.();\n });\n };\n\n return (\n <>\n <Button variant=\"outline\" size=\"sm\" className=\"gap-2\" onClick={() => { setNewOwner(\"\"); setOpen(true); }}>\n <UserRoundCog className=\"h-4 w-4\" />\n Transfer ownership\n </Button>\n\n <Dialog open={open} onOpenChange={(next) => { if (!next) close(); }}>\n <DialogContent className=\"max-w-[calc(100%-6px)] sm:max-w-md p-0 overflow-hidden gap-0 rounded-2xl\">\n <DialogTitle className=\"sr-only\">Transfer ownership of {collectionName ?? \"collection\"}</DialogTitle>\n <DialogDescription className=\"sr-only\">Transfer the on-chain owner of this collection. Existing tokens are unaffected.</DialogDescription>\n\n {confirming ? (\n <MarketplaceConfirmStep\n description={`Transfer ownership to ${shortenAddress(trimmed)}?`}\n secondaryLabel=\"Back\"\n onSecondary={() => setConfirming(false)}\n primaryLabel=\"Transfer ownership\"\n onPrimary={transfer}\n primaryIcon={<UserRoundCog className=\"h-4 w-4\" />}\n />\n ) : (\n <div className=\"p-6 space-y-4\">\n <div className=\"flex items-center gap-2\">\n <UserRoundCog className=\"h-5 w-5\" />\n <p className=\"font-bold text-lg\">Transfer collection ownership</p>\n </div>\n <p className=\"text-sm text-muted-foreground\">\n The new owner will control minting and future ownership transfers for this collection. Existing tokens are unaffected.\n </p>\n <div className=\"space-y-2\">\n <Label htmlFor=\"new-owner\">New owner address</Label>\n <Input\n id=\"new-owner\"\n placeholder=\"0x…\"\n value={newOwner}\n onChange={(e) => setNewOwner(e.target.value)}\n className=\"tabular-nums text-sm\"\n spellCheck={false}\n autoComplete=\"off\"\n />\n {trimmed && !isValid && <p className=\"text-xs text-red-500\">Not a valid Starknet address.</p>}\n {wouldNoop && <p className=\"text-xs text-amber-500\">This is already the current owner.</p>}\n </div>\n <div className=\"flex gap-2 pt-2\">\n <Button variant=\"ghost\" className=\"flex-1\" onClick={close}>\n Cancel\n </Button>\n <Button className=\"flex-1\" onClick={() => setConfirming(true)} disabled={!isValid || wouldNoop || !app.walletAddress}>\n Continue\n </Button>\n </div>\n </div>\n )}\n </DialogContent>\n </Dialog>\n\n <TransactionDialog tx={tx} title=\"Transfer ownership\" workingLabel=\"Transferring ownership…\" firstStepLabel=\"Prepare transfer\">\n <TransactionSuccess\n name={collectionName ?? \"Collection\"}\n {...successMessages.ownershipTransferred({ name: collectionName ?? \"the collection\", to: shortenAddress(trimmed) })}\n txHash={tx.txHash}\n actions={[{ label: \"Done\", onClick: tx.reset }]}\n />\n </TransactionDialog>\n </>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -33,7 +33,7 @@ function TransferCollectionOwnership({ collectionId, currentOwner, collectionNam
|
|
|
33
33
|
void tx.run(async (signer) => {
|
|
34
34
|
await runIntentCalls(
|
|
35
35
|
signer,
|
|
36
|
-
() => app.getClient().
|
|
36
|
+
() => app.getClient().createIntent("transfer-collection-ownership", { owner: signer.address, collectionId: String(collectionId), newOwner: trimmed })
|
|
37
37
|
);
|
|
38
38
|
}).then((ok) => {
|
|
39
39
|
if (ok) onTransferred?.();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/transfer-collection-ownership.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport { UserRoundCog } from \"lucide-react\";\nimport { normalizeAddress } from \"@medialane/sdk\";\nimport { Button } from \"./button.js\";\nimport { Dialog, DialogContent, DialogDescription, DialogTitle } from \"./dialog.js\";\nimport { Input } from \"./input.js\";\nimport { Label } from \"./label.js\";\nimport { MarketplaceConfirmStep } from \"./marketplace-dialog-primitives.js\";\nimport { useMedialaneApp } from \"./medialane-app.js\";\nimport { TransactionDialog } from \"./transaction-dialog.js\";\nimport { TransactionSuccess } from \"./transaction-success.js\";\nimport { shortenAddress } from \"../utils/address.js\";\nimport { runIntentCalls } from \"../utils/run-intent-calls.js\";\nimport { successMessages } from \"../utils/success-messages.js\";\nimport { useTransaction } from \"../utils/use-transaction.js\";\n\nexport interface TransferCollectionOwnershipProps {\n collectionId: string;\n currentOwner: string;\n collectionName?: string | null;\n onTransferred?: () => void;\n}\n\nexport function TransferCollectionOwnership({ collectionId, currentOwner, collectionName, onTransferred }: TransferCollectionOwnershipProps) {\n const app = useMedialaneApp();\n const tx = useTransaction();\n const [open, setOpen] = useState(false);\n const [confirming, setConfirming] = useState(false);\n const [newOwner, setNewOwner] = useState(\"\");\n\n const trimmed = newOwner.trim();\n const isValid = /^0x[0-9a-fA-F]{1,64}$/.test(trimmed);\n const wouldNoop = isValid && normalizeAddress(\"STARKNET\", trimmed) === normalizeAddress(\"STARKNET\", currentOwner);\n\n const close = () => {\n setOpen(false);\n setConfirming(false);\n };\n\n const transfer = () => {\n close();\n void tx\n .run(async (signer) => {\n await runIntentCalls(signer, () =>\n app.getClient().
|
|
1
|
+
{"version":3,"sources":["../../src/components/transfer-collection-ownership.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport { UserRoundCog } from \"lucide-react\";\nimport { normalizeAddress } from \"@medialane/sdk\";\nimport { Button } from \"./button.js\";\nimport { Dialog, DialogContent, DialogDescription, DialogTitle } from \"./dialog.js\";\nimport { Input } from \"./input.js\";\nimport { Label } from \"./label.js\";\nimport { MarketplaceConfirmStep } from \"./marketplace-dialog-primitives.js\";\nimport { useMedialaneApp } from \"./medialane-app.js\";\nimport { TransactionDialog } from \"./transaction-dialog.js\";\nimport { TransactionSuccess } from \"./transaction-success.js\";\nimport { shortenAddress } from \"../utils/address.js\";\nimport { runIntentCalls } from \"../utils/run-intent-calls.js\";\nimport { successMessages } from \"../utils/success-messages.js\";\nimport { useTransaction } from \"../utils/use-transaction.js\";\n\nexport interface TransferCollectionOwnershipProps {\n collectionId: string;\n currentOwner: string;\n collectionName?: string | null;\n onTransferred?: () => void;\n}\n\nexport function TransferCollectionOwnership({ collectionId, currentOwner, collectionName, onTransferred }: TransferCollectionOwnershipProps) {\n const app = useMedialaneApp();\n const tx = useTransaction();\n const [open, setOpen] = useState(false);\n const [confirming, setConfirming] = useState(false);\n const [newOwner, setNewOwner] = useState(\"\");\n\n const trimmed = newOwner.trim();\n const isValid = /^0x[0-9a-fA-F]{1,64}$/.test(trimmed);\n const wouldNoop = isValid && normalizeAddress(\"STARKNET\", trimmed) === normalizeAddress(\"STARKNET\", currentOwner);\n\n const close = () => {\n setOpen(false);\n setConfirming(false);\n };\n\n const transfer = () => {\n close();\n void tx\n .run(async (signer) => {\n await runIntentCalls(signer, () =>\n app.getClient().createIntent(\"transfer-collection-ownership\", { owner: signer.address, collectionId: String(collectionId), newOwner: trimmed }),\n );\n })\n .then((ok) => {\n if (ok) onTransferred?.();\n });\n };\n\n return (\n <>\n <Button variant=\"outline\" size=\"sm\" className=\"gap-2\" onClick={() => { setNewOwner(\"\"); setOpen(true); }}>\n <UserRoundCog className=\"h-4 w-4\" />\n Transfer ownership\n </Button>\n\n <Dialog open={open} onOpenChange={(next) => { if (!next) close(); }}>\n <DialogContent className=\"max-w-[calc(100%-6px)] sm:max-w-md p-0 overflow-hidden gap-0 rounded-2xl\">\n <DialogTitle className=\"sr-only\">Transfer ownership of {collectionName ?? \"collection\"}</DialogTitle>\n <DialogDescription className=\"sr-only\">Transfer the on-chain owner of this collection. Existing tokens are unaffected.</DialogDescription>\n\n {confirming ? (\n <MarketplaceConfirmStep\n description={`Transfer ownership to ${shortenAddress(trimmed)}?`}\n secondaryLabel=\"Back\"\n onSecondary={() => setConfirming(false)}\n primaryLabel=\"Transfer ownership\"\n onPrimary={transfer}\n primaryIcon={<UserRoundCog className=\"h-4 w-4\" />}\n />\n ) : (\n <div className=\"p-6 space-y-4\">\n <div className=\"flex items-center gap-2\">\n <UserRoundCog className=\"h-5 w-5\" />\n <p className=\"font-bold text-lg\">Transfer collection ownership</p>\n </div>\n <p className=\"text-sm text-muted-foreground\">\n The new owner will control minting and future ownership transfers for this collection. Existing tokens are unaffected.\n </p>\n <div className=\"space-y-2\">\n <Label htmlFor=\"new-owner\">New owner address</Label>\n <Input\n id=\"new-owner\"\n placeholder=\"0x…\"\n value={newOwner}\n onChange={(e) => setNewOwner(e.target.value)}\n className=\"tabular-nums text-sm\"\n spellCheck={false}\n autoComplete=\"off\"\n />\n {trimmed && !isValid && <p className=\"text-xs text-red-500\">Not a valid Starknet address.</p>}\n {wouldNoop && <p className=\"text-xs text-amber-500\">This is already the current owner.</p>}\n </div>\n <div className=\"flex gap-2 pt-2\">\n <Button variant=\"ghost\" className=\"flex-1\" onClick={close}>\n Cancel\n </Button>\n <Button className=\"flex-1\" onClick={() => setConfirming(true)} disabled={!isValid || wouldNoop || !app.walletAddress}>\n Continue\n </Button>\n </div>\n </div>\n )}\n </DialogContent>\n </Dialog>\n\n <TransactionDialog tx={tx} title=\"Transfer ownership\" workingLabel=\"Transferring ownership…\" firstStepLabel=\"Prepare transfer\">\n <TransactionSuccess\n name={collectionName ?? \"Collection\"}\n {...successMessages.ownershipTransferred({ name: collectionName ?? \"the collection\", to: shortenAddress(trimmed) })}\n txHash={tx.txHash}\n actions={[{ label: \"Done\", onClick: tx.reset }]}\n />\n </TransactionDialog>\n </>\n );\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.d.cts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/medialane.css
CHANGED
|
@@ -329,3 +329,10 @@ input[type="number"] { -moz-appearance: textfield; }
|
|
|
329
329
|
@media (prefers-reduced-motion: reduce) {
|
|
330
330
|
.ml-gbtn::before { animation: none; }
|
|
331
331
|
}
|
|
332
|
+
|
|
333
|
+
.card-media {
|
|
334
|
+
transition: transform 500ms cubic-bezier(0.22, 1, 0.36, 1), opacity 300ms ease;
|
|
335
|
+
}
|
|
336
|
+
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
|
|
337
|
+
.group:hover .card-media { transform: scale(1.04); }
|
|
338
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var send_token_exports = {};
|
|
20
|
+
__export(send_token_exports, {
|
|
21
|
+
sendToken: () => sendToken
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(send_token_exports);
|
|
24
|
+
var import_run_intent_calls = require("./run-intent-calls.js");
|
|
25
|
+
function sendToken(signer, client, input) {
|
|
26
|
+
return (0, import_run_intent_calls.runIntentCalls)(
|
|
27
|
+
signer,
|
|
28
|
+
() => client.createIntent("transfer-token", {
|
|
29
|
+
owner: signer.address,
|
|
30
|
+
token: input.token,
|
|
31
|
+
recipient: input.recipient,
|
|
32
|
+
amount: input.amount.toString()
|
|
33
|
+
})
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
37
|
+
0 && (module.exports = {
|
|
38
|
+
sendToken
|
|
39
|
+
});
|
|
40
|
+
//# sourceMappingURL=send-token.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utils/send-token.ts"],"sourcesContent":["import type { Call } from \"starknet\";\nimport type { MedialaneClient } from \"@medialane/sdk/starknet\";\nimport { runIntentCalls } from \"./run-intent-calls.js\";\n\nexport function sendToken(\n signer: { address: string; execute(calls: Call[], opts?: { intentIds?: string[] }): Promise<{ txHash: string }> },\n client: Pick<MedialaneClient, \"createIntent\">,\n input: { token: string; recipient: string; amount: bigint },\n): Promise<{ txHash: string }> {\n return runIntentCalls(signer, () =>\n client.createIntent(\"transfer-token\", {\n owner: signer.address,\n token: input.token,\n recipient: input.recipient,\n amount: input.amount.toString(),\n }),\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,8BAA+B;AAExB,SAAS,UACd,QACA,QACA,OAC6B;AAC7B,aAAO;AAAA,IAAe;AAAA,IAAQ,MAC5B,OAAO,aAAa,kBAAkB;AAAA,MACpC,OAAO,OAAO;AAAA,MACd,OAAO,MAAM;AAAA,MACb,WAAW,MAAM;AAAA,MACjB,QAAQ,MAAM,OAAO,SAAS;AAAA,IAChC,CAAC;AAAA,EACH;AACF;","names":[]}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Call } from 'starknet';
|
|
2
|
+
import { MedialaneClient } from '@medialane/sdk/starknet';
|
|
3
|
+
|
|
4
|
+
declare function sendToken(signer: {
|
|
5
|
+
address: string;
|
|
6
|
+
execute(calls: Call[], opts?: {
|
|
7
|
+
intentIds?: string[];
|
|
8
|
+
}): Promise<{
|
|
9
|
+
txHash: string;
|
|
10
|
+
}>;
|
|
11
|
+
}, client: Pick<MedialaneClient, "createIntent">, input: {
|
|
12
|
+
token: string;
|
|
13
|
+
recipient: string;
|
|
14
|
+
amount: bigint;
|
|
15
|
+
}): Promise<{
|
|
16
|
+
txHash: string;
|
|
17
|
+
}>;
|
|
18
|
+
|
|
19
|
+
export { sendToken };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Call } from 'starknet';
|
|
2
|
+
import { MedialaneClient } from '@medialane/sdk/starknet';
|
|
3
|
+
|
|
4
|
+
declare function sendToken(signer: {
|
|
5
|
+
address: string;
|
|
6
|
+
execute(calls: Call[], opts?: {
|
|
7
|
+
intentIds?: string[];
|
|
8
|
+
}): Promise<{
|
|
9
|
+
txHash: string;
|
|
10
|
+
}>;
|
|
11
|
+
}, client: Pick<MedialaneClient, "createIntent">, input: {
|
|
12
|
+
token: string;
|
|
13
|
+
recipient: string;
|
|
14
|
+
amount: bigint;
|
|
15
|
+
}): Promise<{
|
|
16
|
+
txHash: string;
|
|
17
|
+
}>;
|
|
18
|
+
|
|
19
|
+
export { sendToken };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { runIntentCalls } from "./run-intent-calls.js";
|
|
2
|
+
function sendToken(signer, client, input) {
|
|
3
|
+
return runIntentCalls(
|
|
4
|
+
signer,
|
|
5
|
+
() => client.createIntent("transfer-token", {
|
|
6
|
+
owner: signer.address,
|
|
7
|
+
token: input.token,
|
|
8
|
+
recipient: input.recipient,
|
|
9
|
+
amount: input.amount.toString()
|
|
10
|
+
})
|
|
11
|
+
);
|
|
12
|
+
}
|
|
13
|
+
export {
|
|
14
|
+
sendToken
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=send-token.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utils/send-token.ts"],"sourcesContent":["import type { Call } from \"starknet\";\nimport type { MedialaneClient } from \"@medialane/sdk/starknet\";\nimport { runIntentCalls } from \"./run-intent-calls.js\";\n\nexport function sendToken(\n signer: { address: string; execute(calls: Call[], opts?: { intentIds?: string[] }): Promise<{ txHash: string }> },\n client: Pick<MedialaneClient, \"createIntent\">,\n input: { token: string; recipient: string; amount: bigint },\n): Promise<{ txHash: string }> {\n return runIntentCalls(signer, () =>\n client.createIntent(\"transfer-token\", {\n owner: signer.address,\n token: input.token,\n recipient: input.recipient,\n amount: input.amount.toString(),\n }),\n );\n}\n"],"mappings":"AAEA,SAAS,sBAAsB;AAExB,SAAS,UACd,QACA,QACA,OAC6B;AAC7B,SAAO;AAAA,IAAe;AAAA,IAAQ,MAC5B,OAAO,aAAa,kBAAkB;AAAA,MACpC,OAAO,OAAO;AAAA,MACd,OAAO,MAAM;AAAA,MACb,WAAW,MAAM;AAAA,MACjB,QAAQ,MAAM,OAAO,SAAS;AAAA,IAChC,CAAC;AAAA,EACH;AACF;","names":[]}
|
|
@@ -1,45 +1,45 @@
|
|
|
1
1
|
import * as _medialane_sdk from '@medialane/sdk';
|
|
2
|
-
import * as zod from 'zod';
|
|
3
2
|
import { ChangeEvent } from 'react';
|
|
4
3
|
import { CollectionSettingsForm } from './collection-settings-form.cjs';
|
|
5
4
|
|
|
6
5
|
type SaveStatus = "idle" | "saved" | "error";
|
|
7
6
|
declare function useCollectionSettings(contract: string): {
|
|
8
7
|
collection: {
|
|
9
|
-
|
|
8
|
+
id: string;
|
|
10
9
|
chain: string;
|
|
11
|
-
|
|
10
|
+
contractAddress: string;
|
|
12
11
|
collectionId: string | null;
|
|
13
12
|
name: string | null;
|
|
13
|
+
symbol: string | null;
|
|
14
14
|
description: string | null;
|
|
15
15
|
image: string | null;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
attributes: {
|
|
17
|
+
[x: string]: unknown;
|
|
18
|
+
trait_type: string;
|
|
19
|
+
value: string | number | boolean;
|
|
20
|
+
display_type?: string | undefined;
|
|
21
|
+
}[] | null;
|
|
22
|
+
owner: string | null;
|
|
23
|
+
startBlock: string;
|
|
21
24
|
metadataStatus: "PENDING" | "FETCHING" | "FETCHED" | "FAILED";
|
|
22
25
|
standard: "ERC721" | "ERC1155";
|
|
23
|
-
attributes: zod.objectOutputType<{
|
|
24
|
-
trait_type: zod.ZodString;
|
|
25
|
-
value: zod.ZodUnion<[zod.ZodString, zod.ZodNumber, zod.ZodBoolean]>;
|
|
26
|
-
display_type: zod.ZodOptional<zod.ZodString>;
|
|
27
|
-
}, zod.ZodTypeAny, "passthrough">[] | null;
|
|
28
|
-
holderCount: number;
|
|
29
|
-
startBlock: string;
|
|
30
26
|
isFeatured: boolean;
|
|
31
27
|
isHidden: boolean;
|
|
28
|
+
service: string | null;
|
|
32
29
|
claimedBy: string | null;
|
|
33
30
|
floorPrice: string | null;
|
|
34
31
|
totalVolume: string | null;
|
|
32
|
+
holderCount: number;
|
|
35
33
|
totalSupply: number;
|
|
34
|
+
createdAt: string;
|
|
35
|
+
updatedAt: string;
|
|
36
36
|
profile: {
|
|
37
|
-
description: string | null;
|
|
38
|
-
image: string | null;
|
|
39
|
-
displayName: string | null;
|
|
40
|
-
gatedContentTitle: string | null;
|
|
41
37
|
hasGatedContent: boolean;
|
|
38
|
+
gatedContentTitle: string | null;
|
|
42
39
|
slug: string | null;
|
|
40
|
+
image: string | null;
|
|
41
|
+
displayName: string | null;
|
|
42
|
+
description: string | null;
|
|
43
43
|
} | null;
|
|
44
44
|
} | null;
|
|
45
45
|
profile: _medialane_sdk.ApiCollectionProfile | null;
|