@medialane/ui 0.312.0 → 0.314.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/account-page.cjs +48 -46
  2. package/dist/components/account-page.cjs.map +1 -1
  3. package/dist/components/account-page.js +48 -46
  4. package/dist/components/account-page.js.map +1 -1
  5. package/dist/components/approve-mint-dialog.cjs +1 -1
  6. package/dist/components/approve-mint-dialog.cjs.map +1 -1
  7. package/dist/components/approve-mint-dialog.js +1 -1
  8. package/dist/components/approve-mint-dialog.js.map +1 -1
  9. package/dist/components/asset-marketplace-panel.cjs +1 -1
  10. package/dist/components/asset-marketplace-panel.cjs.map +1 -1
  11. package/dist/components/asset-marketplace-panel.js +1 -1
  12. package/dist/components/asset-marketplace-panel.js.map +1 -1
  13. package/dist/components/fast-mint/success-view.cjs +1 -1
  14. package/dist/components/fast-mint/success-view.cjs.map +1 -1
  15. package/dist/components/fast-mint/success-view.js +1 -1
  16. package/dist/components/fast-mint/success-view.js.map +1 -1
  17. package/dist/components/home-page.cjs +1 -1
  18. package/dist/components/home-page.cjs.map +1 -1
  19. package/dist/components/home-page.js +1 -1
  20. package/dist/components/home-page.js.map +1 -1
  21. package/dist/components/launchpad/tier-mint-presets.cjs +3 -3
  22. package/dist/components/launchpad/tier-mint-presets.cjs.map +1 -1
  23. package/dist/components/launchpad/tier-mint-presets.js +3 -3
  24. package/dist/components/launchpad/tier-mint-presets.js.map +1 -1
  25. package/dist/components/listings-grid.cjs +1 -1
  26. package/dist/components/listings-grid.cjs.map +1 -1
  27. package/dist/components/listings-grid.js +1 -1
  28. package/dist/components/listings-grid.js.map +1 -1
  29. package/dist/components/portfolio-header.cjs +4 -1
  30. package/dist/components/portfolio-header.cjs.map +1 -1
  31. package/dist/components/portfolio-header.d.cts +4 -1
  32. package/dist/components/portfolio-header.d.ts +4 -1
  33. package/dist/components/portfolio-header.js +4 -1
  34. package/dist/components/portfolio-header.js.map +1 -1
  35. package/dist/components/portfolio-orders.cjs +1 -1
  36. package/dist/components/portfolio-orders.cjs.map +1 -1
  37. package/dist/components/portfolio-orders.js +1 -1
  38. package/dist/components/portfolio-orders.js.map +1 -1
  39. package/dist/components/rewards/rewards-dashboard.cjs +2 -2
  40. package/dist/components/rewards/rewards-dashboard.cjs.map +1 -1
  41. package/dist/components/rewards/rewards-dashboard.js +2 -2
  42. package/dist/components/rewards/rewards-dashboard.js.map +1 -1
  43. package/dist/components/route-error.cjs +2 -6
  44. package/dist/components/route-error.cjs.map +1 -1
  45. package/dist/components/route-error.d.cts +1 -2
  46. package/dist/components/route-error.d.ts +1 -2
  47. package/dist/components/route-error.js +2 -6
  48. package/dist/components/route-error.js.map +1 -1
  49. package/dist/components/token-card.cjs +2 -2
  50. package/dist/components/token-card.cjs.map +1 -1
  51. package/dist/components/token-card.js +2 -2
  52. package/dist/components/token-card.js.map +1 -1
  53. package/package.json +1 -1
@@ -38,9 +38,8 @@ var import_swr = __toESM(require("swr"), 1);
38
38
  var import_lucide_react = require("lucide-react");
39
39
  var import_load_more_sentinel = require("./load-more-sentinel.js");
40
40
  var import_skeleton = require("./skeleton.js");
41
- var import_tabs = require("./tabs.js");
42
- var import_underline_tabs = require("./underline-tabs.js");
43
- var import_address_display = require("./address-display.js");
41
+ var import_portfolio_header = require("./portfolio-header.js");
42
+ var import_portfolio_chip_filter = require("./portfolio-chip-filter.js");
44
43
  var import_hidden_content_banner = require("./hidden-content-banner.js");
45
44
  var import_tab_empty_state = require("./tab-empty-state.js");
46
45
  var import_token_card = require("./token-card.js");
@@ -61,6 +60,12 @@ var import_use_tokens = require("../utils/use-tokens.js");
61
60
  var import_use_collections = require("../utils/use-collections.js");
62
61
  var import_use_orders = require("../utils/use-orders.js");
63
62
  var import_use_activities = require("../utils/use-activities.js");
63
+ const TABS = [
64
+ { key: "assets", label: "Assets" },
65
+ { key: "collections", label: "Collections" },
66
+ { key: "listings", label: "Listings" },
67
+ { key: "activity", label: "Activity" }
68
+ ];
64
69
  const GRID = "grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 gap-4";
65
70
  const isNft = (itemType) => itemType === "ERC721" || itemType === "ERC1155";
66
71
  function AccountPage({ address, useAssetActions, useMarketActions }) {
@@ -79,53 +84,50 @@ function AccountPage({ address, useAssetActions, useMarketActions }) {
79
84
  const actions = useAssetActions({ refresh: () => void refreshTokens() });
80
85
  const market = useMarketActions();
81
86
  const listings = orders.filter((o) => o.status === "ACTIVE" && isNft(o.offer.itemType));
82
- const tabs = [
83
- { id: "assets", label: "Assets", icon: import_lucide_react.Image, count: total ?? void 0 },
84
- { id: "collections", label: "Collections", icon: import_lucide_react.LayoutGrid, count: collectionsLoading ? void 0 : collections.length },
85
- { id: "listings", label: "Listings", icon: import_lucide_react.ShoppingBag, count: ordersLoading ? void 0 : listings.length },
86
- { id: "activity", label: "Activity", icon: import_lucide_react.Activity }
87
- ];
88
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "min-h-screen overflow-x-hidden pb-20", children: [
87
+ const counts = {
88
+ assets: total ?? void 0,
89
+ collections: collectionsLoading ? void 0 : collections.length,
90
+ listings: ordersLoading ? void 0 : listings.length
91
+ };
92
+ const tabs = TABS.map(({ key, label }) => ({ key, label: counts[key] === void 0 ? label : `${label} (${counts[key]})` }));
93
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-6 px-4 pt-20 pb-8 sm:px-6 lg:px-8", children: [
89
94
  hidden === true ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_hidden_content_banner.HiddenContentBanner, {}) : null,
90
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center justify-between gap-3 px-6 pt-20 pb-6", children: [
91
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_address_display.AddressDisplay, { address, chars: 6, className: "min-w-0 text-2xl font-black tracking-tight tabular-nums sm:text-3xl" }),
92
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "shrink-0 rounded-full bg-muted px-2.5 py-1 text-xs font-medium text-muted-foreground", children: "Starknet" })
93
- ] }),
94
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
95
- import_underline_tabs.UnderlineTabs,
95
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
96
+ import_portfolio_header.PortfolioHeader,
96
97
  {
97
- tabs,
98
- value: activeTab,
99
- onValueChange: (id) => setActiveTab(id),
100
- trailing: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_more_menu.MoreMenu, { explorerHref: `${import_explorer_url.EXPLORER_URL}/contract/${address}`, shareTitle: (0, import_address.shortenAddress)(address), onReport: () => setReportOpen(true) }),
101
- children: [
102
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tabs.TabsContent, { value: "assets", className: "mt-6 px-6", children: tokensLoading ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: GRID, children: Array.from({ length: 8 }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_token_card.TokenCardSkeleton, {}, i)) }) : tokens.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tab_empty_state.TabEmptyState, { icon: import_lucide_react.Image, heading: "No assets yet", body: "Works this account owns appear here." }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
103
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: GRID, children: tokens.map((t) => {
104
- const listing = t.activeOrders?.find((o) => isNft(o.offer.itemType));
105
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
106
- import_token_card.TokenCard,
107
- {
108
- token: t,
109
- isOwner,
110
- usdValue: (0, import_order_usd.orderUsd)(listing?.price, prices),
111
- onList: isOwner ? actions.list : void 0,
112
- onTransfer: isOwner ? actions.transfer : void 0,
113
- onCancel: isOwner ? actions.cancel : void 0,
114
- onBuy: !isOwner && listing ? () => market.buy(listing) : void 0,
115
- onOffer: isOwner ? void 0 : market.offer,
116
- onReport: setReportToken
117
- },
118
- `${t.contractAddress}-${t.tokenId}`
119
- );
120
- }) }),
121
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_load_more_sentinel.LoadMoreSentinel, { hasMore, isLoading: isLoadingMore, onLoadMore: loadMore })
122
- ] }) }),
123
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tabs.TabsContent, { value: "collections", className: "mt-6 px-6", children: collectionsLoading ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "grid grid-cols-2 gap-4 lg:grid-cols-3", children: Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_collection_card.CollectionCardSkeleton, {}, i)) }) : collections.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tab_empty_state.TabEmptyState, { icon: import_lucide_react.LayoutGrid, heading: "No collections yet", body: "Collections this account owns appear here." }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "grid grid-cols-2 gap-4 lg:grid-cols-3", children: collections.map((c) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_collection_card.CollectionCard, { collection: c }, c.contractAddress)) }) }),
124
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tabs.TabsContent, { value: "listings", className: "mt-6 px-6", children: ordersLoading ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: GRID, children: Array.from({ length: 4 }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_listing_card.ListingCardSkeleton, {}, i)) }) : listings.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tab_empty_state.TabEmptyState, { icon: import_lucide_react.ShoppingBag, heading: "No active listings", body: "Works this account lists for sale appear here." }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: GRID, children: listings.map((o) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_listing_card.ListingCard, { order: o, onBuy: isOwner ? void 0 : market.buy, usdValue: (0, import_order_usd.orderUsd)(o.price, prices), overflowMenu: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_listing_card_menu.ListingCardMenu, { order: o }) }, o.orderHash)) }) }),
125
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tabs.TabsContent, { value: "activity", className: "mt-6 max-w-2xl px-6", children: activitiesLoading ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "space-y-5", children: Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_skeleton.Skeleton, { className: "h-10 w-full rounded-xl" }, i)) }) : activities.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tab_empty_state.TabEmptyState, { icon: import_lucide_react.Activity, heading: "No activity yet", body: "This account's activity appears here as it happens." }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: activities.map((a, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_activity_timeline_row.ActivityTimelineRow, { event: a, isLast: i === activities.length - 1 }, i)) }) })
126
- ]
98
+ address,
99
+ label: "Account",
100
+ trailing: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "ml-auto flex shrink-0 items-center gap-2", children: [
101
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rounded-full bg-muted px-2.5 py-1 text-xs font-medium text-muted-foreground", children: "Starknet" }),
102
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_more_menu.MoreMenu, { explorerHref: `${import_explorer_url.EXPLORER_URL}/contract/${address}`, shareTitle: (0, import_address.shortenAddress)(address), onReport: () => setReportOpen(true) })
103
+ ] })
127
104
  }
