@medialane/ui 0.304.0 → 0.305.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 (47) hide show
  1. package/dist/components/account-page.cjs +151 -0
  2. package/dist/components/account-page.cjs.map +1 -0
  3. package/dist/components/account-page.d.cts +15 -0
  4. package/dist/components/account-page.d.ts +15 -0
  5. package/dist/components/account-page.js +117 -0
  6. package/dist/components/account-page.js.map +1 -0
  7. package/dist/components/button.d.cts +1 -1
  8. package/dist/components/button.d.ts +1 -1
  9. package/dist/components/creator-page.cjs +47 -68
  10. package/dist/components/creator-page.cjs.map +1 -1
  11. package/dist/components/creator-page.d.cts +2 -3
  12. package/dist/components/creator-page.d.ts +2 -3
  13. package/dist/components/creator-page.js +48 -69
  14. package/dist/components/creator-page.js.map +1 -1
  15. package/dist/components/fast-mint/fast-mint.d.cts +2 -2
  16. package/dist/components/fast-mint/fast-mint.d.ts +2 -2
  17. package/dist/components/launchpad/edition-mint-schema.d.cts +2 -2
  18. package/dist/components/launchpad/edition-mint-schema.d.ts +2 -2
  19. package/dist/components/sheet.d.cts +1 -1
  20. package/dist/components/sheet.d.ts +1 -1
  21. package/dist/components/underline-tabs.cjs +62 -0
  22. package/dist/components/underline-tabs.cjs.map +1 -0
  23. package/dist/components/underline-tabs.d.cts +20 -0
  24. package/dist/components/underline-tabs.d.ts +20 -0
  25. package/dist/components/underline-tabs.js +28 -0
  26. package/dist/components/underline-tabs.js.map +1 -0
  27. package/dist/index.cjs +8 -0
  28. package/dist/index.cjs.map +1 -1
  29. package/dist/index.d.cts +4 -1
  30. package/dist/index.d.ts +4 -1
  31. package/dist/index.js +6 -1
  32. package/dist/index.js.map +1 -1
  33. package/dist/utils/media-wallet/use-erc20-balance.d.cts +1 -1
  34. package/dist/utils/media-wallet/use-erc20-balance.d.ts +1 -1
  35. package/dist/utils/query-keys.cjs +1 -0
  36. package/dist/utils/query-keys.cjs.map +1 -1
  37. package/dist/utils/query-keys.d.cts +1 -0
  38. package/dist/utils/query-keys.d.ts +1 -0
  39. package/dist/utils/query-keys.js +1 -0
  40. package/dist/utils/query-keys.js.map +1 -1
  41. package/dist/utils/use-tokens.cjs +23 -0
  42. package/dist/utils/use-tokens.cjs.map +1 -1
  43. package/dist/utils/use-tokens.d.cts +180 -1
  44. package/dist/utils/use-tokens.d.ts +180 -1
  45. package/dist/utils/use-tokens.js +23 -1
  46. package/dist/utils/use-tokens.js.map +1 -1
  47. package/package.json +1 -1
