@medialane/ui 0.299.0 → 0.301.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.
Files changed (43) hide show
  1. package/dist/components/badge.d.cts +1 -1
  2. package/dist/components/badge.d.ts +1 -1
  3. package/dist/components/button.d.cts +1 -1
  4. package/dist/components/button.d.ts +1 -1
  5. package/dist/components/collection-page.cjs +2 -11
  6. package/dist/components/collection-page.cjs.map +1 -1
  7. package/dist/components/collection-page.js +2 -11
  8. package/dist/components/collection-page.js.map +1 -1
  9. package/dist/components/collection-provenance-tab.cjs +206 -0
  10. package/dist/components/collection-provenance-tab.cjs.map +1 -0
  11. package/dist/components/collection-provenance-tab.d.cts +8 -0
  12. package/dist/components/collection-provenance-tab.d.ts +8 -0
  13. package/dist/components/collection-provenance-tab.js +172 -0
  14. package/dist/components/collection-provenance-tab.js.map +1 -0
  15. package/dist/components/fast-mint/fast-mint.d.cts +2 -2
  16. package/dist/components/fast-mint/fast-mint.d.ts +2 -2
  17. package/dist/components/launchpad/collection-picker.cjs +1 -1
  18. package/dist/components/launchpad/collection-picker.cjs.map +1 -1
  19. package/dist/components/launchpad/collection-picker.js +1 -1
  20. package/dist/components/launchpad/collection-picker.js.map +1 -1
  21. package/dist/components/launchpad/edition-mint-schema.d.cts +2 -2
  22. package/dist/components/launchpad/edition-mint-schema.d.ts +2 -2
  23. package/dist/index.cjs +3 -6
  24. package/dist/index.cjs.map +1 -1
  25. package/dist/index.d.cts +1 -2
  26. package/dist/index.d.ts +1 -2
  27. package/dist/index.js +2 -4
  28. package/dist/index.js.map +1 -1
  29. package/dist/utils/media-wallet/use-erc20-balance.d.cts +1 -1
  30. package/dist/utils/media-wallet/use-erc20-balance.d.ts +1 -1
  31. package/package.json +1 -1
  32. package/dist/components/collection-activity-tab.cjs +0 -60
  33. package/dist/components/collection-activity-tab.cjs.map +0 -1
  34. package/dist/components/collection-activity-tab.d.cts +0 -8
  35. package/dist/components/collection-activity-tab.d.ts +0 -8
  36. package/dist/components/collection-activity-tab.js +0 -36
  37. package/dist/components/collection-activity-tab.js.map +0 -1
  38. package/dist/components/collection-traits-tab.cjs +0 -79
  39. package/dist/components/collection-traits-tab.cjs.map +0 -1
  40. package/dist/components/collection-traits-tab.d.cts +0 -8
  41. package/dist/components/collection-traits-tab.d.ts +0 -8
  42. package/dist/components/collection-traits-tab.js +0 -55
  43. package/dist/components/collection-traits-tab.js.map +0 -1
@@ -4,7 +4,7 @@ import * as React from 'react';
4
4
  import { VariantProps } from 'class-variance-authority';
5
5
 
6
6
  declare const badgeVariants: (props?: ({
7
- variant?: "default" | "secondary" | "outline" | "destructive" | null | undefined;
7
+ variant?: "default" | "destructive" | "outline" | "secondary" | null | undefined;
8
8
  } & class_variance_authority_types.ClassProp) | undefined) => string;
9
9
  interface BadgeProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof badgeVariants> {
10
10
  }
@@ -4,7 +4,7 @@ import * as React from 'react';
4
4
  import { VariantProps } from 'class-variance-authority';
5
5
 
6
6
  declare const badgeVariants: (props?: ({
7
- variant?: "default" | "secondary" | "outline" | "destructive" | null | undefined;
7
+ variant?: "default" | "destructive" | "outline" | "secondary" | null | undefined;
8
8
  } & class_variance_authority_types.ClassProp) | undefined) => string;
9
9
  interface BadgeProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof badgeVariants> {
10
10
  }
@@ -3,7 +3,7 @@ import * as React from 'react';
3
3
  import { VariantProps } from 'class-variance-authority';
4
4
 
5
5
  declare const buttonVariants: (props?: ({
6
- variant?: "link" | "default" | "secondary" | "outline" | "destructive" | "ghost" | "premium" | "tonal" | "gradient-border" | "gradient-fill" | null | undefined;
6
+ variant?: "link" | "default" | "destructive" | "outline" | "secondary" | "ghost" | "premium" | "tonal" | "gradient-border" | "gradient-fill" | null | undefined;
7
7
  size?: "default" | "icon" | "sm" | "lg" | null | undefined;
8
8
  } & class_variance_authority_types.ClassProp) | undefined) => string;
9
9
  interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
@@ -3,7 +3,7 @@ import * as React from 'react';
3
3
  import { VariantProps } from 'class-variance-authority';
4
4
 
5
5
  declare const buttonVariants: (props?: ({
6
- variant?: "link" | "default" | "secondary" | "outline" | "destructive" | "ghost" | "premium" | "tonal" | "gradient-border" | "gradient-fill" | null | undefined;
6
+ variant?: "link" | "default" | "destructive" | "outline" | "secondary" | "ghost" | "premium" | "tonal" | "gradient-border" | "gradient-fill" | null | undefined;
7
7
  size?: "default" | "icon" | "sm" | "lg" | null | undefined;
8
8
  } & class_variance_authority_types.ClassProp) | undefined) => string;
9
9
  interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
@@ -43,8 +43,7 @@ var import_collection_header = require("./collection-header.js");
43
43
  var import_collection_filters_dialog = require("./collection-filters-dialog.js");
44
44
  var import_more_menu = require("./more-menu.js");
45
45
  var import_explorer_url = require("../utils/explorer-url.js");
46
- var import_collection_activity_tab = require("./collection-activity-tab.js");
47
- var import_collection_traits_tab = require("./collection-traits-tab.js");
46
+ var import_collection_provenance_tab = require("./collection-provenance-tab.js");
48
47
  var import_club_owner_actions = require("./club-owner-actions.js");
49
48
  var import_owner_setup_panel = require("./owner-setup-panel.js");
50
49
  var import_transfer_collection_ownership = require("./transfer-collection-ownership.js");
@@ -176,7 +175,6 @@ function CollectionPage({ contract, slots }) {
176
175
  const [reportOpen, setReportOpen] = (0, import_react.useState)(false);
177
176
  const [activeTab, setActiveTab] = (0, import_react.useState)("assets");
178
177
  const [marketTab, setMarketTab] = (0, import_react.useState)("listings");
179
- const [provenanceTab, setProvenanceTab] = (0, import_react.useState)("activity");
180
178
  const [listingsSort, setListingsSort] = (0, import_react.useState)("recent");
181
179
  const [offersSort, setOffersSort] = (0, import_react.useState)("recent");
182
180
  const usdPrices = (0, import_use_usd_prices.useUsdPrices)();
@@ -259,14 +257,7 @@ function CollectionPage({ contract, slots }) {
259
257
  ordersLoading ? loadingGrid : activeBids.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EmptyState, { title: "No active offers", body: "Make the first offer, or check back when collectors start bidding." }) : listingGrid(activeBids, offersSort, false)
260
258
  ] })
261
259
  ] }) }),