128
105
  ),
106
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_portfolio_chip_filter.PortfolioChipFilter, { options: tabs, value: activeTab, onChange: (key) => setActiveTab(key), showAll: false }),
107
+ activeTab === "assets" && (tokensLoading ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: GRID, children: Array.from({ length: 8 }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_token_card.TokenCardSkeleton, {}, i)) }) : tokens.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tab_empty_state.TabEmptyState, { icon: import_lucide_react.Image, heading: "No assets yet", body: "Works this account owns appear here." }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
108
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: GRID, children: tokens.map((t) => {
109
+ const listing = t.activeOrders?.find((o) => isNft(o.offer.itemType));
110
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
111
+ import_token_card.TokenCard,
112
+ {
113
+ token: t,
114
+ isOwner,
115
+ usdValue: (0, import_order_usd.orderUsd)(listing?.price, prices),
116
+ onList: isOwner ? actions.list : void 0,
117
+ onTransfer: isOwner ? actions.transfer : void 0,
118
+ onCancel: isOwner ? actions.cancel : void 0,
119
+ onBuy: !isOwner && listing ? () => market.buy(listing) : void 0,
120
+ onOffer: isOwner ? void 0 : market.offer,
121
+ onReport: setReportToken
122
+ },
123
+ `${t.contractAddress}-${t.tokenId}`
124
+ );
125
+ }) }),
126
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_load_more_sentinel.LoadMoreSentinel, { hasMore, isLoading: isLoadingMore, onLoadMore: loadMore })
127
+ ] })),
128
+ activeTab === "collections" && (collectionsLoading ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "grid grid-cols-2 gap-4 lg:grid-cols-3", children: Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_collection_card.CollectionCardSkeleton, {}, i)) }) : collections.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tab_empty_state.TabEmptyState, { icon: import_lucide_react.LayoutGrid, heading: "No collections yet", body: "Collections this account owns appear here." }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "grid grid-cols-2 gap-4 lg:grid-cols-3", children: collections.map((c) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_collection_card.CollectionCard, { collection: c }, c.contractAddress)) })),
129
+ activeTab === "listings" && (ordersLoading ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: GRID, children: Array.from({ length: 4 }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_listing_card.ListingCardSkeleton, {}, i)) }) : listings.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tab_empty_state.TabEmptyState, { icon: import_lucide_react.ShoppingBag, heading: "No active listings", body: "Works this account lists for sale appear here." }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: GRID, children: listings.map((o) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_listing_card.ListingCard, { order: o, onBuy: isOwner ? void 0 : market.buy, usdValue: (0, import_order_usd.orderUsd)(o.price, prices), overflowMenu: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_listing_card_menu.ListingCardMenu, { order: o }) }, o.orderHash)) })),
130
+ activeTab === "activity" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "max-w-2xl", children: activitiesLoading ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "space-y-5", children: Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_skeleton.Skeleton, { className: "h-10 w-full rounded-xl" }, i)) }) : activities.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_tab_empty_state.TabEmptyState, { icon: import_lucide_react.Activity, heading: "No activity yet", body: "This account's activity appears here as it happens." }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: activities.map((a, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_activity_timeline_row.ActivityTimelineRow, { event: a, isLast: i === activities.length - 1 }, i)) }) }) : null,
129
131
  actions.dialogs,
130
132
  market.dialogs,
131
133
  reportToken ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/account-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 { LoadMoreSentinel } from \"./load-more-sentinel.js\";\nimport { Skeleton } from \"./skeleton.js\";\nimport { TabsContent } from \"./tabs.js\";\nimport { UnderlineTabs, type UnderlineTab } from \"./underline-tabs.js\";\nimport { AddressDisplay } from \"./address-display.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 { shortenAddress } from \"../utils/address.js\";\nimport { EXPLORER_URL } from \"../utils/explorer-url.js\";\nimport { isSameAddress } from \"../utils/same-address.js\";\nimport { orderUsd } from \"../utils/order-usd.js\";\nimport { useMedialaneClient } from \"../utils/use-medialane-client.js\";\nimport { useUsdPrices } from \"../utils/use-usd-prices.js\";\nimport { useOwnedTokens } 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\";\n\ntype TabId = \"assets\" | \"collections\" | \"listings\" | \"activity\";\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 AccountPageProps {\n address: string;\n useAssetActions: UsePortfolioAssetActions;\n useMarketActions: () => CollectionMarketActions;\n}\n\nexport function AccountPage({ address, useAssetActions, useMarketActions }: AccountPageProps) {\n const { walletAddress } = useMedialaneApp();\n const client = useMedialaneClient();\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 isOwner = !!walletAddress && isSameAddress(address, walletAddress);\n\n const { tokens, total, isLoading: tokensLoading, isLoadingMore, hasMore, loadMore, mutate: refreshTokens } = useOwnedTokens(address);\n const { collections, isLoading: collectionsLoading } = useCollectionsByOwner(address);\n const { orders, isLoading: ordersLoading } = useUserOrders(address);\n const { activities, isLoading: activitiesLoading } = useActivitiesByAddress(activeTab === \"activity\" ? address : null);\n const { data: hidden } = useSWR(`creator-hidden-${address}`, () => 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 tabs: UnderlineTab[] = [\n { id: \"assets\", label: \"Assets\", icon: ImageIcon, count: total ?? undefined },\n { id: \"collections\", label: \"Collections\", icon: LayoutGrid, count: collectionsLoading ? undefined : collections.length },\n { id: \"listings\", label: \"Listings\", icon: ShoppingBag, count: ordersLoading ? undefined : listings.length },\n { id: \"activity\", label: \"Activity\", icon: Activity },\n ];\n\n return (\n <div className=\"min-h-screen overflow-x-hidden pb-20\">\n {hidden === true ? <HiddenContentBanner /> : null}\n\n <div className=\"flex items-center justify-between gap-3 px-6 pt-20 pb-6\">\n <AddressDisplay address={address} chars={6} className=\"min-w-0 text-2xl font-black tracking-tight tabular-nums sm:text-3xl\" />\n <span className=\"shrink-0 rounded-full bg-muted px-2.5 py-1 text-xs font-medium text-muted-foreground\">Starknet</span>\n </div>\n\n <UnderlineTabs\n tabs={tabs}\n value={activeTab}\n onValueChange={(id) => setActiveTab(id as TabId)}\n trailing={<MoreMenu explorerHref={`${EXPLORER_URL}/contract/${address}`} shareTitle={shortenAddress(address)} onReport={() => setReportOpen(true)} />}\n >\n <TabsContent value=\"assets\" className=\"mt-6 px-6\">\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 account owns appear here.\" />\n ) : (\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 <LoadMoreSentinel hasMore={hasMore} isLoading={isLoadingMore} onLoadMore={loadMore} />\n </>\n )}\n </TabsContent>\n\n <TabsContent value=\"collections\" className=\"mt-6 px-6\">\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 account owns 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 </TabsContent>\n\n <TabsContent value=\"listings\" className=\"mt-6 px-6\">\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 account 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 </TabsContent>\n\n <TabsContent value=\"activity\" className=\"mt-6 max-w-2xl px-6\">\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 account'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 </TabsContent>\n </UnderlineTabs>\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 <ReportDialog open={reportOpen} onOpenChange={setReportOpen} target={{ type: \"CREATOR\", address, name: shortenAddress(address) }} />\n </div>\n );\n}\n"],"mappings":"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","names":["useSWR","ImageIcon"]}