@@ -0,0 +1,151 @@
1
+ "use strict";
2
+ "use client";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(to, key) && key !== except)
17
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
+ }
19
+ return to;
20
+ };
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
26
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
+ mod
28
+ ));
29
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
+ var account_page_exports = {};
31
+ __export(account_page_exports, {
32
+ AccountPage: () => AccountPage
33
+ });
34
+ module.exports = __toCommonJS(account_page_exports);
35
+ var import_jsx_runtime = require("react/jsx-runtime");
36
+ var import_react = require("react");
37
+ var import_swr = __toESM(require("swr"), 1);
38
+ var import_lucide_react = require("lucide-react");
39
+ var import_load_more_sentinel = require("./load-more-sentinel.js");
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");
44
+ var import_hidden_content_banner = require("./hidden-content-banner.js");
45
+ var import_tab_empty_state = require("./tab-empty-state.js");
46
+ var import_token_card = require("./token-card.js");
47
+ var import_collection_card = require("./collection-card.js");
48
+ var import_listing_card = require("./listing-card.js");
49
+ var import_listing_card_menu = require("./listing-card-menu.js");
50
+ var import_activity_timeline_row = require("./activity-timeline-row.js");
51
+ var import_more_menu = require("./more-menu.js");
52
+ var import_medialane_app = require("./medialane-app.js");
53
+ var import_report_dialog = require("./report-dialog.js");
54
+ var import_address = require("../utils/address.js");
55
+ var import_explorer_url = require("../utils/explorer-url.js");
56
+ var import_same_address = require("../utils/same-address.js");
57
+ var import_order_usd = require("../utils/order-usd.js");
58
+ var import_use_medialane_client = require("../utils/use-medialane-client.js");
59
+ var import_use_usd_prices = require("../utils/use-usd-prices.js");
60
+ var import_use_tokens = require("../utils/use-tokens.js");
61
+ var import_use_collections = require("../utils/use-collections.js");
62
+ var import_use_orders = require("../utils/use-orders.js");
63
+ var import_use_activities = require("../utils/use-activities.js");
64
+ const GRID = "grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 gap-4";
65
+ const isNft = (itemType) => itemType === "ERC721" || itemType === "ERC1155";
66
+ function AccountPage({ address, useAssetActions, useMarketActions }) {
67
+ const { walletAddress } = (0, import_medialane_app.useMedialaneApp)();
68
+ const client = (0, import_use_medialane_client.useMedialaneClient)();
69
+ const prices = (0, import_use_usd_prices.useUsdPrices)();
70
+ const [activeTab, setActiveTab] = (0, import_react.useState)("assets");
71
+ const [reportOpen, setReportOpen] = (0, import_react.useState)(false);
72
+ const [reportToken, setReportToken] = (0, import_react.useState)(null);
73
+ const isOwner = !!walletAddress && (0, import_same_address.isSameAddress)(address, walletAddress);
74
+ const { tokens, total, isLoading: tokensLoading, isLoadingMore, hasMore, loadMore, mutate: refreshTokens } = (0, import_use_tokens.useOwnedTokens)(address);
75
+ const { collections, isLoading: collectionsLoading } = (0, import_use_collections.useCollectionsByOwner)(address);
76
+ const { orders, isLoading: ordersLoading } = (0, import_use_orders.useUserOrders)(address);
77
+ const { activities, isLoading: activitiesLoading } = (0, import_use_activities.useActivitiesByAddress)(activeTab === "activity" ? address : null);
78
+ const { data: hidden } = (0, import_swr.default)(`creator-hidden-${address}`, () => client.api.creators.isHidden(address).catch(() => false));
79
+ const actions = useAssetActions({ refresh: () => void refreshTokens() });
80
+ const market = useMarketActions();
81
+ 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: [
89
+ hidden === true ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_hidden_content_banner.HiddenContentBanner, {}) : null,
90
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-2 px-6 pt-20 pb-6", children: [
91
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_address_display.AddressDisplay, { address, chars: 10, className: "text-2xl font-black tracking-tight tabular-nums sm:text-3xl" }),
92
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "inline-flex items-center gap-1.5 rounded-full bg-muted px-2.5 py-1 text-xs font-medium text-muted-foreground", children: [
93
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "h-1.5 w-1.5 rounded-full bg-brand-blue" }),
94
+ "Starknet"
95
+ ] })
96
+ ] }),
97
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
98
+ import_underline_tabs.UnderlineTabs,
99
+ {
100
+ tabs,
101
+ value: activeTab,
102
+ onValueChange: (id) => setActiveTab(id),
103
+ 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) }),
104
+ children: [
105
+ /* @__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: [
106
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: GRID, children: tokens.map((t) => {
107
+ const listing = t.activeOrders?.find((o) => isNft(o.offer.itemType));
108
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
109
+ import_token_card.TokenCard,
110
+ {
111
+ token: t,
112
+ isOwner,
113
+ usdValue: (0, import_order_usd.orderUsd)(listing?.price, prices),
114
+ onList: isOwner ? actions.list : void 0,
115
+ onTransfer: isOwner ? actions.transfer : void 0,
116
+ onCancel: isOwner ? actions.cancel : void 0,
117
+ onBuy: !isOwner && listing ? () => market.buy(listing) : void 0,
118
+ onOffer: isOwner ? void 0 : market.offer,
119
+ onReport: setReportToken
120
+ },
121
+ `${t.contractAddress}-${t.tokenId}`
122
+ );
123
+ }) }),
124
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_load_more_sentinel.LoadMoreSentinel, { hasMore, isLoading: isLoadingMore, onLoadMore: loadMore })
125
+ ] }) }),
126
+ /* @__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)) }) }),
127
+ /* @__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)) }) }),
128
+ /* @__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)) }) })
129
+ ]
130
+ }
131
+ ),
132
+ actions.dialogs,
133
+ market.dialogs,
134
+ reportToken ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
135
+ import_report_dialog.ReportDialog,
136
+ {
137
+ open: !!reportToken,
138
+ onOpenChange: (open) => {
139
+ if (!open) setReportToken(null);
140
+ },
141
+ target: { type: "TOKEN", contract: reportToken.contractAddress, tokenId: reportToken.tokenId, name: reportToken.metadata?.name ?? void 0 }
142
+ }
143
+ ) : null,
144
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_report_dialog.ReportDialog, { open: reportOpen, onOpenChange: setReportOpen, target: { type: "CREATOR", address, name: (0, import_address.shortenAddress)(address) } })
145
+ ] });
146
+ }
147
+ // Annotate the CommonJS export names for ESM import in node:
148
+ 0 && (module.exports = {
149
+ AccountPage
150
+ });
151
+ //# sourceMappingURL=account-page.cjs.map
@@ -0,0 +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=\"space-y-2 px-6 pt-20 pb-6\">\n <AddressDisplay address={address} chars={10} className=\"text-2xl font-black tracking-tight tabular-nums sm:text-3xl\" />\n <span className=\"inline-flex items-center gap-1.5 rounded-full bg-muted px-2.5 py-1 text-xs font-medium text-muted-foreground\">\n <span className=\"h-1.5 w-1.5 rounded-full bg-brand-blue\" />\n Starknet\n </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"]}
@@ -0,0 +1,15 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { UsePortfolioAssetActions } from './portfolio-assets.cjs';
3
+ import { CollectionMarketActions } from './collection-page.cjs';
4
+ import 'react';
5
+ import '@medialane/sdk';
6
+ import './gated-content.cjs';
7
+
8
+ interface AccountPageProps {
9
+ address: string;
10
+ useAssetActions: UsePortfolioAssetActions;
11
+ useMarketActions: () => CollectionMarketActions;
12
+ }
13
+ declare function AccountPage({ address, useAssetActions, useMarketActions }: AccountPageProps): react_jsx_runtime.JSX.Element;
14
+
15
+ export { AccountPage, type AccountPageProps };
@@ -0,0 +1,15 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { UsePortfolioAssetActions } from './portfolio-assets.js';
3
+ import { CollectionMarketActions } from './collection-page.js';
4
+ import 'react';
5
+ import '@medialane/sdk';
6
+ import './gated-content.js';
7
+
8
+ interface AccountPageProps {
9
+ address: string;
10
+ useAssetActions: UsePortfolioAssetActions;
11
+ useMarketActions: () => CollectionMarketActions;
12
+ }
13
+ declare function AccountPage({ address, useAssetActions, useMarketActions }: AccountPageProps): react_jsx_runtime.JSX.Element;
14
+
15
+ export { AccountPage, type AccountPageProps };
@@ -0,0 +1,117 @@
1
+ "use client";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import { useState } from "react";
4
+ import useSWR from "swr";
5
+ import { Activity, Image as ImageIcon, LayoutGrid, ShoppingBag } from "lucide-react";
6
+ import { LoadMoreSentinel } from "./load-more-sentinel.js";
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";
11
+ import { HiddenContentBanner } from "./hidden-content-banner.js";
12
+ import { TabEmptyState } from "./tab-empty-state.js";
13
+ import { TokenCard, TokenCardSkeleton } from "./token-card.js";
14
+ import { CollectionCard, CollectionCardSkeleton } from "./collection-card.js";
15
+ import { ListingCard, ListingCardSkeleton } from "./listing-card.js";
16
+ import { ListingCardMenu } from "./listing-card-menu.js";
17
+ import { ActivityTimelineRow } from "./activity-timeline-row.js";
18
+ import { MoreMenu } from "./more-menu.js";
19
+ import { useMedialaneApp } from "./medialane-app.js";
20
+ import { ReportDialog } from "./report-dialog.js";
21
+ import { shortenAddress } from "../utils/address.js";
22
+ import { EXPLORER_URL } from "../utils/explorer-url.js";
23
+ import { isSameAddress } from "../utils/same-address.js";
24
+ import { orderUsd } from "../utils/order-usd.js";
25
+ import { useMedialaneClient } from "../utils/use-medialane-client.js";
26
+ import { useUsdPrices } from "../utils/use-usd-prices.js";
27
+ import { useOwnedTokens } from "../utils/use-tokens.js";
28
+ import { useCollectionsByOwner } from "../utils/use-collections.js";
29
+ import { useUserOrders } from "../utils/use-orders.js";
30
+ import { useActivitiesByAddress } from "../utils/use-activities.js";
31
+ const GRID = "grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 gap-4";
32
+ const isNft = (itemType) => itemType === "ERC721" || itemType === "ERC1155";
33
+ function AccountPage({ address, useAssetActions, useMarketActions }) {
34
+ const { walletAddress } = useMedialaneApp();
35
+ const client = useMedialaneClient();
36
+ const prices = useUsdPrices();
37
+ const [activeTab, setActiveTab] = useState("assets");
38
+ const [reportOpen, setReportOpen] = useState(false);
39
+ const [reportToken, setReportToken] = useState(null);
40
+ const isOwner = !!walletAddress && isSameAddress(address, walletAddress);
41
+ const { tokens, total, isLoading: tokensLoading, isLoadingMore, hasMore, loadMore, mutate: refreshTokens } = useOwnedTokens(address);
42
+ const { collections, isLoading: collectionsLoading } = useCollectionsByOwner(address);
43
+ const { orders, isLoading: ordersLoading } = useUserOrders(address);
44
+ const { activities, isLoading: activitiesLoading } = useActivitiesByAddress(activeTab === "activity" ? address : null);
45
+ const { data: hidden } = useSWR(`creator-hidden-${address}`, () => client.api.creators.isHidden(address).catch(() => false));
46
+ const actions = useAssetActions({ refresh: () => void refreshTokens() });
47
+ const market = useMarketActions();
48
+ 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: [
56
+ hidden === true ? /* @__PURE__ */ jsx(HiddenContentBanner, {}) : null,
57
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2 px-6 pt-20 pb-6", children: [
58
+ /* @__PURE__ */ jsx(AddressDisplay, { address, chars: 10, className: "text-2xl font-black tracking-tight tabular-nums sm:text-3xl" }),
59
+ /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1.5 rounded-full bg-muted px-2.5 py-1 text-xs font-medium text-muted-foreground", children: [
60
+ /* @__PURE__ */ jsx("span", { className: "h-1.5 w-1.5 rounded-full bg-brand-blue" }),
61
+ "Starknet"
62
+ ] })
63
+ ] }),
64
+ /* @__PURE__ */ jsxs(
65
+ UnderlineTabs,
66
+ {
67
+ tabs,
68
+ value: activeTab,
69
+ onValueChange: (id) => setActiveTab(id),
70
+ trailing: /* @__PURE__ */ jsx(MoreMenu, { explorerHref: `${EXPLORER_URL}/contract/${address}`, shareTitle: shortenAddress(address), onReport: () => setReportOpen(true) }),
71
+ children: [
72
+ /* @__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: [
73
+ /* @__PURE__ */ jsx("div", { className: GRID, children: tokens.map((t) => {
74
+ const listing = t.activeOrders?.find((o) => isNft(o.offer.itemType));
75
+ return /* @__PURE__ */ jsx(
76
+ TokenCard,
77
+ {
78
+ token: t,
79
+ isOwner,
80
+ usdValue: orderUsd(listing?.price, prices),
81
+ onList: isOwner ? actions.list : void 0,
82
+ onTransfer: isOwner ? actions.transfer : void 0,
83
+ onCancel: isOwner ? actions.cancel : void 0,
84
+ onBuy: !isOwner && listing ? () => market.buy(listing) : void 0,
85
+ onOffer: isOwner ? void 0 : market.offer,
86
+ onReport: setReportToken
87
+ },
88
+ `${t.contractAddress}-${t.tokenId}`
89
+ );
90
+ }) }),
91
+ /* @__PURE__ */ jsx(LoadMoreSentinel, { hasMore, isLoading: isLoadingMore, onLoadMore: loadMore })
92
+ ] }) }),
93
+ /* @__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)) }) }),
94
+ /* @__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)) }) }),
95
+ /* @__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)) }) })
96
+ ]
97
+ }
98
+ ),
99
+ actions.dialogs,
100
+ market.dialogs,
101
+ reportToken ? /* @__PURE__ */ jsx(
102
+ ReportDialog,
103
+ {
104
+ open: !!reportToken,
105
+ onOpenChange: (open) => {
106
+ if (!open) setReportToken(null);
107
+ },
108
+ target: { type: "TOKEN", contract: reportToken.contractAddress, tokenId: reportToken.tokenId, name: reportToken.metadata?.name ?? void 0 }
109
+ }
110
+ ) : null,
111
+ /* @__PURE__ */ jsx(ReportDialog, { open: reportOpen, onOpenChange: setReportOpen, target: { type: "CREATOR", address, name: shortenAddress(address) } })
112
+ ] });
113
+ }
114
+ export {
115
+ AccountPage
116
+ };
117
+ //# sourceMappingURL=account-page.js.map
@@ -0,0 +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=\"space-y-2 px-6 pt-20 pb-6\">\n <AddressDisplay address={address} chars={10} className=\"text-2xl font-black tracking-tight tabular-nums sm:text-3xl\" />\n <span className=\"inline-flex items-center gap-1.5 rounded-full bg-muted px-2.5 py-1 text-xs font-medium text-muted-foreground\">\n <span className=\"h-1.5 w-1.5 rounded-full bg-brand-blue\" />\n Starknet\n </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":[]}
@@ -3,7 +3,7 @@ import * as React from 'react';
3
3
  import { VariantProps } from 'class-variance-authority';
