@medialane/ui 0.259.0 → 0.260.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/activities-feed.cjs +5 -1
- package/dist/components/activities-feed.cjs.map +1 -1
- package/dist/components/activities-feed.js +5 -1
- package/dist/components/activities-feed.js.map +1 -1
- package/dist/components/activity-feed-shell.cjs +3 -1
- package/dist/components/activity-feed-shell.cjs.map +1 -1
- package/dist/components/activity-feed-shell.js +3 -1
- package/dist/components/activity-feed-shell.js.map +1 -1
- package/dist/components/button.d.cts +1 -1
- package/dist/components/button.d.ts +1 -1
- package/dist/components/coins-explorer.cjs +5 -1
- package/dist/components/coins-explorer.cjs.map +1 -1
- package/dist/components/coins-explorer.js +6 -2
- package/dist/components/coins-explorer.js.map +1 -1
- package/dist/components/comments-section.cjs +2 -2
- package/dist/components/comments-section.cjs.map +1 -1
- package/dist/components/comments-section.js +2 -2
- package/dist/components/comments-section.js.map +1 -1
- package/dist/components/discover-community-section.cjs +5 -1
- package/dist/components/discover-community-section.cjs.map +1 -1
- package/dist/components/discover-community-section.js +5 -1
- package/dist/components/discover-community-section.js.map +1 -1
- package/dist/components/discover-feed-section.cjs +5 -1
- package/dist/components/discover-feed-section.cjs.map +1 -1
- package/dist/components/discover-feed-section.js +5 -1
- package/dist/components/discover-feed-section.js.map +1 -1
- package/dist/components/fast-mint/fast-mint.d.cts +2 -2
- package/dist/components/fast-mint/fast-mint.d.ts +2 -2
- package/dist/components/fast-mint/success-view.cjs +2 -2
- package/dist/components/fast-mint/success-view.cjs.map +1 -1
- package/dist/components/fast-mint/success-view.js +2 -2
- package/dist/components/fast-mint/success-view.js.map +1 -1
- package/dist/components/ip-type-page.cjs +3 -2
- package/dist/components/ip-type-page.cjs.map +1 -1
- package/dist/components/ip-type-page.js +3 -2
- package/dist/components/ip-type-page.js.map +1 -1
- package/dist/components/marketplace-dialog-primitives.cjs +1 -1
- package/dist/components/marketplace-dialog-primitives.cjs.map +1 -1
- package/dist/components/marketplace-dialog-primitives.js +1 -1
- package/dist/components/marketplace-dialog-primitives.js.map +1 -1
- package/dist/components/media-wallet/media-wallet-activity.cjs +5 -1
- package/dist/components/media-wallet/media-wallet-activity.cjs.map +1 -1
- package/dist/components/media-wallet/media-wallet-activity.js +5 -1
- package/dist/components/media-wallet/media-wallet-activity.js.map +1 -1
- package/dist/components/media-wallet/media-wallet-home.cjs +3 -2
- package/dist/components/media-wallet/media-wallet-home.cjs.map +1 -1
- package/dist/components/media-wallet/media-wallet-home.js +3 -2
- package/dist/components/media-wallet/media-wallet-home.js.map +1 -1
- package/dist/components/media-wallet/media-wallet-send.cjs +5 -2
- package/dist/components/media-wallet/media-wallet-send.cjs.map +1 -1
- package/dist/components/media-wallet/media-wallet-send.js +5 -2
- package/dist/components/media-wallet/media-wallet-send.js.map +1 -1
- package/dist/components/media-wallet/success-dialog.cjs +5 -11
- package/dist/components/media-wallet/success-dialog.cjs.map +1 -1
- package/dist/components/media-wallet/success-dialog.js +5 -11
- package/dist/components/media-wallet/success-dialog.js.map +1 -1
- package/dist/components/pop-claim-button.cjs +2 -2
- package/dist/components/pop-claim-button.cjs.map +1 -1
- package/dist/components/pop-claim-button.js +2 -2
- package/dist/components/pop-claim-button.js.map +1 -1
- package/dist/components/pop-manage-page.cjs +3 -2
- package/dist/components/pop-manage-page.cjs.map +1 -1
- package/dist/components/pop-manage-page.js +3 -2
- package/dist/components/pop-manage-page.js.map +1 -1
- package/dist/components/portfolio-sponsorships.cjs +14 -7
- package/dist/components/portfolio-sponsorships.cjs.map +1 -1
- package/dist/components/portfolio-sponsorships.js +14 -7
- package/dist/components/portfolio-sponsorships.js.map +1 -1
- package/dist/components/service-collections-page.cjs +2 -2
- package/dist/components/service-collections-page.cjs.map +1 -1
- package/dist/components/service-collections-page.d.cts +2 -2
- package/dist/components/service-collections-page.d.ts +2 -2
- package/dist/components/service-collections-page.js +2 -2
- package/dist/components/service-collections-page.js.map +1 -1
- package/dist/components/sheet.d.cts +1 -1
- package/dist/components/sheet.d.ts +1 -1
- package/dist/components/sponsorship-offer-page.cjs +4 -4
- package/dist/components/sponsorship-offer-page.cjs.map +1 -1
- package/dist/components/sponsorship-offer-page.js +4 -4
- package/dist/components/sponsorship-offer-page.js.map +1 -1
- package/dist/components/transaction-success.cjs +2 -5
- package/dist/components/transaction-success.cjs.map +1 -1
- package/dist/components/transaction-success.js +3 -6
- package/dist/components/transaction-success.js.map +1 -1
- package/dist/components/transfer-collection-ownership.cjs +2 -5
- package/dist/components/transfer-collection-ownership.cjs.map +1 -1
- package/dist/components/transfer-collection-ownership.js +2 -5
- package/dist/components/transfer-collection-ownership.js.map +1 -1
- package/dist/index.cjs +3 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/utils/empty-messages.cjs +62 -0
- package/dist/utils/empty-messages.cjs.map +1 -0
- package/dist/utils/empty-messages.d.cts +40 -0
- package/dist/utils/empty-messages.d.ts +40 -0
- package/dist/utils/empty-messages.js +38 -0
- package/dist/utils/empty-messages.js.map +1 -0
- package/dist/utils/success-messages.cjs +52 -0
- package/dist/utils/success-messages.cjs.map +1 -1
- package/dist/utils/success-messages.d.cts +27 -0
- package/dist/utils/success-messages.d.ts +27 -0
- package/dist/utils/success-messages.js +52 -0
- package/dist/utils/success-messages.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/ip-type-page.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState, useEffect, useRef } from \"react\";\nimport { SlidersHorizontal, Search, X as XIcon } from \"lucide-react\";\nimport type { ApiToken } from \"@medialane/sdk\";\nimport Link from \"./link.js\";\nimport { Badge } from \"./badge.js\";\nimport { Button } from \"./button.js\";\nimport { Dialog, DialogContent, DialogTitle } from \"./dialog.js\";\nimport { Input } from \"./input.js\";\nimport { PageContainer } from \"./page-container.js\";\nimport { LoadMoreSentinel } from \"./load-more-sentinel.js\";\nimport { IP_TYPE_CONFIG, IP_TYPE_MAP } from \"./ip-type-badge.js\";\nimport { TokenCard, TokenCardSkeleton } from \"./token-card.js\";\nimport { useMedialaneApp } from \"./medialane-app.js\";\nimport type { CollectionMarketActions } from \"./collection-page.js\";\nimport { cn } from \"../utils/cn.js\";\nimport { isSameAddress } from \"../utils/same-address.js\";\nimport { useTokensByIpType } from \"../utils/use-tokens-by-ip-type.js\";\n\nconst PAGE_SIZE = 24;\n\nfunction FilterChip({ active, onClick, label }: { active: boolean; onClick: () => void; label: string }) {\n return (\n <button\n onClick={onClick}\n className={cn(\n \"text-xs px-3 py-1.5 rounded-full border transition-colors whitespace-nowrap\",\n active\n ? \"border-primary bg-primary/10 text-primary font-medium\"\n : \"border-border text-muted-foreground hover:border-primary/50\"\n )}\n >\n {label}\n </button>\n );\n}\n\nexport interface IpTypePageProps {\n slug: string;\n useMarketActions: () => CollectionMarketActions;\n}\n\nexport function IpTypePage({ slug, useMarketActions }: IpTypePageProps) {\n const { walletAddress } = useMedialaneApp();\n const market = useMarketActions();\n const config = IP_TYPE_MAP[slug];\n const Icon = config?.icon;\n const [page, setPage] = useState(1);\n const [listedOnly, setListedOnly] = useState(false);\n const [allTokens, setAllTokens] = useState<ApiToken[]>([]);\n const prevSlug = useRef(slug);\n\n const [filtersOpen, setFiltersOpen] = useState(false);\n const [sortOrder, setSortOrder] = useState<\"recent\" | \"price_asc\" | \"price_desc\">(\"recent\");\n const [licenseFilter, setLicenseFilter] = useState<string>(\"all\");\n const [creatorSearchInput, setCreatorSearchInput] = useState(\"\");\n const [creatorSearch, setCreatorSearch] = useState(\"\");\n\n useEffect(() => {\n if (prevSlug.current !== slug) {\n prevSlug.current = slug;\n setPage(1);\n setAllTokens([]);\n }\n }, [slug]);\n\n useEffect(() => {\n const t = setTimeout(() => setCreatorSearch(creatorSearchInput), 300);\n return () => clearTimeout(t);\n }, [creatorSearchInput]);\n\n const { tokens, meta, isLoading } = useTokensByIpType(slug, page, PAGE_SIZE);\n\n useEffect(() => {\n if (isLoading) return;\n if (page === 1) {\n setAllTokens(tokens);\n } else {\n setAllTokens((prev) => {\n const seen = new Set(prev.map((t) => `${t.contractAddress}:${t.tokenId}`));\n const fresh = tokens.filter((t) => !seen.has(`${t.contractAddress}:${t.tokenId}`));\n return fresh.length > 0 ? [...prev, ...fresh] : prev;\n });\n }\n }, [tokens, isLoading, page]);\n\n const activeFilterCount =\n (sortOrder !== \"recent\" ? 1 : 0) +\n (licenseFilter !== \"all\" ? 1 : 0) +\n (creatorSearch !== \"\" ? 1 : 0);\n const activeChipCount = activeFilterCount + (listedOnly ? 1 : 0);\n const hasActiveFilters = activeChipCount > 0;\n const resetAll = () => {\n setSortOrder(\"recent\");\n setLicenseFilter(\"all\");\n setCreatorSearch(\"\");\n setCreatorSearchInput(\"\");\n setListedOnly(false);\n };\n\n let displayed = listedOnly\n ? allTokens.filter((t) => (t.activeOrders?.length ?? 0) > 0)\n : [...allTokens];\n\n if (licenseFilter !== \"all\") {\n displayed = displayed.filter((t) =>\n t.metadata?.attributes?.some(\n (a) => a.trait_type === \"License\" && a.value === licenseFilter\n )\n );\n }\n if (creatorSearch) {\n const q = creatorSearch.toLowerCase();\n displayed = displayed.filter((t) => {\n const creatorVal =\n t.metadata?.attributes?.find((a) => a.trait_type === \"Creator\")?.value ?? \"\";\n return (\n String(creatorVal).toLowerCase().includes(q) ||\n t.contractAddress.toLowerCase().includes(q)\n );\n });\n }\n if (sortOrder === \"price_asc\") {\n displayed = [...displayed].sort((a, b) => {\n const pa = parseFloat(a.activeOrders?.[0]?.price?.formatted ?? \"Infinity\");\n const pb = parseFloat(b.activeOrders?.[0]?.price?.formatted ?? \"Infinity\");\n return pa - pb;\n });\n } else if (sortOrder === \"price_desc\") {\n displayed = [...displayed].sort((a, b) => {\n const pa = parseFloat(a.activeOrders?.[0]?.price?.formatted ?? \"0\");\n const pb = parseFloat(b.activeOrders?.[0]?.price?.formatted ?? \"0\");\n return pb - pa;\n });\n }\n\n const isInitialLoading = isLoading && allTokens.length === 0;\n const isLoadingMore = isLoading && allTokens.length > 0;\n const hasMore = meta?.total != null ? allTokens.length < meta.total : false;\n const listedCount = allTokens.filter((t) => (t.activeOrders?.length ?? 0) > 0).length;\n\n return (\n <PageContainer className=\"box-border max-w-full pt-20 pb-16 space-y-8\">\n\n <div className=\"space-y-4\">\n <div className=\"flex items-center gap-4\">\n {config && Icon && (\n <div className={cn(\"h-14 w-14 rounded-2xl flex items-center justify-center shadow-lg\", config.bgClass)}>\n <Icon className={cn(\"h-7 w-7\", config.colorClass)} />\n </div>\n )}\n <div>\n <h1 className=\"text-3xl font-semibold\">{config?.label ?? slug}</h1>\n <p className=\"text-muted-foreground mt-0.5\">\n {meta?.total != null ? (\n <>{meta.total.toLocaleString()} assets · {listedCount} market</>\n ) : (\n \"Browsing indexed digital assets on Medialane\"\n )}\n </p>\n </div>\n </div>\n\n <div className=\"flex items-center gap-2 flex-wrap\">\n <button\n onClick={() => setFiltersOpen(true)}\n className={cn(\n \"inline-flex items-center gap-1.5 text-xs px-3.5 py-2 rounded-full border font-medium transition-colors\",\n hasActiveFilters\n ? \"border-primary bg-primary/10 text-primary\"\n : \"border-border text-muted-foreground\"\n )}\n >\n <SlidersHorizontal className=\"h-3.5 w-3.5\" />\n Filters\n {activeChipCount > 0 && (\n <span className=\"ml-0.5 bg-primary text-primary-foreground rounded-full px-1.5 text-2xs font-bold leading-4\">\n {activeChipCount}\n </span>\n )}\n </button>\n\n {listedOnly && (\n <Badge variant=\"secondary\" className=\"cursor-pointer gap-1 text-xs\" onClick={() => setListedOnly(false)}>\n Listed only\n <XIcon className=\"h-3 w-3\" />\n </Badge>\n )}\n {sortOrder !== \"recent\" && (\n <Badge variant=\"secondary\" className=\"cursor-pointer gap-1 text-xs\" onClick={() => setSortOrder(\"recent\")}>\n {sortOrder === \"price_asc\" ? \"Price ↑\" : \"Price ↓\"}\n <XIcon className=\"h-3 w-3\" />\n </Badge>\n )}\n {licenseFilter !== \"all\" && (\n <Badge variant=\"secondary\" className=\"cursor-pointer gap-1 text-xs\" onClick={() => setLicenseFilter(\"all\")}>\n {licenseFilter}\n <XIcon className=\"h-3 w-3\" />\n </Badge>\n )}\n {creatorSearch && (\n <Badge variant=\"secondary\" className=\"cursor-pointer gap-1 text-xs\" onClick={() => { setCreatorSearch(\"\"); setCreatorSearchInput(\"\"); }}>\n {creatorSearch.length > 10 ? `${creatorSearch.slice(0, 10)}…` : creatorSearch}\n <XIcon className=\"h-3 w-3\" />\n </Badge>\n )}\n </div>\n\n <Dialog open={filtersOpen} onOpenChange={setFiltersOpen}>\n <DialogContent className=\"w-full max-w-sm sm:max-w-md p-0 overflow-hidden gap-0 flex flex-col max-h-[85svh]\">\n <div className=\"flex items-center justify-between px-5 py-4 border-b border-border/60 pr-12\">\n <DialogTitle className=\"text-base font-bold flex items-center gap-2\">\n <SlidersHorizontal className=\"h-4 w-4 text-primary\" />\n Filters\n </DialogTitle>\n {hasActiveFilters && (\n <Button variant=\"ghost\" size=\"sm\" className=\"h-7 text-xs text-muted-foreground\" onClick={resetAll}>\n Clear all\n </Button>\n )}\n </div>\n\n <div className=\"flex-1 overflow-y-auto px-5 py-4 space-y-5\">\n\n <div className=\"space-y-2\">\n <p className=\"text-2xs font-semibold text-muted-foreground\">Status</p>\n <div className=\"flex flex-wrap gap-1.5\">\n <FilterChip active={!listedOnly} onClick={() => setListedOnly(false)} label=\"All\" />\n <FilterChip\n active={listedOnly}\n onClick={() => setListedOnly(true)}\n label={`Listed only${listedCount > 0 ? ` (${listedCount})` : \"\"}`}\n />\n </div>\n </div>\n\n <div className=\"space-y-2\">\n <p className=\"text-2xs font-semibold text-muted-foreground\">Sort</p>\n <div className=\"flex flex-wrap gap-1.5\">\n <FilterChip active={sortOrder === \"recent\"} onClick={() => setSortOrder(\"recent\")} label=\"Recent\" />\n <FilterChip active={sortOrder === \"price_asc\"} onClick={() => setSortOrder(\"price_asc\")} label=\"Price ↑\" />\n <FilterChip active={sortOrder === \"price_desc\"} onClick={() => setSortOrder(\"price_desc\")} label=\"Price ↓\" />\n </div>\n </div>\n\n <div className=\"space-y-2\">\n <p className=\"text-2xs font-semibold text-muted-foreground\">License</p>\n <div className=\"flex flex-wrap gap-1.5\">\n {[\"all\", \"CC0\", \"CC BY\", \"CC BY-SA\", \"CC BY-NC\", \"CC BY-ND\", \"Custom\"].map((lic) => (\n <FilterChip\n key={lic}\n active={licenseFilter === lic}\n onClick={() => setLicenseFilter(lic)}\n label={lic === \"all\" ? \"All licenses\" : lic}\n />\n ))}\n </div>\n </div>\n\n <div className=\"space-y-2\">\n <p className=\"text-2xs font-semibold text-muted-foreground\">Creator</p>\n <div className=\"relative\">\n <Search className=\"absolute left-2.5 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-muted-foreground\" />\n <Input\n className=\"h-9 text-sm pl-8\"\n placeholder=\"Name or wallet address…\"\n value={creatorSearchInput}\n onChange={(e) => setCreatorSearchInput(e.target.value)}\n />\n </div>\n </div>\n\n <div className=\"space-y-2 pt-1 border-t border-border/60\">\n <p className=\"text-2xs font-semibold text-muted-foreground\">IP Type</p>\n <div className=\"flex flex-wrap gap-1.5\">\n {IP_TYPE_CONFIG.map((t) => (\n <Link\n key={t.slug}\n href={`/${t.slug}`}\n className={cn(\n \"inline-flex items-center gap-1.5 text-xs px-3 py-1.5 rounded-full border transition-colors whitespace-nowrap\",\n t.slug === slug\n ? \"border-primary bg-primary/10 text-primary font-medium\"\n : \"border-border text-muted-foreground hover:border-primary/50\"\n )}\n >\n <t.icon className={cn(\"h-3 w-3\", t.slug === slug ? t.colorClass : \"\")} />\n {t.label}\n </Link>\n ))}\n </div>\n </div>\n </div>\n\n <div className=\"px-5 py-3 border-t border-border/60\">\n <Button className=\"w-full\" onClick={() => setFiltersOpen(false)}>\n Apply filters\n </Button>\n </div>\n </DialogContent>\n </Dialog>\n </div>\n\n {isInitialLoading ? (\n <div className=\"grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-4\">\n {Array.from({ length: PAGE_SIZE }).map((_, i) => (\n <TokenCardSkeleton key={i} />\n ))}\n </div>\n ) : displayed.length === 0 ? (\n <div className=\"py-24 flex flex-col items-center gap-4 text-center\">\n {config && Icon && (\n <div className={cn(\"h-16 w-16 rounded-2xl flex items-center justify-center\", config.bgClass)}>\n <Icon className={cn(\"h-8 w-8\", config.colorClass)} />\n </div>\n )}\n <div>\n <p className=\"font-semibold text-lg\">\n {listedOnly ? \"No listed assets yet\" : \"No assets indexed yet\"}\n </p>\n <p className=\"text-muted-foreground text-sm mt-1\">\n {listedOnly\n ? \"Try removing the 'Listed only' filter to see all assets.\"\n : `Be the first to mint a ${config?.label ?? slug} asset on Medialane.`}\n </p>\n </div>\n <Button asChild variant=\"outline\">\n <Link href=\"/launchpad/single-editions\">Create Asset</Link>\n </Button>\n </div>\n ) : (\n <div className=\"space-y-6\">\n <div className=\"grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-4\">\n {displayed.map((token) => {\n const listing = token.activeOrders?.find((o) => o.offer.itemType === \"ERC721\" || o.offer.itemType === \"ERC1155\");\n const isOwner = !!walletAddress && !!token.owner && isSameAddress(token.owner, walletAddress);\n return (\n <TokenCard\n key={`${token.contractAddress}:${token.tokenId}`}\n token={token}\n isOwner={isOwner}\n onBuy={!isOwner && listing ? () => market.buy(listing) : undefined}\n onOffer={isOwner ? undefined : market.offer}\n />\n );\n })}\n </div>\n\n {!listedOnly && (\n <LoadMoreSentinel\n hasMore={hasMore}\n isLoading={isLoadingMore}\n onLoadMore={() => setPage((p) => p + 1)}\n />\n )}\n </div>\n )}\n\n {market.dialogs}\n </PageContainer>\n );\n}\n"],"mappings":"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","names":["XIcon","Link"]}
|
|
1
|
+
{"version":3,"sources":["../../src/components/ip-type-page.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState, useEffect, useRef } from \"react\";\nimport { SlidersHorizontal, Search, X as XIcon } from \"lucide-react\";\nimport type { ApiToken } from \"@medialane/sdk\";\nimport Link from \"./link.js\";\nimport { Badge } from \"./badge.js\";\nimport { Button } from \"./button.js\";\nimport { Dialog, DialogContent, DialogTitle } from \"./dialog.js\";\nimport { Input } from \"./input.js\";\nimport { PageContainer } from \"./page-container.js\";\nimport { LoadMoreSentinel } from \"./load-more-sentinel.js\";\nimport { IP_TYPE_CONFIG, IP_TYPE_MAP } from \"./ip-type-badge.js\";\nimport { TokenCard, TokenCardSkeleton } from \"./token-card.js\";\nimport { useMedialaneApp } from \"./medialane-app.js\";\nimport type { CollectionMarketActions } from \"./collection-page.js\";\nimport { cn } from \"../utils/cn.js\";\nimport { isSameAddress } from \"../utils/same-address.js\";\nimport { useTokensByIpType } from \"../utils/use-tokens-by-ip-type.js\";\nimport { emptyMessages } from \"../utils/empty-messages.js\";\n\nconst PAGE_SIZE = 24;\n\nfunction FilterChip({ active, onClick, label }: { active: boolean; onClick: () => void; label: string }) {\n return (\n <button\n onClick={onClick}\n className={cn(\n \"text-xs px-3 py-1.5 rounded-full border transition-colors whitespace-nowrap\",\n active\n ? \"border-primary bg-primary/10 text-primary font-medium\"\n : \"border-border text-muted-foreground hover:border-primary/50\"\n )}\n >\n {label}\n </button>\n );\n}\n\nexport interface IpTypePageProps {\n slug: string;\n useMarketActions: () => CollectionMarketActions;\n}\n\nexport function IpTypePage({ slug, useMarketActions }: IpTypePageProps) {\n const { walletAddress } = useMedialaneApp();\n const market = useMarketActions();\n const config = IP_TYPE_MAP[slug];\n const Icon = config?.icon;\n const [page, setPage] = useState(1);\n const [listedOnly, setListedOnly] = useState(false);\n const [allTokens, setAllTokens] = useState<ApiToken[]>([]);\n const prevSlug = useRef(slug);\n\n const [filtersOpen, setFiltersOpen] = useState(false);\n const [sortOrder, setSortOrder] = useState<\"recent\" | \"price_asc\" | \"price_desc\">(\"recent\");\n const [licenseFilter, setLicenseFilter] = useState<string>(\"all\");\n const [creatorSearchInput, setCreatorSearchInput] = useState(\"\");\n const [creatorSearch, setCreatorSearch] = useState(\"\");\n\n useEffect(() => {\n if (prevSlug.current !== slug) {\n prevSlug.current = slug;\n setPage(1);\n setAllTokens([]);\n }\n }, [slug]);\n\n useEffect(() => {\n const t = setTimeout(() => setCreatorSearch(creatorSearchInput), 300);\n return () => clearTimeout(t);\n }, [creatorSearchInput]);\n\n const { tokens, meta, isLoading } = useTokensByIpType(slug, page, PAGE_SIZE);\n\n useEffect(() => {\n if (isLoading) return;\n if (page === 1) {\n setAllTokens(tokens);\n } else {\n setAllTokens((prev) => {\n const seen = new Set(prev.map((t) => `${t.contractAddress}:${t.tokenId}`));\n const fresh = tokens.filter((t) => !seen.has(`${t.contractAddress}:${t.tokenId}`));\n return fresh.length > 0 ? [...prev, ...fresh] : prev;\n });\n }\n }, [tokens, isLoading, page]);\n\n const activeFilterCount =\n (sortOrder !== \"recent\" ? 1 : 0) +\n (licenseFilter !== \"all\" ? 1 : 0) +\n (creatorSearch !== \"\" ? 1 : 0);\n const activeChipCount = activeFilterCount + (listedOnly ? 1 : 0);\n const hasActiveFilters = activeChipCount > 0;\n const resetAll = () => {\n setSortOrder(\"recent\");\n setLicenseFilter(\"all\");\n setCreatorSearch(\"\");\n setCreatorSearchInput(\"\");\n setListedOnly(false);\n };\n\n let displayed = listedOnly\n ? allTokens.filter((t) => (t.activeOrders?.length ?? 0) > 0)\n : [...allTokens];\n\n if (licenseFilter !== \"all\") {\n displayed = displayed.filter((t) =>\n t.metadata?.attributes?.some(\n (a) => a.trait_type === \"License\" && a.value === licenseFilter\n )\n );\n }\n if (creatorSearch) {\n const q = creatorSearch.toLowerCase();\n displayed = displayed.filter((t) => {\n const creatorVal =\n t.metadata?.attributes?.find((a) => a.trait_type === \"Creator\")?.value ?? \"\";\n return (\n String(creatorVal).toLowerCase().includes(q) ||\n t.contractAddress.toLowerCase().includes(q)\n );\n });\n }\n if (sortOrder === \"price_asc\") {\n displayed = [...displayed].sort((a, b) => {\n const pa = parseFloat(a.activeOrders?.[0]?.price?.formatted ?? \"Infinity\");\n const pb = parseFloat(b.activeOrders?.[0]?.price?.formatted ?? \"Infinity\");\n return pa - pb;\n });\n } else if (sortOrder === \"price_desc\") {\n displayed = [...displayed].sort((a, b) => {\n const pa = parseFloat(a.activeOrders?.[0]?.price?.formatted ?? \"0\");\n const pb = parseFloat(b.activeOrders?.[0]?.price?.formatted ?? \"0\");\n return pb - pa;\n });\n }\n\n const isInitialLoading = isLoading && allTokens.length === 0;\n const isLoadingMore = isLoading && allTokens.length > 0;\n const hasMore = meta?.total != null ? allTokens.length < meta.total : false;\n const listedCount = allTokens.filter((t) => (t.activeOrders?.length ?? 0) > 0).length;\n\n return (\n <PageContainer className=\"box-border max-w-full pt-20 pb-16 space-y-8\">\n\n <div className=\"space-y-4\">\n <div className=\"flex items-center gap-4\">\n {config && Icon && (\n <div className={cn(\"h-14 w-14 rounded-2xl flex items-center justify-center shadow-lg\", config.bgClass)}>\n <Icon className={cn(\"h-7 w-7\", config.colorClass)} />\n </div>\n )}\n <div>\n <h1 className=\"text-3xl font-semibold\">{config?.label ?? slug}</h1>\n <p className=\"text-muted-foreground mt-0.5\">\n {meta?.total != null ? (\n <>{meta.total.toLocaleString()} assets · {listedCount} market</>\n ) : (\n \"Browsing indexed digital assets on Medialane\"\n )}\n </p>\n </div>\n </div>\n\n <div className=\"flex items-center gap-2 flex-wrap\">\n <button\n onClick={() => setFiltersOpen(true)}\n className={cn(\n \"inline-flex items-center gap-1.5 text-xs px-3.5 py-2 rounded-full border font-medium transition-colors\",\n hasActiveFilters\n ? \"border-primary bg-primary/10 text-primary\"\n : \"border-border text-muted-foreground\"\n )}\n >\n <SlidersHorizontal className=\"h-3.5 w-3.5\" />\n Filters\n {activeChipCount > 0 && (\n <span className=\"ml-0.5 bg-primary text-primary-foreground rounded-full px-1.5 text-2xs font-bold leading-4\">\n {activeChipCount}\n </span>\n )}\n </button>\n\n {listedOnly && (\n <Badge variant=\"secondary\" className=\"cursor-pointer gap-1 text-xs\" onClick={() => setListedOnly(false)}>\n Listed only\n <XIcon className=\"h-3 w-3\" />\n </Badge>\n )}\n {sortOrder !== \"recent\" && (\n <Badge variant=\"secondary\" className=\"cursor-pointer gap-1 text-xs\" onClick={() => setSortOrder(\"recent\")}>\n {sortOrder === \"price_asc\" ? \"Price ↑\" : \"Price ↓\"}\n <XIcon className=\"h-3 w-3\" />\n </Badge>\n )}\n {licenseFilter !== \"all\" && (\n <Badge variant=\"secondary\" className=\"cursor-pointer gap-1 text-xs\" onClick={() => setLicenseFilter(\"all\")}>\n {licenseFilter}\n <XIcon className=\"h-3 w-3\" />\n </Badge>\n )}\n {creatorSearch && (\n <Badge variant=\"secondary\" className=\"cursor-pointer gap-1 text-xs\" onClick={() => { setCreatorSearch(\"\"); setCreatorSearchInput(\"\"); }}>\n {creatorSearch.length > 10 ? `${creatorSearch.slice(0, 10)}…` : creatorSearch}\n <XIcon className=\"h-3 w-3\" />\n </Badge>\n )}\n </div>\n\n <Dialog open={filtersOpen} onOpenChange={setFiltersOpen}>\n <DialogContent className=\"w-full max-w-sm sm:max-w-md p-0 overflow-hidden gap-0 flex flex-col max-h-[85svh]\">\n <div className=\"flex items-center justify-between px-5 py-4 border-b border-border/60 pr-12\">\n <DialogTitle className=\"text-base font-bold flex items-center gap-2\">\n <SlidersHorizontal className=\"h-4 w-4 text-primary\" />\n Filters\n </DialogTitle>\n {hasActiveFilters && (\n <Button variant=\"ghost\" size=\"sm\" className=\"h-7 text-xs text-muted-foreground\" onClick={resetAll}>\n Clear all\n </Button>\n )}\n </div>\n\n <div className=\"flex-1 overflow-y-auto px-5 py-4 space-y-5\">\n\n <div className=\"space-y-2\">\n <p className=\"text-2xs font-semibold text-muted-foreground\">Status</p>\n <div className=\"flex flex-wrap gap-1.5\">\n <FilterChip active={!listedOnly} onClick={() => setListedOnly(false)} label=\"All\" />\n <FilterChip\n active={listedOnly}\n onClick={() => setListedOnly(true)}\n label={`Listed only${listedCount > 0 ? ` (${listedCount})` : \"\"}`}\n />\n </div>\n </div>\n\n <div className=\"space-y-2\">\n <p className=\"text-2xs font-semibold text-muted-foreground\">Sort</p>\n <div className=\"flex flex-wrap gap-1.5\">\n <FilterChip active={sortOrder === \"recent\"} onClick={() => setSortOrder(\"recent\")} label=\"Recent\" />\n <FilterChip active={sortOrder === \"price_asc\"} onClick={() => setSortOrder(\"price_asc\")} label=\"Price ↑\" />\n <FilterChip active={sortOrder === \"price_desc\"} onClick={() => setSortOrder(\"price_desc\")} label=\"Price ↓\" />\n </div>\n </div>\n\n <div className=\"space-y-2\">\n <p className=\"text-2xs font-semibold text-muted-foreground\">License</p>\n <div className=\"flex flex-wrap gap-1.5\">\n {[\"all\", \"CC0\", \"CC BY\", \"CC BY-SA\", \"CC BY-NC\", \"CC BY-ND\", \"Custom\"].map((lic) => (\n <FilterChip\n key={lic}\n active={licenseFilter === lic}\n onClick={() => setLicenseFilter(lic)}\n label={lic === \"all\" ? \"All licenses\" : lic}\n />\n ))}\n </div>\n </div>\n\n <div className=\"space-y-2\">\n <p className=\"text-2xs font-semibold text-muted-foreground\">Creator</p>\n <div className=\"relative\">\n <Search className=\"absolute left-2.5 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-muted-foreground\" />\n <Input\n className=\"h-9 text-sm pl-8\"\n placeholder=\"Name or wallet address…\"\n value={creatorSearchInput}\n onChange={(e) => setCreatorSearchInput(e.target.value)}\n />\n </div>\n </div>\n\n <div className=\"space-y-2 pt-1 border-t border-border/60\">\n <p className=\"text-2xs font-semibold text-muted-foreground\">IP Type</p>\n <div className=\"flex flex-wrap gap-1.5\">\n {IP_TYPE_CONFIG.map((t) => (\n <Link\n key={t.slug}\n href={`/${t.slug}`}\n className={cn(\n \"inline-flex items-center gap-1.5 text-xs px-3 py-1.5 rounded-full border transition-colors whitespace-nowrap\",\n t.slug === slug\n ? \"border-primary bg-primary/10 text-primary font-medium\"\n : \"border-border text-muted-foreground hover:border-primary/50\"\n )}\n >\n <t.icon className={cn(\"h-3 w-3\", t.slug === slug ? t.colorClass : \"\")} />\n {t.label}\n </Link>\n ))}\n </div>\n </div>\n </div>\n\n <div className=\"px-5 py-3 border-t border-border/60\">\n <Button className=\"w-full\" onClick={() => setFiltersOpen(false)}>\n Apply filters\n </Button>\n </div>\n </DialogContent>\n </Dialog>\n </div>\n\n {isInitialLoading ? (\n <div className=\"grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-4\">\n {Array.from({ length: PAGE_SIZE }).map((_, i) => (\n <TokenCardSkeleton key={i} />\n ))}\n </div>\n ) : displayed.length === 0 ? (\n <div className=\"py-24 flex flex-col items-center gap-4 text-center\">\n {config && Icon && (\n <div className={cn(\"h-16 w-16 rounded-2xl flex items-center justify-center\", config.bgClass)}>\n <Icon className={cn(\"h-8 w-8\", config.colorClass)} />\n </div>\n )}\n <div>\n <p className=\"font-semibold text-lg\">\n {listedOnly ? \"Listed assets appear here\" : emptyMessages.assetsOfType.title}\n </p>\n <p className=\"text-muted-foreground text-sm mt-1\">\n {listedOnly\n ? \"Try removing the 'Listed only' filter to see all assets.\"\n : emptyMessages.assetsOfType.description}\n </p>\n </div>\n <Button asChild variant=\"outline\">\n <Link href=\"/launchpad/single-editions\">Create Asset</Link>\n </Button>\n </div>\n ) : (\n <div className=\"space-y-6\">\n <div className=\"grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-4\">\n {displayed.map((token) => {\n const listing = token.activeOrders?.find((o) => o.offer.itemType === \"ERC721\" || o.offer.itemType === \"ERC1155\");\n const isOwner = !!walletAddress && !!token.owner && isSameAddress(token.owner, walletAddress);\n return (\n <TokenCard\n key={`${token.contractAddress}:${token.tokenId}`}\n token={token}\n isOwner={isOwner}\n onBuy={!isOwner && listing ? () => market.buy(listing) : undefined}\n onOffer={isOwner ? undefined : market.offer}\n />\n );\n })}\n </div>\n\n {!listedOnly && (\n <LoadMoreSentinel\n hasMore={hasMore}\n isLoading={isLoadingMore}\n onLoadMore={() => setPage((p) => p + 1)}\n />\n )}\n </div>\n )}\n\n {market.dialogs}\n </PageContainer>\n );\n}\n"],"mappings":"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","names":["XIcon","Link"]}
|
|
@@ -15,6 +15,7 @@ import { useMedialaneApp } from "./medialane-app.js";
|
|
|
15
15
|
import { cn } from "../utils/cn.js";
|
|
16
16
|
import { isSameAddress } from "../utils/same-address.js";
|
|
17
17
|
import { useTokensByIpType } from "../utils/use-tokens-by-ip-type.js";
|
|
18
|
+
import { emptyMessages } from "../utils/empty-messages.js";
|
|
18
19
|
const PAGE_SIZE = 24;
|
|
19
20
|
function FilterChip({ active, onClick, label }) {
|
|
20
21
|
return /* @__PURE__ */ jsx(
|
|
@@ -242,8 +243,8 @@ function IpTypePage({ slug, useMarketActions }) {
|
|
|
242
243
|
isInitialLoading ? /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-4", children: Array.from({ length: PAGE_SIZE }).map((_, i) => /* @__PURE__ */ jsx(TokenCardSkeleton, {}, i)) }) : displayed.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "py-24 flex flex-col items-center gap-4 text-center", children: [
|
|
243
244
|
config && Icon && /* @__PURE__ */ jsx("div", { className: cn("h-16 w-16 rounded-2xl flex items-center justify-center", config.bgClass), children: /* @__PURE__ */ jsx(Icon, { className: cn("h-8 w-8", config.colorClass) }) }),
|
|
244
245
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
245
|
-
/* @__PURE__ */ jsx("p", { className: "font-semibold text-lg", children: listedOnly ? "
|
|
246
|
-
/* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-sm mt-1", children: listedOnly ? "Try removing the 'Listed only' filter to see all assets." :
|
|
246
|
+
/* @__PURE__ */ jsx("p", { className: "font-semibold text-lg", children: listedOnly ? "Listed assets appear here" : emptyMessages.assetsOfType.title }),
|
|
247
|
+
/* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-sm mt-1", children: listedOnly ? "Try removing the 'Listed only' filter to see all assets." : emptyMessages.assetsOfType.description })
|
|
247
248
|
] }),
|
|
248
249
|
/* @__PURE__ */ jsx(Button, { asChild: true, variant: "outline", children: /* @__PURE__ */ jsx(Link, { href: "/launchpad/single-editions", children: "Create Asset" }) })
|
|
249
250
|
] }) : /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/ip-type-page.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState, useEffect, useRef } from \"react\";\nimport { SlidersHorizontal, Search, X as XIcon } from \"lucide-react\";\nimport type { ApiToken } from \"@medialane/sdk\";\nimport Link from \"./link.js\";\nimport { Badge } from \"./badge.js\";\nimport { Button } from \"./button.js\";\nimport { Dialog, DialogContent, DialogTitle } from \"./dialog.js\";\nimport { Input } from \"./input.js\";\nimport { PageContainer } from \"./page-container.js\";\nimport { LoadMoreSentinel } from \"./load-more-sentinel.js\";\nimport { IP_TYPE_CONFIG, IP_TYPE_MAP } from \"./ip-type-badge.js\";\nimport { TokenCard, TokenCardSkeleton } from \"./token-card.js\";\nimport { useMedialaneApp } from \"./medialane-app.js\";\nimport type { CollectionMarketActions } from \"./collection-page.js\";\nimport { cn } from \"../utils/cn.js\";\nimport { isSameAddress } from \"../utils/same-address.js\";\nimport { useTokensByIpType } from \"../utils/use-tokens-by-ip-type.js\";\n\nconst PAGE_SIZE = 24;\n\nfunction FilterChip({ active, onClick, label }: { active: boolean; onClick: () => void; label: string }) {\n return (\n <button\n onClick={onClick}\n className={cn(\n \"text-xs px-3 py-1.5 rounded-full border transition-colors whitespace-nowrap\",\n active\n ? \"border-primary bg-primary/10 text-primary font-medium\"\n : \"border-border text-muted-foreground hover:border-primary/50\"\n )}\n >\n {label}\n </button>\n );\n}\n\nexport interface IpTypePageProps {\n slug: string;\n useMarketActions: () => CollectionMarketActions;\n}\n\nexport function IpTypePage({ slug, useMarketActions }: IpTypePageProps) {\n const { walletAddress } = useMedialaneApp();\n const market = useMarketActions();\n const config = IP_TYPE_MAP[slug];\n const Icon = config?.icon;\n const [page, setPage] = useState(1);\n const [listedOnly, setListedOnly] = useState(false);\n const [allTokens, setAllTokens] = useState<ApiToken[]>([]);\n const prevSlug = useRef(slug);\n\n const [filtersOpen, setFiltersOpen] = useState(false);\n const [sortOrder, setSortOrder] = useState<\"recent\" | \"price_asc\" | \"price_desc\">(\"recent\");\n const [licenseFilter, setLicenseFilter] = useState<string>(\"all\");\n const [creatorSearchInput, setCreatorSearchInput] = useState(\"\");\n const [creatorSearch, setCreatorSearch] = useState(\"\");\n\n useEffect(() => {\n if (prevSlug.current !== slug) {\n prevSlug.current = slug;\n setPage(1);\n setAllTokens([]);\n }\n }, [slug]);\n\n useEffect(() => {\n const t = setTimeout(() => setCreatorSearch(creatorSearchInput), 300);\n return () => clearTimeout(t);\n }, [creatorSearchInput]);\n\n const { tokens, meta, isLoading } = useTokensByIpType(slug, page, PAGE_SIZE);\n\n useEffect(() => {\n if (isLoading) return;\n if (page === 1) {\n setAllTokens(tokens);\n } else {\n setAllTokens((prev) => {\n const seen = new Set(prev.map((t) => `${t.contractAddress}:${t.tokenId}`));\n const fresh = tokens.filter((t) => !seen.has(`${t.contractAddress}:${t.tokenId}`));\n return fresh.length > 0 ? [...prev, ...fresh] : prev;\n });\n }\n }, [tokens, isLoading, page]);\n\n const activeFilterCount =\n (sortOrder !== \"recent\" ? 1 : 0) +\n (licenseFilter !== \"all\" ? 1 : 0) +\n (creatorSearch !== \"\" ? 1 : 0);\n const activeChipCount = activeFilterCount + (listedOnly ? 1 : 0);\n const hasActiveFilters = activeChipCount > 0;\n const resetAll = () => {\n setSortOrder(\"recent\");\n setLicenseFilter(\"all\");\n setCreatorSearch(\"\");\n setCreatorSearchInput(\"\");\n setListedOnly(false);\n };\n\n let displayed = listedOnly\n ? allTokens.filter((t) => (t.activeOrders?.length ?? 0) > 0)\n : [...allTokens];\n\n if (licenseFilter !== \"all\") {\n displayed = displayed.filter((t) =>\n t.metadata?.attributes?.some(\n (a) => a.trait_type === \"License\" && a.value === licenseFilter\n )\n );\n }\n if (creatorSearch) {\n const q = creatorSearch.toLowerCase();\n displayed = displayed.filter((t) => {\n const creatorVal =\n t.metadata?.attributes?.find((a) => a.trait_type === \"Creator\")?.value ?? \"\";\n return (\n String(creatorVal).toLowerCase().includes(q) ||\n t.contractAddress.toLowerCase().includes(q)\n );\n });\n }\n if (sortOrder === \"price_asc\") {\n displayed = [...displayed].sort((a, b) => {\n const pa = parseFloat(a.activeOrders?.[0]?.price?.formatted ?? \"Infinity\");\n const pb = parseFloat(b.activeOrders?.[0]?.price?.formatted ?? \"Infinity\");\n return pa - pb;\n });\n } else if (sortOrder === \"price_desc\") {\n displayed = [...displayed].sort((a, b) => {\n const pa = parseFloat(a.activeOrders?.[0]?.price?.formatted ?? \"0\");\n const pb = parseFloat(b.activeOrders?.[0]?.price?.formatted ?? \"0\");\n return pb - pa;\n });\n }\n\n const isInitialLoading = isLoading && allTokens.length === 0;\n const isLoadingMore = isLoading && allTokens.length > 0;\n const hasMore = meta?.total != null ? allTokens.length < meta.total : false;\n const listedCount = allTokens.filter((t) => (t.activeOrders?.length ?? 0) > 0).length;\n\n return (\n <PageContainer className=\"box-border max-w-full pt-20 pb-16 space-y-8\">\n\n <div className=\"space-y-4\">\n <div className=\"flex items-center gap-4\">\n {config && Icon && (\n <div className={cn(\"h-14 w-14 rounded-2xl flex items-center justify-center shadow-lg\", config.bgClass)}>\n <Icon className={cn(\"h-7 w-7\", config.colorClass)} />\n </div>\n )}\n <div>\n <h1 className=\"text-3xl font-semibold\">{config?.label ?? slug}</h1>\n <p className=\"text-muted-foreground mt-0.5\">\n {meta?.total != null ? (\n <>{meta.total.toLocaleString()} assets · {listedCount} market</>\n ) : (\n \"Browsing indexed digital assets on Medialane\"\n )}\n </p>\n </div>\n </div>\n\n <div className=\"flex items-center gap-2 flex-wrap\">\n <button\n onClick={() => setFiltersOpen(true)}\n className={cn(\n \"inline-flex items-center gap-1.5 text-xs px-3.5 py-2 rounded-full border font-medium transition-colors\",\n hasActiveFilters\n ? \"border-primary bg-primary/10 text-primary\"\n : \"border-border text-muted-foreground\"\n )}\n >\n <SlidersHorizontal className=\"h-3.5 w-3.5\" />\n Filters\n {activeChipCount > 0 && (\n <span className=\"ml-0.5 bg-primary text-primary-foreground rounded-full px-1.5 text-2xs font-bold leading-4\">\n {activeChipCount}\n </span>\n )}\n </button>\n\n {listedOnly && (\n <Badge variant=\"secondary\" className=\"cursor-pointer gap-1 text-xs\" onClick={() => setListedOnly(false)}>\n Listed only\n <XIcon className=\"h-3 w-3\" />\n </Badge>\n )}\n {sortOrder !== \"recent\" && (\n <Badge variant=\"secondary\" className=\"cursor-pointer gap-1 text-xs\" onClick={() => setSortOrder(\"recent\")}>\n {sortOrder === \"price_asc\" ? \"Price ↑\" : \"Price ↓\"}\n <XIcon className=\"h-3 w-3\" />\n </Badge>\n )}\n {licenseFilter !== \"all\" && (\n <Badge variant=\"secondary\" className=\"cursor-pointer gap-1 text-xs\" onClick={() => setLicenseFilter(\"all\")}>\n {licenseFilter}\n <XIcon className=\"h-3 w-3\" />\n </Badge>\n )}\n {creatorSearch && (\n <Badge variant=\"secondary\" className=\"cursor-pointer gap-1 text-xs\" onClick={() => { setCreatorSearch(\"\"); setCreatorSearchInput(\"\"); }}>\n {creatorSearch.length > 10 ? `${creatorSearch.slice(0, 10)}…` : creatorSearch}\n <XIcon className=\"h-3 w-3\" />\n </Badge>\n )}\n </div>\n\n <Dialog open={filtersOpen} onOpenChange={setFiltersOpen}>\n <DialogContent className=\"w-full max-w-sm sm:max-w-md p-0 overflow-hidden gap-0 flex flex-col max-h-[85svh]\">\n <div className=\"flex items-center justify-between px-5 py-4 border-b border-border/60 pr-12\">\n <DialogTitle className=\"text-base font-bold flex items-center gap-2\">\n <SlidersHorizontal className=\"h-4 w-4 text-primary\" />\n Filters\n </DialogTitle>\n {hasActiveFilters && (\n <Button variant=\"ghost\" size=\"sm\" className=\"h-7 text-xs text-muted-foreground\" onClick={resetAll}>\n Clear all\n </Button>\n )}\n </div>\n\n <div className=\"flex-1 overflow-y-auto px-5 py-4 space-y-5\">\n\n <div className=\"space-y-2\">\n <p className=\"text-2xs font-semibold text-muted-foreground\">Status</p>\n <div className=\"flex flex-wrap gap-1.5\">\n <FilterChip active={!listedOnly} onClick={() => setListedOnly(false)} label=\"All\" />\n <FilterChip\n active={listedOnly}\n onClick={() => setListedOnly(true)}\n label={`Listed only${listedCount > 0 ? ` (${listedCount})` : \"\"}`}\n />\n </div>\n </div>\n\n <div className=\"space-y-2\">\n <p className=\"text-2xs font-semibold text-muted-foreground\">Sort</p>\n <div className=\"flex flex-wrap gap-1.5\">\n <FilterChip active={sortOrder === \"recent\"} onClick={() => setSortOrder(\"recent\")} label=\"Recent\" />\n <FilterChip active={sortOrder === \"price_asc\"} onClick={() => setSortOrder(\"price_asc\")} label=\"Price ↑\" />\n <FilterChip active={sortOrder === \"price_desc\"} onClick={() => setSortOrder(\"price_desc\")} label=\"Price ↓\" />\n </div>\n </div>\n\n <div className=\"space-y-2\">\n <p className=\"text-2xs font-semibold text-muted-foreground\">License</p>\n <div className=\"flex flex-wrap gap-1.5\">\n {[\"all\", \"CC0\", \"CC BY\", \"CC BY-SA\", \"CC BY-NC\", \"CC BY-ND\", \"Custom\"].map((lic) => (\n <FilterChip\n key={lic}\n active={licenseFilter === lic}\n onClick={() => setLicenseFilter(lic)}\n label={lic === \"all\" ? \"All licenses\" : lic}\n />\n ))}\n </div>\n </div>\n\n <div className=\"space-y-2\">\n <p className=\"text-2xs font-semibold text-muted-foreground\">Creator</p>\n <div className=\"relative\">\n <Search className=\"absolute left-2.5 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-muted-foreground\" />\n <Input\n className=\"h-9 text-sm pl-8\"\n placeholder=\"Name or wallet address…\"\n value={creatorSearchInput}\n onChange={(e) => setCreatorSearchInput(e.target.value)}\n />\n </div>\n </div>\n\n <div className=\"space-y-2 pt-1 border-t border-border/60\">\n <p className=\"text-2xs font-semibold text-muted-foreground\">IP Type</p>\n <div className=\"flex flex-wrap gap-1.5\">\n {IP_TYPE_CONFIG.map((t) => (\n <Link\n key={t.slug}\n href={`/${t.slug}`}\n className={cn(\n \"inline-flex items-center gap-1.5 text-xs px-3 py-1.5 rounded-full border transition-colors whitespace-nowrap\",\n t.slug === slug\n ? \"border-primary bg-primary/10 text-primary font-medium\"\n : \"border-border text-muted-foreground hover:border-primary/50\"\n )}\n >\n <t.icon className={cn(\"h-3 w-3\", t.slug === slug ? t.colorClass : \"\")} />\n {t.label}\n </Link>\n ))}\n </div>\n </div>\n </div>\n\n <div className=\"px-5 py-3 border-t border-border/60\">\n <Button className=\"w-full\" onClick={() => setFiltersOpen(false)}>\n Apply filters\n </Button>\n </div>\n </DialogContent>\n </Dialog>\n </div>\n\n {isInitialLoading ? (\n <div className=\"grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-4\">\n {Array.from({ length: PAGE_SIZE }).map((_, i) => (\n <TokenCardSkeleton key={i} />\n ))}\n </div>\n ) : displayed.length === 0 ? (\n <div className=\"py-24 flex flex-col items-center gap-4 text-center\">\n {config && Icon && (\n <div className={cn(\"h-16 w-16 rounded-2xl flex items-center justify-center\", config.bgClass)}>\n <Icon className={cn(\"h-8 w-8\", config.colorClass)} />\n </div>\n )}\n <div>\n <p className=\"font-semibold text-lg\">\n {listedOnly ? \"No listed assets yet\" : \"No assets indexed yet\"}\n </p>\n <p className=\"text-muted-foreground text-sm mt-1\">\n {listedOnly\n ? \"Try removing the 'Listed only' filter to see all assets.\"\n : `Be the first to mint a ${config?.label ?? slug} asset on Medialane.`}\n </p>\n </div>\n <Button asChild variant=\"outline\">\n <Link href=\"/launchpad/single-editions\">Create Asset</Link>\n </Button>\n </div>\n ) : (\n <div className=\"space-y-6\">\n <div className=\"grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-4\">\n {displayed.map((token) => {\n const listing = token.activeOrders?.find((o) => o.offer.itemType === \"ERC721\" || o.offer.itemType === \"ERC1155\");\n const isOwner = !!walletAddress && !!token.owner && isSameAddress(token.owner, walletAddress);\n return (\n <TokenCard\n key={`${token.contractAddress}:${token.tokenId}`}\n token={token}\n isOwner={isOwner}\n onBuy={!isOwner && listing ? () => market.buy(listing) : undefined}\n onOffer={isOwner ? undefined : market.offer}\n />\n );\n })}\n </div>\n\n {!listedOnly && (\n <LoadMoreSentinel\n hasMore={hasMore}\n isLoading={isLoadingMore}\n onLoadMore={() => setPage((p) => p + 1)}\n />\n )}\n </div>\n )}\n\n {market.dialogs}\n </PageContainer>\n );\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/components/ip-type-page.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState, useEffect, useRef } from \"react\";\nimport { SlidersHorizontal, Search, X as XIcon } from \"lucide-react\";\nimport type { ApiToken } from \"@medialane/sdk\";\nimport Link from \"./link.js\";\nimport { Badge } from \"./badge.js\";\nimport { Button } from \"./button.js\";\nimport { Dialog, DialogContent, DialogTitle } from \"./dialog.js\";\nimport { Input } from \"./input.js\";\nimport { PageContainer } from \"./page-container.js\";\nimport { LoadMoreSentinel } from \"./load-more-sentinel.js\";\nimport { IP_TYPE_CONFIG, IP_TYPE_MAP } from \"./ip-type-badge.js\";\nimport { TokenCard, TokenCardSkeleton } from \"./token-card.js\";\nimport { useMedialaneApp } from \"./medialane-app.js\";\nimport type { CollectionMarketActions } from \"./collection-page.js\";\nimport { cn } from \"../utils/cn.js\";\nimport { isSameAddress } from \"../utils/same-address.js\";\nimport { useTokensByIpType } from \"../utils/use-tokens-by-ip-type.js\";\nimport { emptyMessages } from \"../utils/empty-messages.js\";\n\nconst PAGE_SIZE = 24;\n\nfunction FilterChip({ active, onClick, label }: { active: boolean; onClick: () => void; label: string }) {\n return (\n <button\n onClick={onClick}\n className={cn(\n \"text-xs px-3 py-1.5 rounded-full border transition-colors whitespace-nowrap\",\n active\n ? \"border-primary bg-primary/10 text-primary font-medium\"\n : \"border-border text-muted-foreground hover:border-primary/50\"\n )}\n >\n {label}\n </button>\n );\n}\n\nexport interface IpTypePageProps {\n slug: string;\n useMarketActions: () => CollectionMarketActions;\n}\n\nexport function IpTypePage({ slug, useMarketActions }: IpTypePageProps) {\n const { walletAddress } = useMedialaneApp();\n const market = useMarketActions();\n const config = IP_TYPE_MAP[slug];\n const Icon = config?.icon;\n const [page, setPage] = useState(1);\n const [listedOnly, setListedOnly] = useState(false);\n const [allTokens, setAllTokens] = useState<ApiToken[]>([]);\n const prevSlug = useRef(slug);\n\n const [filtersOpen, setFiltersOpen] = useState(false);\n const [sortOrder, setSortOrder] = useState<\"recent\" | \"price_asc\" | \"price_desc\">(\"recent\");\n const [licenseFilter, setLicenseFilter] = useState<string>(\"all\");\n const [creatorSearchInput, setCreatorSearchInput] = useState(\"\");\n const [creatorSearch, setCreatorSearch] = useState(\"\");\n\n useEffect(() => {\n if (prevSlug.current !== slug) {\n prevSlug.current = slug;\n setPage(1);\n setAllTokens([]);\n }\n }, [slug]);\n\n useEffect(() => {\n const t = setTimeout(() => setCreatorSearch(creatorSearchInput), 300);\n return () => clearTimeout(t);\n }, [creatorSearchInput]);\n\n const { tokens, meta, isLoading } = useTokensByIpType(slug, page, PAGE_SIZE);\n\n useEffect(() => {\n if (isLoading) return;\n if (page === 1) {\n setAllTokens(tokens);\n } else {\n setAllTokens((prev) => {\n const seen = new Set(prev.map((t) => `${t.contractAddress}:${t.tokenId}`));\n const fresh = tokens.filter((t) => !seen.has(`${t.contractAddress}:${t.tokenId}`));\n return fresh.length > 0 ? [...prev, ...fresh] : prev;\n });\n }\n }, [tokens, isLoading, page]);\n\n const activeFilterCount =\n (sortOrder !== \"recent\" ? 1 : 0) +\n (licenseFilter !== \"all\" ? 1 : 0) +\n (creatorSearch !== \"\" ? 1 : 0);\n const activeChipCount = activeFilterCount + (listedOnly ? 1 : 0);\n const hasActiveFilters = activeChipCount > 0;\n const resetAll = () => {\n setSortOrder(\"recent\");\n setLicenseFilter(\"all\");\n setCreatorSearch(\"\");\n setCreatorSearchInput(\"\");\n setListedOnly(false);\n };\n\n let displayed = listedOnly\n ? allTokens.filter((t) => (t.activeOrders?.length ?? 0) > 0)\n : [...allTokens];\n\n if (licenseFilter !== \"all\") {\n displayed = displayed.filter((t) =>\n t.metadata?.attributes?.some(\n (a) => a.trait_type === \"License\" && a.value === licenseFilter\n )\n );\n }\n if (creatorSearch) {\n const q = creatorSearch.toLowerCase();\n displayed = displayed.filter((t) => {\n const creatorVal =\n t.metadata?.attributes?.find((a) => a.trait_type === \"Creator\")?.value ?? \"\";\n return (\n String(creatorVal).toLowerCase().includes(q) ||\n t.contractAddress.toLowerCase().includes(q)\n );\n });\n }\n if (sortOrder === \"price_asc\") {\n displayed = [...displayed].sort((a, b) => {\n const pa = parseFloat(a.activeOrders?.[0]?.price?.formatted ?? \"Infinity\");\n const pb = parseFloat(b.activeOrders?.[0]?.price?.formatted ?? \"Infinity\");\n return pa - pb;\n });\n } else if (sortOrder === \"price_desc\") {\n displayed = [...displayed].sort((a, b) => {\n const pa = parseFloat(a.activeOrders?.[0]?.price?.formatted ?? \"0\");\n const pb = parseFloat(b.activeOrders?.[0]?.price?.formatted ?? \"0\");\n return pb - pa;\n });\n }\n\n const isInitialLoading = isLoading && allTokens.length === 0;\n const isLoadingMore = isLoading && allTokens.length > 0;\n const hasMore = meta?.total != null ? allTokens.length < meta.total : false;\n const listedCount = allTokens.filter((t) => (t.activeOrders?.length ?? 0) > 0).length;\n\n return (\n <PageContainer className=\"box-border max-w-full pt-20 pb-16 space-y-8\">\n\n <div className=\"space-y-4\">\n <div className=\"flex items-center gap-4\">\n {config && Icon && (\n <div className={cn(\"h-14 w-14 rounded-2xl flex items-center justify-center shadow-lg\", config.bgClass)}>\n <Icon className={cn(\"h-7 w-7\", config.colorClass)} />\n </div>\n )}\n <div>\n <h1 className=\"text-3xl font-semibold\">{config?.label ?? slug}</h1>\n <p className=\"text-muted-foreground mt-0.5\">\n {meta?.total != null ? (\n <>{meta.total.toLocaleString()} assets · {listedCount} market</>\n ) : (\n \"Browsing indexed digital assets on Medialane\"\n )}\n </p>\n </div>\n </div>\n\n <div className=\"flex items-center gap-2 flex-wrap\">\n <button\n onClick={() => setFiltersOpen(true)}\n className={cn(\n \"inline-flex items-center gap-1.5 text-xs px-3.5 py-2 rounded-full border font-medium transition-colors\",\n hasActiveFilters\n ? \"border-primary bg-primary/10 text-primary\"\n : \"border-border text-muted-foreground\"\n )}\n >\n <SlidersHorizontal className=\"h-3.5 w-3.5\" />\n Filters\n {activeChipCount > 0 && (\n <span className=\"ml-0.5 bg-primary text-primary-foreground rounded-full px-1.5 text-2xs font-bold leading-4\">\n {activeChipCount}\n </span>\n )}\n </button>\n\n {listedOnly && (\n <Badge variant=\"secondary\" className=\"cursor-pointer gap-1 text-xs\" onClick={() => setListedOnly(false)}>\n Listed only\n <XIcon className=\"h-3 w-3\" />\n </Badge>\n )}\n {sortOrder !== \"recent\" && (\n <Badge variant=\"secondary\" className=\"cursor-pointer gap-1 text-xs\" onClick={() => setSortOrder(\"recent\")}>\n {sortOrder === \"price_asc\" ? \"Price ↑\" : \"Price ↓\"}\n <XIcon className=\"h-3 w-3\" />\n </Badge>\n )}\n {licenseFilter !== \"all\" && (\n <Badge variant=\"secondary\" className=\"cursor-pointer gap-1 text-xs\" onClick={() => setLicenseFilter(\"all\")}>\n {licenseFilter}\n <XIcon className=\"h-3 w-3\" />\n </Badge>\n )}\n {creatorSearch && (\n <Badge variant=\"secondary\" className=\"cursor-pointer gap-1 text-xs\" onClick={() => { setCreatorSearch(\"\"); setCreatorSearchInput(\"\"); }}>\n {creatorSearch.length > 10 ? `${creatorSearch.slice(0, 10)}…` : creatorSearch}\n <XIcon className=\"h-3 w-3\" />\n </Badge>\n )}\n </div>\n\n <Dialog open={filtersOpen} onOpenChange={setFiltersOpen}>\n <DialogContent className=\"w-full max-w-sm sm:max-w-md p-0 overflow-hidden gap-0 flex flex-col max-h-[85svh]\">\n <div className=\"flex items-center justify-between px-5 py-4 border-b border-border/60 pr-12\">\n <DialogTitle className=\"text-base font-bold flex items-center gap-2\">\n <SlidersHorizontal className=\"h-4 w-4 text-primary\" />\n Filters\n </DialogTitle>\n {hasActiveFilters && (\n <Button variant=\"ghost\" size=\"sm\" className=\"h-7 text-xs text-muted-foreground\" onClick={resetAll}>\n Clear all\n </Button>\n )}\n </div>\n\n <div className=\"flex-1 overflow-y-auto px-5 py-4 space-y-5\">\n\n <div className=\"space-y-2\">\n <p className=\"text-2xs font-semibold text-muted-foreground\">Status</p>\n <div className=\"flex flex-wrap gap-1.5\">\n <FilterChip active={!listedOnly} onClick={() => setListedOnly(false)} label=\"All\" />\n <FilterChip\n active={listedOnly}\n onClick={() => setListedOnly(true)}\n label={`Listed only${listedCount > 0 ? ` (${listedCount})` : \"\"}`}\n />\n </div>\n </div>\n\n <div className=\"space-y-2\">\n <p className=\"text-2xs font-semibold text-muted-foreground\">Sort</p>\n <div className=\"flex flex-wrap gap-1.5\">\n <FilterChip active={sortOrder === \"recent\"} onClick={() => setSortOrder(\"recent\")} label=\"Recent\" />\n <FilterChip active={sortOrder === \"price_asc\"} onClick={() => setSortOrder(\"price_asc\")} label=\"Price ↑\" />\n <FilterChip active={sortOrder === \"price_desc\"} onClick={() => setSortOrder(\"price_desc\")} label=\"Price ↓\" />\n </div>\n </div>\n\n <div className=\"space-y-2\">\n <p className=\"text-2xs font-semibold text-muted-foreground\">License</p>\n <div className=\"flex flex-wrap gap-1.5\">\n {[\"all\", \"CC0\", \"CC BY\", \"CC BY-SA\", \"CC BY-NC\", \"CC BY-ND\", \"Custom\"].map((lic) => (\n <FilterChip\n key={lic}\n active={licenseFilter === lic}\n onClick={() => setLicenseFilter(lic)}\n label={lic === \"all\" ? \"All licenses\" : lic}\n />\n ))}\n </div>\n </div>\n\n <div className=\"space-y-2\">\n <p className=\"text-2xs font-semibold text-muted-foreground\">Creator</p>\n <div className=\"relative\">\n <Search className=\"absolute left-2.5 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-muted-foreground\" />\n <Input\n className=\"h-9 text-sm pl-8\"\n placeholder=\"Name or wallet address…\"\n value={creatorSearchInput}\n onChange={(e) => setCreatorSearchInput(e.target.value)}\n />\n </div>\n </div>\n\n <div className=\"space-y-2 pt-1 border-t border-border/60\">\n <p className=\"text-2xs font-semibold text-muted-foreground\">IP Type</p>\n <div className=\"flex flex-wrap gap-1.5\">\n {IP_TYPE_CONFIG.map((t) => (\n <Link\n key={t.slug}\n href={`/${t.slug}`}\n className={cn(\n \"inline-flex items-center gap-1.5 text-xs px-3 py-1.5 rounded-full border transition-colors whitespace-nowrap\",\n t.slug === slug\n ? \"border-primary bg-primary/10 text-primary font-medium\"\n : \"border-border text-muted-foreground hover:border-primary/50\"\n )}\n >\n <t.icon className={cn(\"h-3 w-3\", t.slug === slug ? t.colorClass : \"\")} />\n {t.label}\n </Link>\n ))}\n </div>\n </div>\n </div>\n\n <div className=\"px-5 py-3 border-t border-border/60\">\n <Button className=\"w-full\" onClick={() => setFiltersOpen(false)}>\n Apply filters\n </Button>\n </div>\n </DialogContent>\n </Dialog>\n </div>\n\n {isInitialLoading ? (\n <div className=\"grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-4\">\n {Array.from({ length: PAGE_SIZE }).map((_, i) => (\n <TokenCardSkeleton key={i} />\n ))}\n </div>\n ) : displayed.length === 0 ? (\n <div className=\"py-24 flex flex-col items-center gap-4 text-center\">\n {config && Icon && (\n <div className={cn(\"h-16 w-16 rounded-2xl flex items-center justify-center\", config.bgClass)}>\n <Icon className={cn(\"h-8 w-8\", config.colorClass)} />\n </div>\n )}\n <div>\n <p className=\"font-semibold text-lg\">\n {listedOnly ? \"Listed assets appear here\" : emptyMessages.assetsOfType.title}\n </p>\n <p className=\"text-muted-foreground text-sm mt-1\">\n {listedOnly\n ? \"Try removing the 'Listed only' filter to see all assets.\"\n : emptyMessages.assetsOfType.description}\n </p>\n </div>\n <Button asChild variant=\"outline\">\n <Link href=\"/launchpad/single-editions\">Create Asset</Link>\n </Button>\n </div>\n ) : (\n <div className=\"space-y-6\">\n <div className=\"grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-4\">\n {displayed.map((token) => {\n const listing = token.activeOrders?.find((o) => o.offer.itemType === \"ERC721\" || o.offer.itemType === \"ERC1155\");\n const isOwner = !!walletAddress && !!token.owner && isSameAddress(token.owner, walletAddress);\n return (\n <TokenCard\n key={`${token.contractAddress}:${token.tokenId}`}\n token={token}\n isOwner={isOwner}\n onBuy={!isOwner && listing ? () => market.buy(listing) : undefined}\n onOffer={isOwner ? undefined : market.offer}\n />\n );\n })}\n </div>\n\n {!listedOnly && (\n <LoadMoreSentinel\n hasMore={hasMore}\n isLoading={isLoadingMore}\n onLoadMore={() => setPage((p) => p + 1)}\n />\n )}\n </div>\n )}\n\n {market.dialogs}\n </PageContainer>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -70,7 +70,7 @@ function MarketplaceTxLink({ txHash, explorerUrl, className }) {
|
|
|
70
70
|
}
|
|
71
71
|
function MarketplaceProcessingState({
|
|
72
72
|
title,
|
|
73
|
-
description = "
|
|
73
|
+
description = "Keep this window open until it finishes.",
|
|
74
74
|
imageUrl,
|
|
75
75
|
imageAlt = "Token preview",
|
|
76
76
|
txHash,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/marketplace-dialog-primitives.tsx"],"sourcesContent":["\"use client\";\n\nimport type { ReactNode } from \"react\";\nimport Image from \"./image.js\";\nimport { AlertCircle, ExternalLink, Loader2, Wallet } from \"lucide-react\";\nimport { Alert, AlertDescription } from \"./alert.js\";\nimport { Button } from \"./button.js\";\nimport { CurrencyIcon } from \"./currency-icon.js\";\nimport { cn } from \"../utils/cn.js\";\n\ninterface MarketplaceTxLinkProps {\n txHash: string;\n explorerUrl: string;\n className?: string;\n}\n\nexport function MarketplaceTxLink({ txHash, explorerUrl, className }: MarketplaceTxLinkProps) {\n return (\n <a\n href={`${explorerUrl}/tx/${txHash}`}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={cn(\n \"inline-flex items-center gap-1.5 text-xs text-muted-foreground hover:text-foreground transition-colors\",\n className\n )}\n >\n <span className=\"tabular-nums\">{txHash.slice(0, 10)}…{txHash.slice(-8)}</span>\n <ExternalLink className=\"h-3 w-3\" />\n </a>\n );\n}\n\ninterface MarketplaceProcessingStateProps {\n title: string;\n description?: string;\n imageUrl?: string | null;\n imageAlt?: string;\n txHash?: string | null;\n explorerUrl?: string;\n}\n\nexport function MarketplaceProcessingState({\n title,\n description = \"Please wait, do not close this window.\",\n imageUrl,\n imageAlt = \"Token preview\",\n txHash,\n explorerUrl,\n}: MarketplaceProcessingStateProps) {\n return (\n <div className=\"flex flex-col items-center gap-5 p-6 py-8\">\n {imageUrl ? (\n <div className=\"relative h-20 w-20 rounded-2xl overflow-hidden border border-border\">\n <Image src={imageUrl} alt={imageAlt} fill sizes=\"80px\" className=\"object-cover\" unoptimized />\n <div className=\"absolute inset-0 bg-background/50 flex items-center justify-center\">\n <Loader2 className=\"h-7 w-7 animate-spin text-primary\" />\n </div>\n </div>\n ) : (\n <Loader2 className=\"h-10 w-10 animate-spin text-primary\" />\n )}\n <div className=\"text-center space-y-1\">\n <p className=\"font-semibold\">{title}</p>\n {txHash && explorerUrl ? (\n <MarketplaceTxLink txHash={txHash} explorerUrl={explorerUrl} className=\"mt-1\" />\n ) : null}\n </div>\n <p className=\"text-sm text-muted-foreground\">{description}</p>\n </div>\n );\n}\n\ninterface MarketplaceSignInGateProps {\n title: string;\n description: string;\n href: string;\n ctaLabel?: string;\n}\n\nexport function MarketplaceSignInGate({ title, description, href, ctaLabel = \"Set up account\" }: MarketplaceSignInGateProps) {\n return (\n <div className=\"flex flex-col items-center gap-4 p-6 py-10 text-center\">\n <Wallet className=\"h-10 w-10 text-muted-foreground\" />\n <div>\n <p className=\"font-semibold\">{title}</p>\n <p className=\"text-sm text-muted-foreground mt-1\">{description}</p>\n </div>\n <div className=\"btn-border-animated w-full p-[1px] rounded-lg\">\n <Button\n asChild\n className=\"w-full bg-transparent text-white rounded-[7px] hover:bg-transparent hover:brightness-110 active:scale-[0.98] transition-all\"\n >\n <a href={href}>{ctaLabel}</a>\n </Button>\n </div>\n </div>\n );\n}\n\ninterface MarketplaceErrorStateProps {\n tokenImage?: string | null;\n name: string;\n title: string;\n description: ReactNode;\n error?: string | null;\n txHash?: string | null;\n explorerUrl: string;\n onRetry?: () => void;\n onDone: () => void;\n doneLabel?: string;\n}\n\nexport function MarketplaceErrorState({\n tokenImage,\n name,\n title,\n description,\n error,\n txHash,\n explorerUrl,\n onRetry,\n onDone,\n doneLabel = \"Done\",\n}: MarketplaceErrorStateProps) {\n return (\n <div className=\"flex flex-col items-center gap-5 p-6 py-8\">\n {tokenImage ? (\n <div className=\"relative\">\n <div className=\"relative h-32 w-32 rounded-2xl overflow-hidden border border-border\">\n <Image src={tokenImage} alt={name} fill sizes=\"128px\" className=\"object-cover\" unoptimized />\n </div>\n <div className=\"absolute -bottom-2 -right-2 h-9 w-9 rounded-full bg-destructive flex items-center justify-center border-2 border-background\">\n <AlertCircle className=\"h-5 w-5 text-white\" />\n </div>\n </div>\n ) : (\n <div className=\"h-16 w-16 rounded-full bg-destructive/15 flex items-center justify-center\">\n <AlertCircle className=\"h-9 w-9 text-destructive\" />\n </div>\n )}\n <div className=\"text-center space-y-1 max-w-full\">\n <p className=\"font-bold text-xl break-words\">{title}</p>\n <p className=\"text-sm text-muted-foreground break-words\">{description}</p>\n </div>\n {error ? (\n <Alert variant=\"destructive\" className=\"text-left\">\n <AlertCircle className=\"h-4 w-4\" />\n <AlertDescription>{error}</AlertDescription>\n </Alert>\n ) : null}\n {txHash && <MarketplaceTxLink txHash={txHash} explorerUrl={explorerUrl} />}\n <div className=\"flex w-full gap-2\">\n {onRetry ? (\n <Button variant=\"outline\" className=\"flex-1 h-11\" onClick={onRetry}>\n Try again\n </Button>\n ) : null}\n <Button className=\"flex-1 h-11\" onClick={onDone}>{doneLabel}</Button>\n </div>\n </div>\n );\n}\n\ninterface MarketplaceDialogHeroProps {\n tokenImage?: string | null;\n tokenName?: string;\n tokenId: string;\n fallbackIcon: ReactNode;\n badge?: ReactNode;\n}\n\nexport function MarketplaceDialogHero({\n tokenImage,\n tokenName,\n tokenId,\n fallbackIcon,\n badge,\n}: MarketplaceDialogHeroProps) {\n const name = tokenName || `Token #${tokenId}`;\n\n return (\n <div className=\"relative flex justify-center pt-6 shrink-0\">\n <div className=\"relative h-32 w-32 rounded-2xl overflow-hidden border border-border bg-muted\">\n {tokenImage ? (\n <Image src={tokenImage} alt={name} fill sizes=\"128px\" className=\"object-cover\" unoptimized />\n ) : (\n <div className=\"h-full w-full bg-gradient-to-br from-brand-blue/20 via-brand-purple/10 to-transparent flex items-center justify-center\">\n {fallbackIcon}\n </div>\n )}\n </div>\n {badge}\n </div>\n );\n}\n\ninterface CurrencyPickerProps {\n currencies: string[];\n value: string;\n onChange: (value: string) => void;\n disabled?: boolean;\n}\n\nexport function CurrencyPicker({ currencies, value, onChange, disabled }: CurrencyPickerProps) {\n return (\n <div className=\"grid grid-cols-5 gap-1.5\">\n {currencies.map((c) => (\n <Button\n key={c}\n type=\"button\"\n variant={value === c ? \"default\" : \"outline\"}\n size=\"sm\"\n onClick={() => onChange(c)}\n disabled={disabled}\n className=\"gap-1 px-2 text-xs w-full\"\n >\n <CurrencyIcon symbol={c} size={13} className=\"shrink-0\" />\n <span className=\"truncate\">{c}</span>\n </Button>\n ))}\n </div>\n );\n}\n\ninterface DurationPickerProps {\n options: ReadonlyArray<{ label: string; seconds: number }>;\n value: number;\n onChange: (value: number) => void;\n disabled?: boolean;\n cols?: 3 | 4;\n}\n\nexport function DurationPicker({ options, value, onChange, disabled, cols = 3 }: DurationPickerProps) {\n return (\n <div className={cols === 4 ? \"grid grid-cols-4 gap-2\" : \"grid grid-cols-3 gap-2\"}>\n {options.map((opt) => (\n <Button\n key={opt.label}\n type=\"button\"\n variant={value === opt.seconds ? \"default\" : \"outline\"}\n size=\"sm\"\n onClick={() => onChange(opt.seconds)}\n disabled={disabled}\n className=\"text-xs\"\n >\n {opt.label}\n </Button>\n ))}\n </div>\n );\n}\n\ninterface MarketplaceConfirmStepProps {\n summary?: ReactNode;\n description: string;\n error?: string | null;\n secondaryLabel: string;\n onSecondary: () => void;\n primaryLabel: string;\n onPrimary: () => void;\n primaryDisabled?: boolean;\n primaryIcon?: ReactNode;\n primaryVariant?: \"default\" | \"destructive\";\n footer?: ReactNode;\n}\n\nexport function MarketplaceConfirmStep({\n summary,\n description,\n error,\n secondaryLabel,\n onSecondary,\n primaryLabel,\n onPrimary,\n primaryDisabled,\n primaryIcon,\n primaryVariant = \"default\",\n footer,\n}: MarketplaceConfirmStepProps) {\n const primaryButton = primaryVariant === \"destructive\" ? (\n <Button\n variant=\"destructive\"\n className=\"flex-1 h-11\"\n disabled={primaryDisabled}\n onClick={onPrimary}\n >\n {primaryLabel}\n </Button>\n ) : (\n <div\n className={cn(\n \"btn-border-animated p-[1px] rounded-xl flex-1\",\n primaryDisabled && \"pointer-events-none\"\n )}\n >\n <button\n className=\"w-full h-11 rounded-[11px] flex items-center justify-center gap-2 text-sm font-semibold text-white transition-all hover:brightness-110 active:scale-[0.98] bg-transparent\"\n disabled={primaryDisabled}\n onClick={onPrimary}\n >\n {primaryIcon}\n {primaryLabel}\n </button>\n </div>\n );\n\n return (\n <div className=\"px-6 pb-6 pt-3 space-y-4\">\n {summary}\n <p className=\"text-sm text-muted-foreground\">{description}</p>\n {error ? (\n <Alert variant=\"destructive\">\n <AlertCircle className=\"h-4 w-4\" />\n <AlertDescription>{error}</AlertDescription>\n </Alert>\n ) : null}\n <div className=\"flex gap-2 pt-1\">\n <Button\n variant=\"outline\"\n className=\"gap-1.5\"\n onClick={onSecondary}\n >\n {secondaryLabel}\n </Button>\n {primaryButton}\n </div>\n {footer}\n </div>\n );\n}\n"],"mappings":"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","names":["Image"]}
|
|
1
|
+
{"version":3,"sources":["../../src/components/marketplace-dialog-primitives.tsx"],"sourcesContent":["\"use client\";\n\nimport type { ReactNode } from \"react\";\nimport Image from \"./image.js\";\nimport { AlertCircle, ExternalLink, Loader2, Wallet } from \"lucide-react\";\nimport { Alert, AlertDescription } from \"./alert.js\";\nimport { Button } from \"./button.js\";\nimport { CurrencyIcon } from \"./currency-icon.js\";\nimport { cn } from \"../utils/cn.js\";\n\ninterface MarketplaceTxLinkProps {\n txHash: string;\n explorerUrl: string;\n className?: string;\n}\n\nexport function MarketplaceTxLink({ txHash, explorerUrl, className }: MarketplaceTxLinkProps) {\n return (\n <a\n href={`${explorerUrl}/tx/${txHash}`}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={cn(\n \"inline-flex items-center gap-1.5 text-xs text-muted-foreground hover:text-foreground transition-colors\",\n className\n )}\n >\n <span className=\"tabular-nums\">{txHash.slice(0, 10)}…{txHash.slice(-8)}</span>\n <ExternalLink className=\"h-3 w-3\" />\n </a>\n );\n}\n\ninterface MarketplaceProcessingStateProps {\n title: string;\n description?: string;\n imageUrl?: string | null;\n imageAlt?: string;\n txHash?: string | null;\n explorerUrl?: string;\n}\n\nexport function MarketplaceProcessingState({\n title,\n description = \"Keep this window open until it finishes.\",\n imageUrl,\n imageAlt = \"Token preview\",\n txHash,\n explorerUrl,\n}: MarketplaceProcessingStateProps) {\n return (\n <div className=\"flex flex-col items-center gap-5 p-6 py-8\">\n {imageUrl ? (\n <div className=\"relative h-20 w-20 rounded-2xl overflow-hidden border border-border\">\n <Image src={imageUrl} alt={imageAlt} fill sizes=\"80px\" className=\"object-cover\" unoptimized />\n <div className=\"absolute inset-0 bg-background/50 flex items-center justify-center\">\n <Loader2 className=\"h-7 w-7 animate-spin text-primary\" />\n </div>\n </div>\n ) : (\n <Loader2 className=\"h-10 w-10 animate-spin text-primary\" />\n )}\n <div className=\"text-center space-y-1\">\n <p className=\"font-semibold\">{title}</p>\n {txHash && explorerUrl ? (\n <MarketplaceTxLink txHash={txHash} explorerUrl={explorerUrl} className=\"mt-1\" />\n ) : null}\n </div>\n <p className=\"text-sm text-muted-foreground\">{description}</p>\n </div>\n );\n}\n\ninterface MarketplaceSignInGateProps {\n title: string;\n description: string;\n href: string;\n ctaLabel?: string;\n}\n\nexport function MarketplaceSignInGate({ title, description, href, ctaLabel = \"Set up account\" }: MarketplaceSignInGateProps) {\n return (\n <div className=\"flex flex-col items-center gap-4 p-6 py-10 text-center\">\n <Wallet className=\"h-10 w-10 text-muted-foreground\" />\n <div>\n <p className=\"font-semibold\">{title}</p>\n <p className=\"text-sm text-muted-foreground mt-1\">{description}</p>\n </div>\n <div className=\"btn-border-animated w-full p-[1px] rounded-lg\">\n <Button\n asChild\n className=\"w-full bg-transparent text-white rounded-[7px] hover:bg-transparent hover:brightness-110 active:scale-[0.98] transition-all\"\n >\n <a href={href}>{ctaLabel}</a>\n </Button>\n </div>\n </div>\n );\n}\n\ninterface MarketplaceErrorStateProps {\n tokenImage?: string | null;\n name: string;\n title: string;\n description: ReactNode;\n error?: string | null;\n txHash?: string | null;\n explorerUrl: string;\n onRetry?: () => void;\n onDone: () => void;\n doneLabel?: string;\n}\n\nexport function MarketplaceErrorState({\n tokenImage,\n name,\n title,\n description,\n error,\n txHash,\n explorerUrl,\n onRetry,\n onDone,\n doneLabel = \"Done\",\n}: MarketplaceErrorStateProps) {\n return (\n <div className=\"flex flex-col items-center gap-5 p-6 py-8\">\n {tokenImage ? (\n <div className=\"relative\">\n <div className=\"relative h-32 w-32 rounded-2xl overflow-hidden border border-border\">\n <Image src={tokenImage} alt={name} fill sizes=\"128px\" className=\"object-cover\" unoptimized />\n </div>\n <div className=\"absolute -bottom-2 -right-2 h-9 w-9 rounded-full bg-destructive flex items-center justify-center border-2 border-background\">\n <AlertCircle className=\"h-5 w-5 text-white\" />\n </div>\n </div>\n ) : (\n <div className=\"h-16 w-16 rounded-full bg-destructive/15 flex items-center justify-center\">\n <AlertCircle className=\"h-9 w-9 text-destructive\" />\n </div>\n )}\n <div className=\"text-center space-y-1 max-w-full\">\n <p className=\"font-bold text-xl break-words\">{title}</p>\n <p className=\"text-sm text-muted-foreground break-words\">{description}</p>\n </div>\n {error ? (\n <Alert variant=\"destructive\" className=\"text-left\">\n <AlertCircle className=\"h-4 w-4\" />\n <AlertDescription>{error}</AlertDescription>\n </Alert>\n ) : null}\n {txHash && <MarketplaceTxLink txHash={txHash} explorerUrl={explorerUrl} />}\n <div className=\"flex w-full gap-2\">\n {onRetry ? (\n <Button variant=\"outline\" className=\"flex-1 h-11\" onClick={onRetry}>\n Try again\n </Button>\n ) : null}\n <Button className=\"flex-1 h-11\" onClick={onDone}>{doneLabel}</Button>\n </div>\n </div>\n );\n}\n\ninterface MarketplaceDialogHeroProps {\n tokenImage?: string | null;\n tokenName?: string;\n tokenId: string;\n fallbackIcon: ReactNode;\n badge?: ReactNode;\n}\n\nexport function MarketplaceDialogHero({\n tokenImage,\n tokenName,\n tokenId,\n fallbackIcon,\n badge,\n}: MarketplaceDialogHeroProps) {\n const name = tokenName || `Token #${tokenId}`;\n\n return (\n <div className=\"relative flex justify-center pt-6 shrink-0\">\n <div className=\"relative h-32 w-32 rounded-2xl overflow-hidden border border-border bg-muted\">\n {tokenImage ? (\n <Image src={tokenImage} alt={name} fill sizes=\"128px\" className=\"object-cover\" unoptimized />\n ) : (\n <div className=\"h-full w-full bg-gradient-to-br from-brand-blue/20 via-brand-purple/10 to-transparent flex items-center justify-center\">\n {fallbackIcon}\n </div>\n )}\n </div>\n {badge}\n </div>\n );\n}\n\ninterface CurrencyPickerProps {\n currencies: string[];\n value: string;\n onChange: (value: string) => void;\n disabled?: boolean;\n}\n\nexport function CurrencyPicker({ currencies, value, onChange, disabled }: CurrencyPickerProps) {\n return (\n <div className=\"grid grid-cols-5 gap-1.5\">\n {currencies.map((c) => (\n <Button\n key={c}\n type=\"button\"\n variant={value === c ? \"default\" : \"outline\"}\n size=\"sm\"\n onClick={() => onChange(c)}\n disabled={disabled}\n className=\"gap-1 px-2 text-xs w-full\"\n >\n <CurrencyIcon symbol={c} size={13} className=\"shrink-0\" />\n <span className=\"truncate\">{c}</span>\n </Button>\n ))}\n </div>\n );\n}\n\ninterface DurationPickerProps {\n options: ReadonlyArray<{ label: string; seconds: number }>;\n value: number;\n onChange: (value: number) => void;\n disabled?: boolean;\n cols?: 3 | 4;\n}\n\nexport function DurationPicker({ options, value, onChange, disabled, cols = 3 }: DurationPickerProps) {\n return (\n <div className={cols === 4 ? \"grid grid-cols-4 gap-2\" : \"grid grid-cols-3 gap-2\"}>\n {options.map((opt) => (\n <Button\n key={opt.label}\n type=\"button\"\n variant={value === opt.seconds ? \"default\" : \"outline\"}\n size=\"sm\"\n onClick={() => onChange(opt.seconds)}\n disabled={disabled}\n className=\"text-xs\"\n >\n {opt.label}\n </Button>\n ))}\n </div>\n );\n}\n\ninterface MarketplaceConfirmStepProps {\n summary?: ReactNode;\n description: string;\n error?: string | null;\n secondaryLabel: string;\n onSecondary: () => void;\n primaryLabel: string;\n onPrimary: () => void;\n primaryDisabled?: boolean;\n primaryIcon?: ReactNode;\n primaryVariant?: \"default\" | \"destructive\";\n footer?: ReactNode;\n}\n\nexport function MarketplaceConfirmStep({\n summary,\n description,\n error,\n secondaryLabel,\n onSecondary,\n primaryLabel,\n onPrimary,\n primaryDisabled,\n primaryIcon,\n primaryVariant = \"default\",\n footer,\n}: MarketplaceConfirmStepProps) {\n const primaryButton = primaryVariant === \"destructive\" ? (\n <Button\n variant=\"destructive\"\n className=\"flex-1 h-11\"\n disabled={primaryDisabled}\n onClick={onPrimary}\n >\n {primaryLabel}\n </Button>\n ) : (\n <div\n className={cn(\n \"btn-border-animated p-[1px] rounded-xl flex-1\",\n primaryDisabled && \"pointer-events-none\"\n )}\n >\n <button\n className=\"w-full h-11 rounded-[11px] flex items-center justify-center gap-2 text-sm font-semibold text-white transition-all hover:brightness-110 active:scale-[0.98] bg-transparent\"\n disabled={primaryDisabled}\n onClick={onPrimary}\n >\n {primaryIcon}\n {primaryLabel}\n </button>\n </div>\n );\n\n return (\n <div className=\"px-6 pb-6 pt-3 space-y-4\">\n {summary}\n <p className=\"text-sm text-muted-foreground\">{description}</p>\n {error ? (\n <Alert variant=\"destructive\">\n <AlertCircle className=\"h-4 w-4\" />\n <AlertDescription>{error}</AlertDescription>\n </Alert>\n ) : null}\n <div className=\"flex gap-2 pt-1\">\n <Button\n variant=\"outline\"\n className=\"gap-1.5\"\n onClick={onSecondary}\n >\n {secondaryLabel}\n </Button>\n {primaryButton}\n </div>\n {footer}\n </div>\n );\n}\n"],"mappings":"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","names":["Image"]}
|
|
@@ -30,7 +30,7 @@ function MarketplaceTxLink({ txHash, explorerUrl, className }) {
|
|
|
30
30
|
}
|
|
31
31
|
function MarketplaceProcessingState({
|
|
32
32
|
title,
|
|
33
|
-
description = "
|
|
33
|
+
description = "Keep this window open until it finishes.",
|
|
34
34
|
imageUrl,
|
|
35
35
|
imageAlt = "Token preview",
|
|
36
36
|
txHash,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/marketplace-dialog-primitives.tsx"],"sourcesContent":["\"use client\";\n\nimport type { ReactNode } from \"react\";\nimport Image from \"./image.js\";\nimport { AlertCircle, ExternalLink, Loader2, Wallet } from \"lucide-react\";\nimport { Alert, AlertDescription } from \"./alert.js\";\nimport { Button } from \"./button.js\";\nimport { CurrencyIcon } from \"./currency-icon.js\";\nimport { cn } from \"../utils/cn.js\";\n\ninterface MarketplaceTxLinkProps {\n txHash: string;\n explorerUrl: string;\n className?: string;\n}\n\nexport function MarketplaceTxLink({ txHash, explorerUrl, className }: MarketplaceTxLinkProps) {\n return (\n <a\n href={`${explorerUrl}/tx/${txHash}`}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={cn(\n \"inline-flex items-center gap-1.5 text-xs text-muted-foreground hover:text-foreground transition-colors\",\n className\n )}\n >\n <span className=\"tabular-nums\">{txHash.slice(0, 10)}…{txHash.slice(-8)}</span>\n <ExternalLink className=\"h-3 w-3\" />\n </a>\n );\n}\n\ninterface MarketplaceProcessingStateProps {\n title: string;\n description?: string;\n imageUrl?: string | null;\n imageAlt?: string;\n txHash?: string | null;\n explorerUrl?: string;\n}\n\nexport function MarketplaceProcessingState({\n title,\n description = \"Please wait, do not close this window.\",\n imageUrl,\n imageAlt = \"Token preview\",\n txHash,\n explorerUrl,\n}: MarketplaceProcessingStateProps) {\n return (\n <div className=\"flex flex-col items-center gap-5 p-6 py-8\">\n {imageUrl ? (\n <div className=\"relative h-20 w-20 rounded-2xl overflow-hidden border border-border\">\n <Image src={imageUrl} alt={imageAlt} fill sizes=\"80px\" className=\"object-cover\" unoptimized />\n <div className=\"absolute inset-0 bg-background/50 flex items-center justify-center\">\n <Loader2 className=\"h-7 w-7 animate-spin text-primary\" />\n </div>\n </div>\n ) : (\n <Loader2 className=\"h-10 w-10 animate-spin text-primary\" />\n )}\n <div className=\"text-center space-y-1\">\n <p className=\"font-semibold\">{title}</p>\n {txHash && explorerUrl ? (\n <MarketplaceTxLink txHash={txHash} explorerUrl={explorerUrl} className=\"mt-1\" />\n ) : null}\n </div>\n <p className=\"text-sm text-muted-foreground\">{description}</p>\n </div>\n );\n}\n\ninterface MarketplaceSignInGateProps {\n title: string;\n description: string;\n href: string;\n ctaLabel?: string;\n}\n\nexport function MarketplaceSignInGate({ title, description, href, ctaLabel = \"Set up account\" }: MarketplaceSignInGateProps) {\n return (\n <div className=\"flex flex-col items-center gap-4 p-6 py-10 text-center\">\n <Wallet className=\"h-10 w-10 text-muted-foreground\" />\n <div>\n <p className=\"font-semibold\">{title}</p>\n <p className=\"text-sm text-muted-foreground mt-1\">{description}</p>\n </div>\n <div className=\"btn-border-animated w-full p-[1px] rounded-lg\">\n <Button\n asChild\n className=\"w-full bg-transparent text-white rounded-[7px] hover:bg-transparent hover:brightness-110 active:scale-[0.98] transition-all\"\n >\n <a href={href}>{ctaLabel}</a>\n </Button>\n </div>\n </div>\n );\n}\n\ninterface MarketplaceErrorStateProps {\n tokenImage?: string | null;\n name: string;\n title: string;\n description: ReactNode;\n error?: string | null;\n txHash?: string | null;\n explorerUrl: string;\n onRetry?: () => void;\n onDone: () => void;\n doneLabel?: string;\n}\n\nexport function MarketplaceErrorState({\n tokenImage,\n name,\n title,\n description,\n error,\n txHash,\n explorerUrl,\n onRetry,\n onDone,\n doneLabel = \"Done\",\n}: MarketplaceErrorStateProps) {\n return (\n <div className=\"flex flex-col items-center gap-5 p-6 py-8\">\n {tokenImage ? (\n <div className=\"relative\">\n <div className=\"relative h-32 w-32 rounded-2xl overflow-hidden border border-border\">\n <Image src={tokenImage} alt={name} fill sizes=\"128px\" className=\"object-cover\" unoptimized />\n </div>\n <div className=\"absolute -bottom-2 -right-2 h-9 w-9 rounded-full bg-destructive flex items-center justify-center border-2 border-background\">\n <AlertCircle className=\"h-5 w-5 text-white\" />\n </div>\n </div>\n ) : (\n <div className=\"h-16 w-16 rounded-full bg-destructive/15 flex items-center justify-center\">\n <AlertCircle className=\"h-9 w-9 text-destructive\" />\n </div>\n )}\n <div className=\"text-center space-y-1 max-w-full\">\n <p className=\"font-bold text-xl break-words\">{title}</p>\n <p className=\"text-sm text-muted-foreground break-words\">{description}</p>\n </div>\n {error ? (\n <Alert variant=\"destructive\" className=\"text-left\">\n <AlertCircle className=\"h-4 w-4\" />\n <AlertDescription>{error}</AlertDescription>\n </Alert>\n ) : null}\n {txHash && <MarketplaceTxLink txHash={txHash} explorerUrl={explorerUrl} />}\n <div className=\"flex w-full gap-2\">\n {onRetry ? (\n <Button variant=\"outline\" className=\"flex-1 h-11\" onClick={onRetry}>\n Try again\n </Button>\n ) : null}\n <Button className=\"flex-1 h-11\" onClick={onDone}>{doneLabel}</Button>\n </div>\n </div>\n );\n}\n\ninterface MarketplaceDialogHeroProps {\n tokenImage?: string | null;\n tokenName?: string;\n tokenId: string;\n fallbackIcon: ReactNode;\n badge?: ReactNode;\n}\n\nexport function MarketplaceDialogHero({\n tokenImage,\n tokenName,\n tokenId,\n fallbackIcon,\n badge,\n}: MarketplaceDialogHeroProps) {\n const name = tokenName || `Token #${tokenId}`;\n\n return (\n <div className=\"relative flex justify-center pt-6 shrink-0\">\n <div className=\"relative h-32 w-32 rounded-2xl overflow-hidden border border-border bg-muted\">\n {tokenImage ? (\n <Image src={tokenImage} alt={name} fill sizes=\"128px\" className=\"object-cover\" unoptimized />\n ) : (\n <div className=\"h-full w-full bg-gradient-to-br from-brand-blue/20 via-brand-purple/10 to-transparent flex items-center justify-center\">\n {fallbackIcon}\n </div>\n )}\n </div>\n {badge}\n </div>\n );\n}\n\ninterface CurrencyPickerProps {\n currencies: string[];\n value: string;\n onChange: (value: string) => void;\n disabled?: boolean;\n}\n\nexport function CurrencyPicker({ currencies, value, onChange, disabled }: CurrencyPickerProps) {\n return (\n <div className=\"grid grid-cols-5 gap-1.5\">\n {currencies.map((c) => (\n <Button\n key={c}\n type=\"button\"\n variant={value === c ? \"default\" : \"outline\"}\n size=\"sm\"\n onClick={() => onChange(c)}\n disabled={disabled}\n className=\"gap-1 px-2 text-xs w-full\"\n >\n <CurrencyIcon symbol={c} size={13} className=\"shrink-0\" />\n <span className=\"truncate\">{c}</span>\n </Button>\n ))}\n </div>\n );\n}\n\ninterface DurationPickerProps {\n options: ReadonlyArray<{ label: string; seconds: number }>;\n value: number;\n onChange: (value: number) => void;\n disabled?: boolean;\n cols?: 3 | 4;\n}\n\nexport function DurationPicker({ options, value, onChange, disabled, cols = 3 }: DurationPickerProps) {\n return (\n <div className={cols === 4 ? \"grid grid-cols-4 gap-2\" : \"grid grid-cols-3 gap-2\"}>\n {options.map((opt) => (\n <Button\n key={opt.label}\n type=\"button\"\n variant={value === opt.seconds ? \"default\" : \"outline\"}\n size=\"sm\"\n onClick={() => onChange(opt.seconds)}\n disabled={disabled}\n className=\"text-xs\"\n >\n {opt.label}\n </Button>\n ))}\n </div>\n );\n}\n\ninterface MarketplaceConfirmStepProps {\n summary?: ReactNode;\n description: string;\n error?: string | null;\n secondaryLabel: string;\n onSecondary: () => void;\n primaryLabel: string;\n onPrimary: () => void;\n primaryDisabled?: boolean;\n primaryIcon?: ReactNode;\n primaryVariant?: \"default\" | \"destructive\";\n footer?: ReactNode;\n}\n\nexport function MarketplaceConfirmStep({\n summary,\n description,\n error,\n secondaryLabel,\n onSecondary,\n primaryLabel,\n onPrimary,\n primaryDisabled,\n primaryIcon,\n primaryVariant = \"default\",\n footer,\n}: MarketplaceConfirmStepProps) {\n const primaryButton = primaryVariant === \"destructive\" ? (\n <Button\n variant=\"destructive\"\n className=\"flex-1 h-11\"\n disabled={primaryDisabled}\n onClick={onPrimary}\n >\n {primaryLabel}\n </Button>\n ) : (\n <div\n className={cn(\n \"btn-border-animated p-[1px] rounded-xl flex-1\",\n primaryDisabled && \"pointer-events-none\"\n )}\n >\n <button\n className=\"w-full h-11 rounded-[11px] flex items-center justify-center gap-2 text-sm font-semibold text-white transition-all hover:brightness-110 active:scale-[0.98] bg-transparent\"\n disabled={primaryDisabled}\n onClick={onPrimary}\n >\n {primaryIcon}\n {primaryLabel}\n </button>\n </div>\n );\n\n return (\n <div className=\"px-6 pb-6 pt-3 space-y-4\">\n {summary}\n <p className=\"text-sm text-muted-foreground\">{description}</p>\n {error ? (\n <Alert variant=\"destructive\">\n <AlertCircle className=\"h-4 w-4\" />\n <AlertDescription>{error}</AlertDescription>\n </Alert>\n ) : null}\n <div className=\"flex gap-2 pt-1\">\n <Button\n variant=\"outline\"\n className=\"gap-1.5\"\n onClick={onSecondary}\n >\n {secondaryLabel}\n </Button>\n {primaryButton}\n </div>\n {footer}\n </div>\n );\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/components/marketplace-dialog-primitives.tsx"],"sourcesContent":["\"use client\";\n\nimport type { ReactNode } from \"react\";\nimport Image from \"./image.js\";\nimport { AlertCircle, ExternalLink, Loader2, Wallet } from \"lucide-react\";\nimport { Alert, AlertDescription } from \"./alert.js\";\nimport { Button } from \"./button.js\";\nimport { CurrencyIcon } from \"./currency-icon.js\";\nimport { cn } from \"../utils/cn.js\";\n\ninterface MarketplaceTxLinkProps {\n txHash: string;\n explorerUrl: string;\n className?: string;\n}\n\nexport function MarketplaceTxLink({ txHash, explorerUrl, className }: MarketplaceTxLinkProps) {\n return (\n <a\n href={`${explorerUrl}/tx/${txHash}`}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={cn(\n \"inline-flex items-center gap-1.5 text-xs text-muted-foreground hover:text-foreground transition-colors\",\n className\n )}\n >\n <span className=\"tabular-nums\">{txHash.slice(0, 10)}…{txHash.slice(-8)}</span>\n <ExternalLink className=\"h-3 w-3\" />\n </a>\n );\n}\n\ninterface MarketplaceProcessingStateProps {\n title: string;\n description?: string;\n imageUrl?: string | null;\n imageAlt?: string;\n txHash?: string | null;\n explorerUrl?: string;\n}\n\nexport function MarketplaceProcessingState({\n title,\n description = \"Keep this window open until it finishes.\",\n imageUrl,\n imageAlt = \"Token preview\",\n txHash,\n explorerUrl,\n}: MarketplaceProcessingStateProps) {\n return (\n <div className=\"flex flex-col items-center gap-5 p-6 py-8\">\n {imageUrl ? (\n <div className=\"relative h-20 w-20 rounded-2xl overflow-hidden border border-border\">\n <Image src={imageUrl} alt={imageAlt} fill sizes=\"80px\" className=\"object-cover\" unoptimized />\n <div className=\"absolute inset-0 bg-background/50 flex items-center justify-center\">\n <Loader2 className=\"h-7 w-7 animate-spin text-primary\" />\n </div>\n </div>\n ) : (\n <Loader2 className=\"h-10 w-10 animate-spin text-primary\" />\n )}\n <div className=\"text-center space-y-1\">\n <p className=\"font-semibold\">{title}</p>\n {txHash && explorerUrl ? (\n <MarketplaceTxLink txHash={txHash} explorerUrl={explorerUrl} className=\"mt-1\" />\n ) : null}\n </div>\n <p className=\"text-sm text-muted-foreground\">{description}</p>\n </div>\n );\n}\n\ninterface MarketplaceSignInGateProps {\n title: string;\n description: string;\n href: string;\n ctaLabel?: string;\n}\n\nexport function MarketplaceSignInGate({ title, description, href, ctaLabel = \"Set up account\" }: MarketplaceSignInGateProps) {\n return (\n <div className=\"flex flex-col items-center gap-4 p-6 py-10 text-center\">\n <Wallet className=\"h-10 w-10 text-muted-foreground\" />\n <div>\n <p className=\"font-semibold\">{title}</p>\n <p className=\"text-sm text-muted-foreground mt-1\">{description}</p>\n </div>\n <div className=\"btn-border-animated w-full p-[1px] rounded-lg\">\n <Button\n asChild\n className=\"w-full bg-transparent text-white rounded-[7px] hover:bg-transparent hover:brightness-110 active:scale-[0.98] transition-all\"\n >\n <a href={href}>{ctaLabel}</a>\n </Button>\n </div>\n </div>\n );\n}\n\ninterface MarketplaceErrorStateProps {\n tokenImage?: string | null;\n name: string;\n title: string;\n description: ReactNode;\n error?: string | null;\n txHash?: string | null;\n explorerUrl: string;\n onRetry?: () => void;\n onDone: () => void;\n doneLabel?: string;\n}\n\nexport function MarketplaceErrorState({\n tokenImage,\n name,\n title,\n description,\n error,\n txHash,\n explorerUrl,\n onRetry,\n onDone,\n doneLabel = \"Done\",\n}: MarketplaceErrorStateProps) {\n return (\n <div className=\"flex flex-col items-center gap-5 p-6 py-8\">\n {tokenImage ? (\n <div className=\"relative\">\n <div className=\"relative h-32 w-32 rounded-2xl overflow-hidden border border-border\">\n <Image src={tokenImage} alt={name} fill sizes=\"128px\" className=\"object-cover\" unoptimized />\n </div>\n <div className=\"absolute -bottom-2 -right-2 h-9 w-9 rounded-full bg-destructive flex items-center justify-center border-2 border-background\">\n <AlertCircle className=\"h-5 w-5 text-white\" />\n </div>\n </div>\n ) : (\n <div className=\"h-16 w-16 rounded-full bg-destructive/15 flex items-center justify-center\">\n <AlertCircle className=\"h-9 w-9 text-destructive\" />\n </div>\n )}\n <div className=\"text-center space-y-1 max-w-full\">\n <p className=\"font-bold text-xl break-words\">{title}</p>\n <p className=\"text-sm text-muted-foreground break-words\">{description}</p>\n </div>\n {error ? (\n <Alert variant=\"destructive\" className=\"text-left\">\n <AlertCircle className=\"h-4 w-4\" />\n <AlertDescription>{error}</AlertDescription>\n </Alert>\n ) : null}\n {txHash && <MarketplaceTxLink txHash={txHash} explorerUrl={explorerUrl} />}\n <div className=\"flex w-full gap-2\">\n {onRetry ? (\n <Button variant=\"outline\" className=\"flex-1 h-11\" onClick={onRetry}>\n Try again\n </Button>\n ) : null}\n <Button className=\"flex-1 h-11\" onClick={onDone}>{doneLabel}</Button>\n </div>\n </div>\n );\n}\n\ninterface MarketplaceDialogHeroProps {\n tokenImage?: string | null;\n tokenName?: string;\n tokenId: string;\n fallbackIcon: ReactNode;\n badge?: ReactNode;\n}\n\nexport function MarketplaceDialogHero({\n tokenImage,\n tokenName,\n tokenId,\n fallbackIcon,\n badge,\n}: MarketplaceDialogHeroProps) {\n const name = tokenName || `Token #${tokenId}`;\n\n return (\n <div className=\"relative flex justify-center pt-6 shrink-0\">\n <div className=\"relative h-32 w-32 rounded-2xl overflow-hidden border border-border bg-muted\">\n {tokenImage ? (\n <Image src={tokenImage} alt={name} fill sizes=\"128px\" className=\"object-cover\" unoptimized />\n ) : (\n <div className=\"h-full w-full bg-gradient-to-br from-brand-blue/20 via-brand-purple/10 to-transparent flex items-center justify-center\">\n {fallbackIcon}\n </div>\n )}\n </div>\n {badge}\n </div>\n );\n}\n\ninterface CurrencyPickerProps {\n currencies: string[];\n value: string;\n onChange: (value: string) => void;\n disabled?: boolean;\n}\n\nexport function CurrencyPicker({ currencies, value, onChange, disabled }: CurrencyPickerProps) {\n return (\n <div className=\"grid grid-cols-5 gap-1.5\">\n {currencies.map((c) => (\n <Button\n key={c}\n type=\"button\"\n variant={value === c ? \"default\" : \"outline\"}\n size=\"sm\"\n onClick={() => onChange(c)}\n disabled={disabled}\n className=\"gap-1 px-2 text-xs w-full\"\n >\n <CurrencyIcon symbol={c} size={13} className=\"shrink-0\" />\n <span className=\"truncate\">{c}</span>\n </Button>\n ))}\n </div>\n );\n}\n\ninterface DurationPickerProps {\n options: ReadonlyArray<{ label: string; seconds: number }>;\n value: number;\n onChange: (value: number) => void;\n disabled?: boolean;\n cols?: 3 | 4;\n}\n\nexport function DurationPicker({ options, value, onChange, disabled, cols = 3 }: DurationPickerProps) {\n return (\n <div className={cols === 4 ? \"grid grid-cols-4 gap-2\" : \"grid grid-cols-3 gap-2\"}>\n {options.map((opt) => (\n <Button\n key={opt.label}\n type=\"button\"\n variant={value === opt.seconds ? \"default\" : \"outline\"}\n size=\"sm\"\n onClick={() => onChange(opt.seconds)}\n disabled={disabled}\n className=\"text-xs\"\n >\n {opt.label}\n </Button>\n ))}\n </div>\n );\n}\n\ninterface MarketplaceConfirmStepProps {\n summary?: ReactNode;\n description: string;\n error?: string | null;\n secondaryLabel: string;\n onSecondary: () => void;\n primaryLabel: string;\n onPrimary: () => void;\n primaryDisabled?: boolean;\n primaryIcon?: ReactNode;\n primaryVariant?: \"default\" | \"destructive\";\n footer?: ReactNode;\n}\n\nexport function MarketplaceConfirmStep({\n summary,\n description,\n error,\n secondaryLabel,\n onSecondary,\n primaryLabel,\n onPrimary,\n primaryDisabled,\n primaryIcon,\n primaryVariant = \"default\",\n footer,\n}: MarketplaceConfirmStepProps) {\n const primaryButton = primaryVariant === \"destructive\" ? (\n <Button\n variant=\"destructive\"\n className=\"flex-1 h-11\"\n disabled={primaryDisabled}\n onClick={onPrimary}\n >\n {primaryLabel}\n </Button>\n ) : (\n <div\n className={cn(\n \"btn-border-animated p-[1px] rounded-xl flex-1\",\n primaryDisabled && \"pointer-events-none\"\n )}\n >\n <button\n className=\"w-full h-11 rounded-[11px] flex items-center justify-center gap-2 text-sm font-semibold text-white transition-all hover:brightness-110 active:scale-[0.98] bg-transparent\"\n disabled={primaryDisabled}\n onClick={onPrimary}\n >\n {primaryIcon}\n {primaryLabel}\n </button>\n </div>\n );\n\n return (\n <div className=\"px-6 pb-6 pt-3 space-y-4\">\n {summary}\n <p className=\"text-sm text-muted-foreground\">{description}</p>\n {error ? (\n <Alert variant=\"destructive\">\n <AlertCircle className=\"h-4 w-4\" />\n <AlertDescription>{error}</AlertDescription>\n </Alert>\n ) : null}\n <div className=\"flex gap-2 pt-1\">\n <Button\n variant=\"outline\"\n className=\"gap-1.5\"\n onClick={onSecondary}\n >\n {secondaryLabel}\n </Button>\n {primaryButton}\n </div>\n {footer}\n </div>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -45,6 +45,7 @@ var import_wallet_activity_icon = require("./wallet-activity-icon.js");
|
|
|
45
45
|
var import_action_modal = require("./action-modal.js");
|
|
46
46
|
var import_types = require("./types.js");
|
|
47
47
|
var import_medialane_app = require("../medialane-app.js");
|
|
48
|
+
var import_empty_messages = require("../../utils/empty-messages.js");
|
|
48
49
|
const GRADS = [
|
|
49
50
|
"linear-gradient(135deg,#3b7bff,#8a5cf6)",
|
|
50
51
|
"linear-gradient(135deg,#8a5cf6,#f6608f)",
|
|
@@ -96,7 +97,10 @@ function MediaWalletActivity({ onNavigate }) {
|
|
|
96
97
|
!address && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "text-sm text-muted-foreground", children: "No wallet found on this device." }),
|
|
97
98
|
error && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ActivityLoadError, { onRetry: load }),
|
|
98
99
|
loading && !items && !error && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ActivityLoading, {}),
|
|
99
|
-
items && items.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime.
|
|
100
|
+
items && items.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
101
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-sm font-medium", children: import_empty_messages.emptyMessages.walletActivity.title }),
|
|
102
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-sm text-muted-foreground", children: import_empty_messages.emptyMessages.walletActivity.description })
|
|
103
|
+
] }),
|
|
100
104
|
items && items.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex flex-col gap-2", children: items.map(
|
|
101
105
|
(item) => item.source === "wallet" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(WalletActivityRow, { a: item.data, timestamp: item.timestamp, onOpen: setSelected }, item.data.id) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ProtocolActivityRow, { item: item.data }, `${item.data.txHash}-${item.data.type}`)
|
|
102
106
|
) }),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/media-wallet/media-wallet-activity.tsx"],"sourcesContent":["\"use client\";\n\nimport { describeError } from \"../../utils/describe-error.js\";\nimport { useCallback, useEffect, useState } from \"react\";\nimport Image from \"../image.js\";\nimport type { ApiWalletActivity, ApiActivity } from \"@medialane/sdk\";\nimport { getTokenBySymbol } from \"@medialane/sdk\";\nimport { mergeActivityFeeds, type MergedActivityItem } from \"../../utils/media-wallet/activity-feed.js\";\nimport { walletActivityTitle, walletActivitySubtitle, walletActivityAmount } from \"../../utils/media-wallet/wallet-activity.js\";\nimport { short, when, explorerTxUrl, fmt } from \"../../utils/media-wallet/wallet-format.js\";\nimport { BackButton } from \"./back-button.js\";\nimport { WalletActivityIcon } from \"./wallet-activity-icon.js\";\nimport { ActionModal } from \"./action-modal.js\";\nimport { useMediaWalletApp, type MediaWalletView } from \"./types.js\";\nimport { useMedialaneApp } from \"../medialane-app.js\";\n\nconst GRADS = [\n \"linear-gradient(135deg,#3b7bff,#8a5cf6)\",\n \"linear-gradient(135deg,#8a5cf6,#f6608f)\",\n \"linear-gradient(135deg,#f6608f,#fb8b46)\",\n \"linear-gradient(135deg,#5b4ce6,#3b7bff)\",\n];\nconst gradFor = (seed: string) => {\n let h = 0;\n for (let i = 0; i < seed.length; i++) h = (h * 31 + seed.charCodeAt(i)) | 0;\n return GRADS[Math.abs(h) % GRADS.length];\n};\n\nexport function MediaWalletActivity({ onNavigate }: { onNavigate: (view: MediaWalletView) => void }) {\n const { useWalletSession } = useMediaWalletApp();\n const { getClient } = useMedialaneApp();\n const { address } = useWalletSession();\n const [items, setItems] = useState<MergedActivityItem[] | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [loading, setLoading] = useState(false);\n const [selected, setSelected] = useState<ApiWalletActivity | null>(null);\n\n const load = useCallback(() => {\n if (!address) return;\n let live = true;\n setLoading(true);\n setError(null);\n (async () => {\n try {\n const client = getClient().api;\n const [walletRes, protocolRes] = await Promise.all([\n client.activity.wallet(address),\n client.activity.byAddress(address, { page: 1, limit: 50 }),\n ]);\n if (live) setItems(mergeActivityFeeds(walletRes.data, protocolRes.data));\n } catch (e) {\n if (live) setError(describeError(e).message);\n } finally {\n if (live) setLoading(false);\n }\n })();\n return () => { live = false; };\n }, [address, getClient]);\n\n useEffect(() => load(), [load]);\n\n return (\n <main className=\"flex flex-col gap-4 px-5 pb-8 pt-2\">\n <div className=\"flex items-center gap-3\">\n <BackButton onBack={() => onNavigate({ name: \"home\" })} />\n <h1 className=\"font-[family-name:var(--font-display)] text-2xl font-extrabold tracking-tight\">Activity</h1>\n </div>\n\n {!address && <div className=\"text-sm text-muted-foreground\">No wallet found on this device.</div>}\n {error && <ActivityLoadError onRetry={load} />}\n {loading && !items && !error && <ActivityLoading />}\n {items && items.length === 0 && <div className=\"text-sm text-muted-foreground\">No activity yet.</div>}\n\n {items && items.length > 0 && (\n <div className=\"flex flex-col gap-2\">\n {items.map((item) =>\n item.source === \"wallet\" ? (\n <WalletActivityRow key={item.data.id} a={item.data} timestamp={item.timestamp} onOpen={setSelected} />\n ) : (\n <ProtocolActivityRow key={`${item.data.txHash}-${item.data.type}`} item={item.data} />\n ),\n )}\n </div>\n )}\n\n {selected && <ActivityDetailModal a={selected} onClose={() => setSelected(null)} />}\n </main>\n );\n}\n\nfunction WalletActivityRow({\n a,\n timestamp,\n onOpen,\n}: {\n a: ApiWalletActivity;\n timestamp: string;\n onOpen: (a: ApiWalletActivity) => void;\n}) {\n const subtitle = walletActivitySubtitle(a);\n const amount = walletActivityAmount(a);\n return (\n <button\n onClick={() => onOpen(a)}\n className=\"flex items-center gap-3 rounded-2xl bg-card/40 px-4 py-3 text-left backdrop-blur-sm transition-colors hover:bg-card/60\"\n >\n <WalletActivityIcon a={a} />\n <div className=\"min-w-0 flex-1\">\n <div className=\"text-sm font-semibold\">{walletActivityTitle(a)}</div>\n {subtitle && <div className=\"truncate text-xs text-muted-foreground\">{subtitle}</div>}\n </div>\n <div className=\"shrink-0 text-right\">\n {amount && <div className=\"text-sm font-semibold tabular-nums\">{amount}</div>}\n <div className=\"text-xs text-muted-foreground\">{when(timestamp)}</div>\n </div>\n </button>\n );\n}\n\nfunction ActivityDetailModal({ a, onClose }: { a: ApiWalletActivity; onClose: () => void }) {\n const { explorerUrl } = useMediaWalletApp();\n const [copied, setCopied] = useState(false);\n const subtitle = walletActivitySubtitle(a);\n const amount = walletActivityAmount(a);\n const fullDate = new Date(a.timestamp).toLocaleString(undefined, {\n dateStyle: \"medium\",\n timeStyle: \"short\",\n });\n\n const copyHash = () => {\n navigator.clipboard?.writeText(a.txHash).catch(() => {});\n setCopied(true);\n setTimeout(() => setCopied(false), 1500);\n };\n\n return (\n <ActionModal title={walletActivityTitle(a)} onClose={onClose}>\n <div className=\"flex flex-col gap-4\">\n <div className=\"flex flex-col items-center gap-2 py-2 text-center\">\n <WalletActivityIcon a={a} />\n {amount && <div className=\"text-2xl font-bold tabular-nums\">{amount}</div>}\n {subtitle && <div className=\"text-sm text-muted-foreground\">{subtitle}</div>}\n </div>\n\n <div className=\"flex flex-col divide-y divide-border/40 rounded-2xl bg-foreground/[0.05] px-4\">\n <div className=\"flex items-center justify-between py-3\">\n <span className=\"text-xs text-muted-foreground\">Date</span>\n <span className=\"text-sm font-medium\">{fullDate}</span>\n </div>\n <div className=\"flex items-center justify-between py-3\">\n <span className=\"text-xs text-muted-foreground\">Transaction</span>\n <button onClick={copyHash} className=\"font-mono text-sm font-medium transition-opacity active:opacity-60\">\n {copied ? \"Copied ✓\" : short(a.txHash)}\n </button>\n </div>\n </div>\n\n <a\n href={explorerTxUrl(explorerUrl, a.txHash)}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-center text-xs font-medium text-muted-foreground underline underline-offset-2\"\n >\n View on Voyager ↗\n </a>\n </div>\n </ActionModal>\n );\n}\n\nfunction ProtocolActivityRow({ item }: { item: ApiActivity }) {\n const { resolveImage } = useMediaWalletApp();\n const img = resolveImage(item.token?.image ?? null);\n const seed = item.txHash ?? item.orderHash ?? item.type;\n return (\n <div className=\"flex items-center gap-3 rounded-2xl bg-card/40 px-4 py-3 backdrop-blur-sm\">\n <div className=\"relative h-11 w-11 shrink-0 overflow-hidden rounded-2xl\" style={img ? undefined : { background: gradFor(seed) }}>\n {img && (\n <Image src={img} alt=\"\" fill className=\"object-cover\" />\n )}\n </div>\n <div className=\"min-w-0 flex-1\">\n <div className=\"text-sm font-semibold capitalize\">{item.type}</div>\n {item.token?.name && <div className=\"truncate text-xs text-muted-foreground\">{item.token.name}</div>}\n </div>\n <div className=\"shrink-0 text-right\">\n {item.price?.raw && item.price.currency && (\n <div className=\"text-sm font-semibold tabular-nums\">\n {fmt(BigInt(item.price.raw), getTokenBySymbol(item.price.currency)?.decimals ?? 18)} <span className=\"text-xs text-muted-foreground\">{item.price.currency}</span>\n </div>\n )}\n <div className=\"text-xs text-muted-foreground\">{when(item.timestamp)}</div>\n </div>\n </div>\n );\n}\n\nfunction ActivityLoading() {\n return (\n <div className=\"flex min-h-[40vh] flex-col items-center justify-center gap-3\">\n <span className=\"h-6 w-6 animate-spin rounded-full border-2 border-border border-t-foreground\" />\n <div className=\"text-sm text-muted-foreground\">Loading your activity…</div>\n </div>\n );\n}\n\nfunction ActivityLoadError({ onRetry }: { onRetry: () => void }) {\n return (\n <div className=\"card-base flex flex-col items-center gap-3 px-6 py-8 text-center\">\n <div className=\"grid h-11 w-11 place-items-center rounded-2xl bg-destructive/10 text-destructive\">\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M10.3 3.9L2.3 18a2 2 0 001.7 3h16a2 2 0 001.7-3L13.7 3.9a2 2 0 00-3.4 0z\" />\n <path d=\"M12 9v4M12 17h.01\" />\n </svg>\n </div>\n <div>\n <div className=\"text-sm font-semibold\">Couldn't load your activity</div>\n <p className=\"mx-auto mt-1 max-w-[16rem] text-xs leading-relaxed text-muted-foreground\">\n There was a problem reaching the server. Check your connection and try again.\n </p>\n </div>\n <button\n onClick={onRetry}\n className=\"rounded-full border border-border px-4 py-2 text-xs font-semibold text-foreground transition-colors hover:bg-card\"\n >\n Try again\n </button>\n </div>\n );\n}\n"],"mappings":"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","names":["Image"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/components/media-wallet/media-wallet-activity.tsx"],"sourcesContent":["\"use client\";\n\nimport { describeError } from \"../../utils/describe-error.js\";\nimport { useCallback, useEffect, useState } from \"react\";\nimport Image from \"../image.js\";\nimport type { ApiWalletActivity, ApiActivity } from \"@medialane/sdk\";\nimport { getTokenBySymbol } from \"@medialane/sdk\";\nimport { mergeActivityFeeds, type MergedActivityItem } from \"../../utils/media-wallet/activity-feed.js\";\nimport { walletActivityTitle, walletActivitySubtitle, walletActivityAmount } from \"../../utils/media-wallet/wallet-activity.js\";\nimport { short, when, explorerTxUrl, fmt } from \"../../utils/media-wallet/wallet-format.js\";\nimport { BackButton } from \"./back-button.js\";\nimport { WalletActivityIcon } from \"./wallet-activity-icon.js\";\nimport { ActionModal } from \"./action-modal.js\";\nimport { useMediaWalletApp, type MediaWalletView } from \"./types.js\";\nimport { useMedialaneApp } from \"../medialane-app.js\";\nimport { emptyMessages } from \"../../utils/empty-messages.js\";\n\nconst GRADS = [\n \"linear-gradient(135deg,#3b7bff,#8a5cf6)\",\n \"linear-gradient(135deg,#8a5cf6,#f6608f)\",\n \"linear-gradient(135deg,#f6608f,#fb8b46)\",\n \"linear-gradient(135deg,#5b4ce6,#3b7bff)\",\n];\nconst gradFor = (seed: string) => {\n let h = 0;\n for (let i = 0; i < seed.length; i++) h = (h * 31 + seed.charCodeAt(i)) | 0;\n return GRADS[Math.abs(h) % GRADS.length];\n};\n\nexport function MediaWalletActivity({ onNavigate }: { onNavigate: (view: MediaWalletView) => void }) {\n const { useWalletSession } = useMediaWalletApp();\n const { getClient } = useMedialaneApp();\n const { address } = useWalletSession();\n const [items, setItems] = useState<MergedActivityItem[] | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [loading, setLoading] = useState(false);\n const [selected, setSelected] = useState<ApiWalletActivity | null>(null);\n\n const load = useCallback(() => {\n if (!address) return;\n let live = true;\n setLoading(true);\n setError(null);\n (async () => {\n try {\n const client = getClient().api;\n const [walletRes, protocolRes] = await Promise.all([\n client.activity.wallet(address),\n client.activity.byAddress(address, { page: 1, limit: 50 }),\n ]);\n if (live) setItems(mergeActivityFeeds(walletRes.data, protocolRes.data));\n } catch (e) {\n if (live) setError(describeError(e).message);\n } finally {\n if (live) setLoading(false);\n }\n })();\n return () => { live = false; };\n }, [address, getClient]);\n\n useEffect(() => load(), [load]);\n\n return (\n <main className=\"flex flex-col gap-4 px-5 pb-8 pt-2\">\n <div className=\"flex items-center gap-3\">\n <BackButton onBack={() => onNavigate({ name: \"home\" })} />\n <h1 className=\"font-[family-name:var(--font-display)] text-2xl font-extrabold tracking-tight\">Activity</h1>\n </div>\n\n {!address && <div className=\"text-sm text-muted-foreground\">No wallet found on this device.</div>}\n {error && <ActivityLoadError onRetry={load} />}\n {loading && !items && !error && <ActivityLoading />}\n {items && items.length === 0 && (\n <div>\n <p className=\"text-sm font-medium\">{emptyMessages.walletActivity.title}</p>\n <p className=\"text-sm text-muted-foreground\">{emptyMessages.walletActivity.description}</p>\n </div>\n )}\n\n {items && items.length > 0 && (\n <div className=\"flex flex-col gap-2\">\n {items.map((item) =>\n item.source === \"wallet\" ? (\n <WalletActivityRow key={item.data.id} a={item.data} timestamp={item.timestamp} onOpen={setSelected} />\n ) : (\n <ProtocolActivityRow key={`${item.data.txHash}-${item.data.type}`} item={item.data} />\n ),\n )}\n </div>\n )}\n\n {selected && <ActivityDetailModal a={selected} onClose={() => setSelected(null)} />}\n </main>\n );\n}\n\nfunction WalletActivityRow({\n a,\n timestamp,\n onOpen,\n}: {\n a: ApiWalletActivity;\n timestamp: string;\n onOpen: (a: ApiWalletActivity) => void;\n}) {\n const subtitle = walletActivitySubtitle(a);\n const amount = walletActivityAmount(a);\n return (\n <button\n onClick={() => onOpen(a)}\n className=\"flex items-center gap-3 rounded-2xl bg-card/40 px-4 py-3 text-left backdrop-blur-sm transition-colors hover:bg-card/60\"\n >\n <WalletActivityIcon a={a} />\n <div className=\"min-w-0 flex-1\">\n <div className=\"text-sm font-semibold\">{walletActivityTitle(a)}</div>\n {subtitle && <div className=\"truncate text-xs text-muted-foreground\">{subtitle}</div>}\n </div>\n <div className=\"shrink-0 text-right\">\n {amount && <div className=\"text-sm font-semibold tabular-nums\">{amount}</div>}\n <div className=\"text-xs text-muted-foreground\">{when(timestamp)}</div>\n </div>\n </button>\n );\n}\n\nfunction ActivityDetailModal({ a, onClose }: { a: ApiWalletActivity; onClose: () => void }) {\n const { explorerUrl } = useMediaWalletApp();\n const [copied, setCopied] = useState(false);\n const subtitle = walletActivitySubtitle(a);\n const amount = walletActivityAmount(a);\n const fullDate = new Date(a.timestamp).toLocaleString(undefined, {\n dateStyle: \"medium\",\n timeStyle: \"short\",\n });\n\n const copyHash = () => {\n navigator.clipboard?.writeText(a.txHash).catch(() => {});\n setCopied(true);\n setTimeout(() => setCopied(false), 1500);\n };\n\n return (\n <ActionModal title={walletActivityTitle(a)} onClose={onClose}>\n <div className=\"flex flex-col gap-4\">\n <div className=\"flex flex-col items-center gap-2 py-2 text-center\">\n <WalletActivityIcon a={a} />\n {amount && <div className=\"text-2xl font-bold tabular-nums\">{amount}</div>}\n {subtitle && <div className=\"text-sm text-muted-foreground\">{subtitle}</div>}\n </div>\n\n <div className=\"flex flex-col divide-y divide-border/40 rounded-2xl bg-foreground/[0.05] px-4\">\n <div className=\"flex items-center justify-between py-3\">\n <span className=\"text-xs text-muted-foreground\">Date</span>\n <span className=\"text-sm font-medium\">{fullDate}</span>\n </div>\n <div className=\"flex items-center justify-between py-3\">\n <span className=\"text-xs text-muted-foreground\">Transaction</span>\n <button onClick={copyHash} className=\"font-mono text-sm font-medium transition-opacity active:opacity-60\">\n {copied ? \"Copied ✓\" : short(a.txHash)}\n </button>\n </div>\n </div>\n\n <a\n href={explorerTxUrl(explorerUrl, a.txHash)}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-center text-xs font-medium text-muted-foreground underline underline-offset-2\"\n >\n View on Voyager ↗\n </a>\n </div>\n </ActionModal>\n );\n}\n\nfunction ProtocolActivityRow({ item }: { item: ApiActivity }) {\n const { resolveImage } = useMediaWalletApp();\n const img = resolveImage(item.token?.image ?? null);\n const seed = item.txHash ?? item.orderHash ?? item.type;\n return (\n <div className=\"flex items-center gap-3 rounded-2xl bg-card/40 px-4 py-3 backdrop-blur-sm\">\n <div className=\"relative h-11 w-11 shrink-0 overflow-hidden rounded-2xl\" style={img ? undefined : { background: gradFor(seed) }}>\n {img && (\n <Image src={img} alt=\"\" fill className=\"object-cover\" />\n )}\n </div>\n <div className=\"min-w-0 flex-1\">\n <div className=\"text-sm font-semibold capitalize\">{item.type}</div>\n {item.token?.name && <div className=\"truncate text-xs text-muted-foreground\">{item.token.name}</div>}\n </div>\n <div className=\"shrink-0 text-right\">\n {item.price?.raw && item.price.currency && (\n <div className=\"text-sm font-semibold tabular-nums\">\n {fmt(BigInt(item.price.raw), getTokenBySymbol(item.price.currency)?.decimals ?? 18)} <span className=\"text-xs text-muted-foreground\">{item.price.currency}</span>\n </div>\n )}\n <div className=\"text-xs text-muted-foreground\">{when(item.timestamp)}</div>\n </div>\n </div>\n );\n}\n\nfunction ActivityLoading() {\n return (\n <div className=\"flex min-h-[40vh] flex-col items-center justify-center gap-3\">\n <span className=\"h-6 w-6 animate-spin rounded-full border-2 border-border border-t-foreground\" />\n <div className=\"text-sm text-muted-foreground\">Loading your activity…</div>\n </div>\n );\n}\n\nfunction ActivityLoadError({ onRetry }: { onRetry: () => void }) {\n return (\n <div className=\"card-base flex flex-col items-center gap-3 px-6 py-8 text-center\">\n <div className=\"grid h-11 w-11 place-items-center rounded-2xl bg-destructive/10 text-destructive\">\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M10.3 3.9L2.3 18a2 2 0 001.7 3h16a2 2 0 001.7-3L13.7 3.9a2 2 0 00-3.4 0z\" />\n <path d=\"M12 9v4M12 17h.01\" />\n </svg>\n </div>\n <div>\n <div className=\"text-sm font-semibold\">Couldn't load your activity</div>\n <p className=\"mx-auto mt-1 max-w-[16rem] text-xs leading-relaxed text-muted-foreground\">\n There was a problem reaching the server. Check your connection and try again.\n </p>\n </div>\n <button\n onClick={onRetry}\n className=\"rounded-full border border-border px-4 py-2 text-xs font-semibold text-foreground transition-colors hover:bg-card\"\n >\n Try again\n </button>\n </div>\n );\n}\n"],"mappings":"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","names":["Image"]}
|
|
@@ -12,6 +12,7 @@ import { WalletActivityIcon } from "./wallet-activity-icon.js";
|
|
|
12
12
|
import { ActionModal } from "./action-modal.js";
|
|
13
13
|
import { useMediaWalletApp } from "./types.js";
|
|
14
14
|
import { useMedialaneApp } from "../medialane-app.js";
|
|
15
|
+
import { emptyMessages } from "../../utils/empty-messages.js";
|
|
15
16
|
const GRADS = [
|
|
16
17
|
"linear-gradient(135deg,#3b7bff,#8a5cf6)",
|
|
17
18
|
"linear-gradient(135deg,#8a5cf6,#f6608f)",
|
|
@@ -63,7 +64,10 @@ function MediaWalletActivity({ onNavigate }) {
|
|
|
63
64
|
!address && /* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground", children: "No wallet found on this device." }),
|
|
64
65
|
error && /* @__PURE__ */ jsx(ActivityLoadError, { onRetry: load }),
|
|
65
66
|
loading && !items && !error && /* @__PURE__ */ jsx(ActivityLoading, {}),
|
|
66
|
-
items && items.length === 0 && /* @__PURE__ */
|
|
67
|
+
items && items.length === 0 && /* @__PURE__ */ jsxs("div", { children: [
|
|
68
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: emptyMessages.walletActivity.title }),
|
|
69
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: emptyMessages.walletActivity.description })
|
|
70
|
+
] }),
|
|
67
71
|
items && items.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children: items.map(
|
|
68
72
|
(item) => item.source === "wallet" ? /* @__PURE__ */ jsx(WalletActivityRow, { a: item.data, timestamp: item.timestamp, onOpen: setSelected }, item.data.id) : /* @__PURE__ */ jsx(ProtocolActivityRow, { item: item.data }, `${item.data.txHash}-${item.data.type}`)
|
|
69
73
|
) }),
|