1
+ {"version":3,"sources":["../../src/components/account-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 { LoadMoreSentinel } from \"./load-more-sentinel.js\";\nimport { Skeleton } from \"./skeleton.js\";\nimport { PortfolioHeader } from \"./portfolio-header.js\";\nimport { PortfolioChipFilter } from \"./portfolio-chip-filter.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 { shortenAddress } from \"../utils/address.js\";\nimport { EXPLORER_URL } from \"../utils/explorer-url.js\";\nimport { isSameAddress } from \"../utils/same-address.js\";\nimport { orderUsd } from \"../utils/order-usd.js\";\nimport { useMedialaneClient } from \"../utils/use-medialane-client.js\";\nimport { useUsdPrices } from \"../utils/use-usd-prices.js\";\nimport { useOwnedTokens } 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\";\n\ntype TabId = \"assets\" | \"collections\" | \"listings\" | \"activity\";\n\nconst TABS: { key: TabId; label: string }[] = [\n { key: \"assets\", label: \"Assets\" },\n { key: \"collections\", label: \"Collections\" },\n { key: \"listings\", label: \"Listings\" },\n { key: \"activity\", label: \"Activity\" },\n];\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 AccountPageProps {\n address: string;\n useAssetActions: UsePortfolioAssetActions;\n useMarketActions: () => CollectionMarketActions;\n}\n\nexport function AccountPage({ address, useAssetActions, useMarketActions }: AccountPageProps) {\n const { walletAddress } = useMedialaneApp();\n const client = useMedialaneClient();\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 isOwner = !!walletAddress && isSameAddress(address, walletAddress);\n\n const { tokens, total, isLoading: tokensLoading, isLoadingMore, hasMore, loadMore, mutate: refreshTokens } = useOwnedTokens(address);\n const { collections, isLoading: collectionsLoading } = useCollectionsByOwner(address);\n const { orders, isLoading: ordersLoading } = useUserOrders(address);\n const { activities, isLoading: activitiesLoading } = useActivitiesByAddress(activeTab === \"activity\" ? address : null);\n const { data: hidden } = useSWR(`creator-hidden-${address}`, () => 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 counts: Partial<Record<TabId, number | undefined>> = {\n assets: total ?? undefined,\n collections: collectionsLoading ? undefined : collections.length,\n listings: ordersLoading ? undefined : listings.length,\n };\n const tabs = TABS.map(({ key, label }) => ({ key, label: counts[key] === undefined ? label : `${label} (${counts[key]})` }));\n\n return (\n <div className=\"space-y-6 px-4 pt-20 pb-8 sm:px-6 lg:px-8\">\n {hidden === true ? <HiddenContentBanner /> : null}\n\n <PortfolioHeader\n address={address}\n label=\"Account\"\n trailing={\n <div className=\"ml-auto flex shrink-0 items-center gap-2\">\n <span className=\"rounded-full bg-muted px-2.5 py-1 text-xs font-medium text-muted-foreground\">Starknet</span>\n <MoreMenu explorerHref={`${EXPLORER_URL}/contract/${address}`} shareTitle={shortenAddress(address)} onReport={() => setReportOpen(true)} />\n </div>\n }\n />\n\n <PortfolioChipFilter options={tabs} value={activeTab} onChange={(key) => setActiveTab(key as TabId)} showAll={false} />\n\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 account owns appear here.\" />\n ) : (\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 <LoadMoreSentinel hasMore={hasMore} isLoading={isLoadingMore} onLoadMore={loadMore} />\n </>\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 account owns 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 account 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 account'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 ) : null}\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 <ReportDialog open={reportOpen} onOpenChange={setReportOpen} target={{ type: \"CREATOR\", address, name: shortenAddress(address) }} />\n </div>\n );\n}\n"],"mappings":"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","names":["useSWR","ImageIcon"]}
@@ -5,9 +5,8 @@ import useSWR from "swr";
5
5
  import { Activity, Image as ImageIcon, LayoutGrid, ShoppingBag } from "lucide-react";
6
6
  import { LoadMoreSentinel } from "./load-more-sentinel.js";
7
7
  import { Skeleton } from "./skeleton.js";
8
- import { TabsContent } from "./tabs.js";
9
- import { UnderlineTabs } from "./underline-tabs.js";
10
- import { AddressDisplay } from "./address-display.js";
8
+ import { PortfolioHeader } from "./portfolio-header.js";
9
+ import { PortfolioChipFilter } from "./portfolio-chip-filter.js";
11
10
  import { HiddenContentBanner } from "./hidden-content-banner.js";
12
11
  import { TabEmptyState } from "./tab-empty-state.js";
13
12
  import { TokenCard, TokenCardSkeleton } from "./token-card.js";
@@ -28,6 +27,12 @@ import { useOwnedTokens } from "../utils/use-tokens.js";
28
27
  import { useCollectionsByOwner } from "../utils/use-collections.js";
29
28
  import { useUserOrders } from "../utils/use-orders.js";
30
29
  import { useActivitiesByAddress } from "../utils/use-activities.js";
30
+ const TABS = [
31
+ { key: "assets", label: "Assets" },
32
+ { key: "collections", label: "Collections" },
33
+ { key: "listings", label: "Listings" },
34
+ { key: "activity", label: "Activity" }
35
+ ];
31
36
  const GRID = "grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 gap-4";
32
37
  const isNft = (itemType) => itemType === "ERC721" || itemType === "ERC1155";