4
4
 
5
5
  declare const buttonVariants: (props?: ({
6
- variant?: "ghost" | "link" | "default" | "destructive" | "outline" | "secondary" | "premium" | "tonal" | "gradient-border" | "gradient-fill" | null | undefined;
6
+ variant?: "link" | "default" | "destructive" | "outline" | "secondary" | "ghost" | "premium" | "tonal" | "gradient-border" | "gradient-fill" | null | undefined;
7
7
  size?: "icon" | "default" | "sm" | "lg" | null | undefined;
8
8
  } & class_variance_authority_types.ClassProp) | undefined) => string;
9
9
  interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
@@ -3,7 +3,7 @@ import * as React from 'react';
3
3
  import { VariantProps } from 'class-variance-authority';
4
4
 
5
5
  declare const buttonVariants: (props?: ({
6
- variant?: "ghost" | "link" | "default" | "destructive" | "outline" | "secondary" | "premium" | "tonal" | "gradient-border" | "gradient-fill" | null | undefined;
6
+ variant?: "link" | "default" | "destructive" | "outline" | "secondary" | "ghost" | "premium" | "tonal" | "gradient-border" | "gradient-fill" | null | undefined;
7
7
  size?: "icon" | "default" | "sm" | "lg" | null | undefined;
8
8
  } & class_variance_authority_types.ClassProp) | undefined) => string;
