@medialane/ui 0.287.0 → 0.289.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 (53) hide show
  1. package/dist/components/asset-page.cjs +3 -2
  2. package/dist/components/asset-page.cjs.map +1 -1
  3. package/dist/components/asset-page.js +3 -2
  4. package/dist/components/asset-page.js.map +1 -1
  5. package/dist/components/button.d.cts +1 -1
  6. package/dist/components/button.d.ts +1 -1
  7. package/dist/components/collection-page.cjs +3 -2
  8. package/dist/components/collection-page.cjs.map +1 -1
  9. package/dist/components/collection-page.js +3 -2
  10. package/dist/components/collection-page.js.map +1 -1
  11. package/dist/components/comments-section.cjs +3 -3
  12. package/dist/components/comments-section.cjs.map +1 -1
  13. package/dist/components/comments-section.js +2 -2
  14. package/dist/components/comments-section.js.map +1 -1
  15. package/dist/components/creator-page.cjs +6 -5
  16. package/dist/components/creator-page.cjs.map +1 -1
  17. package/dist/components/creator-page.js +5 -4
  18. package/dist/components/creator-page.js.map +1 -1
  19. package/dist/components/fast-mint/fast-mint.d.cts +2 -2
  20. package/dist/components/fast-mint/fast-mint.d.ts +2 -2
  21. package/dist/components/listing-card-menu.cjs +10 -13
  22. package/dist/components/listing-card-menu.cjs.map +1 -1
  23. package/dist/components/listing-card-menu.js +10 -13
  24. package/dist/components/listing-card-menu.js.map +1 -1
  25. package/dist/components/medialane-app.cjs.map +1 -1
  26. package/dist/components/medialane-app.d.cts +2 -8
  27. package/dist/components/medialane-app.d.ts +2 -8
  28. package/dist/components/medialane-app.js.map +1 -1
  29. package/dist/components/mint-landing.cjs +232 -0
  30. package/dist/components/mint-landing.cjs.map +1 -0
  31. package/dist/components/mint-landing.d.cts +77 -0
  32. package/dist/components/mint-landing.d.ts +77 -0
  33. package/dist/components/mint-landing.js +212 -0
  34. package/dist/components/mint-landing.js.map +1 -0
  35. package/dist/components/portfolio-assets.cjs +4 -5
  36. package/dist/components/portfolio-assets.cjs.map +1 -1
  37. package/dist/components/portfolio-assets.js +3 -4
  38. package/dist/components/portfolio-assets.js.map +1 -1
  39. package/dist/components/report-dialog.cjs +191 -0
  40. package/dist/components/report-dialog.cjs.map +1 -0
  41. package/dist/components/report-dialog.d.cts +17 -0
  42. package/dist/components/report-dialog.d.ts +17 -0
  43. package/dist/components/report-dialog.js +167 -0
  44. package/dist/components/report-dialog.js.map +1 -0
  45. package/dist/components/sheet.d.cts +1 -1
  46. package/dist/components/sheet.d.ts +1 -1
  47. package/dist/index.cjs +6 -0
  48. package/dist/index.cjs.map +1 -1
  49. package/dist/index.d.cts +3 -1
  50. package/dist/index.d.ts +3 -1
  51. package/dist/index.js +4 -0
  52. package/dist/index.js.map +1 -1
  53. package/package.json +1 -1
@@ -23,6 +23,7 @@ import { OrderSortControl, sortOrders } from "./order-sort-control.js";
23
23
  import { GatedContentHero, GatedContentPanel } from "./gated-content.js";
24
24
  import { Tabs, TabsContent, TabsList, TabsTrigger } from "./tabs.js";
25
25
  import { useMedialaneApp } from "./medialane-app.js";
26
+ import { ReportDialog } from "./report-dialog.js";
26
27
  import { useCollection, useCollectionTokens } from "../utils/use-collections.js";
27
28
  import { useOrders } from "../utils/use-orders.js";
28
29
  import { useCollectionProfile } from "../utils/use-profiles.js";
@@ -132,7 +133,7 @@ function OwnerActions({ collection }) {
132
133
  return null;
133
134
  }
134
135
  function CollectionPage({ contract, slots }) {
135
- const { walletAddress, ReportDialog } = useMedialaneApp();
136
+ const { walletAddress } = useMedialaneApp();
136
137
  const { collection, isLoading: collectionLoading } = useCollection(contract);
137
138
  const { profile } = useCollectionProfile(contract);
138
139
  const gatedState = slots.useGatedContent(profile?.hasGatedContent ? contract : void 0);
@@ -241,7 +242,7 @@ function CollectionPage({ contract, slots }) {
241
242
  /* @__PURE__ */ jsx(OwnerSetupPanel, { contract, profile: profile ?? null }),
242
243
  canTransferCollectionOwnership(collection) ? /* @__PURE__ */ jsx("div", { className: "flex justify-end", children: /* @__PURE__ */ jsx(TransferCollectionOwnership, { collectionId: collection.collectionId, currentOwner: collection.owner, collectionName: collection.name }) }) : null
243
244
  ] }) : null,
244
- collection && ReportDialog ? /* @__PURE__ */ jsx(ReportDialog, { open: reportOpen, onOpenChange: setReportOpen, target: { type: "COLLECTION", contract: collection.contractAddress, name: collection.name ?? void 0 } }) : null,
245
+ collection ? /* @__PURE__ */ jsx(ReportDialog, { open: reportOpen, onOpenChange: setReportOpen, target: { type: "COLLECTION", contract: collection.contractAddress, name: collection.name ?? void 0 } }) : null,
245
246
  market.dialogs
246
247
  ] });
247
248
  }
@@ -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 { 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, ReportDialog } = 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 && ReportDialog ? (\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 { 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"]}
@@ -40,6 +40,7 @@ var import_address_display = require("./address-display.js");
40
40
  var import_button = require("./button.js");
41
41
  var import_link = __toESM(require("./link.js"), 1);
42
42
  var import_medialane_app = require("./medialane-app.js");
43
+ var import_report_dialog = require("./report-dialog.js");
43
44
  var import_reward_earned = require("./rewards/reward-earned.js");
44
45
  var import_skeleton = require("./skeleton.js");
45
46
  var import_textarea = require("./textarea.js");
@@ -57,7 +58,6 @@ function CommentsSection({ contract, tokenId, className }) {
57
58
  const app = (0, import_medialane_app.useMedialaneApp)();
58
59
  const walletAddress = app.walletAddress;
59
60
  const hasWallet = !!walletAddress;
60
- const { ReportDialog } = app;
61
61
  const { comments, isLoading, mutate } = (0, import_use_comments.useComments)(contract, tokenId);
62
62
  const tx = (0, import_use_transaction.useTransaction)();
63
63
  const [text, setText] = (0, import_react.useState)("");
@@ -276,8 +276,8 @@ function CommentsSection({ contract, tokenId, className }) {
276
276
  }
277
277
  )
278
278
  ] }) }),
