@medialane/ui 0.252.0 → 0.253.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 (45) hide show
  1. package/dist/components/account/input-otp.d.cts +2 -2
  2. package/dist/components/account/input-otp.d.ts +2 -2
  3. package/dist/components/button.d.cts +2 -2
  4. package/dist/components/button.d.ts +2 -2
  5. package/dist/components/collection-card.cjs +11 -19
  6. package/dist/components/collection-card.cjs.map +1 -1
  7. package/dist/components/collection-card.js +11 -19
  8. package/dist/components/collection-card.js.map +1 -1
  9. package/dist/components/collections-page.cjs +190 -139
  10. package/dist/components/collections-page.cjs.map +1 -1
  11. package/dist/components/collections-page.js +181 -140
  12. package/dist/components/collections-page.js.map +1 -1
  13. package/dist/components/creator-page.cjs +1 -1
  14. package/dist/components/creator-page.cjs.map +1 -1
  15. package/dist/components/creator-page.js +1 -1
  16. package/dist/components/creator-page.js.map +1 -1
  17. package/dist/components/drop/create/drop-create.cjs +1 -1
  18. package/dist/components/drop/create/drop-create.cjs.map +1 -1
  19. package/dist/components/drop/create/drop-create.js +1 -1
  20. package/dist/components/drop/create/drop-create.js.map +1 -1
  21. package/dist/components/drop/create/launch-dialog.cjs +1 -1
  22. package/dist/components/drop/create/launch-dialog.cjs.map +1 -1
  23. package/dist/components/drop/create/launch-dialog.js +1 -1
  24. package/dist/components/drop/create/launch-dialog.js.map +1 -1
  25. package/dist/components/fast-mint/fast-mint.d.cts +2 -2
  26. package/dist/components/fast-mint/fast-mint.d.ts +2 -2
  27. package/dist/components/hero-slider.cjs +2 -1
  28. package/dist/components/hero-slider.cjs.map +1 -1
  29. package/dist/components/hero-slider.js +2 -1
  30. package/dist/components/hero-slider.js.map +1 -1
  31. package/dist/components/launchpad/edition-mint-schema.d.cts +2 -2
  32. package/dist/components/launchpad/edition-mint-schema.d.ts +2 -2
  33. package/dist/components/scroll-section.cjs +1 -1
  34. package/dist/components/scroll-section.cjs.map +1 -1
  35. package/dist/components/scroll-section.d.cts +1 -1
  36. package/dist/components/scroll-section.d.ts +1 -1
  37. package/dist/components/scroll-section.js +1 -1
  38. package/dist/components/scroll-section.js.map +1 -1
  39. package/dist/components/sheet.d.cts +1 -1
  40. package/dist/components/sheet.d.ts +1 -1
  41. package/dist/utils/use-collections.cjs +1 -2
  42. package/dist/utils/use-collections.cjs.map +1 -1
  43. package/dist/utils/use-collections.js +1 -2
  44. package/dist/utils/use-collections.js.map +1 -1
  45. package/package.json +1 -1
@@ -1,8 +1,10 @@
1
1
  "use strict";
2
2
  "use client";
3
+ var __create = Object.create;
3
4
  var __defProp = Object.defineProperty;
4
5
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
6
  var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
6
8
  var __hasOwnProp = Object.prototype.hasOwnProperty;
7
9
  var __export = (target, all) => {
8
10
  for (var name in all)
@@ -16,6 +18,14 @@ var __copyProps = (to, from, except, desc) => {
16
18
  }
17
19
  return to;
18
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
+ ));
19
29
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
30
  var collections_page_exports = {};