33
38
  function AccountPage({ address, useAssetActions, useMarketActions }) {
@@ -46,53 +51,50 @@ function AccountPage({ address, useAssetActions, useMarketActions }) {
46
51
  const actions = useAssetActions({ refresh: () => void refreshTokens() });
47
52
  const market = useMarketActions();
48
53
  const listings = orders.filter((o) => o.status === "ACTIVE" && isNft(o.offer.itemType));
49
- const tabs = [
50
- { id: "assets", label: "Assets", icon: ImageIcon, count: total ?? void 0 },
51
- { id: "collections", label: "Collections", icon: LayoutGrid, count: collectionsLoading ? void 0 : collections.length },
52
- { id: "listings", label: "Listings", icon: ShoppingBag, count: ordersLoading ? void 0 : listings.length },
53
- { id: "activity", label: "Activity", icon: Activity }
54
- ];
55
- return /* @__PURE__ */ jsxs("div", { className: "min-h-screen overflow-x-hidden pb-20", children: [
54
+ const counts = {
55
+ assets: total ?? void 0,
56
+ collections: collectionsLoading ? void 0 : collections.length,
57
+ listings: ordersLoading ? void 0 : listings.length
58
+ };
59
+ const tabs = TABS.map(({ key, label }) => ({ key, label: counts[key] === void 0 ? label : `${label} (${counts[key]})` }));
60
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-6 px-4 pt-20 pb-8 sm:px-6 lg:px-8", children: [
56
61
  hidden === true ? /* @__PURE__ */ jsx(HiddenContentBanner, {}) : null,
57
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3 px-6 pt-20 pb-6", children: [
58
- /* @__PURE__ */ jsx(AddressDisplay, { address, chars: 6, className: "min-w-0 text-2xl font-black tracking-tight tabular-nums sm:text-3xl" }),
59
- /* @__PURE__ */ jsx("span", { className: "shrink-0 rounded-full bg-muted px-2.5 py-1 text-xs font-medium text-muted-foreground", children: "Starknet" })
60
- ] }),
61
- /* @__PURE__ */ jsxs(
62
- UnderlineTabs,
62
+ /* @__PURE__ */ jsx(
63
+ PortfolioHeader,
63
64
  {
64
- tabs,
65
- value: activeTab,
66
- onValueChange: (id) => setActiveTab(id),
67
- trailing: /* @__PURE__ */ jsx(MoreMenu, { explorerHref: `${EXPLORER_URL}/contract/${address}`, shareTitle: shortenAddress(address), onReport: () => setReportOpen(true) }),
68
- children: [
69
- /* @__PURE__ */ jsx(TabsContent, { value: "assets", className: "mt-6 px-6", children: tokensLoading ? /* @__PURE__ */ jsx("div", { className: GRID, children: Array.from({ length: 8 }).map((_, i) => /* @__PURE__ */ jsx(TokenCardSkeleton, {}, i)) }) : tokens.length === 0 ? /* @__PURE__ */ jsx(TabEmptyState, { icon: ImageIcon, heading: "No assets yet", body: "Works this account owns appear here." }) : /* @__PURE__ */ jsxs(Fragment, { children: [
70
- /* @__PURE__ */ jsx("div", { className: GRID, children: tokens.map((t) => {
71
- const listing = t.activeOrders?.find((o) => isNft(o.offer.itemType));
72
- return /* @__PURE__ */ jsx(
73
- TokenCard,
74
- {
75
- token: t,
76
- isOwner,
77
- usdValue: orderUsd(listing?.price, prices),
78
- onList: isOwner ? actions.list : void 0,
79
- onTransfer: isOwner ? actions.transfer : void 0,
80
- onCancel: isOwner ? actions.cancel : void 0,
81
- onBuy: !isOwner && listing ? () => market.buy(listing) : void 0,
82
- onOffer: isOwner ? void 0 : market.offer,
83
- onReport: setReportToken
84
- },
85
- `${t.contractAddress}-${t.tokenId}`
86
- );
87
- }) }),
88
- /* @__PURE__ */ jsx(LoadMoreSentinel, { hasMore, isLoading: isLoadingMore, onLoadMore: loadMore })
89
- ] }) }),
90
- /* @__PURE__ */ jsx(TabsContent, { value: "collections", className: "mt-6 px-6", children: collectionsLoading ? /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 gap-4 lg:grid-cols-3", children: Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ jsx(CollectionCardSkeleton, {}, i)) }) : collections.length === 0 ? /* @__PURE__ */ jsx(TabEmptyState, { icon: LayoutGrid, heading: "No collections yet", body: "Collections this account owns appear here." }) : /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 gap-4 lg:grid-cols-3", children: collections.map((c) => /* @__PURE__ */ jsx(CollectionCard, { collection: c }, c.contractAddress)) }) }),
91
- /* @__PURE__ */ jsx(TabsContent, { value: "listings", className: "mt-6 px-6", children: ordersLoading ? /* @__PURE__ */ jsx("div", { className: GRID, children: Array.from({ length: 4 }).map((_, i) => /* @__PURE__ */ jsx(ListingCardSkeleton, {}, i)) }) : listings.length === 0 ? /* @__PURE__ */ jsx(TabEmptyState, { icon: ShoppingBag, heading: "No active listings", body: "Works this account lists for sale appear here." }) : /* @__PURE__ */ jsx("div", { className: GRID, children: listings.map((o) => /* @__PURE__ */ jsx(ListingCard, { order: o, onBuy: isOwner ? void 0 : market.buy, usdValue: orderUsd(o.price, prices), overflowMenu: /* @__PURE__ */ jsx(ListingCardMenu, { order: o }) }, o.orderHash)) }) }),
92
- /* @__PURE__ */ jsx(TabsContent, { value: "activity", className: "mt-6 max-w-2xl px-6", children: activitiesLoading ? /* @__PURE__ */ jsx("div", { className: "space-y-5", children: Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ jsx(Skeleton, { className: "h-10 w-full rounded-xl" }, i)) }) : activities.length === 0 ? /* @__PURE__ */ jsx(TabEmptyState, { icon: Activity, heading: "No activity yet", body: "This account's activity appears here as it happens." }) : /* @__PURE__ */ jsx("div", { children: activities.map((a, i) => /* @__PURE__ */ jsx(ActivityTimelineRow, { event: a, isLast: i === activities.length - 1 }, i)) }) })
93
- ]
65
+ address,
66
+ label: "Account",
67
+ trailing: /* @__PURE__ */ jsxs("div", { className: "ml-auto flex shrink-0 items-center gap-2", children: [
68
+ /* @__PURE__ */ jsx("span", { className: "rounded-full bg-muted px-2.5 py-1 text-xs font-medium text-muted-foreground", children: "Starknet" }),
69
+ /* @__PURE__ */ jsx(MoreMenu, { explorerHref: `${EXPLORER_URL}/contract/${address}`, shareTitle: shortenAddress(address), onReport: () => setReportOpen(true) })
70
+ ] })
94
71
  }
95
72
  ),
73
+ /* @__PURE__ */ jsx(PortfolioChipFilter, { options: tabs, value: activeTab, onChange: (key) => setActiveTab(key), showAll: false }),
74
+ activeTab === "assets" && (tokensLoading ? /* @__PURE__ */ jsx("div", { className: GRID, children: Array.from({ length: 8 }).map((_, i) => /* @__PURE__ */ jsx(TokenCardSkeleton, {}, i)) }) : tokens.length === 0 ? /* @__PURE__ */ jsx(TabEmptyState, { icon: ImageIcon, heading: "No assets yet", body: "Works this account owns appear here." }) : /* @__PURE__ */ jsxs(Fragment, { children: [
75
+ /* @__PURE__ */ jsx("div", { className: GRID, children: tokens.map((t) => {
76
+ const listing = t.activeOrders?.find((o) => isNft(o.offer.itemType));
77
+ return /* @__PURE__ */ jsx(
78
+ TokenCard,
79
+ {
80
+ token: t,
81
+ isOwner,
82
+ usdValue: orderUsd(listing?.price, prices),
83
+ onList: isOwner ? actions.list : void 0,
84
+ onTransfer: isOwner ? actions.transfer : void 0,
85
+ onCancel: isOwner ? actions.cancel : void 0,
86
+ onBuy: !isOwner && listing ? () => market.buy(listing) : void 0,
87
+ onOffer: isOwner ? void 0 : market.offer,
88
+ onReport: setReportToken
89
+ },
90
+ `${t.contractAddress}-${t.tokenId}`
91
+ );
92
+ }) }),
93
+ /* @__PURE__ */ jsx(LoadMoreSentinel, { hasMore, isLoading: isLoadingMore, onLoadMore: loadMore })
94
+ ] })),
95
+ activeTab === "collections" && (collectionsLoading ? /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 gap-4 lg:grid-cols-3", children: Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ jsx(CollectionCardSkeleton, {}, i)) }) : collections.length === 0 ? /* @__PURE__ */ jsx(TabEmptyState, { icon: LayoutGrid, heading: "No collections yet", body: "Collections this account owns appear here." }) : /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 gap-4 lg:grid-cols-3", children: collections.map((c) => /* @__PURE__ */ jsx(CollectionCard, { collection: c }, c.contractAddress)) })),
96
+ activeTab === "listings" && (ordersLoading ? /* @__PURE__ */ jsx("div", { className: GRID, children: Array.from({ length: 4 }).map((_, i) => /* @__PURE__ */ jsx(ListingCardSkeleton, {}, i)) }) : listings.length === 0 ? /* @__PURE__ */ jsx(TabEmptyState, { icon: ShoppingBag, heading: "No active listings", body: "Works this account lists for sale appear here." }) : /* @__PURE__ */ jsx("div", { className: GRID, children: listings.map((o) => /* @__PURE__ */ jsx(ListingCard, { order: o, onBuy: isOwner ? void 0 : market.buy, usdValue: orderUsd(o.price, prices), overflowMenu: /* @__PURE__ */ jsx(ListingCardMenu, { order: o }) }, o.orderHash)) })),
97
+ activeTab === "activity" ? /* @__PURE__ */ jsx("div", { className: "max-w-2xl", children: activitiesLoading ? /* @__PURE__ */ jsx("div", { className: "space-y-5", children: Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ jsx(Skeleton, { className: "h-10 w-full rounded-xl" }, i)) }) : activities.length === 0 ? /* @__PURE__ */ jsx(TabEmptyState, { icon: Activity, heading: "No activity yet", body: "This account's activity appears here as it happens." }) : /* @__PURE__ */ jsx("div", { children: activities.map((a, i) => /* @__PURE__ */ jsx(ActivityTimelineRow, { event: a, isLast: i === activities.length - 1 }, i)) }) }) : null,
96
98
  actions.dialogs,
97
99
  market.dialogs,