279
- reportTarget && ReportDialog && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
280
- ReportDialog,
279
+ reportTarget && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
280
+ import_report_dialog.ReportDialog,
281
281
  {
282
282
  target: reportTarget,
283
283
  open: !!reportTarget,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/comments-section.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useRef, useState } from \"react\";\nimport { ExternalLink, Flag, Loader2, MessageCircle, Send, Zap } from \"lucide-react\";\nimport { normalizeAddress, profileHref, STARKNET_NFTCOMMENTS_CONTRACT } from \"@medialane/sdk\";\nimport { AddressDisplay } from \"./address-display.js\";\nimport { Button } from \"./button.js\";\nimport Link from \"./link.js\";\nimport { useMedialaneApp, type ReportTarget } from \"./medialane-app.js\";\nimport { RewardEarned } from \"./rewards/reward-earned.js\";\nimport { Skeleton } from \"./skeleton.js\";\nimport { Textarea } from \"./textarea.js\";\nimport { TransactionDialog } from \"./transaction-dialog.js\";\nimport { TransactionSuccess } from \"./transaction-success.js\";\nimport { cn } from \"../utils/cn.js\";\nimport { EXPLORER_URL } from \"../utils/explorer-url.js\";\nimport { runIntentCalls } from \"../utils/run-intent-calls.js\";\nimport { timeAgo } from \"../utils/time.js\";\nimport { successMessages } from \"../utils/success-messages.js\";\nimport { useComments } from \"../utils/use-comments.js\";\nimport { useTransaction } from \"../utils/use-transaction.js\";\n\nconst MAX_LEN = 1000;\n\nexport interface CommentsSectionProps {\n contract: string;\n tokenId: string;\n className?: string;\n}\n\nexport function CommentsSection({ contract, tokenId, className }: CommentsSectionProps) {\n const app = useMedialaneApp();\n const walletAddress = app.walletAddress;\n const hasWallet = !!walletAddress;\n const { ReportDialog } = app;\n const { comments, isLoading, mutate } = useComments(contract, tokenId);\n const tx = useTransaction();\n\n const [text, setText] = useState(\"\");\n const [reportTarget, setReportTarget] = useState<ReportTarget | null>(null);\n\n const messagesRef = useRef<HTMLDivElement>(null);\n const bottomRef = useRef<HTMLDivElement>(null);\n const composeRef = useRef<HTMLTextAreaElement>(null);\n\n const byteLen = new TextEncoder().encode(text).length;\n const canSubmit = text.trim().length > 0 && byteLen <= MAX_LEN && !!STARKNET_NFTCOMMENTS_CONTRACT;\n const isProcessing = tx.phase === \"preparing\" || tx.phase === \"submitting\" || tx.phase === \"confirming\";\n\n const isOwn = (author: string) =>\n !!walletAddress && normalizeAddress(\"STARKNET\", author) === normalizeAddress(\"STARKNET\", walletAddress);\n\n const isNearBottom = () => {\n const el = messagesRef.current;\n if (!el) return true;\n return el.scrollHeight - el.scrollTop - el.clientHeight < 100;\n };\n\n useEffect(() => {\n if (isNearBottom()) {\n bottomRef.current?.scrollIntoView({ behavior: \"smooth\" });\n }\n\n }, [comments.length]);\n\n const handleTextInput = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n setText(e.target.value);\n e.target.style.height = \"auto\";\n e.target.style.height = Math.min(e.target.scrollHeight, 96) + \"px\";\n };\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === \"Enter\" && !e.shiftKey && canSubmit && !isProcessing) {\n e.preventDefault();\n post();\n }\n };\n\n const post = () => {\n const body = text.trim();\n void tx\n .run(async (signer) => {\n await runIntentCalls(signer, () =>\n app.getClient().api.intents.create(\"comment\", { author: signer.address, nftContract: contract, tokenId, text: body }),\n );\n })\n .then((ok) => {\n if (!ok) return;\n setText(\"\");\n if (composeRef.current) composeRef.current.style.height = \"auto\";\n void mutate();\n });\n };\n\n const handleStartConversation = () => {\n if (hasWallet) composeRef.current?.focus();\n };\n\n return (\n <div className={cn(\"flex flex-col h-[480px] overflow-hidden\", className)}>\n\n <div ref={messagesRef} className=\"flex-1 overflow-y-auto px-4 py-4\">\n {isLoading ? (\n <div className=\"space-y-4\">\n {([\n { own: false, w: \"w-40\" },\n { own: true, w: \"w-56\" },\n { own: false, w: \"w-48\" },\n { own: true, w: \"w-32\" },\n ] as const).map((item, i) => (\n <div key={i} className={`flex ${item.own ? \"justify-end\" : \"justify-start\"} gap-2`}>\n {!item.own && <Skeleton className=\"h-8 w-8 rounded-full shrink-0\" />}\n <Skeleton\n className={`h-10 ${item.w} rounded-2xl ${item.own ? \"rounded-tr-sm\" : \"rounded-tl-sm\"}`}\n />\n </div>\n ))}\n </div>\n ) : comments.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center h-full gap-4 text-center px-4\">\n <div className=\"flex h-16 w-16 items-center justify-center rounded-full\" style={{ background: \"linear-gradient(135deg, hsl(var(--brand-blue) / 0.15), hsl(var(--brand-purple) / 0.15))\" }}>\n <MessageCircle className=\"h-7 w-7\" style={{ color: \"hsl(var(--brand-blue))\" }} />\n </div>\n <div>\n <p className=\"text-sm font-semibold\">Nothing here yet</p>\n <p className=\"text-xs text-muted-foreground mt-1 leading-relaxed max-w-[220px]\">\n Your comment will be minted onchain — attached to this NFT forever.\n </p>\n </div>\n <Button\n size=\"sm\"\n onClick={handleStartConversation}\n className=\"rounded-full text-white px-5\"\n style={{ background: \"linear-gradient(135deg, hsl(var(--brand-blue)), hsl(var(--brand-purple)))\" }}\n >\n Write the first comment\n </Button>\n </div>\n ) : (\n <div className=\"space-y-5\">\n {comments.map((comment) => {\n const own = isOwn(comment.author);\n const avatarSeed = parseInt(comment.author.slice(2, 8), 16) % 360;\n const avatarBg = own\n ? \"linear-gradient(135deg, hsl(var(--brand-blue)), hsl(var(--brand-purple)))\"\n : `linear-gradient(135deg, hsl(${avatarSeed}, 65%, 45%), hsl(${(avatarSeed + 60) % 360}, 65%, 55%))`;\n\n return (\n <div\n key={comment.id}\n className={`group flex gap-2.5 ${own ? \"flex-row-reverse\" : \"flex-row\"}`}\n >\n\n <Link href={profileHref({ address: comment.author })} className=\"shrink-0 mt-0.5\">\n <div\n className=\"h-9 w-9 rounded-full flex items-center justify-center text-2xs font-bold text-white select-none ring-2 ring-background hover:ring-primary/40 transition-all\"\n style={{ background: avatarBg }}\n >\n {comment.author.slice(2, 5).toUpperCase()}\n </div>\n </Link>\n\n <div className={`flex flex-col max-w-[75%] gap-1 ${own ? \"items-end\" : \"items-start\"}`}>\n\n <div className={`flex items-center gap-2 px-1 ${own ? \"flex-row-reverse\" : \"flex-row\"}`}>\n <Link\n href={profileHref({ address: comment.author })}\n className=\"text-xs font-semibold text-foreground hover:underline underline-offset-2\"\n >\n {own ? \"You\" : <AddressDisplay address={comment.author} chars={5} showCopy={false} />}\n </Link>\n <span className=\"text-2xs text-muted-foreground\" title={comment.postedAt}>\n {timeAgo(comment.postedAt)}\n </span>\n </div>\n\n <div className=\"relative\">\n {own ? (\n <div\n className=\"px-3.5 py-2.5 text-sm leading-relaxed break-words rounded-2xl rounded-tr-sm text-white\"\n style={{ background: \"linear-gradient(135deg, hsl(var(--brand-blue)), hsl(var(--brand-purple)))\" }}\n >\n {comment.content}\n </div>\n ) : (\n <div className=\"px-3.5 py-2.5 text-sm leading-relaxed break-words bg-muted rounded-2xl rounded-tl-sm border border-border/50\">\n {comment.content}\n </div>\n )}\n {!own && hasWallet && (\n <button\n className=\"absolute -top-1 -right-5 opacity-0 group-hover:opacity-100 transition-opacity text-muted-foreground/40 hover:text-destructive/70\"\n title=\"Report comment\"\n aria-label=\"Report comment\"\n onClick={() => setReportTarget({ type: \"COMMENT\", commentId: comment.id })}\n >\n <Flag className=\"h-3 w-3\" />\n </button>\n )}\n </div>\n\n {comment.txHash && (\n <a\n href={`${EXPLORER_URL}/tx/${comment.txHash}`}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"flex items-center gap-1 px-1 text-2xs font-medium transition-colors\"\n style={{ color: \"hsl(var(--brand-blue) / 0.55)\" }}\n onMouseEnter={(e) => (e.currentTarget.style.color = \"hsl(var(--brand-blue))\")}\n onMouseLeave={(e) => (e.currentTarget.style.color = \"hsl(var(--brand-blue) / 0.55)\")}\n >\n <span>⛓</span>\n <span>onchain proof</span>\n <ExternalLink className=\"h-2.5 w-2.5\" />\n </a>\n )}\n </div>\n </div>\n );\n })}\n <div ref={bottomRef} />\n </div>\n )}\n </div>\n\n <div className=\"border-t border-border/60 shrink-0\">\n {!hasWallet ? (\n <div className=\"flex items-center justify-center px-4 h-16\">\n <button type=\"button\" onClick={app.onRequireWallet} className=\"text-sm text-primary hover:underline\">\n {app.connectLabel ?? \"Connect\"} to comment\n </button>\n </div>\n ) : (\n <div className=\"px-3 pt-2 pb-3 space-y-2\">\n\n <div className=\"flex items-center gap-1.5\">\n <Zap className=\"h-3 w-3\" style={{ color: \"hsl(var(--brand-blue))\" }} />\n <span className=\"text-2xs font-semibold\" style={{ color: \"hsl(var(--brand-blue))\" }}>\n Mint your message onchain\n </span>\n </div>\n\n <div\n className=\"rounded-xl border bg-background/60 transition-all focus-within:ring-2\"\n style={{\n borderColor: \"hsl(var(--border))\",\n }}\n onFocusCapture={(e) => {\n (e.currentTarget as HTMLDivElement).style.borderColor = \"hsl(var(--brand-blue) / 0.6)\";\n (e.currentTarget as HTMLDivElement).style.boxShadow = \"0 0 0 3px hsl(var(--brand-blue) / 0.12)\";\n }}\n onBlurCapture={(e) => {\n (e.currentTarget as HTMLDivElement).style.borderColor = \"hsl(var(--border))\";\n (e.currentTarget as HTMLDivElement).style.boxShadow = \"\";\n }}\n >\n <Textarea\n ref={composeRef}\n placeholder=\"Say something onchain… it's permanent.\"\n value={text}\n onChange={handleTextInput}\n onKeyDown={handleKeyDown}\n rows={2}\n className=\"resize-none min-h-[52px] max-h-[120px] w-full border-0 bg-transparent focus-visible:ring-0 focus-visible:ring-offset-0 px-3 pt-2.5 pb-1 text-sm rounded-xl\"\n disabled={isProcessing}\n />\n <div className=\"flex items-center justify-between px-3 pb-2.5\">\n <span className=\"text-2xs text-muted-foreground/40 flex items-center gap-1\">\n Enter ↵ to post\n </span>\n <div className=\"flex items-center gap-2\">\n {byteLen > 800 && (\n <span className={`text-2xs ${byteLen > MAX_LEN ? \"text-destructive\" : \"text-muted-foreground\"}`}>\n {byteLen}/{MAX_LEN}\n </span>\n )}\n <button\n onClick={post}\n disabled={!canSubmit || isProcessing}\n className=\"flex items-center gap-1.5 h-7 px-3 text-xs font-semibold rounded-full text-white transition-all hover:opacity-90 active:scale-95 disabled:opacity-40 disabled:cursor-not-allowed\"\n style={{ background: \"linear-gradient(135deg, hsl(var(--brand-blue)), hsl(var(--brand-purple)))\" }}\n >\n {isProcessing ? <Loader2 className=\"h-3 w-3 animate-spin\" /> : <Send className=\"h-3 w-3\" />}\n Post onchain\n </button>\n </div>\n </div>\n </div>\n </div>\n )}\n </div>\n\n {reportTarget && ReportDialog && (\n <ReportDialog\n target={reportTarget}\n open={!!reportTarget}\n onOpenChange={(open) => { if (!open) setReportTarget(null); }}\n />\n )}\n\n <TransactionDialog tx={tx} title=\"Comment\" workingLabel=\"Posting your comment…\" firstStepLabel=\"Prepare comment\">\n <TransactionSuccess\n name=\"Comment\"\n {...successMessages.commented()}\n txHash={tx.txHash}\n actions={[{ label: \"Done\", onClick: tx.reset }]}\n >\n <RewardEarned actionType=\"comment\" />\n </TransactionSuccess>\n </TransactionDialog>\n </div>\n );\n}\n"],"mappings":"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","names":["Link"]}