262
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tabs.TabsContent, { value: "provenance", className: "mt-4", children: collection?.standard && (collection.totalSupply ?? 0) > 1 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_tabs.Tabs, { value: provenanceTab, onValueChange: (v) => setProvenanceTab(v), children: [
263
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_tabs.TabsList, { className: "h-9", children: [
264
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tabs.TabsTrigger, { value: "activity", className: "text-xs px-3 py-1", children: "Activity" }),
265
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tabs.TabsTrigger, { value: "traits", className: "text-xs px-3 py-1", children: "Traits" })
266
- ] }),
267
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tabs.TabsContent, { value: "activity", className: "mt-4", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_collection_activity_tab.CollectionActivityTab, { contract }) }),
268
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tabs.TabsContent, { value: "traits", className: "mt-4", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_collection_traits_tab.CollectionTraitsTab, { contract }) })
269
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_collection_activity_tab.CollectionActivityTab, { contract }) }),
260
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tabs.TabsContent, { value: "provenance", className: "mt-4", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_collection_provenance_tab.CollectionProvenanceTab, { contract }) }),
270
261
  profile?.hasGatedContent ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tabs.TabsContent, { value: "exclusive", className: "mt-4", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_gated_content.GatedContentPanel, { state: gatedState, onBrowseListings: () => {
271
262
  setMarketTab("listings");
272
263
  setActiveTab("market");
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/collection-page.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useMemo, useState, type ComponentType, type ReactNode } from \"react\";\nimport { Inbox, Lock, Sparkles, Ticket } from \"lucide-react\";\nimport { assetHref, getService, type ApiCollection, type ApiOrder, type ApiToken, type Chain, type CollectionTokensSort } from \"@medialane/sdk\";\nimport Link from \"./link.js\";\nimport { AssetCard, AssetCardSkeleton } from \"./asset-card.js\";\nimport { CollectionHeader } from \"./collection-header.js\";\nimport { CollectionFiltersDialog, CollectionActiveFilters } from \"./collection-filters-dialog.js\";\nimport { MoreMenu } from \"./more-menu.js\";\nimport { EXPLORER_URL } from \"../utils/explorer-url.js\";\nimport { CollectionActivityTab } from \"./collection-activity-tab.js\";\nimport { CollectionTraitsTab } from \"./collection-traits-tab.js\";\nimport { ClubOwnerActions } from \"./club-owner-actions.js\";\nimport { OwnerSetupPanel } from \"./owner-setup-panel.js\";\nimport { TransferCollectionOwnership } from \"./transfer-collection-ownership.js\";\nimport { HiddenContentBanner } from \"./hidden-content-banner.js\";\nimport { ListingCard, ListingCardSkeleton } from \"./listing-card.js\";\nimport { ListingCardMenu } from \"./listing-card-menu.js\";\nimport { LoadMoreSentinel } from \"./load-more-sentinel.js\";\nimport { MakeOfferPicker } from \"./make-offer-picker.js\";\nimport { OrderSortControl, sortOrders, type OrderSort } from \"./order-sort-control.js\";\nimport { GatedContentHero, GatedContentPanel, type GatedContentState } from \"./gated-content.js\";\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from \"./tabs.js\";\nimport { useMedialaneApp } from \"./medialane-app.js\";\nimport { ReportDialog } from \"./report-dialog.js\";\nimport { useCollection, useCollectionTokens } from \"../utils/use-collections.js\";\nimport { useOrders } from \"../utils/use-orders.js\";\nimport { useCollectionProfile } from \"../utils/use-profiles.js\";\nimport { useUsdPrices, usdPriceFor } from \"../utils/use-usd-prices.js\";\nimport { formatUsd } from \"../utils/format.js\";\nimport { isSameAddress } from \"../utils/same-address.js\";\nimport { isLivingRenderCollection } from \"../data/living-render-collections.js\";\n\nexport interface CollectionMarketActions {\n buy: (order: ApiOrder) => void;\n offer: (token: ApiToken) => void;\n dialogs: ReactNode;\n}\n\nexport interface CollectionPageSlots {\n useMarketActions: () => CollectionMarketActions;\n useGatedContent: (contract: string | undefined) => GatedContentState;\n ServiceAction: ComponentType<{ service: string | null | undefined; contractAddress: string }>;\n}\n\nconst PAGE_SIZE = 24;\nconst GRID = \"grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 gap-3 sm:gap-4\";\n\nconst MINT_HREFS: Partial<Record<string, (contract: string) => string>> = {\n \"mip-erc721\": () => \"/launchpad/single-editions\",\n \"mip-erc1155\": (c) => `/launchpad/nfteditions/${c}/mint`,\n \"ip-tickets\": (c) => `/launchpad/tickets/${c}/mint`,\n \"ip-club\": (c) => `/launchpad/club/${c}/mint`,\n};\n\n/** Ownership transfer exists from the audited v3 collection registry (2026-05-14) on. */\nexport function canTransferCollectionOwnership(collection: ApiCollection): boolean {\n return !!collection.collectionId && collection.standard === \"ERC721\" && collection.createdAt >= \"2026-05-14\";\n}\n\nfunction usdFor(order: ApiOrder | undefined, prices: ReturnType<typeof useUsdPrices>): string | null {\n const currency = order?.price?.currency?.toUpperCase();\n const amount = order?.price?.formatted ? parseFloat(order.price.formatted) : NaN;\n const rate = currency ? usdPriceFor(prices, currency) : undefined;\n return rate == null || isNaN(amount) ? null : formatUsd(amount * rate);\n}\n\nfunction EmptyState({ title, body, action }: { title: string; body: string; action?: { href: string; label: string } }) {\n return (\n <div className=\"py-20 flex flex-col items-center gap-3 text-center\">\n <Inbox className=\"h-10 w-10 text-muted-foreground/40\" />\n <p className=\"text-sm font-medium text-muted-foreground\">{title}</p>\n <p className=\"text-xs text-muted-foreground/70 max-w-xs\">{body}</p>\n {action ? (\n <Link href={action.href} className=\"mt-2 inline-flex items-center gap-1.5 h-9 px-4 rounded-lg text-sm font-semibold bg-foreground text-background hover:opacity-90 transition\">\n <Sparkles className=\"h-3.5 w-3.5\" />\n {action.label}\n </Link>\n ) : null}\n </div>\n );\n}\n\nfunction useCollectionItems(contract: string) {\n const [page, setPage] = useState(1);\n const [sort, setSort] = useState<CollectionTokensSort>(\"recent\");\n const [allTokens, setAllTokens] = useState<ApiToken[]>([]);\n const [selectedFilters, setSelectedFilters] = useState<Record<string, string[]>>({});\n const { tokens, meta, isLoading } = useCollectionTokens(contract, page, PAGE_SIZE, sort);\n\n const handleSortChange = (next: CollectionTokensSort) => {\n setSort(next);\n setPage(1);\n setAllTokens([]);\n };\n\n useEffect(() => {\n if (tokens.length === 0) return;\n setAllTokens((prev) => {\n const ids = new Set(prev.map((t) => `${t.contractAddress}-${t.tokenId}`));\n return page === 1 ? tokens : [...prev, ...tokens.filter((t) => !ids.has(`${t.contractAddress}-${t.tokenId}`))];\n });\n }, [tokens, page]);\n\n return { meta, isLoading, setPage, sort, handleSortChange, allTokens, selectedFilters, setSelectedFilters };\n}\n\ntype CollectionItemsState = ReturnType<typeof useCollectionItems>;\n\nfunction CollectionItems({ items, activeListings, mintHref }: { items: CollectionItemsState; activeListings: ApiOrder[]; mintHref: string | null }) {\n const { meta, isLoading, setPage, sort, handleSortChange, allTokens, selectedFilters, setSelectedFilters } = items;\n const usdPrices = useUsdPrices();\n\n const listingByTokenId = useMemo(() => new Map(activeListings.filter((o) => o.nftTokenId).map((o) => [o.nftTokenId!, o])), [activeListings]);\n\n const visibleTokens = useMemo(() => {\n const filters = Object.entries(selectedFilters);\n return allTokens.filter((token) => {\n if (filters.length === 0) return true;\n const attrs = Array.isArray(token.metadata?.attributes) ? (token.metadata.attributes as { trait_type?: string; value?: string }[]) : [];\n return filters.every(([traitType, values]) => attrs.some((a) => a.trait_type === traitType && values.includes(String(a.value))));\n });\n }, [allTokens, selectedFilters]);\n\n if (isLoading && allTokens.length === 0) {\n return <div className={GRID}>{Array.from({ length: 8 }).map((_, i) => <AssetCardSkeleton key={i} />)}</div>;\n }\n\n if (allTokens.length === 0) {\n return mintHref ? (\n <EmptyState title=\"Ready for your first work\" body=\"Mint into this collection and it appears here.\" action={{ href: mintHref, label: \"Mint your first work\" }} />\n ) : (\n <EmptyState title=\"No items yet\" body=\"Tokens in this collection will appear here once indexed.\" />\n );\n }\n\n return (\n <div className=\"space-y-3\">\n <CollectionActiveFilters tokens={allTokens} selected={selectedFilters} onChange={setSelectedFilters} sort={sort} onSortChange={handleSortChange} />\n {visibleTokens.length === 0 ? (\n <EmptyState title=\"No items match these filters\" body=\"Try removing some filters to see more results.\" />\n ) : (\n <div className={GRID}>\n {visibleTokens.map((t) => {\n const listing =\n t.activeOrders?.find((o) => o.offer.itemType === \"ERC721\" || o.offer.itemType === \"ERC1155\") ?? listingByTokenId.get(t.tokenId);\n return (\n <AssetCard\n key={`${t.contractAddress}-${t.tokenId}`}\n href={assetHref(t.chain as Chain, t.contractAddress, t.tokenId)}\n name={t.metadata?.name || `Token #${t.tokenId}`}\n image={t.metadata?.image}\n animationUrl={t.metadata?.animationUrl}\n live={isLivingRenderCollection(t.chain as Chain, t.contractAddress)}\n ipType={t.metadata?.ipType}\n price={listing ? { ...listing.price, usdValue: usdFor(listing, usdPrices) } : null}\n fallbackId={t.tokenId}\n indexing={t.metadataStatus === \"PENDING\" || t.metadataStatus === \"FETCHING\"}\n />\n );\n })}\n </div>\n )}\n <LoadMoreSentinel hasMore={meta ? allTokens.length < (meta.total ?? 0) : false} isLoading={isLoading} onLoadMore={() => setPage((p) => p + 1)} />\n </div>\n );\n}\n\nfunction OwnerActions({ collection }: { collection: ApiCollection }) {\n const service = getService(collection.service)?.id;\n const contract = collection.contractAddress;\n if (service === \"ip-tickets\") {\n return (\n <Link href={`/launchpad/tickets/${contract}/mint`} className=\"flex w-fit items-center gap-1.5 h-8 px-3 rounded-lg text-xs font-semibold text-white bg-brand-blue hover:brightness-110 active:scale-[0.98] transition\">\n <Ticket className=\"h-3.5 w-3.5\" />\n Mint tickets\n </Link>\n );\n }\n if (service === \"ip-club\") return <ClubOwnerActions contractAddress={contract} isOwner />;\n return null;\n}\n\nexport interface CollectionPageProps {\n contract: string;\n slots: CollectionPageSlots;\n}\n\nexport function CollectionPage({ contract, slots }: CollectionPageProps) {\n const { walletAddress } = useMedialaneApp();\n const { collection, isLoading: collectionLoading } = useCollection(contract);\n const { profile } = useCollectionProfile(contract);\n const gatedState = slots.useGatedContent(profile?.hasGatedContent ? contract : undefined);\n const market = slots.useMarketActions();\n const { orders, isLoading: ordersLoading } = useOrders({ collection: contract, status: \"ACTIVE\", sort: \"recent\", limit: 100 });\n\n const [reportOpen, setReportOpen] = useState(false);\n const [activeTab, setActiveTab] = useState(\"assets\");\n const [marketTab, setMarketTab] = useState<\"listings\" | \"offers\">(\"listings\");\n const [provenanceTab, setProvenanceTab] = useState<\"activity\" | \"traits\">(\"activity\");\n const [listingsSort, setListingsSort] = useState<OrderSort>(\"recent\");\n const [offersSort, setOffersSort] = useState<OrderSort>(\"recent\");\n const usdPrices = useUsdPrices();\n const items = useCollectionItems(contract);\n\n const activeListings = orders.filter((o) => o.status === \"ACTIVE\" && (o.offer.itemType === \"ERC721\" || o.offer.itemType === \"ERC1155\"));\n const activeBids = orders.filter((o) => o.status === \"ACTIVE\" && o.offer.itemType === \"ERC20\");\n const isOwner = !!collection?.owner && !!walletAddress && isSameAddress(collection.owner, walletAddress);\n const mintHref = isOwner && collection ? MINT_HREFS[getService(collection.service)?.id ?? \"\"]?.(contract) ?? null : null;\n const { ServiceAction } = slots;\n\n const listingGrid = (items: ApiOrder[], sort: OrderSort, buyable: boolean) => (\n <div className={GRID}>\n {sortOrders(items, sort).map((o) => (\n <ListingCard\n key={o.orderHash}\n order={o}\n onBuy={buyable && !isSameAddress(o.offerer, walletAddress) ? market.buy : undefined}\n usdValue={usdFor(o, usdPrices)}\n overflowMenu={<ListingCardMenu order={o} />}\n />\n ))}\n </div>\n );\n const loadingGrid = <div className={GRID}>{Array.from({ length: 8 }).map((_, i) => <ListingCardSkeleton key={i} />)}</div>;\n\n return (\n <div className=\"relative z-0 min-h-screen\">\n {(collection as { isHidden?: boolean } | null | undefined)?.isHidden ? <HiddenContentBanner /> : null}\n\n <div className=\"px-4 sm:px-6 pt-20 pb-6 space-y-4\">\n <CollectionHeader collection={collection} loading={collectionLoading}>\n {collection && isOwner ? <OwnerActions collection={collection} /> : null}\n {collection ? <ServiceAction service={collection.service} contractAddress={collection.contractAddress} /> : null}\n </CollectionHeader>\n {collection && profile ? <GatedContentHero profile={profile} state={gatedState} onViewExclusive={() => setActiveTab(\"exclusive\")} /> : null}\n </div>\n\n <div className=\"px-4 sm:px-6 pb-12\">\n <Tabs value={activeTab} onValueChange={setActiveTab}>\n <div className=\"sticky top-0 z-10 flex items-center gap-2 pt-3 pb-1\">\n <TabsList className=\"min-w-0 flex-1 justify-start overflow-x-auto sm:flex-none\">\n <TabsTrigger value=\"assets\" className=\"flex-1 sm:flex-none\">\n Assets{collection?.totalSupply ? ` (${collection.totalSupply.toLocaleString()})` : \"\"}\n </TabsTrigger>\n <TabsTrigger value=\"market\" className=\"flex-1 sm:flex-none\">\n Market{!ordersLoading && activeListings.length + activeBids.length > 0 && ` (${activeListings.length + activeBids.length})`}\n </TabsTrigger>\n <TabsTrigger value=\"provenance\" className=\"flex-1 sm:flex-none\">Provenance</TabsTrigger>\n {profile?.hasGatedContent ? (\n <TabsTrigger value=\"exclusive\" className=\"flex-1 sm:flex-none gap-1.5\">\n <Lock className=\"h-3.5 w-3.5\" />\n Exclusive\n </TabsTrigger>\n ) : null}\n </TabsList>\n <div className=\"ml-auto flex shrink-0 items-center gap-2\">\n {activeTab === \"assets\" && items.allTokens.length > 0 ? (\n <CollectionFiltersDialog tokens={items.allTokens} selected={items.selectedFilters} onChange={items.setSelectedFilters} sort={items.sort} onSortChange={items.handleSortChange} chips={false} />\n ) : null}\n {collection ? (\n <MoreMenu\n explorerHref={`${EXPLORER_URL}/contract/${collection.contractAddress}`}\n shareTitle={collection.name ?? \"Collection\"}\n onReport={() => setReportOpen(true)}\n />\n ) : null}\n </div>\n </div>\n\n <TabsContent value=\"assets\" className=\"mt-4\">\n {collection ? <CollectionItems items={items} activeListings={activeListings} mintHref={mintHref} /> : null}\n </TabsContent>\n\n <TabsContent value=\"market\" className=\"mt-4\">\n <Tabs value={marketTab} onValueChange={(v) => setMarketTab(v as \"listings\" | \"offers\")}>\n <TabsList className=\"h-9\">\n <TabsTrigger value=\"listings\" className=\"text-xs px-3 py-1\">\n Listings{!ordersLoading && activeListings.length > 0 && ` (${activeListings.length})`}\n </TabsTrigger>\n <TabsTrigger value=\"offers\" className=\"text-xs px-3 py-1\">\n Offers{!ordersLoading && activeBids.length > 0 && ` (${activeBids.length})`}\n </TabsTrigger>\n </TabsList>\n\n <TabsContent value=\"listings\" className=\"mt-4\">\n {ordersLoading ? loadingGrid : activeListings.length === 0 ? (\n <EmptyState title=\"No active listings\" body=\"When items in this collection are listed for sale, they'll appear here.\" />\n ) : (\n <div className=\"space-y-3\">\n <div className=\"flex justify-end\">\n <OrderSortControl value={listingsSort} onChange={setListingsSort} />\n </div>\n {listingGrid(activeListings, listingsSort, true)}\n </div>\n )}\n </TabsContent>\n\n <TabsContent value=\"offers\" className=\"mt-4\">\n <div className=\"flex justify-end items-center gap-2 mb-3\">\n {!ordersLoading && activeBids.length > 0 ? <OrderSortControl value={offersSort} onChange={setOffersSort} /> : null}\n <MakeOfferPicker contract={contract} onPick={market.offer} />\n </div>\n {ordersLoading ? loadingGrid : activeBids.length === 0 ? (\n <EmptyState title=\"No active offers\" body=\"Make the first offer, or check back when collectors start bidding.\" />\n ) : (\n listingGrid(activeBids, offersSort, false)\n )}\n </TabsContent>\n </Tabs>\n </TabsContent>\n\n <TabsContent value=\"provenance\" className=\"mt-4\">\n {collection?.standard && (collection.totalSupply ?? 0) > 1 ? (\n <Tabs value={provenanceTab} onValueChange={(v) => setProvenanceTab(v as \"activity\" | \"traits\")}>\n <TabsList className=\"h-9\">\n <TabsTrigger value=\"activity\" className=\"text-xs px-3 py-1\">Activity</TabsTrigger>\n <TabsTrigger value=\"traits\" className=\"text-xs px-3 py-1\">Traits</TabsTrigger>\n </TabsList>\n <TabsContent value=\"activity\" className=\"mt-4\">\n <CollectionActivityTab contract={contract} />\n </TabsContent>\n <TabsContent value=\"traits\" className=\"mt-4\">\n <CollectionTraitsTab contract={contract} />\n </TabsContent>\n </Tabs>\n ) : (\n <CollectionActivityTab contract={contract} />\n )}\n </TabsContent>\n\n {profile?.hasGatedContent ? (\n <TabsContent value=\"exclusive\" className=\"mt-4\">\n <GatedContentPanel state={gatedState} onBrowseListings={() => { setMarketTab(\"listings\"); setActiveTab(\"market\"); }} />\n </TabsContent>\n ) : null}\n </Tabs>\n </div>\n\n {collection && isOwner ? (\n <div className=\"px-4 sm:px-6 pb-8 space-y-4\">\n <OwnerSetupPanel contract={contract} profile={profile ?? null} />\n {canTransferCollectionOwnership(collection) ? (\n <div className=\"flex justify-end\">\n <TransferCollectionOwnership collectionId={collection.collectionId!} currentOwner={collection.owner!} collectionName={collection.name} />\n </div>\n ) : null}\n </div>\n ) : null}\n\n {collection ? (\n <ReportDialog open={reportOpen} onOpenChange={setReportOpen} target={{ type: \"COLLECTION\", contract: collection.contractAddress, name: collection.name ?? undefined }} />\n ) : null}\n {market.dialogs}\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAuEM;AArEN,mBAAiF;AACjF,0BAA8C;AAC9C,iBAA+H;AAC/H,kBAAiB;AACjB,wBAA6C;AAC7C,+BAAiC;AACjC,uCAAiE;AACjE,uBAAyB;AACzB,0BAA6B;AAC7B,qCAAsC;AACtC,mCAAoC;AACpC,gCAAiC;AACjC,+BAAgC;AAChC,2CAA4C;AAC5C,mCAAoC;AACpC,0BAAiD;AACjD,+BAAgC;AAChC,gCAAiC;AACjC,+BAAgC;AAChC,gCAA6D;AAC7D,2BAA4E;AAC5E,kBAAyD;AACzD,2BAAgC;AAChC,2BAA6B;AAC7B,6BAAmD;AACnD,wBAA0B;AAC1B,0BAAqC;AACrC,4BAA0C;AAC1C,oBAA0B;AAC1B,0BAA8B;AAC9B,uCAAyC;AAczC,MAAM,YAAY;AAClB,MAAM,OAAO;AAEb,MAAM,aAAoE;AAAA,EACxE,cAAc,MAAM;AAAA,EACpB,eAAe,CAAC,MAAM,0BAA0B,CAAC;AAAA,EACjD,cAAc,CAAC,MAAM,sBAAsB,CAAC;AAAA,EAC5C,WAAW,CAAC,MAAM,mBAAmB,CAAC;AACxC;AAGO,SAAS,+BAA+B,YAAoC;AACjF,SAAO,CAAC,CAAC,WAAW,gBAAgB,WAAW,aAAa,YAAY,WAAW,aAAa;AAClG;AAEA,SAAS,OAAO,OAA6B,QAAwD;AACnG,QAAM,WAAW,OAAO,OAAO,UAAU,YAAY;AACrD,QAAM,SAAS,OAAO,OAAO,YAAY,WAAW,MAAM,MAAM,SAAS,IAAI;AAC7E,QAAM,OAAO,eAAW,mCAAY,QAAQ,QAAQ,IAAI;AACxD,SAAO,QAAQ,QAAQ,MAAM,MAAM,IAAI,WAAO,yBAAU,SAAS,IAAI;AACvE;AAEA,SAAS,WAAW,EAAE,OAAO,MAAM,OAAO,GAA8E;AACtH,SACE,6CAAC,SAAI,WAAU,sDACb;AAAA,gDAAC,6BAAM,WAAU,sCAAqC;AAAA,IACtD,4CAAC,OAAE,WAAU,6CAA6C,iBAAM;AAAA,IAChE,4CAAC,OAAE,WAAU,6CAA6C,gBAAK;AAAA,IAC9D,SACC,6CAAC,YAAAA,SAAA,EAAK,MAAM,OAAO,MAAM,WAAU,6IACjC;AAAA,kDAAC,gCAAS,WAAU,eAAc;AAAA,MACjC,OAAO;AAAA,OACV,IACE;AAAA,KACN;AAEJ;AAEA,SAAS,mBAAmB,UAAkB;AAC5C,QAAM,CAAC,MAAM,OAAO,QAAI,uBAAS,CAAC;AAClC,QAAM,CAAC,MAAM,OAAO,QAAI,uBAA+B,QAAQ;AAC/D,QAAM,CAAC,WAAW,YAAY,QAAI,uBAAqB,CAAC,CAAC;AACzD,QAAM,CAAC,iBAAiB,kBAAkB,QAAI,uBAAmC,CAAC,CAAC;AACnF,QAAM,EAAE,QAAQ,MAAM,UAAU,QAAI,4CAAoB,UAAU,MAAM,WAAW,IAAI;AAEvF,QAAM,mBAAmB,CAAC,SAA+B;AACvD,YAAQ,IAAI;AACZ,YAAQ,CAAC;AACT,iBAAa,CAAC,CAAC;AAAA,EACjB;AAEA,8BAAU,MAAM;AACd,QAAI,OAAO,WAAW,EAAG;AACzB,iBAAa,CAAC,SAAS;AACrB,YAAM,MAAM,IAAI,IAAI,KAAK,IAAI,CAAC,MAAM,GAAG,EAAE,eAAe,IAAI,EAAE,OAAO,EAAE,CAAC;AACxE,aAAO,SAAS,IAAI,SAAS,CAAC,GAAG,MAAM,GAAG,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,IAAI,GAAG,EAAE,eAAe,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;AAAA,IAC/G,CAAC;AAAA,EACH,GAAG,CAAC,QAAQ,IAAI,CAAC;AAEjB,SAAO,EAAE,MAAM,WAAW,SAAS,MAAM,kBAAkB,WAAW,iBAAiB,mBAAmB;AAC5G;AAIA,SAAS,gBAAgB,EAAE,OAAO,gBAAgB,SAAS,GAAyF;AAClJ,QAAM,EAAE,MAAM,WAAW,SAAS,MAAM,kBAAkB,WAAW,iBAAiB,mBAAmB,IAAI;AAC7G,QAAM,gBAAY,oCAAa;AAE/B,QAAM,uBAAmB,sBAAQ,MAAM,IAAI,IAAI,eAAe,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,YAAa,CAAC,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC;AAE3I,QAAM,oBAAgB,sBAAQ,MAAM;AAClC,UAAM,UAAU,OAAO,QAAQ,eAAe;AAC9C,WAAO,UAAU,OAAO,CAAC,UAAU;AACjC,UAAI,QAAQ,WAAW,EAAG,QAAO;AACjC,YAAM,QAAQ,MAAM,QAAQ,MAAM,UAAU,UAAU,IAAK,MAAM,SAAS,aAA2D,CAAC;AACtI,aAAO,QAAQ,MAAM,CAAC,CAAC,WAAW,MAAM,MAAM,MAAM,KAAK,CAAC,MAAM,EAAE,eAAe,aAAa,OAAO,SAAS,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;AAAA,IACjI,CAAC;AAAA,EACH,GAAG,CAAC,WAAW,eAAe,CAAC;AAE/B,MAAI,aAAa,UAAU,WAAW,GAAG;AACvC,WAAO,4CAAC,SAAI,WAAW,MAAO,gBAAM,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,IAAI,CAAC,GAAG,MAAM,4CAAC,yCAAuB,CAAG,CAAE,GAAE;AAAA,EACvG;AAEA,MAAI,UAAU,WAAW,GAAG;AAC1B,WAAO,WACL,4CAAC,cAAW,OAAM,6BAA4B,MAAK,kDAAiD,QAAQ,EAAE,MAAM,UAAU,OAAO,uBAAuB,GAAG,IAE/J,4CAAC,cAAW,OAAM,gBAAe,MAAK,4DAA2D;AAAA,EAErG;AAEA,SACE,6CAAC,SAAI,WAAU,aACb;AAAA,gDAAC,4DAAwB,QAAQ,WAAW,UAAU,iBAAiB,UAAU,oBAAoB,MAAY,cAAc,kBAAkB;AAAA,IAChJ,cAAc,WAAW,IACxB,4CAAC,cAAW,OAAM,gCAA+B,MAAK,kDAAiD,IAEvG,4CAAC,SAAI,WAAW,MACb,wBAAc,IAAI,CAAC,MAAM;AACxB,YAAM,UACJ,EAAE,cAAc,KAAK,CAAC,MAAM,EAAE,MAAM,aAAa,YAAY,EAAE,MAAM,aAAa,SAAS,KAAK,iBAAiB,IAAI,EAAE,OAAO;AAChI,aACE;AAAA,QAAC;AAAA;AAAA,UAEC,UAAM,sBAAU,EAAE,OAAgB,EAAE,iBAAiB,EAAE,OAAO;AAAA,UAC9D,MAAM,EAAE,UAAU,QAAQ,UAAU,EAAE,OAAO;AAAA,UAC7C,OAAO,EAAE,UAAU;AAAA,UACnB,cAAc,EAAE,UAAU;AAAA,UAC1B,UAAM,2DAAyB,EAAE,OAAgB,EAAE,eAAe;AAAA,UAClE,QAAQ,EAAE,UAAU;AAAA,UACpB,OAAO,UAAU,EAAE,GAAG,QAAQ,OAAO,UAAU,OAAO,SAAS,SAAS,EAAE,IAAI;AAAA,UAC9E,YAAY,EAAE;AAAA,UACd,UAAU,EAAE,mBAAmB,aAAa,EAAE,mBAAmB;AAAA;AAAA,QAT5D,GAAG,EAAE,eAAe,IAAI,EAAE,OAAO;AAAA,MAUxC;AAAA,IAEJ,CAAC,GACH;AAAA,IAEF,4CAAC,8CAAiB,SAAS,OAAO,UAAU,UAAU,KAAK,SAAS,KAAK,OAAO,WAAsB,YAAY,MAAM,QAAQ,CAAC,MAAM,IAAI,CAAC,GAAG;AAAA,KACjJ;AAEJ;AAEA,SAAS,aAAa,EAAE,WAAW,GAAkC;AACnE,QAAM,cAAU,uBAAW,WAAW,OAAO,GAAG;AAChD,QAAM,WAAW,WAAW;AAC5B,MAAI,YAAY,cAAc;AAC5B,WACE,6CAAC,YAAAA,SAAA,EAAK,MAAM,sBAAsB,QAAQ,SAAS,WAAU,0JAC3D;AAAA,kDAAC,8BAAO,WAAU,eAAc;AAAA,MAAE;AAAA,OAEpC;AAAA,EAEJ;AACA,MAAI,YAAY,UAAW,QAAO,4CAAC,8CAAiB,iBAAiB,UAAU,SAAO,MAAC;AACvF,SAAO;AACT;AAOO,SAAS,eAAe,EAAE,UAAU,MAAM,GAAwB;AACvE,QAAM,EAAE,cAAc,QAAI,sCAAgB;AAC1C,QAAM,EAAE,YAAY,WAAW,kBAAkB,QAAI,sCAAc,QAAQ;AAC3E,QAAM,EAAE,QAAQ,QAAI,0CAAqB,QAAQ;AACjD,QAAM,aAAa,MAAM,gBAAgB,SAAS,kBAAkB,WAAW,MAAS;AACxF,QAAM,SAAS,MAAM,iBAAiB;AACtC,QAAM,EAAE,QAAQ,WAAW,cAAc,QAAI,6BAAU,EAAE,YAAY,UAAU,QAAQ,UAAU,MAAM,UAAU,OAAO,IAAI,CAAC;AAE7H,QAAM,CAAC,YAAY,aAAa,QAAI,uBAAS,KAAK;AAClD,QAAM,CAAC,WAAW,YAAY,QAAI,uBAAS,QAAQ;AACnD,QAAM,CAAC,WAAW,YAAY,QAAI,uBAAgC,UAAU;AAC5E,QAAM,CAAC,eAAe,gBAAgB,QAAI,uBAAgC,UAAU;AACpF,QAAM,CAAC,cAAc,eAAe,QAAI,uBAAoB,QAAQ;AACpE,QAAM,CAAC,YAAY,aAAa,QAAI,uBAAoB,QAAQ;AAChE,QAAM,gBAAY,oCAAa;AAC/B,QAAM,QAAQ,mBAAmB,QAAQ;AAEzC,QAAM,iBAAiB,OAAO,OAAO,CAAC,MAAM,EAAE,WAAW,aAAa,EAAE,MAAM,aAAa,YAAY,EAAE,MAAM,aAAa,UAAU;AACtI,QAAM,aAAa,OAAO,OAAO,CAAC,MAAM,EAAE,WAAW,YAAY,EAAE,MAAM,aAAa,OAAO;AAC7F,QAAM,UAAU,CAAC,CAAC,YAAY,SAAS,CAAC,CAAC,qBAAiB,mCAAc,WAAW,OAAO,aAAa;AACvG,QAAM,WAAW,WAAW,aAAa,eAAW,uBAAW,WAAW,OAAO,GAAG,MAAM,EAAE,IAAI,QAAQ,KAAK,OAAO;AACpH,QAAM,EAAE,cAAc,IAAI;AAE1B,QAAM,cAAc,CAACC,QAAmB,MAAiB,YACvD,4CAAC,SAAI,WAAW,MACb,oDAAWA,QAAO,IAAI,EAAE,IAAI,CAAC,MAC5B;AAAA,IAAC;AAAA;AAAA,MAEC,OAAO;AAAA,MACP,OAAO,WAAW,KAAC,mCAAc,EAAE,SAAS,aAAa,IAAI,OAAO,MAAM;AAAA,MAC1E,UAAU,OAAO,GAAG,SAAS;AAAA,MAC7B,cAAc,4CAAC,4CAAgB,OAAO,GAAG;AAAA;AAAA,IAJpC,EAAE;AAAA,EAKT,CACD,GACH;AAEF,QAAM,cAAc,4CAAC,SAAI,WAAW,MAAO,gBAAM,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,IAAI,CAAC,GAAG,MAAM,4CAAC,6CAAyB,CAAG,CAAE,GAAE;AAEpH,SACE,6CAAC,SAAI,WAAU,6BACX;AAAA,gBAA0D,WAAW,4CAAC,oDAAoB,IAAK;AAAA,IAEjG,6CAAC,SAAI,WAAU,qCACb;AAAA,mDAAC,6CAAiB,YAAwB,SAAS,mBAChD;AAAA,sBAAc,UAAU,4CAAC,gBAAa,YAAwB,IAAK;AAAA,QACnE,aAAa,4CAAC,iBAAc,SAAS,WAAW,SAAS,iBAAiB,WAAW,iBAAiB,IAAK;AAAA,SAC9G;AAAA,MACC,cAAc,UAAU,4CAAC,yCAAiB,SAAkB,OAAO,YAAY,iBAAiB,MAAM,aAAa,WAAW,GAAG,IAAK;AAAA,OACzI;AAAA,IAEA,4CAAC,SAAI,WAAU,sBACb,uDAAC,oBAAK,OAAO,WAAW,eAAe,cACrC;AAAA,mDAAC,SAAI,WAAU,uDACb;AAAA,qDAAC,wBAAS,WAAU,6DAClB;AAAA,uDAAC,2BAAY,OAAM,UAAS,WAAU,uBAAsB;AAAA;AAAA,YACnD,YAAY,cAAc,KAAK,WAAW,YAAY,eAAe,CAAC,MAAM;AAAA,aACrF;AAAA,UACA,6CAAC,2BAAY,OAAM,UAAS,WAAU,uBAAsB;AAAA;AAAA,YACnD,CAAC,iBAAiB,eAAe,SAAS,WAAW,SAAS,KAAK,KAAK,eAAe,SAAS,WAAW,MAAM;AAAA,aAC1H;AAAA,UACA,4CAAC,2BAAY,OAAM,cAAa,WAAU,uBAAsB,wBAAU;AAAA,UACzE,SAAS,kBACR,6CAAC,2BAAY,OAAM,aAAY,WAAU,+BACvC;AAAA,wDAAC,4BAAK,WAAU,eAAc;AAAA,YAAE;AAAA,aAElC,IACE;AAAA,WACN;AAAA,QACA,6CAAC,SAAI,WAAU,4CACZ;AAAA,wBAAc,YAAY,MAAM,UAAU,SAAS,IAClD,4CAAC,4DAAwB,QAAQ,MAAM,WAAW,UAAU,MAAM,iBAAiB,UAAU,MAAM,oBAAoB,MAAM,MAAM,MAAM,cAAc,MAAM,kBAAkB,OAAO,OAAO,IAC3L;AAAA,UACH,aACC;AAAA,YAAC;AAAA;AAAA,cACC,cAAc,GAAG,gCAAY,aAAa,WAAW,eAAe;AAAA,cACpE,YAAY,WAAW,QAAQ;AAAA,cAC/B,UAAU,MAAM,cAAc,IAAI;AAAA;AAAA,UACpC,IACE;AAAA,WACN;AAAA,SACF;AAAA,MAEA,4CAAC,2BAAY,OAAM,UAAS,WAAU,QACnC,uBAAa,4CAAC,mBAAgB,OAAc,gBAAgC,UAAoB,IAAK,MACxG;AAAA,MAEA,4CAAC,2BAAY,OAAM,UAAS,WAAU,QACpC,uDAAC,oBAAK,OAAO,WAAW,eAAe,CAAC,MAAM,aAAa,CAA0B,GACnF;AAAA,qDAAC,wBAAS,WAAU,OAClB;AAAA,uDAAC,2BAAY,OAAM,YAAW,WAAU,qBAAoB;AAAA;AAAA,YACjD,CAAC,iBAAiB,eAAe,SAAS,KAAK,KAAK,eAAe,MAAM;AAAA,aACpF;AAAA,UACA,6CAAC,2BAAY,OAAM,UAAS,WAAU,qBAAoB;AAAA;AAAA,YACjD,CAAC,iBAAiB,WAAW,SAAS,KAAK,KAAK,WAAW,MAAM;AAAA,aAC1E;AAAA,WACF;AAAA,QAEA,4CAAC,2BAAY,OAAM,YAAW,WAAU,QACrC,0BAAgB,cAAc,eAAe,WAAW,IACvD,4CAAC,cAAW,OAAM,sBAAqB,MAAK,2EAA0E,IAEtH,6CAAC,SAAI,WAAU,aACb;AAAA,sDAAC,SAAI,WAAU,oBACb,sDAAC,8CAAiB,OAAO,cAAc,UAAU,iBAAiB,GACpE;AAAA,UACC,YAAY,gBAAgB,cAAc,IAAI;AAAA,WACjD,GAEJ;AAAA,QAEA,6CAAC,2BAAY,OAAM,UAAS,WAAU,QACpC;AAAA,uDAAC,SAAI,WAAU,4CACZ;AAAA,aAAC,iBAAiB,WAAW,SAAS,IAAI,4CAAC,8CAAiB,OAAO,YAAY,UAAU,eAAe,IAAK;AAAA,YAC9G,4CAAC,4CAAgB,UAAoB,QAAQ,OAAO,OAAO;AAAA,aAC7D;AAAA,UACC,gBAAgB,cAAc,WAAW,WAAW,IACnD,4CAAC,cAAW,OAAM,oBAAmB,MAAK,sEAAqE,IAE/G,YAAY,YAAY,YAAY,KAAK;AAAA,WAE7C;AAAA,SACF,GACF;AAAA,MAEA,4CAAC,2BAAY,OAAM,cAAa,WAAU,QACvC,sBAAY,aAAa,WAAW,eAAe,KAAK,IACvD,6CAAC,oBAAK,OAAO,eAAe,eAAe,CAAC,MAAM,iBAAiB,CAA0B,GAC3F;AAAA,qDAAC,wBAAS,WAAU,OAClB;AAAA,sDAAC,2BAAY,OAAM,YAAW,WAAU,qBAAoB,sBAAQ;AAAA,UACpE,4CAAC,2BAAY,OAAM,UAAS,WAAU,qBAAoB,oBAAM;AAAA,WAClE;AAAA,QACA,4CAAC,2BAAY,OAAM,YAAW,WAAU,QACtC,sDAAC,wDAAsB,UAAoB,GAC7C;AAAA,QACA,4CAAC,2BAAY,OAAM,UAAS,WAAU,QACpC,sDAAC,oDAAoB,UAAoB,GAC3C;AAAA,SACF,IAEA,4CAAC,wDAAsB,UAAoB,GAE/C;AAAA,MAEC,SAAS,kBACR,4CAAC,2BAAY,OAAM,aAAY,WAAU,QACvC,sDAAC,0CAAkB,OAAO,YAAY,kBAAkB,MAAM;AAAE,qBAAa,UAAU;AAAG,qBAAa,QAAQ;AAAA,MAAG,GAAG,GACvH,IACE;AAAA,OACN,GACF;AAAA,IAEC,cAAc,UACb,6CAAC,SAAI,WAAU,+BACb;AAAA,kDAAC,4CAAgB,UAAoB,SAAS,WAAW,MAAM;AAAA,MAC9D,+BAA+B,UAAU,IACxC,4CAAC,SAAI,WAAU,oBACb,sDAAC,oEAA4B,cAAc,WAAW,cAAe,cAAc,WAAW,OAAQ,gBAAgB,WAAW,MAAM,GACzI,IACE;AAAA,OACN,IACE;AAAA,IAEH,aACC,4CAAC,qCAAa,MAAM,YAAY,cAAc,eAAe,QAAQ,EAAE,MAAM,cAAc,UAAU,WAAW,iBAAiB,MAAM,WAAW,QAAQ,OAAU,GAAG,IACrK;AAAA,IACH,OAAO;AAAA,KACV;AAEJ;","names":["Link","items"]}
1
+ {"version":3,"sources":["../../src/components/collection-page.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useMemo, useState, type ComponentType, type ReactNode } from \"react\";\nimport { Inbox, Lock, Sparkles, Ticket } from \"lucide-react\";\nimport { assetHref, getService, type ApiCollection, type ApiOrder, type ApiToken, type Chain, type CollectionTokensSort } from \"@medialane/sdk\";\nimport Link from \"./link.js\";\nimport { AssetCard, AssetCardSkeleton } from \"./asset-card.js\";\nimport { CollectionHeader } from \"./collection-header.js\";\nimport { CollectionFiltersDialog, CollectionActiveFilters } from \"./collection-filters-dialog.js\";\nimport { MoreMenu } from \"./more-menu.js\";\nimport { EXPLORER_URL } from \"../utils/explorer-url.js\";\nimport { CollectionProvenanceTab } from \"./collection-provenance-tab.js\";\nimport { ClubOwnerActions } from \"./club-owner-actions.js\";\nimport { OwnerSetupPanel } from \"./owner-setup-panel.js\";\nimport { TransferCollectionOwnership } from \"./transfer-collection-ownership.js\";\nimport { HiddenContentBanner } from \"./hidden-content-banner.js\";\nimport { ListingCard, ListingCardSkeleton } from \"./listing-card.js\";\nimport { ListingCardMenu } from \"./listing-card-menu.js\";\nimport { LoadMoreSentinel } from \"./load-more-sentinel.js\";\nimport { MakeOfferPicker } from \"./make-offer-picker.js\";\nimport { OrderSortControl, sortOrders, type OrderSort } from \"./order-sort-control.js\";\nimport { GatedContentHero, GatedContentPanel, type GatedContentState } from \"./gated-content.js\";\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from \"./tabs.js\";\nimport { useMedialaneApp } from \"./medialane-app.js\";\nimport { ReportDialog } from \"./report-dialog.js\";\nimport { useCollection, useCollectionTokens } from \"../utils/use-collections.js\";\nimport { useOrders } from \"../utils/use-orders.js\";\nimport { useCollectionProfile } from \"../utils/use-profiles.js\";\nimport { useUsdPrices, usdPriceFor } from \"../utils/use-usd-prices.js\";\nimport { formatUsd } from \"../utils/format.js\";\nimport { isSameAddress } from \"../utils/same-address.js\";\nimport { isLivingRenderCollection } from \"../data/living-render-collections.js\";\n\nexport interface CollectionMarketActions {\n buy: (order: ApiOrder) => void;\n offer: (token: ApiToken) => void;\n dialogs: ReactNode;\n}\n\nexport interface CollectionPageSlots {\n useMarketActions: () => CollectionMarketActions;\n useGatedContent: (contract: string | undefined) => GatedContentState;\n ServiceAction: ComponentType<{ service: string | null | undefined; contractAddress: string }>;\n}\n\nconst PAGE_SIZE = 24;\nconst GRID = \"grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 gap-3 sm:gap-4\";\n\nconst MINT_HREFS: Partial<Record<string, (contract: string) => string>> = {\n \"mip-erc721\": () => \"/launchpad/single-editions\",\n \"mip-erc1155\": (c) => `/launchpad/nfteditions/${c}/mint`,\n \"ip-tickets\": (c) => `/launchpad/tickets/${c}/mint`,\n \"ip-club\": (c) => `/launchpad/club/${c}/mint`,\n};\n\n/** Ownership transfer exists from the audited v3 collection registry (2026-05-14) on. */\nexport function canTransferCollectionOwnership(collection: ApiCollection): boolean {\n return !!collection.collectionId && collection.standard === \"ERC721\" && collection.createdAt >= \"2026-05-14\";\n}\n\nfunction usdFor(order: ApiOrder | undefined, prices: ReturnType<typeof useUsdPrices>): string | null {\n const currency = order?.price?.currency?.toUpperCase();\n const amount = order?.price?.formatted ? parseFloat(order.price.formatted) : NaN;\n const rate = currency ? usdPriceFor(prices, currency) : undefined;\n return rate == null || isNaN(amount) ? null : formatUsd(amount * rate);\n}\n\nfunction EmptyState({ title, body, action }: { title: string; body: string; action?: { href: string; label: string } }) {\n return (\n <div className=\"py-20 flex flex-col items-center gap-3 text-center\">\n <Inbox className=\"h-10 w-10 text-muted-foreground/40\" />\n <p className=\"text-sm font-medium text-muted-foreground\">{title}</p>\n <p className=\"text-xs text-muted-foreground/70 max-w-xs\">{body}</p>\n {action ? (\n <Link href={action.href} className=\"mt-2 inline-flex items-center gap-1.5 h-9 px-4 rounded-lg text-sm font-semibold bg-foreground text-background hover:opacity-90 transition\">\n <Sparkles className=\"h-3.5 w-3.5\" />\n {action.label}\n </Link>\n ) : null}\n </div>\n );\n}\n\nfunction useCollectionItems(contract: string) {\n const [page, setPage] = useState(1);\n const [sort, setSort] = useState<CollectionTokensSort>(\"recent\");\n const [allTokens, setAllTokens] = useState<ApiToken[]>([]);\n const [selectedFilters, setSelectedFilters] = useState<Record<string, string[]>>({});\n const { tokens, meta, isLoading } = useCollectionTokens(contract, page, PAGE_SIZE, sort);\n\n const handleSortChange = (next: CollectionTokensSort) => {\n setSort(next);\n setPage(1);\n setAllTokens([]);\n };\n\n useEffect(() => {\n if (tokens.length === 0) return;\n setAllTokens((prev) => {\n const ids = new Set(prev.map((t) => `${t.contractAddress}-${t.tokenId}`));\n return page === 1 ? tokens : [...prev, ...tokens.filter((t) => !ids.has(`${t.contractAddress}-${t.tokenId}`))];\n });\n }, [tokens, page]);\n\n return { meta, isLoading, setPage, sort, handleSortChange, allTokens, selectedFilters, setSelectedFilters };\n}\n\ntype CollectionItemsState = ReturnType<typeof useCollectionItems>;\n\nfunction CollectionItems({ items, activeListings, mintHref }: { items: CollectionItemsState; activeListings: ApiOrder[]; mintHref: string | null }) {\n const { meta, isLoading, setPage, sort, handleSortChange, allTokens, selectedFilters, setSelectedFilters } = items;\n const usdPrices = useUsdPrices();\n\n const listingByTokenId = useMemo(() => new Map(activeListings.filter((o) => o.nftTokenId).map((o) => [o.nftTokenId!, o])), [activeListings]);\n\n const visibleTokens = useMemo(() => {\n const filters = Object.entries(selectedFilters);\n return allTokens.filter((token) => {\n if (filters.length === 0) return true;\n const attrs = Array.isArray(token.metadata?.attributes) ? (token.metadata.attributes as { trait_type?: string; value?: string }[]) : [];\n return filters.every(([traitType, values]) => attrs.some((a) => a.trait_type === traitType && values.includes(String(a.value))));\n });\n }, [allTokens, selectedFilters]);\n\n if (isLoading && allTokens.length === 0) {\n return <div className={GRID}>{Array.from({ length: 8 }).map((_, i) => <AssetCardSkeleton key={i} />)}</div>;\n }\n\n if (allTokens.length === 0) {\n return mintHref ? (\n <EmptyState title=\"Ready for your first work\" body=\"Mint into this collection and it appears here.\" action={{ href: mintHref, label: \"Mint your first work\" }} />\n ) : (\n <EmptyState title=\"No items yet\" body=\"Tokens in this collection will appear here once indexed.\" />\n );\n }\n\n return (\n <div className=\"space-y-3\">\n <CollectionActiveFilters tokens={allTokens} selected={selectedFilters} onChange={setSelectedFilters} sort={sort} onSortChange={handleSortChange} />\n {visibleTokens.length === 0 ? (\n <EmptyState title=\"No items match these filters\" body=\"Try removing some filters to see more results.\" />\n ) : (\n <div className={GRID}>\n {visibleTokens.map((t) => {\n const listing =\n t.activeOrders?.find((o) => o.offer.itemType === \"ERC721\" || o.offer.itemType === \"ERC1155\") ?? listingByTokenId.get(t.tokenId);\n return (\n <AssetCard\n key={`${t.contractAddress}-${t.tokenId}`}\n href={assetHref(t.chain as Chain, t.contractAddress, t.tokenId)}\n name={t.metadata?.name || `Token #${t.tokenId}`}\n image={t.metadata?.image}\n animationUrl={t.metadata?.animationUrl}\n live={isLivingRenderCollection(t.chain as Chain, t.contractAddress)}\n ipType={t.metadata?.ipType}\n price={listing ? { ...listing.price, usdValue: usdFor(listing, usdPrices) } : null}\n fallbackId={t.tokenId}\n indexing={t.metadataStatus === \"PENDING\" || t.metadataStatus === \"FETCHING\"}\n />\n );\n })}\n </div>\n )}\n <LoadMoreSentinel hasMore={meta ? allTokens.length < (meta.total ?? 0) : false} isLoading={isLoading} onLoadMore={() => setPage((p) => p + 1)} />\n </div>\n );\n}\n\nfunction OwnerActions({ collection }: { collection: ApiCollection }) {\n const service = getService(collection.service)?.id;\n const contract = collection.contractAddress;\n if (service === \"ip-tickets\") {\n return (\n <Link href={`/launchpad/tickets/${contract}/mint`} className=\"flex w-fit items-center gap-1.5 h-8 px-3 rounded-lg text-xs font-semibold text-white bg-brand-blue hover:brightness-110 active:scale-[0.98] transition\">\n <Ticket className=\"h-3.5 w-3.5\" />\n Mint tickets\n </Link>\n );\n }\n if (service === \"ip-club\") return <ClubOwnerActions contractAddress={contract} isOwner />;\n return null;\n}\n\nexport interface CollectionPageProps {\n contract: string;\n slots: CollectionPageSlots;\n}\n\nexport function CollectionPage({ contract, slots }: CollectionPageProps) {\n const { walletAddress } = useMedialaneApp();\n const { collection, isLoading: collectionLoading } = useCollection(contract);\n const { profile } = useCollectionProfile(contract);\n const gatedState = slots.useGatedContent(profile?.hasGatedContent ? contract : undefined);\n const market = slots.useMarketActions();\n const { orders, isLoading: ordersLoading } = useOrders({ collection: contract, status: \"ACTIVE\", sort: \"recent\", limit: 100 });\n\n const [reportOpen, setReportOpen] = useState(false);\n const [activeTab, setActiveTab] = useState(\"assets\");\n const [marketTab, setMarketTab] = useState<\"listings\" | \"offers\">(\"listings\");\n const [listingsSort, setListingsSort] = useState<OrderSort>(\"recent\");\n const [offersSort, setOffersSort] = useState<OrderSort>(\"recent\");\n const usdPrices = useUsdPrices();\n const items = useCollectionItems(contract);\n\n const activeListings = orders.filter((o) => o.status === \"ACTIVE\" && (o.offer.itemType === \"ERC721\" || o.offer.itemType === \"ERC1155\"));\n const activeBids = orders.filter((o) => o.status === \"ACTIVE\" && o.offer.itemType === \"ERC20\");\n const isOwner = !!collection?.owner && !!walletAddress && isSameAddress(collection.owner, walletAddress);\n const mintHref = isOwner && collection ? MINT_HREFS[getService(collection.service)?.id ?? \"\"]?.(contract) ?? null : null;\n const { ServiceAction } = slots;\n\n const listingGrid = (items: ApiOrder[], sort: OrderSort, buyable: boolean) => (\n <div className={GRID}>\n {sortOrders(items, sort).map((o) => (\n <ListingCard\n key={o.orderHash}\n order={o}\n onBuy={buyable && !isSameAddress(o.offerer, walletAddress) ? market.buy : undefined}\n usdValue={usdFor(o, usdPrices)}\n overflowMenu={<ListingCardMenu order={o} />}\n />\n ))}\n </div>\n );\n const loadingGrid = <div className={GRID}>{Array.from({ length: 8 }).map((_, i) => <ListingCardSkeleton key={i} />)}</div>;\n\n return (\n <div className=\"relative z-0 min-h-screen\">\n {(collection as { isHidden?: boolean } | null | undefined)?.isHidden ? <HiddenContentBanner /> : null}\n\n <div className=\"px-4 sm:px-6 pt-20 pb-6 space-y-4\">\n <CollectionHeader collection={collection} loading={collectionLoading}>\n {collection && isOwner ? <OwnerActions collection={collection} /> : null}\n {collection ? <ServiceAction service={collection.service} contractAddress={collection.contractAddress} /> : null}\n </CollectionHeader>\n {collection && profile ? <GatedContentHero profile={profile} state={gatedState} onViewExclusive={() => setActiveTab(\"exclusive\")} /> : null}\n </div>\n\n <div className=\"px-4 sm:px-6 pb-12\">\n <Tabs value={activeTab} onValueChange={setActiveTab}>\n <div className=\"sticky top-0 z-10 flex items-center gap-2 pt-3 pb-1\">\n <TabsList className=\"min-w-0 flex-1 justify-start overflow-x-auto sm:flex-none\">\n <TabsTrigger value=\"assets\" className=\"flex-1 sm:flex-none\">\n Assets{collection?.totalSupply ? ` (${collection.totalSupply.toLocaleString()})` : \"\"}\n </TabsTrigger>\n <TabsTrigger value=\"market\" className=\"flex-1 sm:flex-none\">\n Market{!ordersLoading && activeListings.length + activeBids.length > 0 && ` (${activeListings.length + activeBids.length})`}\n </TabsTrigger>\n <TabsTrigger value=\"provenance\" className=\"flex-1 sm:flex-none\">Provenance</TabsTrigger>\n {profile?.hasGatedContent ? (\n <TabsTrigger value=\"exclusive\" className=\"flex-1 sm:flex-none gap-1.5\">\n <Lock className=\"h-3.5 w-3.5\" />\n Exclusive\n </TabsTrigger>\n ) : null}\n </TabsList>\n <div className=\"ml-auto flex shrink-0 items-center gap-2\">\n {activeTab === \"assets\" && items.allTokens.length > 0 ? (\n <CollectionFiltersDialog tokens={items.allTokens} selected={items.selectedFilters} onChange={items.setSelectedFilters} sort={items.sort} onSortChange={items.handleSortChange} chips={false} />\n ) : null}\n {collection ? (\n <MoreMenu\n explorerHref={`${EXPLORER_URL}/contract/${collection.contractAddress}`}\n shareTitle={collection.name ?? \"Collection\"}\n onReport={() => setReportOpen(true)}\n />\n ) : null}\n </div>\n </div>\n\n <TabsContent value=\"assets\" className=\"mt-4\">\n {collection ? <CollectionItems items={items} activeListings={activeListings} mintHref={mintHref} /> : null}\n </TabsContent>\n\n <TabsContent value=\"market\" className=\"mt-4\">\n <Tabs value={marketTab} onValueChange={(v) => setMarketTab(v as \"listings\" | \"offers\")}>\n <TabsList className=\"h-9\">\n <TabsTrigger value=\"listings\" className=\"text-xs px-3 py-1\">\n Listings{!ordersLoading && activeListings.length > 0 && ` (${activeListings.length})`}\n </TabsTrigger>\n <TabsTrigger value=\"offers\" className=\"text-xs px-3 py-1\">\n Offers{!ordersLoading && activeBids.length > 0 && ` (${activeBids.length})`}\n </TabsTrigger>\n </TabsList>\n\n <TabsContent value=\"listings\" className=\"mt-4\">\n {ordersLoading ? loadingGrid : activeListings.length === 0 ? (\n <EmptyState title=\"No active listings\" body=\"When items in this collection are listed for sale, they'll appear here.\" />\n ) : (\n <div className=\"space-y-3\">\n <div className=\"flex justify-end\">\n <OrderSortControl value={listingsSort} onChange={setListingsSort} />\n </div>\n {listingGrid(activeListings, listingsSort, true)}\n </div>\n )}\n </TabsContent>\n\n <TabsContent value=\"offers\" className=\"mt-4\">\n <div className=\"flex justify-end items-center gap-2 mb-3\">\n {!ordersLoading && activeBids.length > 0 ? <OrderSortControl value={offersSort} onChange={setOffersSort} /> : null}\n <MakeOfferPicker contract={contract} onPick={market.offer} />\n </div>\n {ordersLoading ? loadingGrid : activeBids.length === 0 ? (\n <EmptyState title=\"No active offers\" body=\"Make the first offer, or check back when collectors start bidding.\" />\n ) : (\n listingGrid(activeBids, offersSort, false)\n )}\n </TabsContent>\n </Tabs>\n </TabsContent>\n\n <TabsContent value=\"provenance\" className=\"mt-4\">\n <CollectionProvenanceTab contract={contract} />\n </TabsContent>\n\n {profile?.hasGatedContent ? (\n <TabsContent value=\"exclusive\" className=\"mt-4\">\n <GatedContentPanel state={gatedState} onBrowseListings={() => { setMarketTab(\"listings\"); setActiveTab(\"market\"); }} />\n </TabsContent>\n ) : null}\n </Tabs>\n </div>\n\n {collection && isOwner ? (\n <div className=\"px-4 sm:px-6 pb-8 space-y-4\">\n <OwnerSetupPanel contract={contract} profile={profile ?? null} />\n {canTransferCollectionOwnership(collection) ? (\n <div className=\"flex justify-end\">\n <TransferCollectionOwnership collectionId={collection.collectionId!} currentOwner={collection.owner!} collectionName={collection.name} />\n </div>\n ) : null}\n </div>\n ) : null}\n\n {collection ? (\n <ReportDialog open={reportOpen} onOpenChange={setReportOpen} target={{ type: \"COLLECTION\", contract: collection.contractAddress, name: collection.name ?? undefined }} />\n ) : null}\n {market.dialogs}\n </div>\n );\n}\n"],"mappings":"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","names":["Link","items"]}
@@ -9,8 +9,7 @@ import { CollectionHeader } from "./collection-header.js";
9
9
  import { CollectionFiltersDialog, CollectionActiveFilters } from "./collection-filters-dialog.js";
10
10
  import { MoreMenu } from "./more-menu.js";
11
11
  import { EXPLORER_URL } from "../utils/explorer-url.js";
12
- import { CollectionActivityTab } from "./collection-activity-tab.js";
13
- import { CollectionTraitsTab } from "./collection-traits-tab.js";
12
+ import { CollectionProvenanceTab } from "./collection-provenance-tab.js";
14
13
  import { ClubOwnerActions } from "./club-owner-actions.js";
15
14
  import { OwnerSetupPanel } from "./owner-setup-panel.js";
16
15
  import { TransferCollectionOwnership } from "./transfer-collection-ownership.js";
@@ -142,7 +141,6 @@ function CollectionPage({ contract, slots }) {
142
141
  const [reportOpen, setReportOpen] = useState(false);
143
142
  const [activeTab, setActiveTab] = useState("assets");
144
143
  const [marketTab, setMarketTab] = useState("listings");
145
- const [provenanceTab, setProvenanceTab] = useState("activity");
146
144
  const [listingsSort, setListingsSort] = useState("recent");
147
145
  const [offersSort, setOffersSort] = useState("recent");
148
146
  const usdPrices = useUsdPrices();
@@ -225,14 +223,7 @@ function CollectionPage({ contract, slots }) {
225
223
  ordersLoading ? loadingGrid : activeBids.length === 0 ? /* @__PURE__ */ jsx(EmptyState, { title: "No active offers", body: "Make the first offer, or check back when collectors start bidding." }) : listingGrid(activeBids, offersSort, false)
226
224
  ] })