98
100
  reportToken ? /* @__PURE__ */ jsx(
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/account-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 { LoadMoreSentinel } from \"./load-more-sentinel.js\";\nimport { Skeleton } from \"./skeleton.js\";\nimport { TabsContent } from \"./tabs.js\";\nimport { UnderlineTabs, type UnderlineTab } from \"./underline-tabs.js\";\nimport { AddressDisplay } from \"./address-display.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 { shortenAddress } from \"../utils/address.js\";\nimport { EXPLORER_URL } from \"../utils/explorer-url.js\";\nimport { isSameAddress } from \"../utils/same-address.js\";\nimport { orderUsd } from \"../utils/order-usd.js\";\nimport { useMedialaneClient } from \"../utils/use-medialane-client.js\";\nimport { useUsdPrices } from \"../utils/use-usd-prices.js\";\nimport { useOwnedTokens } 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\";\n\ntype TabId = \"assets\" | \"collections\" | \"listings\" | \"activity\";\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 AccountPageProps {\n address: string;\n useAssetActions: UsePortfolioAssetActions;\n useMarketActions: () => CollectionMarketActions;\n}\n\nexport function AccountPage({ address, useAssetActions, useMarketActions }: AccountPageProps) {\n const { walletAddress } = useMedialaneApp();\n const client = useMedialaneClient();\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 isOwner = !!walletAddress && isSameAddress(address, walletAddress);\n\n const { tokens, total, isLoading: tokensLoading, isLoadingMore, hasMore, loadMore, mutate: refreshTokens } = useOwnedTokens(address);\n const { collections, isLoading: collectionsLoading } = useCollectionsByOwner(address);\n const { orders, isLoading: ordersLoading } = useUserOrders(address);\n const { activities, isLoading: activitiesLoading } = useActivitiesByAddress(activeTab === \"activity\" ? address : null);\n const { data: hidden } = useSWR(`creator-hidden-${address}`, () => 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 tabs: UnderlineTab[] = [\n { id: \"assets\", label: \"Assets\", icon: ImageIcon, count: total ?? undefined },\n { id: \"collections\", label: \"Collections\", icon: LayoutGrid, count: collectionsLoading ? undefined : collections.length },\n { id: \"listings\", label: \"Listings\", icon: ShoppingBag, count: ordersLoading ? undefined : listings.length },\n { id: \"activity\", label: \"Activity\", icon: Activity },\n ];\n\n return (\n <div className=\"min-h-screen overflow-x-hidden pb-20\">\n {hidden === true ? <HiddenContentBanner /> : null}\n\n <div className=\"flex items-center justify-between gap-3 px-6 pt-20 pb-6\">\n <AddressDisplay address={address} chars={6} className=\"min-w-0 text-2xl font-black tracking-tight tabular-nums sm:text-3xl\" />\n <span className=\"shrink-0 rounded-full bg-muted px-2.5 py-1 text-xs font-medium text-muted-foreground\">Starknet</span>\n </div>\n\n <UnderlineTabs\n tabs={tabs}\n value={activeTab}\n onValueChange={(id) => setActiveTab(id as TabId)}\n trailing={<MoreMenu explorerHref={`${EXPLORER_URL}/contract/${address}`} shareTitle={shortenAddress(address)} onReport={() => setReportOpen(true)} />}\n >\n <TabsContent value=\"assets\" className=\"mt-6 px-6\">\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 account owns appear here.\" />\n ) : (\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 <LoadMoreSentinel hasMore={hasMore} isLoading={isLoadingMore} onLoadMore={loadMore} />\n </>\n )}\n </TabsContent>\n\n <TabsContent value=\"collections\" className=\"mt-6 px-6\">\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 account owns 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 </TabsContent>\n\n <TabsContent value=\"listings\" className=\"mt-6 px-6\">\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 account 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 </TabsContent>\n\n <TabsContent value=\"activity\" className=\"mt-6 max-w-2xl px-6\">\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 account'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 </TabsContent>\n </UnderlineTabs>\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 <ReportDialog open={reportOpen} onOpenChange={setReportOpen} target={{ type: \"CREATOR\", address, name: shortenAddress(address) }} />\n </div>\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/components/account-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 { LoadMoreSentinel } from \"./load-more-sentinel.js\";\nimport { Skeleton } from \"./skeleton.js\";\nimport { PortfolioHeader } from \"./portfolio-header.js\";\nimport { PortfolioChipFilter } from \"./portfolio-chip-filter.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 { shortenAddress } from \"../utils/address.js\";\nimport { EXPLORER_URL } from \"../utils/explorer-url.js\";\nimport { isSameAddress } from \"../utils/same-address.js\";\nimport { orderUsd } from \"../utils/order-usd.js\";\nimport { useMedialaneClient } from \"../utils/use-medialane-client.js\";\nimport { useUsdPrices } from \"../utils/use-usd-prices.js\";\nimport { useOwnedTokens } 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\";\n\ntype TabId = \"assets\" | \"collections\" | \"listings\" | \"activity\";\n\nconst TABS: { key: TabId; label: string }[] = [\n { key: \"assets\", label: \"Assets\" },\n { key: \"collections\", label: \"Collections\" },\n { key: \"listings\", label: \"Listings\" },\n { key: \"activity\", label: \"Activity\" },\n];\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 AccountPageProps {\n address: string;\n useAssetActions: UsePortfolioAssetActions;\n useMarketActions: () => CollectionMarketActions;\n}\n\nexport function AccountPage({ address, useAssetActions, useMarketActions }: AccountPageProps) {\n const { walletAddress } = useMedialaneApp();\n const client = useMedialaneClient();\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 isOwner = !!walletAddress && isSameAddress(address, walletAddress);\n\n const { tokens, total, isLoading: tokensLoading, isLoadingMore, hasMore, loadMore, mutate: refreshTokens } = useOwnedTokens(address);\n const { collections, isLoading: collectionsLoading } = useCollectionsByOwner(address);\n const { orders, isLoading: ordersLoading } = useUserOrders(address);\n const { activities, isLoading: activitiesLoading } = useActivitiesByAddress(activeTab === \"activity\" ? address : null);\n const { data: hidden } = useSWR(`creator-hidden-${address}`, () => 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 counts: Partial<Record<TabId, number | undefined>> = {\n assets: total ?? undefined,\n collections: collectionsLoading ? undefined : collections.length,\n listings: ordersLoading ? undefined : listings.length,\n };\n const tabs = TABS.map(({ key, label }) => ({ key, label: counts[key] === undefined ? label : `${label} (${counts[key]})` }));\n\n return (\n <div className=\"space-y-6 px-4 pt-20 pb-8 sm:px-6 lg:px-8\">\n {hidden === true ? <HiddenContentBanner /> : null}\n\n <PortfolioHeader\n address={address}\n label=\"Account\"\n trailing={\n <div className=\"ml-auto flex shrink-0 items-center gap-2\">\n <span className=\"rounded-full bg-muted px-2.5 py-1 text-xs font-medium text-muted-foreground\">Starknet</span>\n <MoreMenu explorerHref={`${EXPLORER_URL}/contract/${address}`} shareTitle={shortenAddress(address)} onReport={() => setReportOpen(true)} />\n </div>\n }\n />\n\n <PortfolioChipFilter options={tabs} value={activeTab} onChange={(key) => setActiveTab(key as TabId)} showAll={false} />\n\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 account owns appear here.\" />\n ) : (\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 <LoadMoreSentinel hasMore={hasMore} isLoading={isLoadingMore} onLoadMore={loadMore} />\n </>\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 account owns 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 account 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 account'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 ) : null}\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 <ReportDialog open={reportOpen} onOpenChange={setReportOpen} target={{ type: \"CREATOR\", address, name: shortenAddress(address) }} />\n </div>\n );\n}\n"],"mappings":"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","names":[]}
@@ -65,7 +65,7 @@ function ApproveMintDialog({ offer, open, onOpenChange, collections, footerNote,
65
65
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.GitBranch, { className: "h-4 w-4 text-primary shrink-0" }),
66
66
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dialog.DialogTitle, { className: "text-base font-bold", children: "Grant license & mint" })
67
67
  ] }),
68
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dialog.DialogDescription, { className: "sr-only", children: "Mint the derivative into one of your collections and list it for the requester." }),
68
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dialog.DialogDescription, { className: "sr-only", children: "Mint the derivative into one of your collections and sell it to the requester." }),
69
69
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
70
70
  import_transaction_dialog_states.TransactionDialogStates,