1
+ {"version":3,"sources":["../../src/components/comments-section.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useRef, useState } from \"react\";\nimport { ExternalLink, Flag, Loader2, MessageCircle, Send, Zap } from \"lucide-react\";\nimport { normalizeAddress, profileHref, STARKNET_NFTCOMMENTS_CONTRACT } from \"@medialane/sdk\";\nimport { AddressDisplay } from \"./address-display.js\";\nimport { Button } from \"./button.js\";\nimport Link from \"./link.js\";\nimport { useMedialaneApp, type ReportTarget } from \"./medialane-app.js\";\nimport { ReportDialog } from \"./report-dialog.js\";\nimport { RewardEarned } from \"./rewards/reward-earned.js\";\nimport { Skeleton } from \"./skeleton.js\";\nimport { Textarea } from \"./textarea.js\";\nimport { TransactionDialog } from \"./transaction-dialog.js\";\nimport { TransactionSuccess } from \"./transaction-success.js\";\nimport { cn } from \"../utils/cn.js\";\nimport { EXPLORER_URL } from \"../utils/explorer-url.js\";\nimport { runIntentCalls } from \"../utils/run-intent-calls.js\";\nimport { timeAgo } from \"../utils/time.js\";\nimport { successMessages } from \"../utils/success-messages.js\";\nimport { useComments } from \"../utils/use-comments.js\";\nimport { useTransaction } from \"../utils/use-transaction.js\";\n\nconst MAX_LEN = 1000;\n\nexport interface CommentsSectionProps {\n contract: string;\n tokenId: string;\n className?: string;\n}\n\nexport function CommentsSection({ contract, tokenId, className }: CommentsSectionProps) {\n const app = useMedialaneApp();\n const walletAddress = app.walletAddress;\n const hasWallet = !!walletAddress;\n const { comments, isLoading, mutate } = useComments(contract, tokenId);\n const tx = useTransaction();\n\n const [text, setText] = useState(\"\");\n const [reportTarget, setReportTarget] = useState<ReportTarget | null>(null);\n\n const messagesRef = useRef<HTMLDivElement>(null);\n const bottomRef = useRef<HTMLDivElement>(null);\n const composeRef = useRef<HTMLTextAreaElement>(null);\n\n const byteLen = new TextEncoder().encode(text).length;\n const canSubmit = text.trim().length > 0 && byteLen <= MAX_LEN && !!STARKNET_NFTCOMMENTS_CONTRACT;\n const isProcessing = tx.phase === \"preparing\" || tx.phase === \"submitting\" || tx.phase === \"confirming\";\n\n const isOwn = (author: string) =>\n !!walletAddress && normalizeAddress(\"STARKNET\", author) === normalizeAddress(\"STARKNET\", walletAddress);\n\n const isNearBottom = () => {\n const el = messagesRef.current;\n if (!el) return true;\n return el.scrollHeight - el.scrollTop - el.clientHeight < 100;\n };\n\n useEffect(() => {\n if (isNearBottom()) {\n bottomRef.current?.scrollIntoView({ behavior: \"smooth\" });\n }\n\n }, [comments.length]);\n\n const handleTextInput = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n setText(e.target.value);\n e.target.style.height = \"auto\";\n e.target.style.height = Math.min(e.target.scrollHeight, 96) + \"px\";\n };\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === \"Enter\" && !e.shiftKey && canSubmit && !isProcessing) {\n e.preventDefault();\n post();\n }\n };\n\n const post = () => {\n const body = text.trim();\n void tx\n .run(async (signer) => {\n await runIntentCalls(signer, () =>\n app.getClient().api.intents.create(\"comment\", { author: signer.address, nftContract: contract, tokenId, text: body }),\n );\n })\n .then((ok) => {\n if (!ok) return;\n setText(\"\");\n if (composeRef.current) composeRef.current.style.height = \"auto\";\n void mutate();\n });\n };\n\n const handleStartConversation = () => {\n if (hasWallet) composeRef.current?.focus();\n };\n\n return (\n <div className={cn(\"flex flex-col h-[480px] overflow-hidden\", className)}>\n\n <div ref={messagesRef} className=\"flex-1 overflow-y-auto px-4 py-4\">\n {isLoading ? (\n <div className=\"space-y-4\">\n {([\n { own: false, w: \"w-40\" },\n { own: true, w: \"w-56\" },\n { own: false, w: \"w-48\" },\n { own: true, w: \"w-32\" },\n ] as const).map((item, i) => (\n <div key={i} className={`flex ${item.own ? \"justify-end\" : \"justify-start\"} gap-2`}>\n {!item.own && <Skeleton className=\"h-8 w-8 rounded-full shrink-0\" />}\n <Skeleton\n className={`h-10 ${item.w} rounded-2xl ${item.own ? \"rounded-tr-sm\" : \"rounded-tl-sm\"}`}\n />\n </div>\n ))}\n </div>\n ) : comments.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center h-full gap-4 text-center px-4\">\n <div className=\"flex h-16 w-16 items-center justify-center rounded-full\" style={{ background: \"linear-gradient(135deg, hsl(var(--brand-blue) / 0.15), hsl(var(--brand-purple) / 0.15))\" }}>\n <MessageCircle className=\"h-7 w-7\" style={{ color: \"hsl(var(--brand-blue))\" }} />\n </div>\n <div>\n <p className=\"text-sm font-semibold\">Nothing here yet</p>\n <p className=\"text-xs text-muted-foreground mt-1 leading-relaxed max-w-[220px]\">\n Your comment will be minted onchain — attached to this NFT forever.\n </p>\n </div>\n <Button\n size=\"sm\"\n onClick={handleStartConversation}\n className=\"rounded-full text-white px-5\"\n style={{ background: \"linear-gradient(135deg, hsl(var(--brand-blue)), hsl(var(--brand-purple)))\" }}\n >\n Write the first comment\n </Button>\n </div>\n ) : (\n <div className=\"space-y-5\">\n {comments.map((comment) => {\n const own = isOwn(comment.author);\n const avatarSeed = parseInt(comment.author.slice(2, 8), 16) % 360;\n const avatarBg = own\n ? \"linear-gradient(135deg, hsl(var(--brand-blue)), hsl(var(--brand-purple)))\"\n : `linear-gradient(135deg, hsl(${avatarSeed}, 65%, 45%), hsl(${(avatarSeed + 60) % 360}, 65%, 55%))`;\n\n return (\n <div\n key={comment.id}\n className={`group flex gap-2.5 ${own ? \"flex-row-reverse\" : \"flex-row\"}`}\n >\n\n <Link href={profileHref({ address: comment.author })} className=\"shrink-0 mt-0.5\">\n <div\n className=\"h-9 w-9 rounded-full flex items-center justify-center text-2xs font-bold text-white select-none ring-2 ring-background hover:ring-primary/40 transition-all\"\n style={{ background: avatarBg }}\n >\n {comment.author.slice(2, 5).toUpperCase()}\n </div>\n </Link>\n\n <div className={`flex flex-col max-w-[75%] gap-1 ${own ? \"items-end\" : \"items-start\"}`}>\n\n <div className={`flex items-center gap-2 px-1 ${own ? \"flex-row-reverse\" : \"flex-row\"}`}>\n <Link\n href={profileHref({ address: comment.author })}\n className=\"text-xs font-semibold text-foreground hover:underline underline-offset-2\"\n >\n {own ? \"You\" : <AddressDisplay address={comment.author} chars={5} showCopy={false} />}\n </Link>\n <span className=\"text-2xs text-muted-foreground\" title={comment.postedAt}>\n {timeAgo(comment.postedAt)}\n </span>\n </div>\n\n <div className=\"relative\">\n {own ? (\n <div\n className=\"px-3.5 py-2.5 text-sm leading-relaxed break-words rounded-2xl rounded-tr-sm text-white\"\n style={{ background: \"linear-gradient(135deg, hsl(var(--brand-blue)), hsl(var(--brand-purple)))\" }}\n >\n {comment.content}\n </div>\n ) : (\n <div className=\"px-3.5 py-2.5 text-sm leading-relaxed break-words bg-muted rounded-2xl rounded-tl-sm border border-border/50\">\n {comment.content}\n </div>\n )}\n {!own && hasWallet && (\n <button\n className=\"absolute -top-1 -right-5 opacity-0 group-hover:opacity-100 transition-opacity text-muted-foreground/40 hover:text-destructive/70\"\n title=\"Report comment\"\n aria-label=\"Report comment\"\n onClick={() => setReportTarget({ type: \"COMMENT\", commentId: comment.id })}\n >\n <Flag className=\"h-3 w-3\" />\n </button>\n )}\n </div>\n\n {comment.txHash && (\n <a\n href={`${EXPLORER_URL}/tx/${comment.txHash}`}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"flex items-center gap-1 px-1 text-2xs font-medium transition-colors\"\n style={{ color: \"hsl(var(--brand-blue) / 0.55)\" }}\n onMouseEnter={(e) => (e.currentTarget.style.color = \"hsl(var(--brand-blue))\")}\n onMouseLeave={(e) => (e.currentTarget.style.color = \"hsl(var(--brand-blue) / 0.55)\")}\n >\n <span>⛓</span>\n <span>onchain proof</span>\n <ExternalLink className=\"h-2.5 w-2.5\" />\n </a>\n )}\n </div>\n </div>\n );\n })}\n <div ref={bottomRef} />\n </div>\n )}\n </div>\n\n <div className=\"border-t border-border/60 shrink-0\">\n {!hasWallet ? (\n <div className=\"flex items-center justify-center px-4 h-16\">\n <button type=\"button\" onClick={app.onRequireWallet} className=\"text-sm text-primary hover:underline\">\n {app.connectLabel ?? \"Connect\"} to comment\n </button>\n </div>\n ) : (\n <div className=\"px-3 pt-2 pb-3 space-y-2\">\n\n <div className=\"flex items-center gap-1.5\">\n <Zap className=\"h-3 w-3\" style={{ color: \"hsl(var(--brand-blue))\" }} />\n <span className=\"text-2xs font-semibold\" style={{ color: \"hsl(var(--brand-blue))\" }}>\n Mint your message onchain\n </span>\n </div>\n\n <div\n className=\"rounded-xl border bg-background/60 transition-all focus-within:ring-2\"\n style={{\n borderColor: \"hsl(var(--border))\",\n }}\n onFocusCapture={(e) => {\n (e.currentTarget as HTMLDivElement).style.borderColor = \"hsl(var(--brand-blue) / 0.6)\";\n (e.currentTarget as HTMLDivElement).style.boxShadow = \"0 0 0 3px hsl(var(--brand-blue) / 0.12)\";\n }}\n onBlurCapture={(e) => {\n (e.currentTarget as HTMLDivElement).style.borderColor = \"hsl(var(--border))\";\n (e.currentTarget as HTMLDivElement).style.boxShadow = \"\";\n }}\n >\n <Textarea\n ref={composeRef}\n placeholder=\"Say something onchain… it's permanent.\"\n value={text}\n onChange={handleTextInput}\n onKeyDown={handleKeyDown}\n rows={2}\n className=\"resize-none min-h-[52px] max-h-[120px] w-full border-0 bg-transparent focus-visible:ring-0 focus-visible:ring-offset-0 px-3 pt-2.5 pb-1 text-sm rounded-xl\"\n disabled={isProcessing}\n />\n <div className=\"flex items-center justify-between px-3 pb-2.5\">\n <span className=\"text-2xs text-muted-foreground/40 flex items-center gap-1\">\n Enter ↵ to post\n </span>\n <div className=\"flex items-center gap-2\">\n {byteLen > 800 && (\n <span className={`text-2xs ${byteLen > MAX_LEN ? \"text-destructive\" : \"text-muted-foreground\"}`}>\n {byteLen}/{MAX_LEN}\n </span>\n )}\n <button\n onClick={post}\n disabled={!canSubmit || isProcessing}\n className=\"flex items-center gap-1.5 h-7 px-3 text-xs font-semibold rounded-full text-white transition-all hover:opacity-90 active:scale-95 disabled:opacity-40 disabled:cursor-not-allowed\"\n style={{ background: \"linear-gradient(135deg, hsl(var(--brand-blue)), hsl(var(--brand-purple)))\" }}\n >\n {isProcessing ? <Loader2 className=\"h-3 w-3 animate-spin\" /> : <Send className=\"h-3 w-3\" />}\n Post onchain\n </button>\n </div>\n </div>\n </div>\n </div>\n )}\n </div>\n\n {reportTarget && (\n <ReportDialog\n target={reportTarget}\n open={!!reportTarget}\n onOpenChange={(open) => { if (!open) setReportTarget(null); }}\n />\n )}\n\n <TransactionDialog tx={tx} title=\"Comment\" workingLabel=\"Posting your comment…\" firstStepLabel=\"Prepare comment\">\n <TransactionSuccess\n name=\"Comment\"\n {...successMessages.commented()}\n txHash={tx.txHash}\n actions={[{ label: \"Done\", onClick: tx.reset }]}\n >\n <RewardEarned actionType=\"comment\" />\n </TransactionSuccess>\n </TransactionDialog>\n </div>\n );\n}\n"],"mappings":"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","names":["Link"]}
@@ -7,6 +7,7 @@ import { AddressDisplay } from "./address-display.js";
7
7
  import { Button } from "./button.js";