9
9
  interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
@@ -39,7 +39,8 @@ var import_lucide_react = require("lucide-react");
39
39
  var import_link = __toESM(require("./link.js"), 1);
40
40
  var import_button = require("./button.js");
41
41
  var import_skeleton = require("./skeleton.js");
42
- var import_address_display = require("./address-display.js");
42
+ var import_tabs = require("./tabs.js");
43
+ var import_underline_tabs = require("./underline-tabs.js");
43
44
  var import_creator_header = require("./creator-header.js");
44
45
  var import_hidden_content_banner = require("./hidden-content-banner.js");
45
46
  var import_tab_empty_state = require("./tab-empty-state.js");
@@ -64,15 +65,9 @@ var import_use_collections = require("../utils/use-collections.js");
64
65
  var import_use_orders = require("../utils/use-orders.js");
65
66
  var import_use_activities = require("../utils/use-activities.js");
66
67
  var import_use_profiles = require("../utils/use-profiles.js");
67
- const TABS = [
68
- { id: "assets", label: "Assets", Icon: import_lucide_react.Image },
69
- { id: "collections", label: "Collections", Icon: import_lucide_react.LayoutGrid },
70
- { id: "listings", label: "Listings", Icon: import_lucide_react.ShoppingBag },
71
- { id: "activity", label: "Activity", Icon: import_lucide_react.Activity }
72
- ];
73
68
  const GRID = "grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 gap-4";