71
71
  {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/approve-mint-dialog.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { AlertCircle, GitBranch, Loader2 } from \"lucide-react\";\nimport type { ApiCollection, ApiRemixOffer } from \"@medialane/sdk\";\nimport { Dialog, DialogContent, DialogDescription, DialogTitle } from \"./dialog.js\";\nimport { Input } from \"./input.js\";\nimport { Label } from \"./label.js\";\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from \"./select.js\";\nimport { Alert, AlertDescription } from \"./alert.js\";\nimport { TransactionDialogStates } from \"./transaction-dialog-states.js\";\nimport { isBusyPhase, type TransactionPhase } from \"../utils/use-transaction.js\";\nimport { formatDisplayPrice } from \"../utils/format.js\";\nimport { successMessages } from \"../utils/success-messages.js\";\n\nexport interface ApproveMintDialogProps {\n offer: ApiRemixOffer | null;\n open: boolean;\n onOpenChange: (open: boolean) => void;\n collections: ApiCollection[];\n footerNote: string;\n newAssetHref?: string | null;\n tx: {\n phase: TransactionPhase;\n txHash: string | null;\n error: string | null;\n retryable?: boolean;\n reset: () => void;\n };\n onApprove: (collection: ApiCollection, name: string) => void;\n}\n\nconst keyOf = (c: ApiCollection) => c.collectionId ?? c.contractAddress;\n\nexport function ApproveMintDialog({ offer, open, onOpenChange, collections, footerNote, newAssetHref, tx, onApprove }: ApproveMintDialogProps) {\n const { phase, txHash, error, retryable = true, reset } = tx;\n const busy = isBusyPhase(phase);\n const [selectedKey, setSelectedKey] = useState<string | null>(null);\n const [remixName, setRemixName] = useState(\"\");\n\n const defaultCollection = collections.find((c) => c.contractAddress === offer?.originalContract) ?? collections[0];\n const effectiveKey = selectedKey ?? (defaultCollection ? keyOf(defaultCollection) : null);\n const selected = collections.find((c) => keyOf(c) === effectiveKey);\n const effectiveName = remixName.trim() || `Remix of Token #${offer?.originalTokenId}`;\n const priceDisplay = offer?.price ? `${formatDisplayPrice(offer.price.formatted)} ${offer.price.currency}` : \"—\";\n\n const clear = () => {\n setSelectedKey(null);\n setRemixName(\"\");\n reset();\n };\n\n useEffect(() => {\n if (open) clear();\n }, [open]);\n\n const close = () => {\n clear();\n onOpenChange(false);\n };\n\n const handleOpenChange = (value: boolean) => {\n if (!value && !busy) close();\n };\n\n return (\n <Dialog open={open} onOpenChange={handleOpenChange}>\n <DialogContent className=\"w-full max-w-sm p-0 overflow-hidden gap-0 flex flex-col max-h-[90svh]\">\n <div className=\"flex items-center gap-2 pr-10 pl-5 py-4 border-b border-border/60\">\n <GitBranch className=\"h-4 w-4 text-primary shrink-0\" />\n <DialogTitle className=\"text-base font-bold\">Grant license &amp; mint</DialogTitle>\n </div>\n <DialogDescription className=\"sr-only\">Mint the derivative into one of your collections and list it for the requester.</DialogDescription>\n\n <TransactionDialogStates\n phase={phase}\n asset={{ name: effectiveName }}\n statusMessage=\"Minting and listing…\"\n txHash={txHash}\n error={error}\n success={successMessages.licenseGranted({ price: priceDisplay })}\n successActions={[\n { label: \"Done\", onClick: close },\n ...(newAssetHref ? [{ label: \"View new asset\", href: newAssetHref }] : []),\n ]}\n errorTitle=\"Minting failed\"\n errorDescription=\"The transaction was submitted, but the remix could not be completed.\"\n onRetry={retryable ? reset : undefined}\n onDone={close}\n >\n <div className=\"flex-1 overflow-y-auto px-5 py-4 space-y-5\">\n {error && (\n <Alert variant=\"destructive\">\n <AlertCircle className=\"h-4 w-4\" />\n <AlertDescription>{error}</AlertDescription>\n </Alert>\n )}\n {offer && (\n <div className=\"rounded-xl border border-border bg-muted/30 p-3 text-sm space-y-1\">\n <p><span className=\"text-muted-foreground\">License</span> {offer.licenseType}</p>\n <p><span className=\"text-muted-foreground\">Price</span> {priceDisplay}</p>\n {offer.message && <p className=\"text-muted-foreground italic\">&quot;{offer.message}&quot;</p>}\n </div>\n )}\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"remix-name\">Remix Name</Label>\n <Input id=\"remix-name\" placeholder={effectiveName} value={remixName} onChange={(e) => setRemixName(e.target.value)} />\n </div>\n\n <div className=\"space-y-1.5\">\n <Label>Mint into collection</Label>\n {collections.length === 0 ? (\n <p className=\"text-xs text-destructive\">No eligible collections.</p>\n ) : (\n <Select value={effectiveKey ?? \"\"} onValueChange={setSelectedKey}>\n <SelectTrigger>\n <SelectValue placeholder=\"Select collection\" />\n </SelectTrigger>\n <SelectContent>\n {collections.map((c) => (\n <SelectItem key={keyOf(c)} value={keyOf(c)}>\n <span className=\"flex items-center gap-2\">\n {c.name ?? `${c.contractAddress.slice(0, 14)}…`}\n {c.standard && <span className=\"text-2xs tabular-nums text-muted-foreground\">{c.standard}</span>}\n </span>\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n )}\n </div>\n </div>\n\n <div className=\"px-5 pt-3 pb-5 border-t border-border/60 space-y-3\">\n <button\n className=\"w-full h-11 rounded-[11px] bg-brand-purple text-white text-sm font-semibold flex items-center justify-center gap-2 hover:brightness-110 active:scale-[0.98] transition-all disabled:opacity-50\"\n onClick={() => { if (selected) onApprove(selected, effectiveName); }}\n disabled={busy || !selected}\n >\n {busy ? <Loader2 className=\"h-4 w-4 animate-spin\" /> : <GitBranch className=\"h-4 w-4\" />}\n Grant license &amp; mint\n </button>\n <p className=\"text-2xs text-center text-muted-foreground\">{footerNote}</p>\n </div>\n </TransactionDialogStates>\n </DialogContent>\n </Dialog>\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/components/approve-mint-dialog.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { AlertCircle, GitBranch, Loader2 } from \"lucide-react\";\nimport type { ApiCollection, ApiRemixOffer } from \"@medialane/sdk\";\nimport { Dialog, DialogContent, DialogDescription, DialogTitle } from \"./dialog.js\";\nimport { Input } from \"./input.js\";\nimport { Label } from \"./label.js\";\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from \"./select.js\";\nimport { Alert, AlertDescription } from \"./alert.js\";\nimport { TransactionDialogStates } from \"./transaction-dialog-states.js\";\nimport { isBusyPhase, type TransactionPhase } from \"../utils/use-transaction.js\";\nimport { formatDisplayPrice } from \"../utils/format.js\";\nimport { successMessages } from \"../utils/success-messages.js\";\n\nexport interface ApproveMintDialogProps {\n offer: ApiRemixOffer | null;\n open: boolean;\n onOpenChange: (open: boolean) => void;\n collections: ApiCollection[];\n footerNote: string;\n newAssetHref?: string | null;\n tx: {\n phase: TransactionPhase;\n txHash: string | null;\n error: string | null;\n retryable?: boolean;\n reset: () => void;\n };\n onApprove: (collection: ApiCollection, name: string) => void;\n}\n\nconst keyOf = (c: ApiCollection) => c.collectionId ?? c.contractAddress;\n\nexport function ApproveMintDialog({ offer, open, onOpenChange, collections, footerNote, newAssetHref, tx, onApprove }: ApproveMintDialogProps) {\n const { phase, txHash, error, retryable = true, reset } = tx;\n const busy = isBusyPhase(phase);\n const [selectedKey, setSelectedKey] = useState<string | null>(null);\n const [remixName, setRemixName] = useState(\"\");\n\n const defaultCollection = collections.find((c) => c.contractAddress === offer?.originalContract) ?? collections[0];\n const effectiveKey = selectedKey ?? (defaultCollection ? keyOf(defaultCollection) : null);\n const selected = collections.find((c) => keyOf(c) === effectiveKey);\n const effectiveName = remixName.trim() || `Remix of Token #${offer?.originalTokenId}`;\n const priceDisplay = offer?.price ? `${formatDisplayPrice(offer.price.formatted)} ${offer.price.currency}` : \"—\";\n\n const clear = () => {\n setSelectedKey(null);\n setRemixName(\"\");\n reset();\n };\n\n useEffect(() => {\n if (open) clear();\n }, [open]);\n\n const close = () => {\n clear();\n onOpenChange(false);\n };\n\n const handleOpenChange = (value: boolean) => {\n if (!value && !busy) close();\n };\n\n return (\n <Dialog open={open} onOpenChange={handleOpenChange}>\n <DialogContent className=\"w-full max-w-sm p-0 overflow-hidden gap-0 flex flex-col max-h-[90svh]\">\n <div className=\"flex items-center gap-2 pr-10 pl-5 py-4 border-b border-border/60\">\n <GitBranch className=\"h-4 w-4 text-primary shrink-0\" />\n <DialogTitle className=\"text-base font-bold\">Grant license &amp; mint</DialogTitle>\n </div>\n <DialogDescription className=\"sr-only\">Mint the derivative into one of your collections and sell it to the requester.</DialogDescription>\n\n <TransactionDialogStates\n phase={phase}\n asset={{ name: effectiveName }}\n statusMessage=\"Minting and listing…\"\n txHash={txHash}\n error={error}\n success={successMessages.licenseGranted({ price: priceDisplay })}\n successActions={[\n { label: \"Done\", onClick: close },\n ...(newAssetHref ? [{ label: \"View new asset\", href: newAssetHref }] : []),\n ]}\n errorTitle=\"Minting failed\"\n errorDescription=\"The transaction was submitted, but the remix could not be completed.\"\n onRetry={retryable ? reset : undefined}\n onDone={close}\n >\n <div className=\"flex-1 overflow-y-auto px-5 py-4 space-y-5\">\n {error && (\n <Alert variant=\"destructive\">\n <AlertCircle className=\"h-4 w-4\" />\n <AlertDescription>{error}</AlertDescription>\n </Alert>\n )}\n {offer && (\n <div className=\"rounded-xl border border-border bg-muted/30 p-3 text-sm space-y-1\">\n <p><span className=\"text-muted-foreground\">License</span> {offer.licenseType}</p>\n <p><span className=\"text-muted-foreground\">Price</span> {priceDisplay}</p>\n {offer.message && <p className=\"text-muted-foreground italic\">&quot;{offer.message}&quot;</p>}\n </div>\n )}\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"remix-name\">Remix Name</Label>\n <Input id=\"remix-name\" placeholder={effectiveName} value={remixName} onChange={(e) => setRemixName(e.target.value)} />\n </div>\n\n <div className=\"space-y-1.5\">\n <Label>Mint into collection</Label>\n {collections.length === 0 ? (\n <p className=\"text-xs text-destructive\">No eligible collections.</p>\n ) : (\n <Select value={effectiveKey ?? \"\"} onValueChange={setSelectedKey}>\n <SelectTrigger>\n <SelectValue placeholder=\"Select collection\" />\n </SelectTrigger>\n <SelectContent>\n {collections.map((c) => (\n <SelectItem key={keyOf(c)} value={keyOf(c)}>\n <span className=\"flex items-center gap-2\">\n {c.name ?? `${c.contractAddress.slice(0, 14)}…`}\n {c.standard && <span className=\"text-2xs tabular-nums text-muted-foreground\">{c.standard}</span>}\n </span>\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n )}\n </div>\n </div>\n\n <div className=\"px-5 pt-3 pb-5 border-t border-border/60 space-y-3\">\n <button\n className=\"w-full h-11 rounded-[11px] bg-brand-purple text-white text-sm font-semibold flex items-center justify-center gap-2 hover:brightness-110 active:scale-[0.98] transition-all disabled:opacity-50\"\n onClick={() => { if (selected) onApprove(selected, effectiveName); }}\n disabled={busy || !selected}\n >\n {busy ? <Loader2 className=\"h-4 w-4 animate-spin\" /> : <GitBranch className=\"h-4 w-4\" />}\n Grant license &amp; mint\n </button>\n <p className=\"text-2xs text-center text-muted-foreground\">{footerNote}</p>\n </div>\n </TransactionDialogStates>\n </DialogContent>\n </Dialog>\n );\n}\n"],"mappings":"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","names":[]}