227
225
  ] }) }),
228
- /* @__PURE__ */ jsx(TabsContent, { value: "provenance", className: "mt-4", children: collection?.standard && (collection.totalSupply ?? 0) > 1 ? /* @__PURE__ */ jsxs(Tabs, { value: provenanceTab, onValueChange: (v) => setProvenanceTab(v), children: [
229
- /* @__PURE__ */ jsxs(TabsList, { className: "h-9", children: [
230
- /* @__PURE__ */ jsx(TabsTrigger, { value: "activity", className: "text-xs px-3 py-1", children: "Activity" }),
231
- /* @__PURE__ */ jsx(TabsTrigger, { value: "traits", className: "text-xs px-3 py-1", children: "Traits" })
232
- ] }),
233
- /* @__PURE__ */ jsx(TabsContent, { value: "activity", className: "mt-4", children: /* @__PURE__ */ jsx(CollectionActivityTab, { contract }) }),
234
- /* @__PURE__ */ jsx(TabsContent, { value: "traits", className: "mt-4", children: /* @__PURE__ */ jsx(CollectionTraitsTab, { contract }) })
235
- ] }) : /* @__PURE__ */ jsx(CollectionActivityTab, { contract }) }),
226
+ /* @__PURE__ */ jsx(TabsContent, { value: "provenance", className: "mt-4", children: /* @__PURE__ */ jsx(CollectionProvenanceTab, { contract }) }),
236
227
  profile?.hasGatedContent ? /* @__PURE__ */ jsx(TabsContent, { value: "exclusive", className: "mt-4", children: /* @__PURE__ */ jsx(GatedContentPanel, { state: gatedState, onBrowseListings: () => {
237
228
  setMarketTab("listings");
238
229
  setActiveTab("market");
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/collection-page.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useMemo, useState, type ComponentType, type ReactNode } from \"react\";\nimport { Inbox, Lock, Sparkles, Ticket } from \"lucide-react\";\nimport { assetHref, getService, type ApiCollection, type ApiOrder, type ApiToken, type Chain, type CollectionTokensSort } from \"@medialane/sdk\";\nimport Link from \"./link.js\";\nimport { AssetCard, AssetCardSkeleton } from \"./asset-card.js\";\nimport { CollectionHeader } from \"./collection-header.js\";\nimport { CollectionFiltersDialog, CollectionActiveFilters } from \"./collection-filters-dialog.js\";\nimport { MoreMenu } from \"./more-menu.js\";\nimport { EXPLORER_URL } from \"../utils/explorer-url.js\";\nimport { CollectionActivityTab } from \"./collection-activity-tab.js\";\nimport { CollectionTraitsTab } from \"./collection-traits-tab.js\";\nimport { ClubOwnerActions } from \"./club-owner-actions.js\";\nimport { OwnerSetupPanel } from \"./owner-setup-panel.js\";\nimport { TransferCollectionOwnership } from \"./transfer-collection-ownership.js\";\nimport { HiddenContentBanner } from \"./hidden-content-banner.js\";\nimport { ListingCard, ListingCardSkeleton } from \"./listing-card.js\";\nimport { ListingCardMenu } from \"./listing-card-menu.js\";\nimport { LoadMoreSentinel } from \"./load-more-sentinel.js\";\nimport { MakeOfferPicker } from \"./make-offer-picker.js\";\nimport { OrderSortControl, sortOrders, type OrderSort } from \"./order-sort-control.js\";\nimport { GatedContentHero, GatedContentPanel, type GatedContentState } from \"./gated-content.js\";\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from \"./tabs.js\";\nimport { useMedialaneApp } from \"./medialane-app.js\";\nimport { ReportDialog } from \"./report-dialog.js\";\nimport { useCollection, useCollectionTokens } from \"../utils/use-collections.js\";\nimport { useOrders } from \"../utils/use-orders.js\";\nimport { useCollectionProfile } from \"../utils/use-profiles.js\";\nimport { useUsdPrices, usdPriceFor } from \"../utils/use-usd-prices.js\";\nimport { formatUsd } from \"../utils/format.js\";\nimport { isSameAddress } from \"../utils/same-address.js\";\nimport { isLivingRenderCollection } from \"../data/living-render-collections.js\";\n\nexport interface CollectionMarketActions {\n buy: (order: ApiOrder) => void;\n offer: (token: ApiToken) => void;\n dialogs: ReactNode;\n}\n\nexport interface CollectionPageSlots {\n useMarketActions: () => CollectionMarketActions;\n useGatedContent: (contract: string | undefined) => GatedContentState;\n ServiceAction: ComponentType<{ service: string | null | undefined; contractAddress: string }>;\n}\n\nconst PAGE_SIZE = 24;\nconst GRID = \"grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 gap-3 sm:gap-4\";\n\nconst MINT_HREFS: Partial<Record<string, (contract: string) => string>> = {\n \"mip-erc721\": () => \"/launchpad/single-editions\",\n \"mip-erc1155\": (c) => `/launchpad/nfteditions/${c}/mint`,\n \"ip-tickets\": (c) => `/launchpad/tickets/${c}/mint`,\n \"ip-club\": (c) => `/launchpad/club/${c}/mint`,\n};\n\n/** Ownership transfer exists from the audited v3 collection registry (2026-05-14) on. */\nexport function canTransferCollectionOwnership(collection: ApiCollection): boolean {\n return !!collection.collectionId && collection.standard === \"ERC721\" && collection.createdAt >= \"2026-05-14\";\n}\n\nfunction usdFor(order: ApiOrder | undefined, prices: ReturnType<typeof useUsdPrices>): string | null {\n const currency = order?.price?.currency?.toUpperCase();\n const amount = order?.price?.formatted ? parseFloat(order.price.formatted) : NaN;\n const rate = currency ? usdPriceFor(prices, currency) : undefined;\n return rate == null || isNaN(amount) ? null : formatUsd(amount * rate);\n}\n\nfunction EmptyState({ title, body, action }: { title: string; body: string; action?: { href: string; label: string } }) {\n return (\n <div className=\"py-20 flex flex-col items-center gap-3 text-center\">\n <Inbox className=\"h-10 w-10 text-muted-foreground/40\" />\n <p className=\"text-sm font-medium text-muted-foreground\">{title}</p>\n <p className=\"text-xs text-muted-foreground/70 max-w-xs\">{body}</p>\n {action ? (\n <Link href={action.href} className=\"mt-2 inline-flex items-center gap-1.5 h-9 px-4 rounded-lg text-sm font-semibold bg-foreground text-background hover:opacity-90 transition\">\n <Sparkles className=\"h-3.5 w-3.5\" />\n {action.label}\n </Link>\n ) : null}\n </div>\n );\n}\n\nfunction useCollectionItems(contract: string) {\n const [page, setPage] = useState(1);\n const [sort, setSort] = useState<CollectionTokensSort>(\"recent\");\n const [allTokens, setAllTokens] = useState<ApiToken[]>([]);\n const [selectedFilters, setSelectedFilters] = useState<Record<string, string[]>>({});\n const { tokens, meta, isLoading } = useCollectionTokens(contract, page, PAGE_SIZE, sort);\n\n const handleSortChange = (next: CollectionTokensSort) => {\n setSort(next);\n setPage(1);\n setAllTokens([]);\n };\n\n useEffect(() => {\n if (tokens.length === 0) return;\n setAllTokens((prev) => {\n const ids = new Set(prev.map((t) => `${t.contractAddress}-${t.tokenId}`));\n return page === 1 ? tokens : [...prev, ...tokens.filter((t) => !ids.has(`${t.contractAddress}-${t.tokenId}`))];\n });\n }, [tokens, page]);\n\n return { meta, isLoading, setPage, sort, handleSortChange, allTokens, selectedFilters, setSelectedFilters };\n}\n\ntype CollectionItemsState = ReturnType<typeof useCollectionItems>;\n\nfunction CollectionItems({ items, activeListings, mintHref }: { items: CollectionItemsState; activeListings: ApiOrder[]; mintHref: string | null }) {\n const { meta, isLoading, setPage, sort, handleSortChange, allTokens, selectedFilters, setSelectedFilters } = items;\n const usdPrices = useUsdPrices();\n\n const listingByTokenId = useMemo(() => new Map(activeListings.filter((o) => o.nftTokenId).map((o) => [o.nftTokenId!, o])), [activeListings]);\n\n const visibleTokens = useMemo(() => {\n const filters = Object.entries(selectedFilters);\n return allTokens.filter((token) => {\n if (filters.length === 0) return true;\n const attrs = Array.isArray(token.metadata?.attributes) ? (token.metadata.attributes as { trait_type?: string; value?: string }[]) : [];\n return filters.every(([traitType, values]) => attrs.some((a) => a.trait_type === traitType && values.includes(String(a.value))));\n });\n }, [allTokens, selectedFilters]);\n\n if (isLoading && allTokens.length === 0) {\n return <div className={GRID}>{Array.from({ length: 8 }).map((_, i) => <AssetCardSkeleton key={i} />)}</div>;\n }\n\n if (allTokens.length === 0) {\n return mintHref ? (\n <EmptyState title=\"Ready for your first work\" body=\"Mint into this collection and it appears here.\" action={{ href: mintHref, label: \"Mint your first work\" }} />\n ) : (\n <EmptyState title=\"No items yet\" body=\"Tokens in this collection will appear here once indexed.\" />\n );\n }\n\n return (\n <div className=\"space-y-3\">\n <CollectionActiveFilters tokens={allTokens} selected={selectedFilters} onChange={setSelectedFilters} sort={sort} onSortChange={handleSortChange} />\n {visibleTokens.length === 0 ? (\n <EmptyState title=\"No items match these filters\" body=\"Try removing some filters to see more results.\" />\n ) : (\n <div className={GRID}>\n {visibleTokens.map((t) => {\n const listing =\n t.activeOrders?.find((o) => o.offer.itemType === \"ERC721\" || o.offer.itemType === \"ERC1155\") ?? listingByTokenId.get(t.tokenId);\n return (\n <AssetCard\n key={`${t.contractAddress}-${t.tokenId}`}\n href={assetHref(t.chain as Chain, t.contractAddress, t.tokenId)}\n name={t.metadata?.name || `Token #${t.tokenId}`}\n image={t.metadata?.image}\n animationUrl={t.metadata?.animationUrl}\n live={isLivingRenderCollection(t.chain as Chain, t.contractAddress)}\n ipType={t.metadata?.ipType}\n price={listing ? { ...listing.price, usdValue: usdFor(listing, usdPrices) } : null}\n fallbackId={t.tokenId}\n indexing={t.metadataStatus === \"PENDING\" || t.metadataStatus === \"FETCHING\"}\n />\n );\n })}\n </div>\n )}\n <LoadMoreSentinel hasMore={meta ? allTokens.length < (meta.total ?? 0) : false} isLoading={isLoading} onLoadMore={() => setPage((p) => p + 1)} />\n </div>\n );\n}\n\nfunction OwnerActions({ collection }: { collection: ApiCollection }) {\n const service = getService(collection.service)?.id;\n const contract = collection.contractAddress;\n if (service === \"ip-tickets\") {\n return (\n <Link href={`/launchpad/tickets/${contract}/mint`} className=\"flex w-fit items-center gap-1.5 h-8 px-3 rounded-lg text-xs font-semibold text-white bg-brand-blue hover:brightness-110 active:scale-[0.98] transition\">\n <Ticket className=\"h-3.5 w-3.5\" />\n Mint tickets\n </Link>\n );\n }\n if (service === \"ip-club\") return <ClubOwnerActions contractAddress={contract} isOwner />;\n return null;\n}\n\nexport interface CollectionPageProps {\n contract: string;\n slots: CollectionPageSlots;\n}\n\nexport function CollectionPage({ contract, slots }: CollectionPageProps) {\n const { walletAddress } = useMedialaneApp();\n const { collection, isLoading: collectionLoading } = useCollection(contract);\n const { profile } = useCollectionProfile(contract);\n const gatedState = slots.useGatedContent(profile?.hasGatedContent ? contract : undefined);\n const market = slots.useMarketActions();\n const { orders, isLoading: ordersLoading } = useOrders({ collection: contract, status: \"ACTIVE\", sort: \"recent\", limit: 100 });\n\n const [reportOpen, setReportOpen] = useState(false);\n const [activeTab, setActiveTab] = useState(\"assets\");\n const [marketTab, setMarketTab] = useState<\"listings\" | \"offers\">(\"listings\");\n const [provenanceTab, setProvenanceTab] = useState<\"activity\" | \"traits\">(\"activity\");\n const [listingsSort, setListingsSort] = useState<OrderSort>(\"recent\");\n const [offersSort, setOffersSort] = useState<OrderSort>(\"recent\");\n const usdPrices = useUsdPrices();\n const items = useCollectionItems(contract);\n\n const activeListings = orders.filter((o) => o.status === \"ACTIVE\" && (o.offer.itemType === \"ERC721\" || o.offer.itemType === \"ERC1155\"));\n const activeBids = orders.filter((o) => o.status === \"ACTIVE\" && o.offer.itemType === \"ERC20\");\n const isOwner = !!collection?.owner && !!walletAddress && isSameAddress(collection.owner, walletAddress);\n const mintHref = isOwner && collection ? MINT_HREFS[getService(collection.service)?.id ?? \"\"]?.(contract) ?? null : null;\n const { ServiceAction } = slots;\n\n const listingGrid = (items: ApiOrder[], sort: OrderSort, buyable: boolean) => (\n <div className={GRID}>\n {sortOrders(items, sort).map((o) => (\n <ListingCard\n key={o.orderHash}\n order={o}\n onBuy={buyable && !isSameAddress(o.offerer, walletAddress) ? market.buy : undefined}\n usdValue={usdFor(o, usdPrices)}\n overflowMenu={<ListingCardMenu order={o} />}\n />\n ))}\n </div>\n );\n const loadingGrid = <div className={GRID}>{Array.from({ length: 8 }).map((_, i) => <ListingCardSkeleton key={i} />)}</div>;\n\n return (\n <div className=\"relative z-0 min-h-screen\">\n {(collection as { isHidden?: boolean } | null | undefined)?.isHidden ? <HiddenContentBanner /> : null}\n\n <div className=\"px-4 sm:px-6 pt-20 pb-6 space-y-4\">\n <CollectionHeader collection={collection} loading={collectionLoading}>\n {collection && isOwner ? <OwnerActions collection={collection} /> : null}\n {collection ? <ServiceAction service={collection.service} contractAddress={collection.contractAddress} /> : null}\n </CollectionHeader>\n {collection && profile ? <GatedContentHero profile={profile} state={gatedState} onViewExclusive={() => setActiveTab(\"exclusive\")} /> : null}\n </div>\n\n <div className=\"px-4 sm:px-6 pb-12\">\n <Tabs value={activeTab} onValueChange={setActiveTab}>\n <div className=\"sticky top-0 z-10 flex items-center gap-2 pt-3 pb-1\">\n <TabsList className=\"min-w-0 flex-1 justify-start overflow-x-auto sm:flex-none\">\n <TabsTrigger value=\"assets\" className=\"flex-1 sm:flex-none\">\n Assets{collection?.totalSupply ? ` (${collection.totalSupply.toLocaleString()})` : \"\"}\n </TabsTrigger>\n <TabsTrigger value=\"market\" className=\"flex-1 sm:flex-none\">\n Market{!ordersLoading && activeListings.length + activeBids.length > 0 && ` (${activeListings.length + activeBids.length})`}\n </TabsTrigger>\n <TabsTrigger value=\"provenance\" className=\"flex-1 sm:flex-none\">Provenance</TabsTrigger>\n {profile?.hasGatedContent ? (\n <TabsTrigger value=\"exclusive\" className=\"flex-1 sm:flex-none gap-1.5\">\n <Lock className=\"h-3.5 w-3.5\" />\n Exclusive\n </TabsTrigger>\n ) : null}\n </TabsList>\n <div className=\"ml-auto flex shrink-0 items-center gap-2\">\n {activeTab === \"assets\" && items.allTokens.length > 0 ? (\n <CollectionFiltersDialog tokens={items.allTokens} selected={items.selectedFilters} onChange={items.setSelectedFilters} sort={items.sort} onSortChange={items.handleSortChange} chips={false} />\n ) : null}\n {collection ? (\n <MoreMenu\n explorerHref={`${EXPLORER_URL}/contract/${collection.contractAddress}`}\n shareTitle={collection.name ?? \"Collection\"}\n onReport={() => setReportOpen(true)}\n />\n ) : null}\n </div>\n </div>\n\n <TabsContent value=\"assets\" className=\"mt-4\">\n {collection ? <CollectionItems items={items} activeListings={activeListings} mintHref={mintHref} /> : null}\n </TabsContent>\n\n <TabsContent value=\"market\" className=\"mt-4\">\n <Tabs value={marketTab} onValueChange={(v) => setMarketTab(v as \"listings\" | \"offers\")}>\n <TabsList className=\"h-9\">\n <TabsTrigger value=\"listings\" className=\"text-xs px-3 py-1\">\n Listings{!ordersLoading && activeListings.length > 0 && ` (${activeListings.length})`}\n </TabsTrigger>\n <TabsTrigger value=\"offers\" className=\"text-xs px-3 py-1\">\n Offers{!ordersLoading && activeBids.length > 0 && ` (${activeBids.length})`}\n </TabsTrigger>\n </TabsList>\n\n <TabsContent value=\"listings\" className=\"mt-4\">\n {ordersLoading ? loadingGrid : activeListings.length === 0 ? (\n <EmptyState title=\"No active listings\" body=\"When items in this collection are listed for sale, they'll appear here.\" />\n ) : (\n <div className=\"space-y-3\">\n <div className=\"flex justify-end\">\n <OrderSortControl value={listingsSort} onChange={setListingsSort} />\n </div>\n {listingGrid(activeListings, listingsSort, true)}\n </div>\n )}\n </TabsContent>\n\n <TabsContent value=\"offers\" className=\"mt-4\">\n <div className=\"flex justify-end items-center gap-2 mb-3\">\n {!ordersLoading && activeBids.length > 0 ? <OrderSortControl value={offersSort} onChange={setOffersSort} /> : null}\n <MakeOfferPicker contract={contract} onPick={market.offer} />\n </div>\n {ordersLoading ? loadingGrid : activeBids.length === 0 ? (\n <EmptyState title=\"No active offers\" body=\"Make the first offer, or check back when collectors start bidding.\" />\n ) : (\n listingGrid(activeBids, offersSort, false)\n )}\n </TabsContent>\n </Tabs>\n </TabsContent>\n\n <TabsContent value=\"provenance\" className=\"mt-4\">\n {collection?.standard && (collection.totalSupply ?? 0) > 1 ? (\n <Tabs value={provenanceTab} onValueChange={(v) => setProvenanceTab(v as \"activity\" | \"traits\")}>\n <TabsList className=\"h-9\">\n <TabsTrigger value=\"activity\" className=\"text-xs px-3 py-1\">Activity</TabsTrigger>\n <TabsTrigger value=\"traits\" className=\"text-xs px-3 py-1\">Traits</TabsTrigger>\n </TabsList>\n <TabsContent value=\"activity\" className=\"mt-4\">\n <CollectionActivityTab contract={contract} />\n </TabsContent>\n <TabsContent value=\"traits\" className=\"mt-4\">\n <CollectionTraitsTab contract={contract} />\n </TabsContent>\n </Tabs>\n ) : (\n <CollectionActivityTab contract={contract} />\n )}\n </TabsContent>\n\n {profile?.hasGatedContent ? (\n <TabsContent value=\"exclusive\" className=\"mt-4\">\n <GatedContentPanel state={gatedState} onBrowseListings={() => { setMarketTab(\"listings\"); setActiveTab(\"market\"); }} />\n </TabsContent>\n ) : null}\n </Tabs>\n </div>\n\n {collection && isOwner ? (\n <div className=\"px-4 sm:px-6 pb-8 space-y-4\">\n <OwnerSetupPanel contract={contract} profile={profile ?? null} />\n {canTransferCollectionOwnership(collection) ? (\n <div className=\"flex justify-end\">\n <TransferCollectionOwnership collectionId={collection.collectionId!} currentOwner={collection.owner!} collectionName={collection.name} />\n </div>\n ) : null}\n </div>\n ) : null}\n\n {collection ? (\n <ReportDialog open={reportOpen} onOpenChange={setReportOpen} target={{ type: \"COLLECTION\", contract: collection.contractAddress, name: collection.name ?? undefined }} />\n ) : null}\n {market.dialogs}\n </div>\n );\n}\n"],"mappings":"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","names":["items"]}
1
+ {"version":3,"sources":["../../src/components/collection-page.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useMemo, useState, type ComponentType, type ReactNode } from \"react\";\nimport { Inbox, Lock, Sparkles, Ticket } from \"lucide-react\";\nimport { assetHref, getService, type ApiCollection, type ApiOrder, type ApiToken, type Chain, type CollectionTokensSort } from \"@medialane/sdk\";\nimport Link from \"./link.js\";\nimport { AssetCard, AssetCardSkeleton } from \"./asset-card.js\";\nimport { CollectionHeader } from \"./collection-header.js\";\nimport { CollectionFiltersDialog, CollectionActiveFilters } from \"./collection-filters-dialog.js\";\nimport { MoreMenu } from \"./more-menu.js\";\nimport { EXPLORER_URL } from \"../utils/explorer-url.js\";\nimport { CollectionProvenanceTab } from \"./collection-provenance-tab.js\";\nimport { ClubOwnerActions } from \"./club-owner-actions.js\";\nimport { OwnerSetupPanel } from \"./owner-setup-panel.js\";\nimport { TransferCollectionOwnership } from \"./transfer-collection-ownership.js\";\nimport { HiddenContentBanner } from \"./hidden-content-banner.js\";\nimport { ListingCard, ListingCardSkeleton } from \"./listing-card.js\";\nimport { ListingCardMenu } from \"./listing-card-menu.js\";\nimport { LoadMoreSentinel } from \"./load-more-sentinel.js\";\nimport { MakeOfferPicker } from \"./make-offer-picker.js\";\nimport { OrderSortControl, sortOrders, type OrderSort } from \"./order-sort-control.js\";\nimport { GatedContentHero, GatedContentPanel, type GatedContentState } from \"./gated-content.js\";\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from \"./tabs.js\";\nimport { useMedialaneApp } from \"./medialane-app.js\";\nimport { ReportDialog } from \"./report-dialog.js\";\nimport { useCollection, useCollectionTokens } from \"../utils/use-collections.js\";\nimport { useOrders } from \"../utils/use-orders.js\";\nimport { useCollectionProfile } from \"../utils/use-profiles.js\";\nimport { useUsdPrices, usdPriceFor } from \"../utils/use-usd-prices.js\";\nimport { formatUsd } from \"../utils/format.js\";\nimport { isSameAddress } from \"../utils/same-address.js\";\nimport { isLivingRenderCollection } from \"../data/living-render-collections.js\";\n\nexport interface CollectionMarketActions {\n buy: (order: ApiOrder) => void;\n offer: (token: ApiToken) => void;\n dialogs: ReactNode;\n}\n\nexport interface CollectionPageSlots {\n useMarketActions: () => CollectionMarketActions;\n useGatedContent: (contract: string | undefined) => GatedContentState;\n ServiceAction: ComponentType<{ service: string | null | undefined; contractAddress: string }>;\n}\n\nconst PAGE_SIZE = 24;\nconst GRID = \"grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 gap-3 sm:gap-4\";\n\nconst MINT_HREFS: Partial<Record<string, (contract: string) => string>> = {\n \"mip-erc721\": () => \"/launchpad/single-editions\",\n \"mip-erc1155\": (c) => `/launchpad/nfteditions/${c}/mint`,\n \"ip-tickets\": (c) => `/launchpad/tickets/${c}/mint`,\n \"ip-club\": (c) => `/launchpad/club/${c}/mint`,\n};\n\n/** Ownership transfer exists from the audited v3 collection registry (2026-05-14) on. */\nexport function canTransferCollectionOwnership(collection: ApiCollection): boolean {\n return !!collection.collectionId && collection.standard === \"ERC721\" && collection.createdAt >= \"2026-05-14\";\n}\n\nfunction usdFor(order: ApiOrder | undefined, prices: ReturnType<typeof useUsdPrices>): string | null {\n const currency = order?.price?.currency?.toUpperCase();\n const amount = order?.price?.formatted ? parseFloat(order.price.formatted) : NaN;\n const rate = currency ? usdPriceFor(prices, currency) : undefined;\n return rate == null || isNaN(amount) ? null : formatUsd(amount * rate);\n}\n\nfunction EmptyState({ title, body, action }: { title: string; body: string; action?: { href: string; label: string } }) {\n return (\n <div className=\"py-20 flex flex-col items-center gap-3 text-center\">\n <Inbox className=\"h-10 w-10 text-muted-foreground/40\" />\n <p className=\"text-sm font-medium text-muted-foreground\">{title}</p>\n <p className=\"text-xs text-muted-foreground/70 max-w-xs\">{body}</p>\n {action ? (\n <Link href={action.href} className=\"mt-2 inline-flex items-center gap-1.5 h-9 px-4 rounded-lg text-sm font-semibold bg-foreground text-background hover:opacity-90 transition\">\n <Sparkles className=\"h-3.5 w-3.5\" />\n {action.label}\n </Link>\n ) : null}\n </div>\n );\n}\n\nfunction useCollectionItems(contract: string) {\n const [page, setPage] = useState(1);\n const [sort, setSort] = useState<CollectionTokensSort>(\"recent\");\n const [allTokens, setAllTokens] = useState<ApiToken[]>([]);\n const [selectedFilters, setSelectedFilters] = useState<Record<string, string[]>>({});\n const { tokens, meta, isLoading } = useCollectionTokens(contract, page, PAGE_SIZE, sort);\n\n const handleSortChange = (next: CollectionTokensSort) => {\n setSort(next);\n setPage(1);\n setAllTokens([]);\n };\n\n useEffect(() => {\n if (tokens.length === 0) return;\n setAllTokens((prev) => {\n const ids = new Set(prev.map((t) => `${t.contractAddress}-${t.tokenId}`));\n return page === 1 ? tokens : [...prev, ...tokens.filter((t) => !ids.has(`${t.contractAddress}-${t.tokenId}`))];\n });\n }, [tokens, page]);\n\n return { meta, isLoading, setPage, sort, handleSortChange, allTokens, selectedFilters, setSelectedFilters };\n}\n\ntype CollectionItemsState = ReturnType<typeof useCollectionItems>;\n\nfunction CollectionItems({ items, activeListings, mintHref }: { items: CollectionItemsState; activeListings: ApiOrder[]; mintHref: string | null }) {\n const { meta, isLoading, setPage, sort, handleSortChange, allTokens, selectedFilters, setSelectedFilters } = items;\n const usdPrices = useUsdPrices();\n\n const listingByTokenId = useMemo(() => new Map(activeListings.filter((o) => o.nftTokenId).map((o) => [o.nftTokenId!, o])), [activeListings]);\n\n const visibleTokens = useMemo(() => {\n const filters = Object.entries(selectedFilters);\n return allTokens.filter((token) => {\n if (filters.length === 0) return true;\n const attrs = Array.isArray(token.metadata?.attributes) ? (token.metadata.attributes as { trait_type?: string; value?: string }[]) : [];\n return filters.every(([traitType, values]) => attrs.some((a) => a.trait_type === traitType && values.includes(String(a.value))));\n });\n }, [allTokens, selectedFilters]);\n\n if (isLoading && allTokens.length === 0) {\n return <div className={GRID}>{Array.from({ length: 8 }).map((_, i) => <AssetCardSkeleton key={i} />)}</div>;\n }\n\n if (allTokens.length === 0) {\n return mintHref ? (\n <EmptyState title=\"Ready for your first work\" body=\"Mint into this collection and it appears here.\" action={{ href: mintHref, label: \"Mint your first work\" }} />\n ) : (\n <EmptyState title=\"No items yet\" body=\"Tokens in this collection will appear here once indexed.\" />\n );\n }\n\n return (\n <div className=\"space-y-3\">\n <CollectionActiveFilters tokens={allTokens} selected={selectedFilters} onChange={setSelectedFilters} sort={sort} onSortChange={handleSortChange} />\n {visibleTokens.length === 0 ? (\n <EmptyState title=\"No items match these filters\" body=\"Try removing some filters to see more results.\" />\n ) : (\n <div className={GRID}>\n {visibleTokens.map((t) => {\n const listing =\n t.activeOrders?.find((o) => o.offer.itemType === \"ERC721\" || o.offer.itemType === \"ERC1155\") ?? listingByTokenId.get(t.tokenId);\n return (\n <AssetCard\n key={`${t.contractAddress}-${t.tokenId}`}\n href={assetHref(t.chain as Chain, t.contractAddress, t.tokenId)}\n name={t.metadata?.name || `Token #${t.tokenId}`}\n image={t.metadata?.image}\n animationUrl={t.metadata?.animationUrl}\n live={isLivingRenderCollection(t.chain as Chain, t.contractAddress)}\n ipType={t.metadata?.ipType}\n price={listing ? { ...listing.price, usdValue: usdFor(listing, usdPrices) } : null}\n fallbackId={t.tokenId}\n indexing={t.metadataStatus === \"PENDING\" || t.metadataStatus === \"FETCHING\"}\n />\n );\n })}\n </div>\n )}\n <LoadMoreSentinel hasMore={meta ? allTokens.length < (meta.total ?? 0) : false} isLoading={isLoading} onLoadMore={() => setPage((p) => p + 1)} />\n </div>\n );\n}\n\nfunction OwnerActions({ collection }: { collection: ApiCollection }) {\n const service = getService(collection.service)?.id;\n const contract = collection.contractAddress;\n if (service === \"ip-tickets\") {\n return (\n <Link href={`/launchpad/tickets/${contract}/mint`} className=\"flex w-fit items-center gap-1.5 h-8 px-3 rounded-lg text-xs font-semibold text-white bg-brand-blue hover:brightness-110 active:scale-[0.98] transition\">\n <Ticket className=\"h-3.5 w-3.5\" />\n Mint tickets\n </Link>\n );\n }\n if (service === \"ip-club\") return <ClubOwnerActions contractAddress={contract} isOwner />;\n return null;\n}\n\nexport interface CollectionPageProps {\n contract: string;\n slots: CollectionPageSlots;\n}\n\nexport function CollectionPage({ contract, slots }: CollectionPageProps) {\n const { walletAddress } = useMedialaneApp();\n const { collection, isLoading: collectionLoading } = useCollection(contract);\n const { profile } = useCollectionProfile(contract);\n const gatedState = slots.useGatedContent(profile?.hasGatedContent ? contract : undefined);\n const market = slots.useMarketActions();\n const { orders, isLoading: ordersLoading } = useOrders({ collection: contract, status: \"ACTIVE\", sort: \"recent\", limit: 100 });\n\n const [reportOpen, setReportOpen] = useState(false);\n const [activeTab, setActiveTab] = useState(\"assets\");\n const [marketTab, setMarketTab] = useState<\"listings\" | \"offers\">(\"listings\");\n const [listingsSort, setListingsSort] = useState<OrderSort>(\"recent\");\n const [offersSort, setOffersSort] = useState<OrderSort>(\"recent\");\n const usdPrices = useUsdPrices();\n const items = useCollectionItems(contract);\n\n const activeListings = orders.filter((o) => o.status === \"ACTIVE\" && (o.offer.itemType === \"ERC721\" || o.offer.itemType === \"ERC1155\"));\n const activeBids = orders.filter((o) => o.status === \"ACTIVE\" && o.offer.itemType === \"ERC20\");\n const isOwner = !!collection?.owner && !!walletAddress && isSameAddress(collection.owner, walletAddress);\n const mintHref = isOwner && collection ? MINT_HREFS[getService(collection.service)?.id ?? \"\"]?.(contract) ?? null : null;\n const { ServiceAction } = slots;\n\n const listingGrid = (items: ApiOrder[], sort: OrderSort, buyable: boolean) => (\n <div className={GRID}>\n {sortOrders(items, sort).map((o) => (\n <ListingCard\n key={o.orderHash}\n order={o}\n onBuy={buyable && !isSameAddress(o.offerer, walletAddress) ? market.buy : undefined}\n usdValue={usdFor(o, usdPrices)}\n overflowMenu={<ListingCardMenu order={o} />}\n />\n ))}\n </div>\n );\n const loadingGrid = <div className={GRID}>{Array.from({ length: 8 }).map((_, i) => <ListingCardSkeleton key={i} />)}</div>;\n\n return (\n <div className=\"relative z-0 min-h-screen\">\n {(collection as { isHidden?: boolean } | null | undefined)?.isHidden ? <HiddenContentBanner /> : null}\n\n <div className=\"px-4 sm:px-6 pt-20 pb-6 space-y-4\">\n <CollectionHeader collection={collection} loading={collectionLoading}>\n {collection && isOwner ? <OwnerActions collection={collection} /> : null}\n {collection ? <ServiceAction service={collection.service} contractAddress={collection.contractAddress} /> : null}\n </CollectionHeader>\n {collection && profile ? <GatedContentHero profile={profile} state={gatedState} onViewExclusive={() => setActiveTab(\"exclusive\")} /> : null}\n </div>\n\n <div className=\"px-4 sm:px-6 pb-12\">\n <Tabs value={activeTab} onValueChange={setActiveTab}>\n <div className=\"sticky top-0 z-10 flex items-center gap-2 pt-3 pb-1\">\n <TabsList className=\"min-w-0 flex-1 justify-start overflow-x-auto sm:flex-none\">\n <TabsTrigger value=\"assets\" className=\"flex-1 sm:flex-none\">\n Assets{collection?.totalSupply ? ` (${collection.totalSupply.toLocaleString()})` : \"\"}\n </TabsTrigger>\n <TabsTrigger value=\"market\" className=\"flex-1 sm:flex-none\">\n Market{!ordersLoading && activeListings.length + activeBids.length > 0 && ` (${activeListings.length + activeBids.length})`}\n </TabsTrigger>\n <TabsTrigger value=\"provenance\" className=\"flex-1 sm:flex-none\">Provenance</TabsTrigger>\n {profile?.hasGatedContent ? (\n <TabsTrigger value=\"exclusive\" className=\"flex-1 sm:flex-none gap-1.5\">\n <Lock className=\"h-3.5 w-3.5\" />\n Exclusive\n </TabsTrigger>\n ) : null}\n </TabsList>\n <div className=\"ml-auto flex shrink-0 items-center gap-2\">\n {activeTab === \"assets\" && items.allTokens.length > 0 ? (\n <CollectionFiltersDialog tokens={items.allTokens} selected={items.selectedFilters} onChange={items.setSelectedFilters} sort={items.sort} onSortChange={items.handleSortChange} chips={false} />\n ) : null}\n {collection ? (\n <MoreMenu\n explorerHref={`${EXPLORER_URL}/contract/${collection.contractAddress}`}\n shareTitle={collection.name ?? \"Collection\"}\n onReport={() => setReportOpen(true)}\n />\n ) : null}\n </div>\n </div>\n\n <TabsContent value=\"assets\" className=\"mt-4\">\n {collection ? <CollectionItems items={items} activeListings={activeListings} mintHref={mintHref} /> : null}\n </TabsContent>\n\n <TabsContent value=\"market\" className=\"mt-4\">\n <Tabs value={marketTab} onValueChange={(v) => setMarketTab(v as \"listings\" | \"offers\")}>\n <TabsList className=\"h-9\">\n <TabsTrigger value=\"listings\" className=\"text-xs px-3 py-1\">\n Listings{!ordersLoading && activeListings.length > 0 && ` (${activeListings.length})`}\n </TabsTrigger>\n <TabsTrigger value=\"offers\" className=\"text-xs px-3 py-1\">\n Offers{!ordersLoading && activeBids.length > 0 && ` (${activeBids.length})`}\n </TabsTrigger>\n </TabsList>\n\n <TabsContent value=\"listings\" className=\"mt-4\">\n {ordersLoading ? loadingGrid : activeListings.length === 0 ? (\n <EmptyState title=\"No active listings\" body=\"When items in this collection are listed for sale, they'll appear here.\" />\n ) : (\n <div className=\"space-y-3\">\n <div className=\"flex justify-end\">\n <OrderSortControl value={listingsSort} onChange={setListingsSort} />\n </div>\n {listingGrid(activeListings, listingsSort, true)}\n </div>\n )}\n </TabsContent>\n\n <TabsContent value=\"offers\" className=\"mt-4\">\n <div className=\"flex justify-end items-center gap-2 mb-3\">\n {!ordersLoading && activeBids.length > 0 ? <OrderSortControl value={offersSort} onChange={setOffersSort} /> : null}\n <MakeOfferPicker contract={contract} onPick={market.offer} />\n </div>\n {ordersLoading ? loadingGrid : activeBids.length === 0 ? (\n <EmptyState title=\"No active offers\" body=\"Make the first offer, or check back when collectors start bidding.\" />\n ) : (\n listingGrid(activeBids, offersSort, false)\n )}\n </TabsContent>\n </Tabs>\n </TabsContent>\n\n <TabsContent value=\"provenance\" className=\"mt-4\">\n <CollectionProvenanceTab contract={contract} />\n </TabsContent>\n\n {profile?.hasGatedContent ? (\n <TabsContent value=\"exclusive\" className=\"mt-4\">\n <GatedContentPanel state={gatedState} onBrowseListings={() => { setMarketTab(\"listings\"); setActiveTab(\"market\"); }} />\n </TabsContent>\n ) : null}\n </Tabs>\n </div>\n\n {collection && isOwner ? (\n <div className=\"px-4 sm:px-6 pb-8 space-y-4\">\n <OwnerSetupPanel contract={contract} profile={profile ?? null} />\n {canTransferCollectionOwnership(collection) ? (\n <div className=\"flex justify-end\">\n <TransferCollectionOwnership collectionId={collection.collectionId!} currentOwner={collection.owner!} collectionName={collection.name} />\n </div>\n ) : null}\n </div>\n ) : null}\n\n {collection ? (\n <ReportDialog open={reportOpen} onOpenChange={setReportOpen} target={{ type: \"COLLECTION\", contract: collection.contractAddress, name: collection.name ?? undefined }} />\n ) : null}\n {market.dialogs}\n </div>\n );\n}\n"],"mappings":"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","names":["items"]}
@@ -0,0 +1,206 @@
1
+ "use strict";
2
+ "use client";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(to, key) && key !== except)
17
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
+ }
19
+ return to;
20
+ };
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
26
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
+ mod
28
+ ));
29
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
+ var collection_provenance_tab_exports = {};
31
+ __export(collection_provenance_tab_exports, {
32
+ CollectionProvenanceTab: () => CollectionProvenanceTab
33
+ });
34
+ module.exports = __toCommonJS(collection_provenance_tab_exports);
35
+ var import_jsx_runtime = require("react/jsx-runtime");
36
+ var import_react = require("react");
37
+ var import_sdk = require("@medialane/sdk");
38
+ var import_lucide_react = require("lucide-react");
39
+ var import_image = __toESM(require("./image.js"), 1);
40
+ var import_link = __toESM(require("./link.js"), 1);
41
+ var import_address_display = require("./address-display.js");
42
+ var import_currency_icon = require("./currency-icon.js");
43
+ var import_load_more_sentinel = require("./load-more-sentinel.js");
44
+ var import_use_activities = require("../utils/use-activities.js");
45
+ var import_use_image_url = require("../utils/use-image-url.js");
46
+ var import_activity = require("../data/activity.js");
47
+ var import_explorer_url = require("../utils/explorer-url.js");
48
+ var import_format = require("../utils/format.js");
49
+ var import_time = require("../utils/time.js");
50
+ var import_cn = require("../utils/cn.js");
51
+ const PAGE_SIZE = 30;
52
+ const EVENT_TITLE = {
53
+ mint: "Minted",
54
+ listing: "Listed for sale",
55
+ sale: "Purchased",
56
+ offer: "Offer made",
57
+ transfer: "Transferred",
58
+ cancelled: "Listing cancelled"
59
+ };
60
+ function dayLabel(iso) {
61
+ const date = new Date(iso);
62
+ const today = /* @__PURE__ */ new Date();
63
+ const yesterday = /* @__PURE__ */ new Date();
64
+ yesterday.setDate(today.getDate() - 1);
65
+ if (date.toDateString() === today.toDateString()) return "Today";
66
+ if (date.toDateString() === yesterday.toDateString()) return "Yesterday";
67
+ return date.toLocaleDateString(void 0, { day: "numeric", month: "long", year: "numeric" });
68
+ }
69
+ function groupByDay(events) {
70
+ const groups = [];
71
+ for (const event of events) {
72
+ const label = dayLabel(event.timestamp);
73
+ const last = groups[groups.length - 1];
74
+ if (last && last.label === label) last.events.push(event);
75
+ else groups.push({ label, events: [event] });
76
+ }
77
+ return groups;
78
+ }
79
+ function ProvenanceEvent({ event, showAsset }) {
80
+ const resolveImage = (0, import_use_image_url.useImageUrl)();
81
+ const config = import_activity.ACTIVITY_TYPE_CONFIG[event.type];
82
+ const Icon = config?.icon ?? import_lucide_react.ExternalLink;
83
+ const contract = event.nftContract ?? event.contractAddress ?? null;
84
+ const tokenId = event.nftTokenId ?? event.tokenId ?? null;
85
+ const actor = event.offerer ?? event.fulfiller ?? (event.type === "mint" ? event.to : event.from) ?? null;
86
+ const amount = event.amount && Number(event.amount) > 1 ? event.amount : null;
87
+ const name = event.token?.name ?? (tokenId ? `#${tokenId}` : null);
88
+ const image = resolveImage(event.token?.image ?? null);
89
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { className: "relative pl-12 pb-6 last:pb-0", children: [
90
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
91
+ "span",
92
+ {
93
+ className: (0, import_cn.cn)(
94
+ "absolute left-0 top-0 flex h-8 w-8 items-center justify-center rounded-full ring-4 ring-background",
95
+ config?.bgClass ?? "bg-muted"
96
+ ),
97
+ "aria-hidden": true,
98
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Icon, { className: (0, import_cn.cn)("h-4 w-4", config?.colorClass ?? "text-muted-foreground") })
99
+ }
100
+ ),
101
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-start gap-3", children: [
102
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "min-w-0 flex-1", children: [
103
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "text-sm font-semibold leading-8 sm:leading-8", children: [
104
+ EVENT_TITLE[event.type] ?? event.type,
105
+ amount ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "ml-1.5 text-xs font-medium text-muted-foreground", children: [
106
+ "\xD7",
107
+ amount
108
+ ] }) : null,
109
+ actor ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "font-normal text-muted-foreground", children: [
110
+ " by ",
111
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
112
+ import_link.default,
113
+ {
114
+ href: (0, import_sdk.profileHref)({ address: actor }),
115
+ className: "hover:text-primary transition-colors",
116
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_address_display.AddressDisplay, { address: actor, chars: 4, showCopy: false, className: "text-xs" })
117
+ }
118
+ )
119
+ ] }) : null
120
+ ] }),
121
+ showAsset && name ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
122
+ import_link.default,
123
+ {
124
+ href: contract && tokenId ? (0, import_sdk.assetHref)(event.chain ?? "STARKNET", contract, tokenId) : "#",
125
+ className: "mt-1 inline-flex max-w-full items-center gap-2 rounded-lg bg-muted/40 py-1 pl-1 pr-3 hover:bg-muted transition-colors",
126
+ children: [
127
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "relative h-8 w-8 shrink-0 overflow-hidden rounded-md bg-muted", children: image ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_image.default, { src: image, alt: "", width: 32, height: 32, className: "h-full w-full object-cover", unoptimized: true }) : null }),
128
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "truncate text-xs font-medium", children: name })
129
+ ]
130
+ }
131
+ ) : null
132
+ ] }),
133
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex shrink-0 flex-col items-end gap-0.5 pt-1.5", children: [
134
+ event.price?.formatted ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "flex items-center gap-1.5 text-sm font-bold tabular-nums", children: [
135
+ event.price.currency ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_currency_icon.CurrencyIcon, { symbol: event.price.currency, size: 13, "aria-hidden": true }) : null,
136
+ (0, import_format.formatDisplayPrice)(event.price.formatted)
137
+ ] }) : null,
138
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "flex items-center gap-1.5 text-xs text-muted-foreground", children: [
139
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("time", { dateTime: event.timestamp, title: new Date(event.timestamp).toLocaleString(), children: (0, import_time.timeAgo)(event.timestamp) }),
140
+ event.txHash ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
141
+ "a",
142
+ {
143
+ href: `${import_explorer_url.EXPLORER_URL}/tx/${event.txHash}`,
144
+ target: "_blank",
145
+ rel: "noopener noreferrer",
146
+ className: "rounded p-0.5 hover:bg-muted hover:text-foreground transition-colors",
147
+ "aria-label": "View transaction",
148
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.ExternalLink, { className: "h-3 w-3", "aria-hidden": true })
149
+ }
150
+ ) : null
151
+ ] })
152
+ ] })
153
+ ] })
154
+ ] });
155
+ }
156
+ function ProvenanceSkeleton() {
157
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "space-y-6", "aria-hidden": true, children: Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-start gap-4", children: [
158
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-8 w-8 shrink-0 rounded-full bg-muted animate-pulse" }),
159
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex-1 space-y-2 pt-1", children: [
160
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-3.5 w-40 rounded bg-muted animate-pulse" }),
161
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-3 w-24 rounded bg-muted animate-pulse" })
162
+ ] })
163
+ ] }, i)) });
164
+ }
165
+ function CollectionProvenanceTab({ contract }) {
166
+ const [page, setPage] = (0, import_react.useState)(1);
167
+ const [all, setAll] = (0, import_react.useState)([]);
168
+ const { activities, meta, isLoading } = (0, import_use_activities.useActivities)({ contract, page, limit: PAGE_SIZE });
169
+ (0, import_react.useEffect)(() => {
170
+ if (activities.length === 0) return;
171
+ setAll((prev) => page === 1 ? activities : [...prev, ...activities]);
172
+ }, [activities, page]);
173
+ const groups = (0, import_react.useMemo)(() => groupByDay(all), [all]);
174
+ const showAsset = (0, import_react.useMemo)(
175
+ () => new Set(all.map((e) => e.nftTokenId ?? e.tokenId ?? "")).size > 1,
176
+ [all]
177
+ );
178
+ const hasMore = meta ? all.length < (meta.total ?? 0) : false;
179
+ if (isLoading && all.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ProvenanceSkeleton, {});
180
+ if (all.length === 0) {
181
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "py-20 flex flex-col items-center gap-3 text-center", children: [
182
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Inbox, { className: "h-10 w-10 text-muted-foreground/40" }),
183
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-sm font-medium text-muted-foreground", children: "No history yet" }),
184
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-xs text-muted-foreground/70 max-w-xs", children: "Mints, transfers, listings and sales will appear here as they happen." })
185
+ ] });
186
+ }
187
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mx-auto max-w-2xl", children: [
188
+ groups.map((group) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "mb-8 last:mb-0", children: [
189
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { className: "mb-4 pl-12 text-xs font-medium text-muted-foreground", children: group.label }),
190
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ol", { className: "relative before:absolute before:left-4 before:top-4 before:bottom-4 before:w-px before:bg-border", children: group.events.map((event, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
191
+ ProvenanceEvent,
192
+ {
193
+ event,
194
+ showAsset
195
+ },
196
+ `${event.txHash ?? event.orderHash}-${event.type}-${i}`
197
+ )) })
198
+ ] }, group.label)),
199
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_load_more_sentinel.LoadMoreSentinel, { hasMore, isLoading, onLoadMore: () => setPage((p) => p + 1) })
200
+ ] });
201
+ }
202
+ // Annotate the CommonJS export names for ESM import in node:
203
+ 0 && (module.exports = {
204
+ CollectionProvenanceTab
205
+ });
206
+ //# sourceMappingURL=collection-provenance-tab.cjs.map