74
69
  const isNft = (itemType) => itemType === "ERC721" || itemType === "ERC1155";
75
- function CreatorPage({ address: addressProp, username, useAssetActions, useMarketActions }) {
70
+ function CreatorPage({ username, useAssetActions, useMarketActions }) {
76
71
  const { walletAddress } = (0, import_medialane_app.useMedialaneApp)();
77
72
  const client = (0, import_use_medialane_client.useMedialaneClient)();
78
73
  const resolveImage = (0, import_use_image_url.useImageUrl)();
@@ -80,10 +75,8 @@ function CreatorPage({ address: addressProp, username, useAssetActions, useMarke
80
75
  const [activeTab, setActiveTab] = (0, import_react.useState)("assets");
81
76
  const [reportOpen, setReportOpen] = (0, import_react.useState)(false);
82
77
  const [reportToken, setReportToken] = (0, import_react.useState)(null);
83
- const byName = (0, import_use_profiles.useCreatorByUsername)(username);
84
- const byAddress = (0, import_use_profiles.useCreatorProfile)(username ? void 0 : addressProp);
85
- const creator = username ? byName.creator : byAddress.profile;
86
- const address = username ? creator?.walletAddress ?? null : addressProp ?? null;
78
+ const { creator, isLoading: creatorLoading } = (0, import_use_profiles.useCreatorByUsername)(username);
79
+ const address = creator?.walletAddress ?? null;
87
80
  const isOwner = !!address && !!walletAddress && (0, import_same_address.isSameAddress)(address, walletAddress);
88
81
  const { tokens, meta, isLoading: tokensLoading, mutate: refreshTokens } = (0, import_use_tokens.useTokensByOwner)(address, 1, 20);
89
82
  const { collections, isLoading: collectionsLoading } = (0, import_use_collections.useCollectionsByOwner)(address);
@@ -94,13 +87,13 @@ function CreatorPage({ address: addressProp, username, useAssetActions, useMarke
94
87
  const market = useMarketActions();
95
88
  const listings = orders.filter((o) => o.status === "ACTIVE" && isNft(o.offer.itemType));
96
89
  const identity = (0, import_profile_identity.profileIdentity)({ username: creator?.username, name: creator?.name, walletAddress: address });
97
- if (username && byName.isLoading) {
90
+ if (creatorLoading) {
98
91
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "min-h-screen pb-20", children: [
99
92
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "px-6 pt-20 pb-6", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_creator_header.CreatorHeader, { creator: null, image: null, stats: [], loading: true }) }),
100
93
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: (0, import_cn.cn)("px-6", GRID), children: Array.from({ length: 8 }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_token_card.TokenCardSkeleton, {}, i)) })
101
94
  ] });