@@ -42,7 +42,7 @@ function ApproveMintDialog({ offer, open, onOpenChange, collections, footerNote,
42
42
  /* @__PURE__ */ jsx(GitBranch, { className: "h-4 w-4 text-primary shrink-0" }),
43
43
  /* @__PURE__ */ jsx(DialogTitle, { className: "text-base font-bold", children: "Grant license & mint" })
44
44
  ] }),
45
- /* @__PURE__ */ jsx(DialogDescription, { className: "sr-only", children: "Mint the derivative into one of your collections and list it for the requester." }),
45
+ /* @__PURE__ */ jsx(DialogDescription, { className: "sr-only", children: "Mint the derivative into one of your collections and sell it to the requester." }),
46
46
  /* @__PURE__ */ jsxs(
47
47
  TransactionDialogStates,
48
48
  {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/approve-mint-dialog.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { AlertCircle, GitBranch, Loader2 } from \"lucide-react\";\nimport type { ApiCollection, ApiRemixOffer } from \"@medialane/sdk\";\nimport { Dialog, DialogContent, DialogDescription, DialogTitle } from \"./dialog.js\";\nimport { Input } from \"./input.js\";\nimport { Label } from \"./label.js\";\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from \"./select.js\";\nimport { Alert, AlertDescription } from \"./alert.js\";\nimport { TransactionDialogStates } from \"./transaction-dialog-states.js\";\nimport { isBusyPhase, type TransactionPhase } from \"../utils/use-transaction.js\";\nimport { formatDisplayPrice } from \"../utils/format.js\";\nimport { successMessages } from \"../utils/success-messages.js\";\n\nexport interface ApproveMintDialogProps {\n offer: ApiRemixOffer | null;\n open: boolean;\n onOpenChange: (open: boolean) => void;\n collections: ApiCollection[];\n footerNote: string;\n newAssetHref?: string | null;\n tx: {\n phase: TransactionPhase;\n txHash: string | null;\n error: string | null;\n retryable?: boolean;\n reset: () => void;\n };\n onApprove: (collection: ApiCollection, name: string) => void;\n}\n\nconst keyOf = (c: ApiCollection) => c.collectionId ?? c.contractAddress;\n\nexport function ApproveMintDialog({ offer, open, onOpenChange, collections, footerNote, newAssetHref, tx, onApprove }: ApproveMintDialogProps) {\n const { phase, txHash, error, retryable = true, reset } = tx;\n const busy = isBusyPhase(phase);\n const [selectedKey, setSelectedKey] = useState<string | null>(null);\n const [remixName, setRemixName] = useState(\"\");\n\n const defaultCollection = collections.find((c) => c.contractAddress === offer?.originalContract) ?? collections[0];\n const effectiveKey = selectedKey ?? (defaultCollection ? keyOf(defaultCollection) : null);\n const selected = collections.find((c) => keyOf(c) === effectiveKey);\n const effectiveName = remixName.trim() || `Remix of Token #${offer?.originalTokenId}`;\n const priceDisplay = offer?.price ? `${formatDisplayPrice(offer.price.formatted)} ${offer.price.currency}` : \"—\";\n\n const clear = () => {\n setSelectedKey(null);\n setRemixName(\"\");\n reset();\n };\n\n useEffect(() => {\n if (open) clear();\n }, [open]);\n\n const close = () => {\n clear();\n onOpenChange(false);\n };\n\n const handleOpenChange = (value: boolean) => {\n if (!value && !busy) close();\n };\n\n return (\n <Dialog open={open} onOpenChange={handleOpenChange}>\n <DialogContent className=\"w-full max-w-sm p-0 overflow-hidden gap-0 flex flex-col max-h-[90svh]\">\n <div className=\"flex items-center gap-2 pr-10 pl-5 py-4 border-b border-border/60\">\n <GitBranch className=\"h-4 w-4 text-primary shrink-0\" />\n <DialogTitle className=\"text-base font-bold\">Grant license &amp; mint</DialogTitle>\n </div>\n <DialogDescription className=\"sr-only\">Mint the derivative into one of your collections and list it for the requester.</DialogDescription>\n\n <TransactionDialogStates\n phase={phase}\n asset={{ name: effectiveName }}\n statusMessage=\"Minting and listing…\"\n txHash={txHash}\n error={error}\n success={successMessages.licenseGranted({ price: priceDisplay })}\n successActions={[\n { label: \"Done\", onClick: close },\n ...(newAssetHref ? [{ label: \"View new asset\", href: newAssetHref }] : []),\n ]}\n errorTitle=\"Minting failed\"\n errorDescription=\"The transaction was submitted, but the remix could not be completed.\"\n onRetry={retryable ? reset : undefined}\n onDone={close}\n >\n <div className=\"flex-1 overflow-y-auto px-5 py-4 space-y-5\">\n {error && (\n <Alert variant=\"destructive\">\n <AlertCircle className=\"h-4 w-4\" />\n <AlertDescription>{error}</AlertDescription>\n </Alert>\n )}\n {offer && (\n <div className=\"rounded-xl border border-border bg-muted/30 p-3 text-sm space-y-1\">\n <p><span className=\"text-muted-foreground\">License</span> {offer.licenseType}</p>\n <p><span className=\"text-muted-foreground\">Price</span> {priceDisplay}</p>\n {offer.message && <p className=\"text-muted-foreground italic\">&quot;{offer.message}&quot;</p>}\n </div>\n )}\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"remix-name\">Remix Name</Label>\n <Input id=\"remix-name\" placeholder={effectiveName} value={remixName} onChange={(e) => setRemixName(e.target.value)} />\n </div>\n\n <div className=\"space-y-1.5\">\n <Label>Mint into collection</Label>\n {collections.length === 0 ? (\n <p className=\"text-xs text-destructive\">No eligible collections.</p>\n ) : (\n <Select value={effectiveKey ?? \"\"} onValueChange={setSelectedKey}>\n <SelectTrigger>\n <SelectValue placeholder=\"Select collection\" />\n </SelectTrigger>\n <SelectContent>\n {collections.map((c) => (\n <SelectItem key={keyOf(c)} value={keyOf(c)}>\n <span className=\"flex items-center gap-2\">\n {c.name ?? `${c.contractAddress.slice(0, 14)}…`}\n {c.standard && <span className=\"text-2xs tabular-nums text-muted-foreground\">{c.standard}</span>}\n </span>\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n )}\n </div>\n </div>\n\n <div className=\"px-5 pt-3 pb-5 border-t border-border/60 space-y-3\">\n <button\n className=\"w-full h-11 rounded-[11px] bg-brand-purple text-white text-sm font-semibold flex items-center justify-center gap-2 hover:brightness-110 active:scale-[0.98] transition-all disabled:opacity-50\"\n onClick={() => { if (selected) onApprove(selected, effectiveName); }}\n disabled={busy || !selected}\n >\n {busy ? <Loader2 className=\"h-4 w-4 animate-spin\" /> : <GitBranch className=\"h-4 w-4\" />}\n Grant license &amp; mint\n </button>\n <p className=\"text-2xs text-center text-muted-foreground\">{footerNote}</p>\n </div>\n </TransactionDialogStates>\n </DialogContent>\n </Dialog>\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/components/approve-mint-dialog.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { AlertCircle, GitBranch, Loader2 } from \"lucide-react\";\nimport type { ApiCollection, ApiRemixOffer } from \"@medialane/sdk\";\nimport { Dialog, DialogContent, DialogDescription, DialogTitle } from \"./dialog.js\";\nimport { Input } from \"./input.js\";\nimport { Label } from \"./label.js\";\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from \"./select.js\";\nimport { Alert, AlertDescription } from \"./alert.js\";\nimport { TransactionDialogStates } from \"./transaction-dialog-states.js\";\nimport { isBusyPhase, type TransactionPhase } from \"../utils/use-transaction.js\";\nimport { formatDisplayPrice } from \"../utils/format.js\";\nimport { successMessages } from \"../utils/success-messages.js\";\n\nexport interface ApproveMintDialogProps {\n offer: ApiRemixOffer | null;\n open: boolean;\n onOpenChange: (open: boolean) => void;\n collections: ApiCollection[];\n footerNote: string;\n newAssetHref?: string | null;\n tx: {\n phase: TransactionPhase;\n txHash: string | null;\n error: string | null;\n retryable?: boolean;\n reset: () => void;\n };\n onApprove: (collection: ApiCollection, name: string) => void;\n}\n\nconst keyOf = (c: ApiCollection) => c.collectionId ?? c.contractAddress;\n\nexport function ApproveMintDialog({ offer, open, onOpenChange, collections, footerNote, newAssetHref, tx, onApprove }: ApproveMintDialogProps) {\n const { phase, txHash, error, retryable = true, reset } = tx;\n const busy = isBusyPhase(phase);\n const [selectedKey, setSelectedKey] = useState<string | null>(null);\n const [remixName, setRemixName] = useState(\"\");\n\n const defaultCollection = collections.find((c) => c.contractAddress === offer?.originalContract) ?? collections[0];\n const effectiveKey = selectedKey ?? (defaultCollection ? keyOf(defaultCollection) : null);\n const selected = collections.find((c) => keyOf(c) === effectiveKey);\n const effectiveName = remixName.trim() || `Remix of Token #${offer?.originalTokenId}`;\n const priceDisplay = offer?.price ? `${formatDisplayPrice(offer.price.formatted)} ${offer.price.currency}` : \"—\";\n\n const clear = () => {\n setSelectedKey(null);\n setRemixName(\"\");\n reset();\n };\n\n useEffect(() => {\n if (open) clear();\n }, [open]);\n\n const close = () => {\n clear();\n onOpenChange(false);\n };\n\n const handleOpenChange = (value: boolean) => {\n if (!value && !busy) close();\n };\n\n return (\n <Dialog open={open} onOpenChange={handleOpenChange}>\n <DialogContent className=\"w-full max-w-sm p-0 overflow-hidden gap-0 flex flex-col max-h-[90svh]\">\n <div className=\"flex items-center gap-2 pr-10 pl-5 py-4 border-b border-border/60\">\n <GitBranch className=\"h-4 w-4 text-primary shrink-0\" />\n <DialogTitle className=\"text-base font-bold\">Grant license &amp; mint</DialogTitle>\n </div>\n <DialogDescription className=\"sr-only\">Mint the derivative into one of your collections and sell it to the requester.</DialogDescription>\n\n <TransactionDialogStates\n phase={phase}\n asset={{ name: effectiveName }}\n statusMessage=\"Minting and listing…\"\n txHash={txHash}\n error={error}\n success={successMessages.licenseGranted({ price: priceDisplay })}\n successActions={[\n { label: \"Done\", onClick: close },\n ...(newAssetHref ? [{ label: \"View new asset\", href: newAssetHref }] : []),\n ]}\n errorTitle=\"Minting failed\"\n errorDescription=\"The transaction was submitted, but the remix could not be completed.\"\n onRetry={retryable ? reset : undefined}\n onDone={close}\n >\n <div className=\"flex-1 overflow-y-auto px-5 py-4 space-y-5\">\n {error && (\n <Alert variant=\"destructive\">\n <AlertCircle className=\"h-4 w-4\" />\n <AlertDescription>{error}</AlertDescription>\n </Alert>\n )}\n {offer && (\n <div className=\"rounded-xl border border-border bg-muted/30 p-3 text-sm space-y-1\">\n <p><span className=\"text-muted-foreground\">License</span> {offer.licenseType}</p>\n <p><span className=\"text-muted-foreground\">Price</span> {priceDisplay}</p>\n {offer.message && <p className=\"text-muted-foreground italic\">&quot;{offer.message}&quot;</p>}\n </div>\n )}\n\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"remix-name\">Remix Name</Label>\n <Input id=\"remix-name\" placeholder={effectiveName} value={remixName} onChange={(e) => setRemixName(e.target.value)} />\n </div>\n\n <div className=\"space-y-1.5\">\n <Label>Mint into collection</Label>\n {collections.length === 0 ? (\n <p className=\"text-xs text-destructive\">No eligible collections.</p>\n ) : (\n <Select value={effectiveKey ?? \"\"} onValueChange={setSelectedKey}>\n <SelectTrigger>\n <SelectValue placeholder=\"Select collection\" />\n </SelectTrigger>\n <SelectContent>\n {collections.map((c) => (\n <SelectItem key={keyOf(c)} value={keyOf(c)}>\n <span className=\"flex items-center gap-2\">\n {c.name ?? `${c.contractAddress.slice(0, 14)}…`}\n {c.standard && <span className=\"text-2xs tabular-nums text-muted-foreground\">{c.standard}</span>}\n </span>\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n )}\n </div>\n </div>\n\n <div className=\"px-5 pt-3 pb-5 border-t border-border/60 space-y-3\">\n <button\n className=\"w-full h-11 rounded-[11px] bg-brand-purple text-white text-sm font-semibold flex items-center justify-center gap-2 hover:brightness-110 active:scale-[0.98] transition-all disabled:opacity-50\"\n onClick={() => { if (selected) onApprove(selected, effectiveName); }}\n disabled={busy || !selected}\n >\n {busy ? <Loader2 className=\"h-4 w-4 animate-spin\" /> : <GitBranch className=\"h-4 w-4\" />}\n Grant license &amp; mint\n </button>\n <p className=\"text-2xs text-center text-muted-foreground\">{footerNote}</p>\n </div>\n </TransactionDialogStates>\n </DialogContent>\n </Dialog>\n );\n}\n"],"mappings":"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","names":[]}
@@ -128,7 +128,7 @@ function AssetMarketplacePanel({
128
128
  ]
129
129
  }
130
130
  ) : null,
131
- !liveMyListing || isERC1155 && canListMoreEditions !== false ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_action_button.ActionButton, { tone: "blue", icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Tag, { className: "h-4 w-4" }), onClick: onOpenListing, children: liveMyListing ? "List more" : "List for sale" }) : null,
131
+ !liveMyListing || isERC1155 && canListMoreEditions !== false ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_action_button.ActionButton, { tone: "blue", icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Tag, { className: "h-4 w-4" }), onClick: onOpenListing, children: liveMyListing ? "Sell more" : "Sell" }) : null,
132
132
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_action_button.ActionButton, { tone: "orange", icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.ArrowRightLeft, { className: "h-4 w-4" }), onClick: onOpenTransfer, children: "Transfer" }),
133
133
  remixButton,
134
134
  showSponsorSolicitOption && onOpenSponsorSolicit ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(