21
31
  __export(collections_page_exports, {
@@ -24,17 +34,26 @@ __export(collections_page_exports, {
24
34
  module.exports = __toCommonJS(collections_page_exports);
25
35
  var import_jsx_runtime = require("react/jsx-runtime");
26
36
  var import_react = require("react");
37
+ var import_swr = __toESM(require("swr"), 1);
27
38
  var import_lucide_react = require("lucide-react");
28
39
  var import_button = require("./button.js");
29
40
  var import_dialog = require("./dialog.js");
41
+ var import_select = require("./select.js");
30
42
  var import_help_icon = require("./help-icon.js");
43
+ var import_input = require("./input.js");
44
+ var import_result_thumbnail = require("./result-thumbnail.js");
45
+ var import_link = __toESM(require("./link.js"), 1);
46
+ var import_router = require("./router.js");
31
47
  var import_page_container = require("./page-container.js");
48
+ var import_scroll_section = require("./scroll-section.js");
32
49
  var import_collection_card = require("./collection-card.js");
33
50
  var import_load_more_sentinel = require("./load-more-sentinel.js");
34
51
  var import_cn = require("../utils/cn.js");
35
52
  var import_use_collections = require("../utils/use-collections.js");
36
- var import_use_platform_stats = require("../utils/use-platform-stats.js");
37
- const PAGE_SIZE = 18;
53
+ var import_use_medialane_client = require("../utils/use-medialane-client.js");
54
+ var import_use_search = require("../utils/use-search.js");
55
+ var import_sdk = require("@medialane/sdk");
56
+ const PAGE_SIZE = 24;
38
57
  const SORT_OPTIONS = [
39
58
  { label: "Recent", value: "recent" },
40
59
  { label: "Most assets", value: "supply" },
@@ -47,12 +66,90 @@ const SERVICE_TABS = [
47
66
  { label: "POP Events", value: "pop-protocol" },
48
67
  { label: "Drops", value: "drop-collection" }
49
68
  ];
69
+ function useStandardCounts() {
70
+ const client = (0, import_use_medialane_client.useMedialaneClient)();
71
+ const { data } = (0, import_swr.default)(
72
+ "collection-standard-counts",
73
+ async () => {
74
+ const [single, multi] = await Promise.all(
75
+ ["ERC721", "ERC1155"].map(
76
+ (standard) => client.api.collections.list({ standard, hideEmpty: true, limit: 1 })
77
+ )
78
+ );
79
+ return { single: single.meta?.total, multi: multi.meta?.total };
80
+ },
81
+ { revalidateOnFocus: false, dedupingInterval: 6e4 }
82
+ );
83
+ return data ?? null;
84
+ }
85
+ function CollectionSearch() {
86
+ const router = (0, import_router.useRouter)();
87
+ const [value, setValue] = (0, import_react.useState)("");
88
+ const [query, setQuery] = (0, import_react.useState)("");
89
+ const [open, setOpen] = (0, import_react.useState)(false);
90
+ const { results } = (0, import_use_search.useSearch)(query, { limit: 6 });
91
+ const matches = results?.collections ?? [];
92
+ (0, import_react.useEffect)(() => {
93
+ const timer = setTimeout(() => setQuery(value), 300);
94
+ return () => clearTimeout(timer);
95
+ }, [value]);
96
+ const clear = () => {
97
+ setValue("");
98
+ setQuery("");
99
+ setOpen(false);
100
+ };
101
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "relative w-full sm:max-w-sm sm:flex-1", children: [
102
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Search, { className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
103
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
104
+ import_input.Input,
105
+ {
106
+ className: "h-9 pl-9 pr-9 text-sm",
107
+ placeholder: "Search collections",
108
+ "aria-label": "Search collections",
109
+ value,
110
+ onChange: (e) => {
111
+ setValue(e.target.value);
112
+ setOpen(true);
113
+ },
114
+ onFocus: () => setOpen(true),
115
+ onBlur: () => setTimeout(() => setOpen(false), 200),
116
+ onKeyDown: (e) => {
117
+ if (e.key === "Enter" && value.trim().length >= import_use_search.SEARCH_MIN_LENGTH) {
118
+ router.push(`/search?q=${encodeURIComponent(value.trim())}`);
119
+ }
120
+ }
121
+ }
122
+ ),
123
+ value && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
124
+ "button",
125
+ {
126
+ "aria-label": "Clear search",
127
+ className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
128
+ onClick: clear,
129
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.X, { className: "h-3.5 w-3.5" })
130
+ }
131
+ ),
132
+ open && matches.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "absolute left-0 right-0 top-full z-50 mt-1 overflow-hidden rounded-xl border border-border bg-popover shadow-lg", children: matches.map((col) => {
133
+ const label = col.name ?? "Untitled";
134
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
135
+ import_link.default,
136
+ {
137
+ href: (0, import_sdk.collectionHref)("STARKNET", col.contractAddress),
138
+ className: "flex items-center gap-3 px-3 py-2.5 transition-colors hover:bg-muted/50",
139
+ children: [
140
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_result_thumbnail.ResultThumbnail, { src: col.image, label }),
141
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "truncate text-sm font-medium", children: label })
142
+ ]
143
+ },
144
+ col.contractAddress
145
+ );
146
+ }) })
147
+ ] });
148
+ }
50
149
  function CollectionsPage() {
51
- const { stats } = (0, import_use_platform_stats.usePlatformStats)();
150
+ const counts = useStandardCounts();
52
151
  const [sort, setSort] = (0, import_react.useState)("recent");
53
- const [featured, setFeatured] = (0, import_react.useState)(false);
54
152
  const [hideEmpty, setHideEmpty] = (0, import_react.useState)(true);
55
- const [exclusive, setExclusive] = (0, import_react.useState)(false);
56
153
  const [service, setService] = (0, import_react.useState)(void 0);
57
154
  const [filtersOpen, setFiltersOpen] = (0, import_react.useState)(false);
58
155
  const [page, setPage] = (0, import_react.useState)(1);
@@ -60,21 +157,30 @@ function CollectionsPage() {
60
157
  const { collections, meta, isLoading } = (0, import_use_collections.useCollections)(
61
158
  page,
62
159
  PAGE_SIZE,
63
- featured ? true : void 0,
160
+ void 0,
64
161
  sort,
65
162
  service === "pop-protocol" || service === "drop-collection" ? false : hideEmpty,
66
163
  service,
67
164
  "ERC721,ERC1155"
68
165
  );
69
- const prevFilters = (0, import_react.useRef)({ sort, featured, hideEmpty, service });
166
+ const { collections: featuredCollections, isLoading: featuredLoading } = (0, import_use_collections.useCollections)(
167
+ 1,
168
+ 8,
169
+ true,
170
+ "recent",
171
+ true,
172
+ void 0,
173
+ "ERC721,ERC1155"
174
+ );
175
+ const prevFilters = (0, import_react.useRef)({ sort, hideEmpty, service });
70
176
  (0, import_react.useEffect)(() => {
71
177
  const f = prevFilters.current;
72
- if (f.sort !== sort || f.featured !== featured || f.hideEmpty !== hideEmpty || f.service !== service) {
73
- prevFilters.current = { sort, featured, hideEmpty, service };
178
+ if (f.sort !== sort || f.hideEmpty !== hideEmpty || f.service !== service) {
179
+ prevFilters.current = { sort, hideEmpty, service };
74
180
  setPage(1);
75
181
  setAllCollections([]);
76
182
  }
77
- }, [sort, featured, hideEmpty, service]);
183
+ }, [sort, hideEmpty, service]);
78
184
  (0, import_react.useEffect)(() => {
79
185
  if (isLoading || collections.length === 0) return;
80
186
  setAllCollections((prev) => {
@@ -85,13 +191,9 @@ function CollectionsPage() {
85
191
  }, [collections, isLoading, page]);
86
192
  const hasMore = meta?.total != null ? allCollections.length < meta.total : false;
87
193
  const isInitialLoading = isLoading && allCollections.length === 0;
88
- const activeFilters = [sort !== "recent", featured, !hideEmpty, exclusive].filter(Boolean).length;
89
- const displayCollections = exclusive ? allCollections.filter((c) => !!c.profile?.hasGatedContent) : allCollections;
194
+ const activeFilters = [!hideEmpty].filter(Boolean).length;
90
195
  const resetAll = () => {
91
- setSort("recent");
92
- setFeatured(false);
93
196
  setHideEmpty(true);
94
- setExclusive(false);
95
197
  };
96
198
  const handleServiceChange = (val) => {
97
199
  setService(val);
@@ -100,58 +202,63 @@ function CollectionsPage() {
100
202
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-2 pt-8", children: [
101
203
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h1", { className: "text-3xl font-bold", children: "Onchain Collections" }),
102
204
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-wrap items-center gap-2 mt-1", children: [
103
- meta?.total != null && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-1.5 rounded-full border border-border bg-card px-3.5 py-1.5 text-sm", children: [
104
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "font-bold tabular-nums", children: (meta.total ?? 0).toLocaleString() }),
105
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-muted-foreground", children: "Collections" })
106
- ] }),
107
- stats?.tokens != null && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-1.5 rounded-full border border-border bg-card px-3.5 py-1.5 text-sm", children: [
108
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "font-bold tabular-nums", children: stats.tokens.toLocaleString() }),
109
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-muted-foreground", children: "Assets" })
205
+ counts?.single != null && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-1.5 rounded-full border border-border bg-card px-3.5 py-1.5 text-sm", children: [
206
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "font-bold tabular-nums", children: counts.single.toLocaleString() }),
207
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-muted-foreground", children: "Single NFTs" })
110
208
  ] }),
111
- stats?.sales != null && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-1.5 rounded-full border border-border bg-card px-3.5 py-1.5 text-sm", children: [
112
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "font-bold tabular-nums", children: stats.sales.toLocaleString() }),
113
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-muted-foreground", children: "Sales" })
209
+ counts?.multi != null && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-1.5 rounded-full border border-border bg-card px-3.5 py-1.5 text-sm", children: [
210
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "font-bold tabular-nums", children: counts.multi.toLocaleString() }),
211
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-muted-foreground", children: "Multi editions" })
114
212
  ] })
115
213
  ] })
116
214
  ] }),