102
95
  }
103
- if (username && !creator) {
96
+ if (!creator) {
104
97
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mx-auto max-w-lg space-y-4 px-4 py-24 text-center", children: [
105
98
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h1", { className: "text-2xl font-bold", children: "Creator not found" }),
106
99
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "text-muted-foreground", children: [
@@ -113,14 +106,15 @@ function CreatorPage({ address: addressProp, username, useAssetActions, useMarke
113
106
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_button.Button, { variant: "outline", asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_link.default, { href: "/creators", children: "Browse creators" }) })
114
107
  ] });
115
108
  }
116
- const counts = {
117
- assets: meta?.total ?? void 0,
118
- collections: collectionsLoading ? void 0 : collections.length,
119
- ...activeTab === "listings" && !ordersLoading ? { listings: listings.length } : {}
120
- };
109
+ const tabs = [
110
+ { id: "assets", label: "Assets", icon: import_lucide_react.Image, count: meta?.total ?? void 0 },
111
+ { id: "collections", label: "Collections", icon: import_lucide_react.LayoutGrid, count: collectionsLoading ? void 0 : collections.length },
112
+ { id: "listings", label: "Listings", icon: import_lucide_react.ShoppingBag, count: activeTab === "listings" && !ordersLoading ? listings.length : void 0 },
113
+ { id: "activity", label: "Activity", icon: import_lucide_react.Activity }
114
+ ];
121
115
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "min-h-screen overflow-x-hidden pb-20", children: [
122
116
  hidden === true ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_hidden_content_banner.HiddenContentBanner, {}) : null,
123
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "px-6 pt-20 pb-6", children: creator ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
117
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "px-6 pt-20 pb-6", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
124
118
  import_creator_header.CreatorHeader,