8
8
  import Link from "./link.js";
9
9
  import { useMedialaneApp } from "./medialane-app.js";
10
+ import { ReportDialog } from "./report-dialog.js";
10
11
  import { RewardEarned } from "./rewards/reward-earned.js";
11
12
  import { Skeleton } from "./skeleton.js";
12
13
  import { Textarea } from "./textarea.js";
@@ -24,7 +25,6 @@ function CommentsSection({ contract, tokenId, className }) {
24
25
  const app = useMedialaneApp();
25
26
  const walletAddress = app.walletAddress;
26
27
  const hasWallet = !!walletAddress;
27
- const { ReportDialog } = app;
28
28
  const { comments, isLoading, mutate } = useComments(contract, tokenId);
29
29
  const tx = useTransaction();
30
30
  const [text, setText] = useState("");
@@ -243,7 +243,7 @@ function CommentsSection({ contract, tokenId, className }) {
243
243
  }
244
244
  )
245
245
  ] }) }),
246
- reportTarget && ReportDialog && /* @__PURE__ */ jsx(
246
+ reportTarget && /* @__PURE__ */ jsx(
247
247
  ReportDialog,
248
248
  {
249
249
  target: reportTarget,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/comments-section.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useRef, useState } from \"react\";\nimport { ExternalLink, Flag, Loader2, MessageCircle, Send, Zap } from \"lucide-react\";\nimport { normalizeAddress, profileHref, STARKNET_NFTCOMMENTS_CONTRACT } from \"@medialane/sdk\";\nimport { AddressDisplay } from \"./address-display.js\";\nimport { Button } from \"./button.js\";\nimport Link from \"./link.js\";\nimport { useMedialaneApp, type ReportTarget } from \"./medialane-app.js\";\nimport { RewardEarned } from \"./rewards/reward-earned.js\";\nimport { Skeleton } from \"./skeleton.js\";\nimport { Textarea } from \"./textarea.js\";\nimport { TransactionDialog } from \"./transaction-dialog.js\";\nimport { TransactionSuccess } from \"./transaction-success.js\";\nimport { cn } from \"../utils/cn.js\";\nimport { EXPLORER_URL } from \"../utils/explorer-url.js\";\nimport { runIntentCalls } from \"../utils/run-intent-calls.js\";\nimport { timeAgo } from \"../utils/time.js\";\nimport { successMessages } from \"../utils/success-messages.js\";\nimport { useComments } from \"../utils/use-comments.js\";\nimport { useTransaction } from \"../utils/use-transaction.js\";\n\nconst MAX_LEN = 1000;\n\nexport interface CommentsSectionProps {\n contract: string;\n tokenId: string;\n className?: string;\n}\n\nexport function CommentsSection({ contract, tokenId, className }: CommentsSectionProps) {\n const app = useMedialaneApp();\n const walletAddress = app.walletAddress;\n const hasWallet = !!walletAddress;\n const { ReportDialog } = app;\n const { comments, isLoading, mutate } = useComments(contract, tokenId);\n const tx = useTransaction();\n\n const [text, setText] = useState(\"\");\n const [reportTarget, setReportTarget] = useState<ReportTarget | null>(null);\n\n const messagesRef = useRef<HTMLDivElement>(null);\n const bottomRef = useRef<HTMLDivElement>(null);\n const composeRef = useRef<HTMLTextAreaElement>(null);\n\n const byteLen = new TextEncoder().encode(text).length;\n const canSubmit = text.trim().length > 0 && byteLen <= MAX_LEN && !!STARKNET_NFTCOMMENTS_CONTRACT;\n const isProcessing = tx.phase === \"preparing\" || tx.phase === \"submitting\" || tx.phase === \"confirming\";\n\n const isOwn = (author: string) =>\n !!walletAddress && normalizeAddress(\"STARKNET\", author) === normalizeAddress(\"STARKNET\", walletAddress);\n\n const isNearBottom = () => {\n const el = messagesRef.current;\n if (!el) return true;\n return el.scrollHeight - el.scrollTop - el.clientHeight < 100;\n };\n\n useEffect(() => {\n if (isNearBottom()) {\n bottomRef.current?.scrollIntoView({ behavior: \"smooth\" });\n }\n\n }, [comments.length]);\n\n const handleTextInput = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n setText(e.target.value);\n e.target.style.height = \"auto\";\n e.target.style.height = Math.min(e.target.scrollHeight, 96) + \"px\";\n };\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === \"Enter\" && !e.shiftKey && canSubmit && !isProcessing) {\n e.preventDefault();\n post();\n }\n };\n\n const post = () => {\n const body = text.trim();\n void tx\n .run(async (signer) => {\n await runIntentCalls(signer, () =>\n app.getClient().api.intents.create(\"comment\", { author: signer.address, nftContract: contract, tokenId, text: body }),\n );\n })\n .then((ok) => {\n if (!ok) return;\n setText(\"\");\n if (composeRef.current) composeRef.current.style.height = \"auto\";\n void mutate();\n });\n };\n\n const handleStartConversation = () => {\n if (hasWallet) composeRef.current?.focus();\n };\n\n return (\n <div className={cn(\"flex flex-col h-[480px] overflow-hidden\", className)}>\n\n <div ref={messagesRef} className=\"flex-1 overflow-y-auto px-4 py-4\">\n {isLoading ? (\n <div className=\"space-y-4\">\n {([\n { own: false, w: \"w-40\" },\n { own: true, w: \"w-56\" },\n { own: false, w: \"w-48\" },\n { own: true, w: \"w-32\" },\n ] as const).map((item, i) => (\n <div key={i} className={`flex ${item.own ? \"justify-end\" : \"justify-start\"} gap-2`}>\n {!item.own && <Skeleton className=\"h-8 w-8 rounded-full shrink-0\" />}\n <Skeleton\n className={`h-10 ${item.w} rounded-2xl ${item.own ? \"rounded-tr-sm\" : \"rounded-tl-sm\"}`}\n />\n </div>\n ))}\n </div>\n ) : comments.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center h-full gap-4 text-center px-4\">\n <div className=\"flex h-16 w-16 items-center justify-center rounded-full\" style={{ background: \"linear-gradient(135deg, hsl(var(--brand-blue) / 0.15), hsl(var(--brand-purple) / 0.15))\" }}>\n <MessageCircle className=\"h-7 w-7\" style={{ color: \"hsl(var(--brand-blue))\" }} />\n </div>\n <div>\n <p className=\"text-sm font-semibold\">Nothing here yet</p>\n <p className=\"text-xs text-muted-foreground mt-1 leading-relaxed max-w-[220px]\">\n Your comment will be minted onchain — attached to this NFT forever.\n </p>\n </div>\n <Button\n size=\"sm\"\n onClick={handleStartConversation}\n className=\"rounded-full text-white px-5\"\n style={{ background: \"linear-gradient(135deg, hsl(var(--brand-blue)), hsl(var(--brand-purple)))\" }}\n >\n Write the first comment\n </Button>\n </div>\n ) : (\n <div className=\"space-y-5\">\n {comments.map((comment) => {\n const own = isOwn(comment.author);\n const avatarSeed = parseInt(comment.author.slice(2, 8), 16) % 360;\n const avatarBg = own\n ? \"linear-gradient(135deg, hsl(var(--brand-blue)), hsl(var(--brand-purple)))\"\n : `linear-gradient(135deg, hsl(${avatarSeed}, 65%, 45%), hsl(${(avatarSeed + 60) % 360}, 65%, 55%))`;\n\n return (\n <div\n key={comment.id}\n className={`group flex gap-2.5 ${own ? \"flex-row-reverse\" : \"flex-row\"}`}\n >\n\n <Link href={profileHref({ address: comment.author })} className=\"shrink-0 mt-0.5\">\n <div\n className=\"h-9 w-9 rounded-full flex items-center justify-center text-2xs font-bold text-white select-none ring-2 ring-background hover:ring-primary/40 transition-all\"\n style={{ background: avatarBg }}\n >\n {comment.author.slice(2, 5).toUpperCase()}\n </div>\n </Link>\n\n <div className={`flex flex-col max-w-[75%] gap-1 ${own ? \"items-end\" : \"items-start\"}`}>\n\n <div className={`flex items-center gap-2 px-1 ${own ? \"flex-row-reverse\" : \"flex-row\"}`}>\n <Link\n href={profileHref({ address: comment.author })}\n className=\"text-xs font-semibold text-foreground hover:underline underline-offset-2\"\n >\n {own ? \"You\" : <AddressDisplay address={comment.author} chars={5} showCopy={false} />}\n </Link>\n <span className=\"text-2xs text-muted-foreground\" title={comment.postedAt}>\n {timeAgo(comment.postedAt)}\n </span>\n </div>\n\n <div className=\"relative\">\n {own ? (\n <div\n className=\"px-3.5 py-2.5 text-sm leading-relaxed break-words rounded-2xl rounded-tr-sm text-white\"\n style={{ background: \"linear-gradient(135deg, hsl(var(--brand-blue)), hsl(var(--brand-purple)))\" }}\n >\n {comment.content}\n </div>\n ) : (\n <div className=\"px-3.5 py-2.5 text-sm leading-relaxed break-words bg-muted rounded-2xl rounded-tl-sm border border-border/50\">\n {comment.content}\n </div>\n )}\n {!own && hasWallet && (\n <button\n className=\"absolute -top-1 -right-5 opacity-0 group-hover:opacity-100 transition-opacity text-muted-foreground/40 hover:text-destructive/70\"\n title=\"Report comment\"\n aria-label=\"Report comment\"\n onClick={() => setReportTarget({ type: \"COMMENT\", commentId: comment.id })}\n >\n <Flag className=\"h-3 w-3\" />\n </button>\n )}\n </div>\n\n {comment.txHash && (\n <a\n href={`${EXPLORER_URL}/tx/${comment.txHash}`}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"flex items-center gap-1 px-1 text-2xs font-medium transition-colors\"\n style={{ color: \"hsl(var(--brand-blue) / 0.55)\" }}\n onMouseEnter={(e) => (e.currentTarget.style.color = \"hsl(var(--brand-blue))\")}\n onMouseLeave={(e) => (e.currentTarget.style.color = \"hsl(var(--brand-blue) / 0.55)\")}\n >\n <span>⛓</span>\n <span>onchain proof</span>\n <ExternalLink className=\"h-2.5 w-2.5\" />\n </a>\n )}\n </div>\n </div>\n );\n })}\n <div ref={bottomRef} />\n </div>\n )}\n </div>\n\n <div className=\"border-t border-border/60 shrink-0\">\n {!hasWallet ? (\n <div className=\"flex items-center justify-center px-4 h-16\">\n <button type=\"button\" onClick={app.onRequireWallet} className=\"text-sm text-primary hover:underline\">\n {app.connectLabel ?? \"Connect\"} to comment\n </button>\n </div>\n ) : (\n <div className=\"px-3 pt-2 pb-3 space-y-2\">\n\n <div className=\"flex items-center gap-1.5\">\n <Zap className=\"h-3 w-3\" style={{ color: \"hsl(var(--brand-blue))\" }} />\n <span className=\"text-2xs font-semibold\" style={{ color: \"hsl(var(--brand-blue))\" }}>\n Mint your message onchain\n </span>\n </div>\n\n <div\n className=\"rounded-xl border bg-background/60 transition-all focus-within:ring-2\"\n style={{\n borderColor: \"hsl(var(--border))\",\n }}\n onFocusCapture={(e) => {\n (e.currentTarget as HTMLDivElement).style.borderColor = \"hsl(var(--brand-blue) / 0.6)\";\n (e.currentTarget as HTMLDivElement).style.boxShadow = \"0 0 0 3px hsl(var(--brand-blue) / 0.12)\";\n }}\n onBlurCapture={(e) => {\n (e.currentTarget as HTMLDivElement).style.borderColor = \"hsl(var(--border))\";\n (e.currentTarget as HTMLDivElement).style.boxShadow = \"\";\n }}\n >\n <Textarea\n ref={composeRef}\n placeholder=\"Say something onchain… it's permanent.\"\n value={text}\n onChange={handleTextInput}\n onKeyDown={handleKeyDown}\n rows={2}\n className=\"resize-none min-h-[52px] max-h-[120px] w-full border-0 bg-transparent focus-visible:ring-0 focus-visible:ring-offset-0 px-3 pt-2.5 pb-1 text-sm rounded-xl\"\n disabled={isProcessing}\n />\n <div className=\"flex items-center justify-between px-3 pb-2.5\">\n <span className=\"text-2xs text-muted-foreground/40 flex items-center gap-1\">\n Enter ↵ to post\n </span>\n <div className=\"flex items-center gap-2\">\n {byteLen > 800 && (\n <span className={`text-2xs ${byteLen > MAX_LEN ? \"text-destructive\" : \"text-muted-foreground\"}`}>\n {byteLen}/{MAX_LEN}\n </span>\n )}\n <button\n onClick={post}\n disabled={!canSubmit || isProcessing}\n className=\"flex items-center gap-1.5 h-7 px-3 text-xs font-semibold rounded-full text-white transition-all hover:opacity-90 active:scale-95 disabled:opacity-40 disabled:cursor-not-allowed\"\n style={{ background: \"linear-gradient(135deg, hsl(var(--brand-blue)), hsl(var(--brand-purple)))\" }}\n >\n {isProcessing ? <Loader2 className=\"h-3 w-3 animate-spin\" /> : <Send className=\"h-3 w-3\" />}\n Post onchain\n </button>\n </div>\n </div>\n </div>\n </div>\n )}\n </div>\n\n {reportTarget && ReportDialog && (\n <ReportDialog\n target={reportTarget}\n open={!!reportTarget}\n onOpenChange={(open) => { if (!open) setReportTarget(null); }}\n />\n )}\n\n <TransactionDialog tx={tx} title=\"Comment\" workingLabel=\"Posting your comment…\" firstStepLabel=\"Prepare comment\">\n <TransactionSuccess\n name=\"Comment\"\n {...successMessages.commented()}\n txHash={tx.txHash}\n actions={[{ label: \"Done\", onClick: tx.reset }]}\n >\n <RewardEarned actionType=\"comment\" />\n </TransactionSuccess>\n </TransactionDialog>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/components/comments-section.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useRef, useState } from \"react\";\nimport { ExternalLink, Flag, Loader2, MessageCircle, Send, Zap } from \"lucide-react\";\nimport { normalizeAddress, profileHref, STARKNET_NFTCOMMENTS_CONTRACT } from \"@medialane/sdk\";\nimport { AddressDisplay } from \"./address-display.js\";\nimport { Button } from \"./button.js\";\nimport Link from \"./link.js\";\nimport { useMedialaneApp, type ReportTarget } from \"./medialane-app.js\";\nimport { ReportDialog } from \"./report-dialog.js\";\nimport { RewardEarned } from \"./rewards/reward-earned.js\";\nimport { Skeleton } from \"./skeleton.js\";\nimport { Textarea } from \"./textarea.js\";\nimport { TransactionDialog } from \"./transaction-dialog.js\";\nimport { TransactionSuccess } from \"./transaction-success.js\";\nimport { cn } from \"../utils/cn.js\";\nimport { EXPLORER_URL } from \"../utils/explorer-url.js\";\nimport { runIntentCalls } from \"../utils/run-intent-calls.js\";\nimport { timeAgo } from \"../utils/time.js\";\nimport { successMessages } from \"../utils/success-messages.js\";\nimport { useComments } from \"../utils/use-comments.js\";\nimport { useTransaction } from \"../utils/use-transaction.js\";\n\nconst MAX_LEN = 1000;\n\nexport interface CommentsSectionProps {\n contract: string;\n tokenId: string;\n className?: string;\n}\n\nexport function CommentsSection({ contract, tokenId, className }: CommentsSectionProps) {\n const app = useMedialaneApp();\n const walletAddress = app.walletAddress;\n const hasWallet = !!walletAddress;\n const { comments, isLoading, mutate } = useComments(contract, tokenId);\n const tx = useTransaction();\n\n const [text, setText] = useState(\"\");\n const [reportTarget, setReportTarget] = useState<ReportTarget | null>(null);\n\n const messagesRef = useRef<HTMLDivElement>(null);\n const bottomRef = useRef<HTMLDivElement>(null);\n const composeRef = useRef<HTMLTextAreaElement>(null);\n\n const byteLen = new TextEncoder().encode(text).length;\n const canSubmit = text.trim().length > 0 && byteLen <= MAX_LEN && !!STARKNET_NFTCOMMENTS_CONTRACT;\n const isProcessing = tx.phase === \"preparing\" || tx.phase === \"submitting\" || tx.phase === \"confirming\";\n\n const isOwn = (author: string) =>\n !!walletAddress && normalizeAddress(\"STARKNET\", author) === normalizeAddress(\"STARKNET\", walletAddress);\n\n const isNearBottom = () => {\n const el = messagesRef.current;\n if (!el) return true;\n return el.scrollHeight - el.scrollTop - el.clientHeight < 100;\n };\n\n useEffect(() => {\n if (isNearBottom()) {\n bottomRef.current?.scrollIntoView({ behavior: \"smooth\" });\n }\n\n }, [comments.length]);\n\n const handleTextInput = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n setText(e.target.value);\n e.target.style.height = \"auto\";\n e.target.style.height = Math.min(e.target.scrollHeight, 96) + \"px\";\n };\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === \"Enter\" && !e.shiftKey && canSubmit && !isProcessing) {\n e.preventDefault();\n post();\n }\n };\n\n const post = () => {\n const body = text.trim();\n void tx\n .run(async (signer) => {\n await runIntentCalls(signer, () =>\n app.getClient().api.intents.create(\"comment\", { author: signer.address, nftContract: contract, tokenId, text: body }),\n );\n })\n .then((ok) => {\n if (!ok) return;\n setText(\"\");\n if (composeRef.current) composeRef.current.style.height = \"auto\";\n void mutate();\n });\n };\n\n const handleStartConversation = () => {\n if (hasWallet) composeRef.current?.focus();\n };\n\n return (\n <div className={cn(\"flex flex-col h-[480px] overflow-hidden\", className)}>\n\n <div ref={messagesRef} className=\"flex-1 overflow-y-auto px-4 py-4\">\n {isLoading ? (\n <div className=\"space-y-4\">\n {([\n { own: false, w: \"w-40\" },\n { own: true, w: \"w-56\" },\n { own: false, w: \"w-48\" },\n { own: true, w: \"w-32\" },\n ] as const).map((item, i) => (\n <div key={i} className={`flex ${item.own ? \"justify-end\" : \"justify-start\"} gap-2`}>\n {!item.own && <Skeleton className=\"h-8 w-8 rounded-full shrink-0\" />}\n <Skeleton\n className={`h-10 ${item.w} rounded-2xl ${item.own ? \"rounded-tr-sm\" : \"rounded-tl-sm\"}`}\n />\n </div>\n ))}\n </div>\n ) : comments.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center h-full gap-4 text-center px-4\">\n <div className=\"flex h-16 w-16 items-center justify-center rounded-full\" style={{ background: \"linear-gradient(135deg, hsl(var(--brand-blue) / 0.15), hsl(var(--brand-purple) / 0.15))\" }}>\n <MessageCircle className=\"h-7 w-7\" style={{ color: \"hsl(var(--brand-blue))\" }} />\n </div>\n <div>\n <p className=\"text-sm font-semibold\">Nothing here yet</p>\n <p className=\"text-xs text-muted-foreground mt-1 leading-relaxed max-w-[220px]\">\n Your comment will be minted onchain — attached to this NFT forever.\n </p>\n </div>\n <Button\n size=\"sm\"\n onClick={handleStartConversation}\n className=\"rounded-full text-white px-5\"\n style={{ background: \"linear-gradient(135deg, hsl(var(--brand-blue)), hsl(var(--brand-purple)))\" }}\n >\n Write the first comment\n </Button>\n </div>\n ) : (\n <div className=\"space-y-5\">\n {comments.map((comment) => {\n const own = isOwn(comment.author);\n const avatarSeed = parseInt(comment.author.slice(2, 8), 16) % 360;\n const avatarBg = own\n ? \"linear-gradient(135deg, hsl(var(--brand-blue)), hsl(var(--brand-purple)))\"\n : `linear-gradient(135deg, hsl(${avatarSeed}, 65%, 45%), hsl(${(avatarSeed + 60) % 360}, 65%, 55%))`;\n\n return (\n <div\n key={comment.id}\n className={`group flex gap-2.5 ${own ? \"flex-row-reverse\" : \"flex-row\"}`}\n >\n\n <Link href={profileHref({ address: comment.author })} className=\"shrink-0 mt-0.5\">\n <div\n className=\"h-9 w-9 rounded-full flex items-center justify-center text-2xs font-bold text-white select-none ring-2 ring-background hover:ring-primary/40 transition-all\"\n style={{ background: avatarBg }}\n >\n {comment.author.slice(2, 5).toUpperCase()}\n </div>\n </Link>\n\n <div className={`flex flex-col max-w-[75%] gap-1 ${own ? \"items-end\" : \"items-start\"}`}>\n\n <div className={`flex items-center gap-2 px-1 ${own ? \"flex-row-reverse\" : \"flex-row\"}`}>\n <Link\n href={profileHref({ address: comment.author })}\n className=\"text-xs font-semibold text-foreground hover:underline underline-offset-2\"\n >\n {own ? \"You\" : <AddressDisplay address={comment.author} chars={5} showCopy={false} />}\n </Link>\n <span className=\"text-2xs text-muted-foreground\" title={comment.postedAt}>\n {timeAgo(comment.postedAt)}\n </span>\n </div>\n\n <div className=\"relative\">\n {own ? (\n <div\n className=\"px-3.5 py-2.5 text-sm leading-relaxed break-words rounded-2xl rounded-tr-sm text-white\"\n style={{ background: \"linear-gradient(135deg, hsl(var(--brand-blue)), hsl(var(--brand-purple)))\" }}\n >\n {comment.content}\n </div>\n ) : (\n <div className=\"px-3.5 py-2.5 text-sm leading-relaxed break-words bg-muted rounded-2xl rounded-tl-sm border border-border/50\">\n {comment.content}\n </div>\n )}\n {!own && hasWallet && (\n <button\n className=\"absolute -top-1 -right-5 opacity-0 group-hover:opacity-100 transition-opacity text-muted-foreground/40 hover:text-destructive/70\"\n title=\"Report comment\"\n aria-label=\"Report comment\"\n onClick={() => setReportTarget({ type: \"COMMENT\", commentId: comment.id })}\n >\n <Flag className=\"h-3 w-3\" />\n </button>\n )}\n </div>\n\n {comment.txHash && (\n <a\n href={`${EXPLORER_URL}/tx/${comment.txHash}`}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"flex items-center gap-1 px-1 text-2xs font-medium transition-colors\"\n style={{ color: \"hsl(var(--brand-blue) / 0.55)\" }}\n onMouseEnter={(e) => (e.currentTarget.style.color = \"hsl(var(--brand-blue))\")}\n onMouseLeave={(e) => (e.currentTarget.style.color = \"hsl(var(--brand-blue) / 0.55)\")}\n >\n <span>⛓</span>\n <span>onchain proof</span>\n <ExternalLink className=\"h-2.5 w-2.5\" />\n </a>\n )}\n </div>\n </div>\n );\n })}\n <div ref={bottomRef} />\n </div>\n )}\n </div>\n\n <div className=\"border-t border-border/60 shrink-0\">\n {!hasWallet ? (\n <div className=\"flex items-center justify-center px-4 h-16\">\n <button type=\"button\" onClick={app.onRequireWallet} className=\"text-sm text-primary hover:underline\">\n {app.connectLabel ?? \"Connect\"} to comment\n </button>\n </div>\n ) : (\n <div className=\"px-3 pt-2 pb-3 space-y-2\">\n\n <div className=\"flex items-center gap-1.5\">\n <Zap className=\"h-3 w-3\" style={{ color: \"hsl(var(--brand-blue))\" }} />\n <span className=\"text-2xs font-semibold\" style={{ color: \"hsl(var(--brand-blue))\" }}>\n Mint your message onchain\n </span>\n </div>\n\n <div\n className=\"rounded-xl border bg-background/60 transition-all focus-within:ring-2\"\n style={{\n borderColor: \"hsl(var(--border))\",\n }}\n onFocusCapture={(e) => {\n (e.currentTarget as HTMLDivElement).style.borderColor = \"hsl(var(--brand-blue) / 0.6)\";\n (e.currentTarget as HTMLDivElement).style.boxShadow = \"0 0 0 3px hsl(var(--brand-blue) / 0.12)\";\n }}\n onBlurCapture={(e) => {\n (e.currentTarget as HTMLDivElement).style.borderColor = \"hsl(var(--border))\";\n (e.currentTarget as HTMLDivElement).style.boxShadow = \"\";\n }}\n >\n <Textarea\n ref={composeRef}\n placeholder=\"Say something onchain… it's permanent.\"\n value={text}\n onChange={handleTextInput}\n onKeyDown={handleKeyDown}\n rows={2}\n className=\"resize-none min-h-[52px] max-h-[120px] w-full border-0 bg-transparent focus-visible:ring-0 focus-visible:ring-offset-0 px-3 pt-2.5 pb-1 text-sm rounded-xl\"\n disabled={isProcessing}\n />\n <div className=\"flex items-center justify-between px-3 pb-2.5\">\n <span className=\"text-2xs text-muted-foreground/40 flex items-center gap-1\">\n Enter ↵ to post\n </span>\n <div className=\"flex items-center gap-2\">\n {byteLen > 800 && (\n <span className={`text-2xs ${byteLen > MAX_LEN ? \"text-destructive\" : \"text-muted-foreground\"}`}>\n {byteLen}/{MAX_LEN}\n </span>\n )}\n <button\n onClick={post}\n disabled={!canSubmit || isProcessing}\n className=\"flex items-center gap-1.5 h-7 px-3 text-xs font-semibold rounded-full text-white transition-all hover:opacity-90 active:scale-95 disabled:opacity-40 disabled:cursor-not-allowed\"\n style={{ background: \"linear-gradient(135deg, hsl(var(--brand-blue)), hsl(var(--brand-purple)))\" }}\n >\n {isProcessing ? <Loader2 className=\"h-3 w-3 animate-spin\" /> : <Send className=\"h-3 w-3\" />}\n Post onchain\n </button>\n </div>\n </div>\n </div>\n </div>\n )}\n </div>\n\n {reportTarget && (\n <ReportDialog\n target={reportTarget}\n open={!!reportTarget}\n onOpenChange={(open) => { if (!open) setReportTarget(null); }}\n />\n )}\n\n <TransactionDialog tx={tx} title=\"Comment\" workingLabel=\"Posting your comment…\" firstStepLabel=\"Prepare comment\">\n <TransactionSuccess\n name=\"Comment\"\n {...successMessages.commented()}\n txHash={tx.txHash}\n actions={[{ label: \"Done\", onClick: tx.reset }]}\n >\n <RewardEarned actionType=\"comment\" />\n </TransactionSuccess>\n </TransactionDialog>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
@@ -50,6 +50,7 @@ var import_listing_card_menu = require("./listing-card-menu.js");
50
50
  var import_activity_timeline_row = require("./activity-timeline-row.js");
51
51
  var import_more_menu = require("./more-menu.js");
52
52
  var import_medialane_app = require("./medialane-app.js");
53
+ var import_report_dialog = require("./report-dialog.js");
53
54
  var import_cn = require("../utils/cn.js");
54
55
  var import_explorer_url = require("../utils/explorer-url.js");
55
56
  var import_same_address = require("../utils/same-address.js");
@@ -72,7 +73,7 @@ const TABS = [
72
73
  const GRID = "grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 gap-4";
73
74
  const isNft = (itemType) => itemType === "ERC721" || itemType === "ERC1155";
74
75
  function CreatorPage({ address: addressProp, username, useAssetActions, useMarketActions }) {
75
- const { walletAddress, ReportDialog } = (0, import_medialane_app.useMedialaneApp)();
76
+ const { walletAddress } = (0, import_medialane_app.useMedialaneApp)();
76
77
  const client = (0, import_use_medialane_client.useMedialaneClient)();
77
78
  const resolveImage = (0, import_use_image_url.useImageUrl)();
78
79
  const prices = (0, import_use_usd_prices.useUsdPrices)();
@@ -168,7 +169,7 @@ function CreatorPage({ address: addressProp, username, useAssetActions, useMarke
168
169
  onCancel: isOwner ? actions.cancel : void 0,
169
170
  onBuy: !isOwner && listing ? () => market.buy(listing) : void 0,
170
171
  onOffer: isOwner ? void 0 : market.offer,
171
- onReport: ReportDialog ? setReportToken : void 0
172
+ onReport: setReportToken
172
173
  },
173
174
  `${t.contractAddress}-${t.tokenId}`
174
175
  );
@@ -179,8 +180,8 @@ function CreatorPage({ address: addressProp, username, useAssetActions, useMarke
179
180
  ] }),
180
181
  actions.dialogs,
181
182
  market.dialogs,
182
- ReportDialog && reportToken ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
183
- ReportDialog,
183
+ reportToken ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
184
+ import_report_dialog.ReportDialog,
184
185
  {
185
186
  open: !!reportToken,
186
187
  onOpenChange: (open) => {
@@ -189,7 +190,7 @@ function CreatorPage({ address: addressProp, username, useAssetActions, useMarke
189
190
  target: { type: "TOKEN", contract: reportToken.contractAddress, tokenId: reportToken.tokenId, name: reportToken.metadata?.name ?? void 0 }
190
191
  }
191
192
  ) : null,
192
- ReportDialog && address ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ReportDialog, { open: reportOpen, onOpenChange: setReportOpen, target: { type: "CREATOR", address, name: identity.name ?? identity.identity } }) : null
193
+ address ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_report_dialog.ReportDialog, { open: reportOpen, onOpenChange: setReportOpen, target: { type: "CREATOR", address, name: identity.name ?? identity.identity } }) : null
193
194
  ] });