117
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-2 pb-3 border-b border-border/60 flex-wrap", children: [
118
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
119
- "button",
120
- {
121
- onClick: () => setFiltersOpen(true),
122
- className: (0, import_cn.cn)(
123
- "relative flex items-center gap-1.5 h-9 px-3 rounded-lg border text-xs font-medium transition-colors",
124
- activeFilters > 0 || service !== void 0 ? "border-primary bg-primary/10 text-primary" : "border-border text-muted-foreground hover:border-primary/50 hover:text-foreground"
125
- ),
126
- children: [
127
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.SlidersHorizontal, { className: "h-3.5 w-3.5" }),
128
- "Filters",
129
- (activeFilters > 0 || service !== void 0) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "flex h-4 w-4 items-center justify-center rounded-full bg-primary text-2xs font-bold text-primary-foreground", children: activeFilters + (service !== void 0 ? 1 : 0) })
130
- ]
131
- }
132
- ),
133
- service !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "flex items-center gap-1 text-xs px-2.5 py-1 rounded-full border border-primary/40 bg-primary/10 text-primary", children: [
134
- service === "drop-collection" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Package, { className: "h-3 w-3" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Award, { className: "h-3 w-3" }),
135
- SERVICE_TABS.find((t) => t.value === service)?.label,
136
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: () => setService(void 0), className: "ml-0.5 hover:text-primary/60", children: "\xD7" })
137
- ] }),
138
- sort !== "recent" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "flex items-center gap-1 text-xs px-2.5 py-1 rounded-full border border-primary/40 bg-primary/10 text-primary", children: [
139
- SORT_OPTIONS.find((o) => o.value === sort)?.label,
140
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: () => setSort("recent"), className: "ml-0.5 hover:text-primary/60", children: "\xD7" })
141
- ] }),
142
- featured && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "flex items-center gap-1 text-xs px-2.5 py-1 rounded-full border border-primary/40 bg-primary/10 text-primary", children: [
143
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.BadgeCheck, { className: "h-3 w-3" }),
144
- "Featured",
145
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: () => setFeatured(false), className: "ml-0.5 hover:text-primary/60", children: "\xD7" })
146
- ] }),
147
- !hideEmpty && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "flex items-center gap-1 text-xs px-2.5 py-1 rounded-full border border-primary/40 bg-primary/10 text-primary", children: [
148
- "Show empty",
149
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: () => setHideEmpty(true), className: "ml-0.5 hover:text-primary/60", children: "\xD7" })
215
+ (featuredLoading || featuredCollections.length > 0) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
216
+ import_scroll_section.ScrollSection,
217
+ {
218
+ icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.BadgeCheck, { className: "h-3.5 w-3.5 text-white" }),
219
+ iconBg: "bg-gradient-to-br from-brand-blue to-indigo-600 shadow-md shadow-brand-blue/20",
220
+ title: "Featured",
221
+ children: featuredLoading ? Array.from({ length: 4 }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "w-56 shrink-0 snap-start sm:w-64", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_collection_card.CollectionCardSkeleton, {}) }, i)) : featuredCollections.map((col) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "w-56 shrink-0 snap-start sm:w-64", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_collection_card.CollectionCard, { collection: col }) }, col.contractAddress))
222
+ }
223
+ ),
224
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-3", children: [
225
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-wrap items-center gap-2", children: [
226
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CollectionSearch, {}),
227
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-2 sm:ml-auto", children: [
228
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_select.Select, { value: sort, onValueChange: (v) => setSort(v), children: [
229
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_select.SelectTrigger, { className: "h-9 w-auto gap-1.5 text-xs", "aria-label": "Sort collections", children: [
230
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.ArrowDownUp, { className: "h-3.5 w-3.5 text-muted-foreground" }),
231
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_select.SelectValue, {})
232
+ ] }),
233
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_select.SelectContent, { children: SORT_OPTIONS.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_select.SelectItem, { value: opt.value, className: "text-xs", children: opt.label }, opt.value)) })
234
+ ] }),
235
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
236
+ "button",
237
+ {
238
+ onClick: () => setFiltersOpen(true),
239
+ className: (0, import_cn.cn)(
240
+ "relative flex items-center gap-1.5 h-9 px-3 rounded-lg border text-xs font-medium transition-colors",
241
+ activeFilters > 0 || service !== void 0 ? "border-primary bg-primary/10 text-primary" : "border-border text-muted-foreground hover:border-primary/50 hover:text-foreground"
242
+ ),
243
+ children: [
244
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.SlidersHorizontal, { className: "h-3.5 w-3.5" }),
245
+ "Filters",
246
+ (activeFilters > 0 || service !== void 0) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "flex h-4 w-4 items-center justify-center rounded-full bg-primary text-2xs font-bold text-primary-foreground", children: activeFilters + (service !== void 0 ? 1 : 0) })
247
+ ]
248
+ }
249
+ )
250
+ ] })
150
251
  ] }),
151
- exclusive && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "flex items-center gap-1 text-xs px-2.5 py-1 rounded-full border border-primary/40 bg-primary/10 text-primary", children: [
152
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Sparkles, { className: "h-3 w-3" }),
153
- "Exclusive",
154
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: () => setExclusive(false), className: "ml-0.5 hover:text-primary/60", children: "\xD7" })
252
+ (service !== void 0 || !hideEmpty) && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-wrap items-center gap-2", children: [
253
+ service !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "flex items-center gap-1 text-xs px-2.5 py-1 rounded-full border border-primary/40 bg-primary/10 text-primary", children: [
254
+ service === "drop-collection" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Package, { className: "h-3 w-3" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Award, { className: "h-3 w-3" }),
255
+ SERVICE_TABS.find((t) => t.value === service)?.label,
256
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: () => setService(void 0), className: "ml-0.5 hover:text-primary/60", "aria-label": "Remove source filter", children: "\xD7" })
257
+ ] }),
258
+ !hideEmpty && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "flex items-center gap-1 text-xs px-2.5 py-1 rounded-full border border-primary/40 bg-primary/10 text-primary", children: [
259
+ "Show empty",
260
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: () => setHideEmpty(true), className: "ml-0.5 hover:text-primary/60", "aria-label": "Remove show empty filter", children: "\xD7" })
261
+ ] })
155
262
  ] })
156
263
  ] }),
157
264
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dialog.Dialog, { open: filtersOpen, onOpenChange: setFiltersOpen, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_dialog.DialogContent, { className: "w-full max-w-sm sm:max-w-md p-0 overflow-hidden gap-0 flex flex-col max-h-[85svh]", children: [
@@ -185,92 +292,36 @@ function CollectionsPage() {
185
292
  label
186
293
  )) })
187
294
  ] }),