125
119
  {
126
120
  creator,
@@ -130,54 +124,39 @@ function CreatorPage({ address: addressProp, username, useAssetActions, useMarke
130
124
  { label: "Collections", value: collectionsLoading ? null : collections.length }
131
125
  ]
132
126
  }
133
- ) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex flex-wrap items-center gap-2", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_address_display.AddressDisplay, { address: address ?? "", chars: 10, className: "text-base font-semibold tabular-nums" }) }) }),
134
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("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", children: [
135
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "-mb-px flex min-w-0 flex-1 items-center gap-0.5 overflow-x-auto scrollbar-none", children: TABS.map(({ id, label, Icon }) => {
136
- const count = counts[id];
137
- const active = activeTab === id;
138
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
139
- "button",
140
- {
141
- onClick: () => setActiveTab(id),
142
- className: (0, import_cn.cn)(
143
- "relative flex shrink-0 items-center gap-2 whitespace-nowrap px-4 py-3 text-sm font-medium transition-colors duration-200",
144
- active ? "text-foreground" : "text-muted-foreground hover:text-foreground"
145
- ),
146
- children: [
147
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Icon, { className: "h-3.5 w-3.5" }),
148
- label,
149
- count ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: (0, import_cn.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"), children: count }) : null,
150
- active ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "absolute inset-x-0 bottom-0 h-0.5 rounded-full bg-primary" }) : null
151
- ]
152
- },
153
- id
154
- );
155
- }) }),
156
- address ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_more_menu.MoreMenu, { explorerHref: `${import_explorer_url.EXPLORER_URL}/contract/${address}`, shareTitle: identity.name ?? identity.identity, onReport: () => setReportOpen(true) }) : null
157
- ] }),
158
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mt-6 px-6", children: [
159
- 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 creator makes on Medialane appear here." }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: GRID, children: tokens.map((t) => {
160
- const listing = t.activeOrders?.find((o) => isNft(o.offer.itemType));
161
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
162
- import_token_card.TokenCard,
163
- {
164
- token: t,
165
- isOwner,
166
- usdValue: (0, import_order_usd.orderUsd)(listing?.price, prices),
167
- onList: isOwner ? actions.list : void 0,
168
- onTransfer: isOwner ? actions.transfer : void 0,
169
- onCancel: isOwner ? actions.cancel : void 0,
170
- onBuy: !isOwner && listing ? () => market.buy(listing) : void 0,
171
- onOffer: isOwner ? void 0 : market.offer,
172
- onReport: setReportToken
173
- },
174
- `${t.contractAddress}-${t.tokenId}`
175
- );
176
- }) })),
177
- 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 creator makes 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)) })),
178
- 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 creator 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)) })),
179
- 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 creator'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)) }) })
180
- ] }),
127
+ ) }),
128
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
129
+ import_underline_tabs.UnderlineTabs,
130
+ {
131
+ tabs,
132
+ value: activeTab,
133
+ onValueChange: (id) => setActiveTab(id),
134
+ trailing: address ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_more_menu.MoreMenu, { explorerHref: `${import_explorer_url.EXPLORER_URL}/contract/${address}`, shareTitle: identity.name ?? identity.identity, onReport: () => setReportOpen(true) }) : null,
135
+ children: [
136
+ /* @__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 creator makes on Medialane appear here." }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: GRID, children: tokens.map((t) => {
137
+ const listing = t.activeOrders?.find((o) => isNft(o.offer.itemType));
138
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
139
+ import_token_card.TokenCard,
140
+ {
141
+ token: t,
142
+ isOwner,
143
+ usdValue: (0, import_order_usd.orderUsd)(listing?.price, prices),
144
+ onList: isOwner ? actions.list : void 0,
145
+ onTransfer: isOwner ? actions.transfer : void 0,
146
+ onCancel: isOwner ? actions.cancel : void 0,
147
+ onBuy: !isOwner && listing ? () => market.buy(listing) : void 0,
148
+ onOffer: isOwner ? void 0 : market.offer,
149
+ onReport: setReportToken
150
+ },
151
+ `${t.contractAddress}-${t.tokenId}`
152
+ );
153
+ }) }) }),
154
+ /* @__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 creator makes 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)) }) }),
155
+ /* @__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 creator 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)) }) }),
156
+ /* @__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 creator'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)) }) })
157
+ ]
158
+ }
159
+ ),
181
160
  actions.dialogs,
182
161
  market.dialogs,
183
162
  reportToken ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(