194
195
  }
195
196
  // Annotate the CommonJS export names for ESM import in node:
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/creator-page.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport useSWR from \"swr\";\nimport { Activity, Image as ImageIcon, LayoutGrid, ShoppingBag } from \"lucide-react\";\nimport type { ApiToken } from \"@medialane/sdk\";\nimport Link from \"./link.js\";\nimport { Button } from \"./button.js\";\nimport { Skeleton } from \"./skeleton.js\";\nimport { AddressDisplay } from \"./address-display.js\";\nimport { CreatorHeader } from \"./creator-header.js\";\nimport { HiddenContentBanner } from \"./hidden-content-banner.js\";\nimport { TabEmptyState } from \"./tab-empty-state.js\";\nimport { TokenCard, TokenCardSkeleton } from \"./token-card.js\";\nimport { CollectionCard, CollectionCardSkeleton } from \"./collection-card.js\";\nimport { ListingCard, ListingCardSkeleton } from \"./listing-card.js\";\nimport { ListingCardMenu } from \"./listing-card-menu.js\";\nimport { ActivityTimelineRow } from \"./activity-timeline-row.js\";\nimport { MoreMenu } from \"./more-menu.js\";\nimport { useMedialaneApp } from \"./medialane-app.js\";\nimport type { UsePortfolioAssetActions } from \"./portfolio-assets.js\";\nimport type { CollectionMarketActions } from \"./collection-page.js\";\nimport { cn } from \"../utils/cn.js\";\nimport { EXPLORER_URL } from \"../utils/explorer-url.js\";\nimport { isSameAddress } from \"../utils/same-address.js\";\nimport { orderUsd } from \"../utils/order-usd.js\";\nimport { profileIdentity } from \"../utils/profile-identity.js\";\nimport { useImageUrl } from \"../utils/use-image-url.js\";\nimport { useMedialaneClient } from \"../utils/use-medialane-client.js\";\nimport { useUsdPrices } from \"../utils/use-usd-prices.js\";\nimport { useTokensByOwner } from \"../utils/use-tokens.js\";\nimport { useCollectionsByOwner } from \"../utils/use-collections.js\";\nimport { useUserOrders } from \"../utils/use-orders.js\";\nimport { useActivitiesByAddress } from \"../utils/use-activities.js\";\nimport { useCreatorByUsername, useCreatorProfile } from \"../utils/use-profiles.js\";\n\nconst TABS = [\n { id: \"assets\", label: \"Assets\", Icon: ImageIcon },\n { id: \"collections\", label: \"Collections\", Icon: LayoutGrid },\n { id: \"listings\", label: \"Listings\", Icon: ShoppingBag },\n { id: \"activity\", label: \"Activity\", Icon: Activity },\n] as const;\n\ntype TabId = (typeof TABS)[number][\"id\"];\n\nconst GRID = \"grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 gap-4\";\nconst isNft = (itemType: string) => itemType === \"ERC721\" || itemType === \"ERC1155\";\n\nexport interface CreatorPageProps {\n address?: string;\n username?: string;\n useAssetActions: UsePortfolioAssetActions;\n useMarketActions: () => CollectionMarketActions;\n}\n\nexport function CreatorPage({ address: addressProp, username, useAssetActions, useMarketActions }: CreatorPageProps) {\n const { walletAddress, ReportDialog } = useMedialaneApp();\n const client = useMedialaneClient();\n const resolveImage = useImageUrl();\n const prices = useUsdPrices();\n const [activeTab, setActiveTab] = useState<TabId>(\"assets\");\n const [reportOpen, setReportOpen] = useState(false);\n const [reportToken, setReportToken] = useState<ApiToken | null>(null);\n\n const byName = useCreatorByUsername(username);\n const byAddress = useCreatorProfile(username ? undefined : addressProp);\n const creator = username ? byName.creator : byAddress.profile;\n const address = username ? creator?.walletAddress ?? null : addressProp ?? null;\n const isOwner = !!address && !!walletAddress && isSameAddress(address, walletAddress);\n\n const { tokens, meta, isLoading: tokensLoading, mutate: refreshTokens } = useTokensByOwner(address, 1, 20);\n const { collections, isLoading: collectionsLoading } = useCollectionsByOwner(address);\n const { orders, isLoading: ordersLoading } = useUserOrders(activeTab === \"listings\" ? address : null);\n const { activities, isLoading: activitiesLoading } = useActivitiesByAddress(activeTab === \"activity\" ? address : null);\n const { data: hidden } = useSWR(address ? `creator-hidden-${address}` : null, () => client.api.creators.isHidden(address!).catch(() => false));\n const actions = useAssetActions({ refresh: () => void refreshTokens() });\n const market = useMarketActions();\n\n const listings = orders.filter((o) => o.status === \"ACTIVE\" && isNft(o.offer.itemType));\n const identity = profileIdentity({ username: creator?.username, name: creator?.name, walletAddress: address });\n\n if (username && byName.isLoading) {\n return (\n <div className=\"min-h-screen pb-20\">\n <div className=\"px-6 pt-20 pb-6\"><CreatorHeader creator={null} image={null} stats={[]} loading /></div>\n <div className={cn(\"px-6\", GRID)}>{Array.from({ length: 8 }).map((_, i) => <TokenCardSkeleton key={i} />)}</div>\n </div>\n );\n }\n\n if (username && !creator) {\n return (\n <div className=\"mx-auto max-w-lg space-y-4 px-4 py-24 text-center\">\n <h1 className=\"text-2xl font-bold\">Creator not found</h1>\n <p className=\"text-muted-foreground\"><span className=\"tabular-nums\">@{username}</span> isn&apos;t a profile yet.</p>\n <Button variant=\"outline\" asChild><Link href=\"/creators\">Browse creators</Link></Button>\n </div>\n );\n }\n\n const counts: Partial<Record<TabId, number>> = {\n assets: meta?.total ?? undefined,\n collections: collectionsLoading ? undefined : collections.length,\n ...(activeTab === \"listings\" && !ordersLoading ? { listings: listings.length } : {}),\n };\n\n return (\n <div className=\"min-h-screen overflow-x-hidden pb-20\">\n {hidden === true ? <HiddenContentBanner /> : null}\n\n <div className=\"px-6 pt-20 pb-6\">\n {creator ? (\n <CreatorHeader\n creator={creator}\n image={resolveImage(creator.avatarImage || tokens[0]?.metadata?.image)}\n stats={[\n { label: \"Assets\", value: meta?.total ?? null },\n { label: \"Collections\", value: collectionsLoading ? null : collections.length },\n ]}\n />\n ) : (\n <div className=\"flex flex-wrap items-center gap-2\">\n <AddressDisplay address={address ?? \"\"} chars={10} className=\"text-base font-semibold tabular-nums\" />\n </div>\n )}\n </div>\n\n <div className=\"sticky top-0 z-20 mt-4 flex items-center gap-2 border-b border-border bg-background/95 px-6 backdrop-blur-sm\">\n <div className=\"-mb-px flex min-w-0 flex-1 items-center gap-0.5 overflow-x-auto scrollbar-none\">\n {TABS.map(({ id, label, Icon }) => {\n const count = counts[id];\n const active = activeTab === id;\n return (\n <button\n key={id}\n onClick={() => setActiveTab(id)}\n className={cn(\n \"relative flex shrink-0 items-center gap-2 whitespace-nowrap px-4 py-3 text-sm font-medium transition-colors duration-200\",\n active ? \"text-foreground\" : \"text-muted-foreground hover:text-foreground\"\n )}\n >\n <Icon className=\"h-3.5 w-3.5\" />\n {label}\n {count ? (\n <span className={cn(\"min-w-[18px] rounded-full px-1.5 py-px text-center text-2xs font-bold tabular-nums\", active ? \"bg-primary/15 text-primary\" : \"bg-muted text-muted-foreground\")}>{count}</span>\n ) : null}\n {active ? <span className=\"absolute inset-x-0 bottom-0 h-0.5 rounded-full bg-primary\" /> : null}\n </button>\n );\n })}\n </div>\n {address ? (\n <MoreMenu explorerHref={`${EXPLORER_URL}/contract/${address}`} shareTitle={identity.name ?? identity.identity} onReport={() => setReportOpen(true)} />\n ) : null}\n </div>\n\n <div className=\"mt-6 px-6\">\n {activeTab === \"assets\" && (\n tokensLoading ? (\n <div className={GRID}>{Array.from({ length: 8 }).map((_, i) => <TokenCardSkeleton key={i} />)}</div>\n ) : tokens.length === 0 ? (\n <TabEmptyState icon={ImageIcon} heading=\"No assets yet\" body=\"Works this creator makes on Medialane appear here.\" />\n ) : (\n <div className={GRID}>\n {tokens.map((t: ApiToken) => {\n const listing = t.activeOrders?.find((o) => isNft(o.offer.itemType));\n return (\n <TokenCard\n key={`${t.contractAddress}-${t.tokenId}`}\n token={t}\n isOwner={isOwner}\n usdValue={orderUsd(listing?.price, prices)}\n onList={isOwner ? actions.list : undefined}\n onTransfer={isOwner ? actions.transfer : undefined}\n onCancel={isOwner ? actions.cancel : undefined}\n onBuy={!isOwner && listing ? () => market.buy(listing) : undefined}\n onOffer={isOwner ? undefined : market.offer}\n onReport={ReportDialog ? setReportToken : undefined}\n />\n );\n })}\n </div>\n )\n )}\n\n {activeTab === \"collections\" && (\n collectionsLoading ? (\n <div className=\"grid grid-cols-2 gap-4 lg:grid-cols-3\">{Array.from({ length: 6 }).map((_, i) => <CollectionCardSkeleton key={i} />)}</div>\n ) : collections.length === 0 ? (\n <TabEmptyState icon={LayoutGrid} heading=\"No collections yet\" body=\"Collections this creator makes appear here.\" />\n ) : (\n <div className=\"grid grid-cols-2 gap-4 lg:grid-cols-3\">{collections.map((c) => <CollectionCard key={c.contractAddress} collection={c} />)}</div>\n )\n )}\n\n {activeTab === \"listings\" && (\n ordersLoading ? (\n <div className={GRID}>{Array.from({ length: 4 }).map((_, i) => <ListingCardSkeleton key={i} />)}</div>\n ) : listings.length === 0 ? (\n <TabEmptyState icon={ShoppingBag} heading=\"No active listings\" body=\"Works this creator lists for sale appear here.\" />\n ) : (\n <div className={GRID}>\n {listings.map((o) => <ListingCard key={o.orderHash} order={o} onBuy={isOwner ? undefined : market.buy} usdValue={orderUsd(o.price, prices)} overflowMenu={<ListingCardMenu order={o} />} />)}\n </div>\n )\n )}\n\n {activeTab === \"activity\" && (\n <div className=\"max-w-2xl\">\n {activitiesLoading ? (\n <div className=\"space-y-5\">{Array.from({ length: 6 }).map((_, i) => <Skeleton key={i} className=\"h-10 w-full rounded-xl\" />)}</div>\n ) : activities.length === 0 ? (\n <TabEmptyState icon={Activity} heading=\"No activity yet\" body=\"This creator's activity appears here as it happens.\" />\n ) : (\n <div>{activities.map((a, i) => <ActivityTimelineRow key={i} event={a} isLast={i === activities.length - 1} />)}</div>\n )}\n </div>\n )}\n </div>\n\n {actions.dialogs}\n {market.dialogs}\n {ReportDialog && reportToken ? (\n <ReportDialog\n open={!!reportToken}\n onOpenChange={(open) => { if (!open) setReportToken(null); }}\n target={{ type: \"TOKEN\", contract: reportToken.contractAddress, tokenId: reportToken.tokenId, name: reportToken.metadata?.name ?? undefined }}\n />\n ) : null}\n {ReportDialog && address ? (\n <ReportDialog open={reportOpen} onOpenChange={setReportOpen} target={{ type: \"CREATOR\", address, name: identity.name ?? identity.identity }} />\n ) : null}\n </div>\n );\n}\n"],"mappings":"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","names":["ImageIcon","useSWR","Link"]}
1
+ {"version":3,"sources":["../../src/components/creator-page.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport useSWR from \"swr\";\nimport { Activity, Image as ImageIcon, LayoutGrid, ShoppingBag } from \"lucide-react\";\nimport type { ApiToken } from \"@medialane/sdk\";\nimport Link from \"./link.js\";\nimport { Button } from \"./button.js\";\nimport { Skeleton } from \"./skeleton.js\";\nimport { AddressDisplay } from \"./address-display.js\";\nimport { CreatorHeader } from \"./creator-header.js\";\nimport { HiddenContentBanner } from \"./hidden-content-banner.js\";\nimport { TabEmptyState } from \"./tab-empty-state.js\";\nimport { TokenCard, TokenCardSkeleton } from \"./token-card.js\";\nimport { CollectionCard, CollectionCardSkeleton } from \"./collection-card.js\";\nimport { ListingCard, ListingCardSkeleton } from \"./listing-card.js\";\nimport { ListingCardMenu } from \"./listing-card-menu.js\";\nimport { ActivityTimelineRow } from \"./activity-timeline-row.js\";\nimport { MoreMenu } from \"./more-menu.js\";\nimport { useMedialaneApp } from \"./medialane-app.js\";\nimport { ReportDialog } from \"./report-dialog.js\";\nimport type { UsePortfolioAssetActions } from \"./portfolio-assets.js\";\nimport type { CollectionMarketActions } from \"./collection-page.js\";\nimport { cn } from \"../utils/cn.js\";\nimport { EXPLORER_URL } from \"../utils/explorer-url.js\";\nimport { isSameAddress } from \"../utils/same-address.js\";\nimport { orderUsd } from \"../utils/order-usd.js\";\nimport { profileIdentity } from \"../utils/profile-identity.js\";\nimport { useImageUrl } from \"../utils/use-image-url.js\";\nimport { useMedialaneClient } from \"../utils/use-medialane-client.js\";\nimport { useUsdPrices } from \"../utils/use-usd-prices.js\";\nimport { useTokensByOwner } from \"../utils/use-tokens.js\";\nimport { useCollectionsByOwner } from \"../utils/use-collections.js\";\nimport { useUserOrders } from \"../utils/use-orders.js\";\nimport { useActivitiesByAddress } from \"../utils/use-activities.js\";\nimport { useCreatorByUsername, useCreatorProfile } from \"../utils/use-profiles.js\";\n\nconst TABS = [\n { id: \"assets\", label: \"Assets\", Icon: ImageIcon },\n { id: \"collections\", label: \"Collections\", Icon: LayoutGrid },\n { id: \"listings\", label: \"Listings\", Icon: ShoppingBag },\n { id: \"activity\", label: \"Activity\", Icon: Activity },\n] as const;\n\ntype TabId = (typeof TABS)[number][\"id\"];\n\nconst GRID = \"grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 gap-4\";\nconst isNft = (itemType: string) => itemType === \"ERC721\" || itemType === \"ERC1155\";\n\nexport interface CreatorPageProps {\n address?: string;\n username?: string;\n useAssetActions: UsePortfolioAssetActions;\n useMarketActions: () => CollectionMarketActions;\n}\n\nexport function CreatorPage({ address: addressProp, username, useAssetActions, useMarketActions }: CreatorPageProps) {\n const { walletAddress } = useMedialaneApp();\n const client = useMedialaneClient();\n const resolveImage = useImageUrl();\n const prices = useUsdPrices();\n const [activeTab, setActiveTab] = useState<TabId>(\"assets\");\n const [reportOpen, setReportOpen] = useState(false);\n const [reportToken, setReportToken] = useState<ApiToken | null>(null);\n\n const byName = useCreatorByUsername(username);\n const byAddress = useCreatorProfile(username ? undefined : addressProp);\n const creator = username ? byName.creator : byAddress.profile;\n const address = username ? creator?.walletAddress ?? null : addressProp ?? null;\n const isOwner = !!address && !!walletAddress && isSameAddress(address, walletAddress);\n\n const { tokens, meta, isLoading: tokensLoading, mutate: refreshTokens } = useTokensByOwner(address, 1, 20);\n const { collections, isLoading: collectionsLoading } = useCollectionsByOwner(address);\n const { orders, isLoading: ordersLoading } = useUserOrders(activeTab === \"listings\" ? address : null);\n const { activities, isLoading: activitiesLoading } = useActivitiesByAddress(activeTab === \"activity\" ? address : null);\n const { data: hidden } = useSWR(address ? `creator-hidden-${address}` : null, () => client.api.creators.isHidden(address!).catch(() => false));\n const actions = useAssetActions({ refresh: () => void refreshTokens() });\n const market = useMarketActions();\n\n const listings = orders.filter((o) => o.status === \"ACTIVE\" && isNft(o.offer.itemType));\n const identity = profileIdentity({ username: creator?.username, name: creator?.name, walletAddress: address });\n\n if (username && byName.isLoading) {\n return (\n <div className=\"min-h-screen pb-20\">\n <div className=\"px-6 pt-20 pb-6\"><CreatorHeader creator={null} image={null} stats={[]} loading /></div>\n <div className={cn(\"px-6\", GRID)}>{Array.from({ length: 8 }).map((_, i) => <TokenCardSkeleton key={i} />)}</div>\n </div>\n );\n }\n\n if (username && !creator) {\n return (\n <div className=\"mx-auto max-w-lg space-y-4 px-4 py-24 text-center\">\n <h1 className=\"text-2xl font-bold\">Creator not found</h1>\n <p className=\"text-muted-foreground\"><span className=\"tabular-nums\">@{username}</span> isn&apos;t a profile yet.</p>\n <Button variant=\"outline\" asChild><Link href=\"/creators\">Browse creators</Link></Button>\n </div>\n );\n }\n\n const counts: Partial<Record<TabId, number>> = {\n assets: meta?.total ?? undefined,\n collections: collectionsLoading ? undefined : collections.length,\n ...(activeTab === \"listings\" && !ordersLoading ? { listings: listings.length } : {}),\n };\n\n return (\n <div className=\"min-h-screen overflow-x-hidden pb-20\">\n {hidden === true ? <HiddenContentBanner /> : null}\n\n <div className=\"px-6 pt-20 pb-6\">\n {creator ? (\n <CreatorHeader\n creator={creator}\n image={resolveImage(creator.avatarImage || tokens[0]?.metadata?.image)}\n stats={[\n { label: \"Assets\", value: meta?.total ?? null },\n { label: \"Collections\", value: collectionsLoading ? null : collections.length },\n ]}\n />\n ) : (\n <div className=\"flex flex-wrap items-center gap-2\">\n <AddressDisplay address={address ?? \"\"} chars={10} className=\"text-base font-semibold tabular-nums\" />\n </div>\n )}\n </div>\n\n <div className=\"sticky top-0 z-20 mt-4 flex items-center gap-2 border-b border-border bg-background/95 px-6 backdrop-blur-sm\">\n <div className=\"-mb-px flex min-w-0 flex-1 items-center gap-0.5 overflow-x-auto scrollbar-none\">\n {TABS.map(({ id, label, Icon }) => {\n const count = counts[id];\n const active = activeTab === id;\n return (\n <button\n key={id}\n onClick={() => setActiveTab(id)}\n className={cn(\n \"relative flex shrink-0 items-center gap-2 whitespace-nowrap px-4 py-3 text-sm font-medium transition-colors duration-200\",\n active ? \"text-foreground\" : \"text-muted-foreground hover:text-foreground\"\n )}\n >\n <Icon className=\"h-3.5 w-3.5\" />\n {label}\n {count ? (\n <span className={cn(\"min-w-[18px] rounded-full px-1.5 py-px text-center text-2xs font-bold tabular-nums\", active ? \"bg-primary/15 text-primary\" : \"bg-muted text-muted-foreground\")}>{count}</span>\n ) : null}\n {active ? <span className=\"absolute inset-x-0 bottom-0 h-0.5 rounded-full bg-primary\" /> : null}\n </button>\n );\n })}\n </div>\n {address ? (\n <MoreMenu explorerHref={`${EXPLORER_URL}/contract/${address}`} shareTitle={identity.name ?? identity.identity} onReport={() => setReportOpen(true)} />\n ) : null}\n </div>\n\n <div className=\"mt-6 px-6\">\n {activeTab === \"assets\" && (\n tokensLoading ? (\n <div className={GRID}>{Array.from({ length: 8 }).map((_, i) => <TokenCardSkeleton key={i} />)}</div>\n ) : tokens.length === 0 ? (\n <TabEmptyState icon={ImageIcon} heading=\"No assets yet\" body=\"Works this creator makes on Medialane appear here.\" />\n ) : (\n <div className={GRID}>\n {tokens.map((t: ApiToken) => {\n const listing = t.activeOrders?.find((o) => isNft(o.offer.itemType));\n return (\n <TokenCard\n key={`${t.contractAddress}-${t.tokenId}`}\n token={t}\n isOwner={isOwner}\n usdValue={orderUsd(listing?.price, prices)}\n onList={isOwner ? actions.list : undefined}\n onTransfer={isOwner ? actions.transfer : undefined}\n onCancel={isOwner ? actions.cancel : undefined}\n onBuy={!isOwner && listing ? () => market.buy(listing) : undefined}\n onOffer={isOwner ? undefined : market.offer}\n onReport={setReportToken}\n />\n );\n })}\n </div>\n )\n )}\n\n {activeTab === \"collections\" && (\n collectionsLoading ? (\n <div className=\"grid grid-cols-2 gap-4 lg:grid-cols-3\">{Array.from({ length: 6 }).map((_, i) => <CollectionCardSkeleton key={i} />)}</div>\n ) : collections.length === 0 ? (\n <TabEmptyState icon={LayoutGrid} heading=\"No collections yet\" body=\"Collections this creator makes appear here.\" />\n ) : (\n <div className=\"grid grid-cols-2 gap-4 lg:grid-cols-3\">{collections.map((c) => <CollectionCard key={c.contractAddress} collection={c} />)}</div>\n )\n )}\n\n {activeTab === \"listings\" && (\n ordersLoading ? (\n <div className={GRID}>{Array.from({ length: 4 }).map((_, i) => <ListingCardSkeleton key={i} />)}</div>\n ) : listings.length === 0 ? (\n <TabEmptyState icon={ShoppingBag} heading=\"No active listings\" body=\"Works this creator lists for sale appear here.\" />\n ) : (\n <div className={GRID}>\n {listings.map((o) => <ListingCard key={o.orderHash} order={o} onBuy={isOwner ? undefined : market.buy} usdValue={orderUsd(o.price, prices)} overflowMenu={<ListingCardMenu order={o} />} />)}\n </div>\n )\n )}\n\n {activeTab === \"activity\" && (\n <div className=\"max-w-2xl\">\n {activitiesLoading ? (\n <div className=\"space-y-5\">{Array.from({ length: 6 }).map((_, i) => <Skeleton key={i} className=\"h-10 w-full rounded-xl\" />)}</div>\n ) : activities.length === 0 ? (\n <TabEmptyState icon={Activity} heading=\"No activity yet\" body=\"This creator's activity appears here as it happens.\" />\n ) : (\n <div>{activities.map((a, i) => <ActivityTimelineRow key={i} event={a} isLast={i === activities.length - 1} />)}</div>\n )}\n </div>\n )}\n </div>\n\n {actions.dialogs}\n {market.dialogs}\n {reportToken ? (\n <ReportDialog\n open={!!reportToken}\n onOpenChange={(open) => { if (!open) setReportToken(null); }}\n target={{ type: \"TOKEN\", contract: reportToken.contractAddress, tokenId: reportToken.tokenId, name: reportToken.metadata?.name ?? undefined }}\n />\n ) : null}\n {address ? (\n <ReportDialog open={reportOpen} onOpenChange={setReportOpen} target={{ type: \"CREATOR\", address, name: identity.name ?? identity.identity }} />\n ) : null}\n </div>\n );\n}\n"],"mappings":"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","names":["ImageIcon","useSWR","Link"]}