188
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-2", children: [
189
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-2xs font-semibold text-muted-foreground", children: "Sort" }),
190
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex flex-wrap gap-1.5", children: SORT_OPTIONS.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
191
- "button",
192
- {
193
- onClick: () => setSort(opt.value),
194
- className: (0, import_cn.cn)(
195
- "text-xs px-3 py-1.5 rounded-full border transition-colors whitespace-nowrap",
196
- sort === opt.value ? "border-primary bg-primary/10 text-primary font-medium" : "border-border text-muted-foreground hover:border-primary/50"
197
- ),
198
- children: opt.label
199
- },
200
- opt.value
201
- )) })
202
- ] }),
203
295
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-2", children: [
204
296
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-2xs font-semibold text-muted-foreground", children: "Show" }),
205
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-col gap-2", children: [
206
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-2", children: [
207
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
208
- "button",
209
- {
210
- onClick: () => setFeatured((v) => !v),
211
- className: (0, import_cn.cn)(
212
- "flex flex-1 items-center gap-2 text-sm px-3 py-2 rounded-lg border transition-colors text-left",
213
- featured ? "border-primary bg-primary/10 text-primary" : "border-border text-muted-foreground hover:border-primary/50"
214
- ),
215
- children: [
216
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.BadgeCheck, { className: "h-4 w-4 shrink-0" }),
217
- "Featured only"
218
- ]
219
- }
220
- ),
221
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_help_icon.HelpIcon, { content: "Show only collections featured by Medialane", side: "left" })
222
- ] }),
223
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-2", children: [
224
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
225
- "button",
226
- {
227
- onClick: () => setHideEmpty((v) => !v),
228
- className: (0, import_cn.cn)(
229
- "flex flex-1 items-center gap-2 text-sm px-3 py-2 rounded-lg border transition-colors text-left",
230
- !hideEmpty ? "border-primary bg-primary/10 text-primary" : "border-border text-muted-foreground hover:border-primary/50"
231
- ),
232
- children: [
233
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Eye, { className: "h-4 w-4 shrink-0" }),
234
- "Show empty collections"
235
- ]
236
- }
237
- ),
238
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_help_icon.HelpIcon, { content: "Include collections with no minted assets yet \u2014 hidden by default to keep the feed clean", side: "left" })
239
- ] }),
240
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-2", children: [
241
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
242
- "button",
243
- {
244
- onClick: () => setExclusive((v) => !v),
245
- className: (0, import_cn.cn)(
246
- "flex flex-1 items-center gap-2 text-sm px-3 py-2 rounded-lg border transition-colors text-left",
247
- exclusive ? "border-primary bg-primary/10 text-primary" : "border-border text-muted-foreground hover:border-primary/50"
248
- ),
249
- children: [
250
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Sparkles, { className: "h-4 w-4 shrink-0" }),
251
- "Exclusive content only"
252
- ]
253
- }
254
- ),
255
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_help_icon.HelpIcon, { content: "Show only collections with holder-exclusive content", side: "left" })
256
- ] })
257
- ] })
297
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex flex-col gap-2", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-2", children: [
298
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
299
+ "button",
300
+ {
301
+ onClick: () => setHideEmpty((v) => !v),
302
+ className: (0, import_cn.cn)(
303
+ "flex flex-1 items-center gap-2 text-sm px-3 py-2 rounded-lg border transition-colors text-left",
304
+ !hideEmpty ? "border-primary bg-primary/10 text-primary" : "border-border text-muted-foreground hover:border-primary/50"
305
+ ),
306
+ children: [
307
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Eye, { className: "h-4 w-4 shrink-0" }),
308
+ "Show empty collections"
309
+ ]
310
+ }
311
+ ),
312
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_help_icon.HelpIcon, { content: "Include collections with no minted assets yet \u2014 hidden by default to keep the feed clean", side: "left" })
313
+ ] }) })
258
314
  ] })
259
315
  ] }),
260
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "px-5 py-3 border-t border-border/60", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_button.Button, { className: "w-full", onClick: () => setFiltersOpen(false), children: "Apply filters" }) })
316
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "px-5 py-3 border-t border-border/60", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_button.Button, { className: "w-full", onClick: () => setFiltersOpen(false), children: "Show results" }) })
261
317
  ] }) }),
262
- isInitialLoading ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-5", children: Array.from({ length: 9 }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_collection_card.CollectionCardSkeleton, {}, i)) }) : allCollections.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-col items-center justify-center py-24 gap-4 text-center", children: [
318
+ isInitialLoading ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "grid grid-cols-2 lg:grid-cols-4 gap-4 sm:gap-5", children: Array.from({ length: 8 }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_collection_card.CollectionCardSkeleton, {}, i)) }) : allCollections.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-col items-center justify-center py-24 gap-4 text-center", children: [
263
319
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Layers, { className: "h-12 w-12 text-muted-foreground/30" }),
264
320
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-2xl font-bold", children: "No collections found" }),
265
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-muted-foreground max-w-sm", children: featured ? "No featured collections match the current filters." : hideEmpty ? "No collections with assets yet." : "Deploy the first collection on Medialane." }),
321
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-muted-foreground max-w-sm", children: hideEmpty ? "No collections with assets yet." : "Deploy the first collection on Medialane." }),
266
322
  activeFilters > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_button.Button, { variant: "outline", size: "sm", onClick: resetAll, children: "Clear filters" })
267
323
  ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-6", children: [
268
- exclusive && displayCollections.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-col items-center justify-center py-16 gap-3 text-center", children: [
269
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Sparkles, { className: "h-10 w-10 text-muted-foreground/30" }),
270
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-base font-semibold text-muted-foreground", children: "No exclusive collections in this batch" }),
271
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-sm text-muted-foreground/70 max-w-xs", children: "Load more collections below, then the filter will catch them." })
272
- ] }),
273
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-5", children: displayCollections.map((col) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_collection_card.CollectionCard, { collection: col }, col.contractAddress)) }),
324
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "grid grid-cols-2 lg:grid-cols-4 gap-4 sm:gap-5", children: allCollections.map((col) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_collection_card.CollectionCard, { collection: col }, col.contractAddress)) }),
274
325
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
275
326
  import_load_more_sentinel.LoadMoreSentinel,
276
327
  {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/collections-page.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState, useEffect, useRef } from \"react\";\nimport { Layers, BadgeCheck, Eye, SlidersHorizontal, Award, Sparkles, Package } from \"lucide-react\";\nimport { Button } from \"./button.js\";\nimport { Dialog, DialogContent, DialogTitle } from \"./dialog.js\";\nimport { HelpIcon } from \"./help-icon.js\";\nimport { PageContainer } from \"./page-container.js\";\nimport { CollectionCard, CollectionCardSkeleton } from \"./collection-card.js\";\nimport { LoadMoreSentinel } from \"./load-more-sentinel.js\";\nimport { cn } from \"../utils/cn.js\";\nimport { useCollections, type CollectionSort } from \"../utils/use-collections.js\";\nimport { usePlatformStats } from \"../utils/use-platform-stats.js\";\nimport type { ApiCollection } from \"@medialane/sdk\";\n\nconst PAGE_SIZE = 18;\n\nconst SORT_OPTIONS: { label: string; value: CollectionSort }[] = [\n { label: \"Recent\", value: \"recent\" },\n { label: \"Most assets\", value: \"supply\" },\n { label: \"Top volume\", value: \"volume\" },\n { label: \"Floor ↑\", value: \"floor\" },\n { label: \"A → Z\", value: \"name\" },\n];\n\nconst SERVICE_TABS = [\n { label: \"All\", value: undefined },\n { label: \"POP Events\", value: \"pop-protocol\" },\n { label: \"Drops\", value: \"drop-collection\" },\n] as const;\n\nexport function CollectionsPage() {\n const { stats } = usePlatformStats();\n const [sort, setSort] = useState<CollectionSort>(\"recent\");\n const [featured, setFeatured] = useState(false);\n const [hideEmpty, setHideEmpty] = useState(true);\n const [exclusive, setExclusive] = useState(false);\n const [service, setService] = useState<string | undefined>(undefined);\n const [filtersOpen, setFiltersOpen] = useState(false);\n const [page, setPage] = useState(1);\n const [allCollections, setAllCollections] = useState<ApiCollection[]>([]);\n\n const { collections, meta, isLoading } = useCollections(\n page,\n PAGE_SIZE,\n featured ? true : undefined,\n sort,\n service === \"pop-protocol\" || service === \"drop-collection\" ? false : hideEmpty,\n service,\n \"ERC721,ERC1155\"\n );\n\n const prevFilters = useRef({ sort, featured, hideEmpty, service });\n useEffect(() => {\n const f = prevFilters.current;\n if (f.sort !== sort || f.featured !== featured || f.hideEmpty !== hideEmpty || f.service !== service) {\n prevFilters.current = { sort, featured, hideEmpty, service };\n setPage(1);\n setAllCollections([]);\n }\n }, [sort, featured, hideEmpty, service]);\n\n useEffect(() => {\n if (isLoading || collections.length === 0) return;\n setAllCollections((prev) => {\n const ids = new Set(prev.map((c) => c.contractAddress));\n const next = collections.filter((c) => !ids.has(c.contractAddress));\n return page === 1 ? collections : [...prev, ...next];\n });\n }, [collections, isLoading, page]);\n\n const hasMore = meta?.total != null ? allCollections.length < meta.total : false;\n const isInitialLoading = isLoading && allCollections.length === 0;\n\n const activeFilters = [sort !== \"recent\", featured, !hideEmpty, exclusive].filter(Boolean).length;\n\n const displayCollections = exclusive\n ? allCollections.filter((c) => !!c.profile?.hasGatedContent)\n : allCollections;\n\n const resetAll = () => {\n setSort(\"recent\");\n setFeatured(false);\n setHideEmpty(true);\n setExclusive(false);\n };\n\n const handleServiceChange = (val: string | undefined) => {\n setService(val);\n };\n\n return (\n <PageContainer className=\"box-border max-w-full pt-14 pb-8 space-y-8\">\n\n <div className=\"space-y-2 pt-8\">\n\n <h1 className=\"text-3xl font-bold\">Onchain Collections</h1>\n <div className=\"flex flex-wrap items-center gap-2 mt-1\">\n {meta?.total != null && (\n <div className=\"flex items-center gap-1.5 rounded-full border border-border bg-card px-3.5 py-1.5 text-sm\">\n <span className=\"font-bold tabular-nums\">{(meta.total ?? 0).toLocaleString()}</span>\n <span className=\"text-muted-foreground\">Collections</span>\n </div>\n )}\n {stats?.tokens != null && (\n <div className=\"flex items-center gap-1.5 rounded-full border border-border bg-card px-3.5 py-1.5 text-sm\">\n <span className=\"font-bold tabular-nums\">{stats.tokens.toLocaleString()}</span>\n <span className=\"text-muted-foreground\">Assets</span>\n </div>\n )}\n {stats?.sales != null && (\n <div className=\"flex items-center gap-1.5 rounded-full border border-border bg-card px-3.5 py-1.5 text-sm\">\n <span className=\"font-bold tabular-nums\">{stats.sales.toLocaleString()}</span>\n <span className=\"text-muted-foreground\">Sales</span>\n </div>\n )}\n </div>\n </div>\n\n <div className=\"flex items-center gap-2 pb-3 border-b border-border/60 flex-wrap\">\n <button\n onClick={() => setFiltersOpen(true)}\n className={cn(\n \"relative flex items-center gap-1.5 h-9 px-3 rounded-lg border text-xs font-medium transition-colors\",\n activeFilters > 0 || service !== undefined\n ? \"border-primary bg-primary/10 text-primary\"\n : \"border-border text-muted-foreground hover:border-primary/50 hover:text-foreground\"\n )}\n >\n <SlidersHorizontal className=\"h-3.5 w-3.5\" />\n Filters\n {(activeFilters > 0 || service !== undefined) && (\n <span className=\"flex h-4 w-4 items-center justify-center rounded-full bg-primary text-2xs font-bold text-primary-foreground\">\n {activeFilters + (service !== undefined ? 1 : 0)}\n </span>\n )}\n </button>\n\n {service !== undefined && (\n <span className=\"flex items-center gap-1 text-xs px-2.5 py-1 rounded-full border border-primary/40 bg-primary/10 text-primary\">\n {service === \"drop-collection\" ? <Package className=\"h-3 w-3\" /> : <Award className=\"h-3 w-3\" />}\n {SERVICE_TABS.find((t) => t.value === service)?.label}\n <button onClick={() => setService(undefined)} className=\"ml-0.5 hover:text-primary/60\">×</button>\n </span>\n )}\n {sort !== \"recent\" && (\n <span className=\"flex items-center gap-1 text-xs px-2.5 py-1 rounded-full border border-primary/40 bg-primary/10 text-primary\">\n {SORT_OPTIONS.find((o) => o.value === sort)?.label}\n <button onClick={() => setSort(\"recent\")} className=\"ml-0.5 hover:text-primary/60\">×</button>\n </span>\n )}\n {featured && (\n <span className=\"flex items-center gap-1 text-xs px-2.5 py-1 rounded-full border border-primary/40 bg-primary/10 text-primary\">\n <BadgeCheck className=\"h-3 w-3\" />\n Featured\n <button onClick={() => setFeatured(false)} className=\"ml-0.5 hover:text-primary/60\">×</button>\n </span>\n )}\n {!hideEmpty && (\n <span className=\"flex items-center gap-1 text-xs px-2.5 py-1 rounded-full border border-primary/40 bg-primary/10 text-primary\">\n Show empty\n <button onClick={() => setHideEmpty(true)} className=\"ml-0.5 hover:text-primary/60\">×</button>\n </span>\n )}\n {exclusive && (\n <span className=\"flex items-center gap-1 text-xs px-2.5 py-1 rounded-full border border-primary/40 bg-primary/10 text-primary\">\n <Sparkles className=\"h-3 w-3\" />\n Exclusive\n <button onClick={() => setExclusive(false)} className=\"ml-0.5 hover:text-primary/60\">×</button>\n </span>\n )}\n </div>\n\n <Dialog open={filtersOpen} onOpenChange={setFiltersOpen}>\n <DialogContent className=\"w-full max-w-sm sm:max-w-md p-0 overflow-hidden gap-0 flex flex-col max-h-[85svh]\">\n\n <div className=\"flex items-center justify-between px-5 py-4 border-b border-border/60 pr-12\">\n <DialogTitle className=\"text-base font-bold flex items-center gap-2\">\n <SlidersHorizontal className=\"h-4 w-4 text-primary\" />\n Filters\n </DialogTitle>\n {(activeFilters > 0 || service !== undefined) && (\n <Button variant=\"ghost\" size=\"sm\" className=\"h-7 text-xs text-muted-foreground\" onClick={() => { resetAll(); setService(undefined); }}>\n Clear all\n </Button>\n )}\n </div>\n\n <div className=\"flex-1 overflow-y-auto px-5 py-4 space-y-5\">\n\n <div className=\"space-y-2\">\n <p className=\"text-2xs font-semibold text-muted-foreground\">Source</p>\n <div className=\"flex flex-wrap gap-1.5\">\n {SERVICE_TABS.map(({ label, value }) => (\n <button\n key={label}\n onClick={() => handleServiceChange(value)}\n className={cn(\n \"flex items-center gap-1.5 text-xs px-3 py-1.5 rounded-full border transition-colors whitespace-nowrap\",\n service === value\n ? \"border-primary bg-primary/10 text-primary font-medium\"\n : \"border-border text-muted-foreground hover:border-primary/50\"\n )}\n >\n {value === \"pop-protocol\" && <Award className=\"h-3 w-3\" />}\n {value === \"drop-collection\" && <Package className=\"h-3 w-3\" />}\n {label}\n </button>\n ))}\n </div>\n </div>\n\n <div className=\"space-y-2\">\n <p className=\"text-2xs font-semibold text-muted-foreground\">Sort</p>\n <div className=\"flex flex-wrap gap-1.5\">\n {SORT_OPTIONS.map((opt) => (\n <button\n key={opt.value}\n onClick={() => setSort(opt.value)}\n className={cn(\n \"text-xs px-3 py-1.5 rounded-full border transition-colors whitespace-nowrap\",\n sort === opt.value\n ? \"border-primary bg-primary/10 text-primary font-medium\"\n : \"border-border text-muted-foreground hover:border-primary/50\"\n )}\n >\n {opt.label}\n </button>\n ))}\n </div>\n </div>\n\n <div className=\"space-y-2\">\n <p className=\"text-2xs font-semibold text-muted-foreground\">Show</p>\n <div className=\"flex flex-col gap-2\">\n <div className=\"flex items-center gap-2\">\n <button\n onClick={() => setFeatured((v) => !v)}\n className={cn(\n \"flex flex-1 items-center gap-2 text-sm px-3 py-2 rounded-lg border transition-colors text-left\",\n featured\n ? \"border-primary bg-primary/10 text-primary\"\n : \"border-border text-muted-foreground hover:border-primary/50\"\n )}\n >\n <BadgeCheck className=\"h-4 w-4 shrink-0\" />\n Featured only\n </button>\n <HelpIcon content=\"Show only collections featured by Medialane\" side=\"left\" />\n </div>\n <div className=\"flex items-center gap-2\">\n <button\n onClick={() => setHideEmpty((v) => !v)}\n className={cn(\n \"flex flex-1 items-center gap-2 text-sm px-3 py-2 rounded-lg border transition-colors text-left\",\n !hideEmpty\n ? \"border-primary bg-primary/10 text-primary\"\n : \"border-border text-muted-foreground hover:border-primary/50\"\n )}\n >\n <Eye className=\"h-4 w-4 shrink-0\" />\n Show empty collections\n </button>\n <HelpIcon content=\"Include collections with no minted assets yet — hidden by default to keep the feed clean\" side=\"left\" />\n </div>\n <div className=\"flex items-center gap-2\">\n <button\n onClick={() => setExclusive((v) => !v)}\n className={cn(\n \"flex flex-1 items-center gap-2 text-sm px-3 py-2 rounded-lg border transition-colors text-left\",\n exclusive\n ? \"border-primary bg-primary/10 text-primary\"\n : \"border-border text-muted-foreground hover:border-primary/50\"\n )}\n >\n <Sparkles className=\"h-4 w-4 shrink-0\" />\n Exclusive content only\n </button>\n <HelpIcon content=\"Show only collections with holder-exclusive content\" side=\"left\" />\n </div>\n </div>\n </div>\n\n </div>\n\n <div className=\"px-5 py-3 border-t border-border/60\">\n <Button className=\"w-full\" onClick={() => setFiltersOpen(false)}>\n Apply filters\n </Button>\n </div>\n\n </DialogContent>\n </Dialog>\n\n {isInitialLoading ? (\n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-5\">\n {Array.from({ length: 9 }).map((_, i) => <CollectionCardSkeleton key={i} />)}\n </div>\n ) : allCollections.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center py-24 gap-4 text-center\">\n <Layers className=\"h-12 w-12 text-muted-foreground/30\" />\n <p className=\"text-2xl font-bold\">No collections found</p>\n <p className=\"text-muted-foreground max-w-sm\">\n {featured\n ? \"No featured collections match the current filters.\"\n : hideEmpty\n ? \"No collections with assets yet.\"\n : \"Deploy the first collection on Medialane.\"}\n </p>\n {activeFilters > 0 && (\n <Button variant=\"outline\" size=\"sm\" onClick={resetAll}>\n Clear filters\n </Button>\n )}\n </div>\n ) : (\n <div className=\"space-y-6\">\n {exclusive && displayCollections.length === 0 && (\n <div className=\"flex flex-col items-center justify-center py-16 gap-3 text-center\">\n <Sparkles className=\"h-10 w-10 text-muted-foreground/30\" />\n <p className=\"text-base font-semibold text-muted-foreground\">No exclusive collections in this batch</p>\n <p className=\"text-sm text-muted-foreground/70 max-w-xs\">Load more collections below, then the filter will catch them.</p>\n </div>\n )}\n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-5\">\n {displayCollections.map((col) => (\n <CollectionCard key={col.contractAddress} collection={col} />\n ))}\n </div>\n\n <LoadMoreSentinel\n hasMore={hasMore}\n isLoading={isLoading}\n onLoadMore={() => setPage((p) => p + 1)}\n />\n </div>\n )}\n </PageContainer>\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/components/collections-page.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState, useEffect, useRef } from \"react\";\nimport useSWR from \"swr\";\nimport { Layers, BadgeCheck, Eye, SlidersHorizontal, Award, Package, ArrowDownUp, Search, X } from \"lucide-react\";\nimport { Button } from \"./button.js\";\nimport { Dialog, DialogContent, DialogTitle } from \"./dialog.js\";\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from \"./select.js\";\nimport { HelpIcon } from \"./help-icon.js\";\nimport { Input } from \"./input.js\";\nimport { ResultThumbnail } from \"./result-thumbnail.js\";\nimport Link from \"./link.js\";\nimport { useRouter } from \"./router.js\";\nimport { PageContainer } from \"./page-container.js\";\nimport { ScrollSection } from \"./scroll-section.js\";\nimport { CollectionCard, CollectionCardSkeleton } from \"./collection-card.js\";\nimport { LoadMoreSentinel } from \"./load-more-sentinel.js\";\nimport { cn } from \"../utils/cn.js\";\nimport { useCollections, type CollectionSort } from \"../utils/use-collections.js\";\nimport { useMedialaneClient } from \"../utils/use-medialane-client.js\";\nimport { SEARCH_MIN_LENGTH, useSearch } from \"../utils/use-search.js\";\nimport { collectionHref, type ApiCollection } from \"@medialane/sdk\";\n\nconst PAGE_SIZE = 24;\n\nconst SORT_OPTIONS: { label: string; value: CollectionSort }[] = [\n { label: \"Recent\", value: \"recent\" },\n { label: \"Most assets\", value: \"supply\" },\n { label: \"Top volume\", value: \"volume\" },\n { label: \"Floor ↑\", value: \"floor\" },\n { label: \"A → Z\", value: \"name\" },\n];\n\nconst SERVICE_TABS = [\n { label: \"All\", value: undefined },\n { label: \"POP Events\", value: \"pop-protocol\" },\n { label: \"Drops\", value: \"drop-collection\" },\n] as const;\n\nfunction useStandardCounts() {\n const client = useMedialaneClient();\n const { data } = useSWR(\n \"collection-standard-counts\",\n async () => {\n const [single, multi] = await Promise.all(\n [\"ERC721\", \"ERC1155\"].map((standard) =>\n client.api.collections.list({ standard, hideEmpty: true, limit: 1 })\n )\n );\n return { single: single.meta?.total, multi: multi.meta?.total };\n },\n { revalidateOnFocus: false, dedupingInterval: 60_000 }\n );\n return data ?? null;\n}\n\nfunction CollectionSearch() {\n const router = useRouter();\n const [value, setValue] = useState(\"\");\n const [query, setQuery] = useState(\"\");\n const [open, setOpen] = useState(false);\n const { results } = useSearch(query, { limit: 6 });\n const matches = results?.collections ?? [];\n\n useEffect(() => {\n const timer = setTimeout(() => setQuery(value), 300);\n return () => clearTimeout(timer);\n }, [value]);\n\n const clear = () => {\n setValue(\"\");\n setQuery(\"\");\n setOpen(false);\n };\n\n return (\n <div className=\"relative w-full sm:max-w-sm sm:flex-1\">\n <Search className=\"pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground\" />\n <Input\n className=\"h-9 pl-9 pr-9 text-sm\"\n placeholder=\"Search collections\"\n aria-label=\"Search collections\"\n value={value}\n onChange={(e) => { setValue(e.target.value); setOpen(true); }}\n onFocus={() => setOpen(true)}\n onBlur={() => setTimeout(() => setOpen(false), 200)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" && value.trim().length >= SEARCH_MIN_LENGTH) {\n router.push(`/search?q=${encodeURIComponent(value.trim())}`);\n }\n }}\n />\n {value && (\n <button\n aria-label=\"Clear search\"\n className=\"absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground\"\n onClick={clear}\n >\n <X className=\"h-3.5 w-3.5\" />\n </button>\n )}\n {open && matches.length > 0 && (\n <div className=\"absolute left-0 right-0 top-full z-50 mt-1 overflow-hidden rounded-xl border border-border bg-popover shadow-lg\">\n {matches.map((col) => {\n const label = col.name ?? \"Untitled\";\n return (\n <Link\n key={col.contractAddress}\n href={collectionHref(\"STARKNET\", col.contractAddress)}\n className=\"flex items-center gap-3 px-3 py-2.5 transition-colors hover:bg-muted/50\"\n >\n <ResultThumbnail src={col.image} label={label} />\n <span className=\"truncate text-sm font-medium\">{label}</span>\n </Link>\n );\n })}\n </div>\n )}\n </div>\n );\n}\n\nexport function CollectionsPage() {\n const counts = useStandardCounts();\n const [sort, setSort] = useState<CollectionSort>(\"recent\");\n const [hideEmpty, setHideEmpty] = useState(true);\n const [service, setService] = useState<string | undefined>(undefined);\n const [filtersOpen, setFiltersOpen] = useState(false);\n const [page, setPage] = useState(1);\n const [allCollections, setAllCollections] = useState<ApiCollection[]>([]);\n\n const { collections, meta, isLoading } = useCollections(\n page,\n PAGE_SIZE,\n undefined,\n sort,\n service === \"pop-protocol\" || service === \"drop-collection\" ? false : hideEmpty,\n service,\n \"ERC721,ERC1155\"\n );\n\n const { collections: featuredCollections, isLoading: featuredLoading } = useCollections(\n 1,\n 8,\n true,\n \"recent\",\n true,\n undefined,\n \"ERC721,ERC1155\"\n );\n\n const prevFilters = useRef({ sort, hideEmpty, service });\n useEffect(() => {\n const f = prevFilters.current;\n if (f.sort !== sort || f.hideEmpty !== hideEmpty || f.service !== service) {\n prevFilters.current = { sort, hideEmpty, service };\n setPage(1);\n setAllCollections([]);\n }\n }, [sort, hideEmpty, service]);\n\n useEffect(() => {\n if (isLoading || collections.length === 0) return;\n setAllCollections((prev) => {\n const ids = new Set(prev.map((c) => c.contractAddress));\n const next = collections.filter((c) => !ids.has(c.contractAddress));\n return page === 1 ? collections : [...prev, ...next];\n });\n }, [collections, isLoading, page]);\n\n const hasMore = meta?.total != null ? allCollections.length < meta.total : false;\n const isInitialLoading = isLoading && allCollections.length === 0;\n\n const activeFilters = [!hideEmpty].filter(Boolean).length;\n\n const resetAll = () => {\n setHideEmpty(true);\n };\n\n const handleServiceChange = (val: string | undefined) => {\n setService(val);\n };\n\n return (\n <PageContainer className=\"box-border max-w-full pt-14 pb-8 space-y-8\">\n\n <div className=\"space-y-2 pt-8\">\n\n <h1 className=\"text-3xl font-bold\">Onchain Collections</h1>\n <div className=\"flex flex-wrap items-center gap-2 mt-1\">\n {counts?.single != null && (\n <div className=\"flex items-center gap-1.5 rounded-full border border-border bg-card px-3.5 py-1.5 text-sm\">\n <span className=\"font-bold tabular-nums\">{counts.single.toLocaleString()}</span>\n <span className=\"text-muted-foreground\">Single NFTs</span>\n </div>\n )}\n {counts?.multi != null && (\n <div className=\"flex items-center gap-1.5 rounded-full border border-border bg-card px-3.5 py-1.5 text-sm\">\n <span className=\"font-bold tabular-nums\">{counts.multi.toLocaleString()}</span>\n <span className=\"text-muted-foreground\">Multi editions</span>\n </div>\n )}\n </div>\n </div>\n\n {(featuredLoading || featuredCollections.length > 0) && (\n <ScrollSection\n icon={<BadgeCheck className=\"h-3.5 w-3.5 text-white\" />}\n iconBg=\"bg-gradient-to-br from-brand-blue to-indigo-600 shadow-md shadow-brand-blue/20\"\n title=\"Featured\"\n >\n {featuredLoading\n ? Array.from({ length: 4 }).map((_, i) => (\n <div key={i} className=\"w-56 shrink-0 snap-start sm:w-64\"><CollectionCardSkeleton /></div>\n ))\n : featuredCollections.map((col) => (\n <div key={col.contractAddress} className=\"w-56 shrink-0 snap-start sm:w-64\">\n <CollectionCard collection={col} />\n </div>\n ))}\n </ScrollSection>\n )}\n\n <div className=\"space-y-3\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <CollectionSearch />\n <div className=\"flex items-center gap-2 sm:ml-auto\">\n <Select value={sort} onValueChange={(v) => setSort(v as CollectionSort)}>\n <SelectTrigger className=\"h-9 w-auto gap-1.5 text-xs\" aria-label=\"Sort collections\">\n <ArrowDownUp className=\"h-3.5 w-3.5 text-muted-foreground\" />\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {SORT_OPTIONS.map((opt) => (\n <SelectItem key={opt.value} value={opt.value} className=\"text-xs\">{opt.label}</SelectItem>\n ))}\n </SelectContent>\n </Select>\n <button\n onClick={() => setFiltersOpen(true)}\n className={cn(\n \"relative flex items-center gap-1.5 h-9 px-3 rounded-lg border text-xs font-medium transition-colors\",\n activeFilters > 0 || service !== undefined\n ? \"border-primary bg-primary/10 text-primary\"\n : \"border-border text-muted-foreground hover:border-primary/50 hover:text-foreground\"\n )}\n >\n <SlidersHorizontal className=\"h-3.5 w-3.5\" />\n Filters\n {(activeFilters > 0 || service !== undefined) && (\n <span className=\"flex h-4 w-4 items-center justify-center rounded-full bg-primary text-2xs font-bold text-primary-foreground\">\n {activeFilters + (service !== undefined ? 1 : 0)}\n </span>\n )}\n </button>\n </div>\n </div>\n {(service !== undefined || !hideEmpty) && (\n <div className=\"flex flex-wrap items-center gap-2\">\n {service !== undefined && (\n <span className=\"flex items-center gap-1 text-xs px-2.5 py-1 rounded-full border border-primary/40 bg-primary/10 text-primary\">\n {service === \"drop-collection\" ? <Package className=\"h-3 w-3\" /> : <Award className=\"h-3 w-3\" />}\n {SERVICE_TABS.find((t) => t.value === service)?.label}\n <button onClick={() => setService(undefined)} className=\"ml-0.5 hover:text-primary/60\" aria-label=\"Remove source filter\">×</button>\n </span>\n )}\n {!hideEmpty && (\n <span className=\"flex items-center gap-1 text-xs px-2.5 py-1 rounded-full border border-primary/40 bg-primary/10 text-primary\">\n Show empty\n <button onClick={() => setHideEmpty(true)} className=\"ml-0.5 hover:text-primary/60\" aria-label=\"Remove show empty filter\">×</button>\n </span>\n )}\n </div>\n )}\n </div>\n\n <Dialog open={filtersOpen} onOpenChange={setFiltersOpen}>\n <DialogContent className=\"w-full max-w-sm sm:max-w-md p-0 overflow-hidden gap-0 flex flex-col max-h-[85svh]\">\n\n <div className=\"flex items-center justify-between px-5 py-4 border-b border-border/60 pr-12\">\n <DialogTitle className=\"text-base font-bold flex items-center gap-2\">\n <SlidersHorizontal className=\"h-4 w-4 text-primary\" />\n Filters\n </DialogTitle>\n {(activeFilters > 0 || service !== undefined) && (\n <Button variant=\"ghost\" size=\"sm\" className=\"h-7 text-xs text-muted-foreground\" onClick={() => { resetAll(); setService(undefined); }}>\n Clear all\n </Button>\n )}\n </div>\n\n <div className=\"flex-1 overflow-y-auto px-5 py-4 space-y-5\">\n\n <div className=\"space-y-2\">\n <p className=\"text-2xs font-semibold text-muted-foreground\">Source</p>\n <div className=\"flex flex-wrap gap-1.5\">\n {SERVICE_TABS.map(({ label, value }) => (\n <button\n key={label}\n onClick={() => handleServiceChange(value)}\n className={cn(\n \"flex items-center gap-1.5 text-xs px-3 py-1.5 rounded-full border transition-colors whitespace-nowrap\",\n service === value\n ? \"border-primary bg-primary/10 text-primary font-medium\"\n : \"border-border text-muted-foreground hover:border-primary/50\"\n )}\n >\n {value === \"pop-protocol\" && <Award className=\"h-3 w-3\" />}\n {value === \"drop-collection\" && <Package className=\"h-3 w-3\" />}\n {label}\n </button>\n ))}\n </div>\n </div>\n\n <div className=\"space-y-2\">\n <p className=\"text-2xs font-semibold text-muted-foreground\">Show</p>\n <div className=\"flex flex-col gap-2\">\n <div className=\"flex items-center gap-2\">\n <button\n onClick={() => setHideEmpty((v) => !v)}\n className={cn(\n \"flex flex-1 items-center gap-2 text-sm px-3 py-2 rounded-lg border transition-colors text-left\",\n !hideEmpty\n ? \"border-primary bg-primary/10 text-primary\"\n : \"border-border text-muted-foreground hover:border-primary/50\"\n )}\n >\n <Eye className=\"h-4 w-4 shrink-0\" />\n Show empty collections\n </button>\n <HelpIcon content=\"Include collections with no minted assets yet — hidden by default to keep the feed clean\" side=\"left\" />\n </div>\n </div>\n </div>\n\n </div>\n\n <div className=\"px-5 py-3 border-t border-border/60\">\n <Button className=\"w-full\" onClick={() => setFiltersOpen(false)}>\n Show results\n </Button>\n </div>\n\n </DialogContent>\n </Dialog>\n\n {isInitialLoading ? (\n <div className=\"grid grid-cols-2 lg:grid-cols-4 gap-4 sm:gap-5\">\n {Array.from({ length: 8 }).map((_, i) => <CollectionCardSkeleton key={i} />)}\n </div>\n ) : allCollections.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center py-24 gap-4 text-center\">\n <Layers className=\"h-12 w-12 text-muted-foreground/30\" />\n <p className=\"text-2xl font-bold\">No collections found</p>\n <p className=\"text-muted-foreground max-w-sm\">\n {hideEmpty\n ? \"No collections with assets yet.\"\n : \"Deploy the first collection on Medialane.\"}\n </p>\n {activeFilters > 0 && (\n <Button variant=\"outline\" size=\"sm\" onClick={resetAll}>\n Clear filters\n </Button>\n )}\n </div>\n ) : (\n <div className=\"space-y-6\">\n <div className=\"grid grid-cols-2 lg:grid-cols-4 gap-4 sm:gap-5\">\n {allCollections.map((col) => (\n <CollectionCard key={col.contractAddress} collection={col} />\n ))}\n </div>\n\n <LoadMoreSentinel\n hasMore={hasMore}\n isLoading={isLoading}\n onLoadMore={() => setPage((p) => p + 1)}\n />\n </div>\n )}\n </PageContainer>\n );\n}\n"],"mappings":"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","names":["useSWR","Link"]}