@medialane/ui 0.251.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 (73) 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/asset-page.cjs +11 -4
  4. package/dist/components/asset-page.cjs.map +1 -1
  5. package/dist/components/asset-page.js +11 -4
  6. package/dist/components/asset-page.js.map +1 -1
  7. package/dist/components/asset-publication.cjs +5 -13
  8. package/dist/components/asset-publication.cjs.map +1 -1
  9. package/dist/components/asset-publication.d.cts +2 -2
  10. package/dist/components/asset-publication.d.ts +2 -2
  11. package/dist/components/asset-publication.js +5 -13
  12. package/dist/components/asset-publication.js.map +1 -1
  13. package/dist/components/asset-top-sections.cjs +9 -1
  14. package/dist/components/asset-top-sections.cjs.map +1 -1
  15. package/dist/components/asset-top-sections.d.cts +2 -1
  16. package/dist/components/asset-top-sections.d.ts +2 -1
  17. package/dist/components/asset-top-sections.js +9 -1
  18. package/dist/components/asset-top-sections.js.map +1 -1
  19. package/dist/components/button.d.cts +2 -2
  20. package/dist/components/button.d.ts +2 -2
  21. package/dist/components/collection-card.cjs +11 -19
  22. package/dist/components/collection-card.cjs.map +1 -1
  23. package/dist/components/collection-card.js +11 -19
  24. package/dist/components/collection-card.js.map +1 -1
  25. package/dist/components/collections-page.cjs +190 -139
  26. package/dist/components/collections-page.cjs.map +1 -1
  27. package/dist/components/collections-page.js +181 -140
  28. package/dist/components/collections-page.js.map +1 -1
  29. package/dist/components/creator-page.cjs +1 -1
  30. package/dist/components/creator-page.cjs.map +1 -1
  31. package/dist/components/creator-page.js +1 -1
  32. package/dist/components/creator-page.js.map +1 -1
  33. package/dist/components/drop/create/drop-create.cjs +1 -1
  34. package/dist/components/drop/create/drop-create.cjs.map +1 -1
  35. package/dist/components/drop/create/drop-create.js +1 -1
  36. package/dist/components/drop/create/drop-create.js.map +1 -1
  37. package/dist/components/drop/create/launch-dialog.cjs +1 -1
  38. package/dist/components/drop/create/launch-dialog.cjs.map +1 -1
  39. package/dist/components/drop/create/launch-dialog.js +1 -1
  40. package/dist/components/drop/create/launch-dialog.js.map +1 -1
  41. package/dist/components/fast-mint/fast-mint.d.cts +2 -2
  42. package/dist/components/fast-mint/fast-mint.d.ts +2 -2
  43. package/dist/components/hero-slider.cjs +2 -1
  44. package/dist/components/hero-slider.cjs.map +1 -1
  45. package/dist/components/hero-slider.js +2 -1
  46. package/dist/components/hero-slider.js.map +1 -1
  47. package/dist/components/launchpad/edition-mint-schema.d.cts +2 -2
  48. package/dist/components/launchpad/edition-mint-schema.d.ts +2 -2
  49. package/dist/components/scroll-section.cjs +1 -1
  50. package/dist/components/scroll-section.cjs.map +1 -1
  51. package/dist/components/scroll-section.d.cts +1 -1
  52. package/dist/components/scroll-section.d.ts +1 -1
  53. package/dist/components/scroll-section.js +1 -1
  54. package/dist/components/scroll-section.js.map +1 -1
  55. package/dist/components/sheet.d.cts +1 -1
  56. package/dist/components/sheet.d.ts +1 -1
  57. package/dist/utils/external-link.cjs +44 -0
  58. package/dist/utils/external-link.cjs.map +1 -0
  59. package/dist/utils/external-link.d.cts +4 -0
  60. package/dist/utils/external-link.d.ts +4 -0
  61. package/dist/utils/external-link.js +19 -0
  62. package/dist/utils/external-link.js.map +1 -0
  63. package/dist/utils/use-collections.cjs +1 -2
  64. package/dist/utils/use-collections.cjs.map +1 -1
  65. package/dist/utils/use-collections.d.cts +3 -0
  66. package/dist/utils/use-collections.d.ts +3 -0
  67. package/dist/utils/use-collections.js +1 -2
  68. package/dist/utils/use-collections.js.map +1 -1
  69. package/dist/utils/use-tokens-by-ip-type.d.cts +2 -0
  70. package/dist/utils/use-tokens-by-ip-type.d.ts +2 -0
  71. package/dist/utils/use-tokens.d.cts +4 -0
  72. package/dist/utils/use-tokens.d.ts +4 -0
  73. package/package.json +3 -3
@@ -1,17 +1,26 @@
1
1
  "use client";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import { useState, useEffect, useRef } from "react";
4
- import { Layers, BadgeCheck, Eye, SlidersHorizontal, Award, Sparkles, Package } from "lucide-react";
4
+ import useSWR from "swr";
5
+ import { Layers, BadgeCheck, Eye, SlidersHorizontal, Award, Package, ArrowDownUp, Search, X } from "lucide-react";
5
6
  import { Button } from "./button.js";
6
7
  import { Dialog, DialogContent, DialogTitle } from "./dialog.js";
8
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "./select.js";
7
9
  import { HelpIcon } from "./help-icon.js";
10
+ import { Input } from "./input.js";
11
+ import { ResultThumbnail } from "./result-thumbnail.js";
12
+ import Link from "./link.js";
13
+ import { useRouter } from "./router.js";
8
14
  import { PageContainer } from "./page-container.js";
15
+ import { ScrollSection } from "./scroll-section.js";
9
16
  import { CollectionCard, CollectionCardSkeleton } from "./collection-card.js";
10
17
  import { LoadMoreSentinel } from "./load-more-sentinel.js";
11
18
  import { cn } from "../utils/cn.js";
12
19
  import { useCollections } from "../utils/use-collections.js";
13
- import { usePlatformStats } from "../utils/use-platform-stats.js";
14
- const PAGE_SIZE = 18;
20
+ import { useMedialaneClient } from "../utils/use-medialane-client.js";
21
+ import { SEARCH_MIN_LENGTH, useSearch } from "../utils/use-search.js";
22
+ import { collectionHref } from "@medialane/sdk";
23
+ const PAGE_SIZE = 24;
15
24
  const SORT_OPTIONS = [
16
25
  { label: "Recent", value: "recent" },
17
26
  { label: "Most assets", value: "supply" },
@@ -24,12 +33,90 @@ const SERVICE_TABS = [
24
33
  { label: "POP Events", value: "pop-protocol" },
25
34
  { label: "Drops", value: "drop-collection" }
26
35
  ];
36
+ function useStandardCounts() {
37
+ const client = useMedialaneClient();
38
+ const { data } = useSWR(
39
+ "collection-standard-counts",
40
+ async () => {
41
+ const [single, multi] = await Promise.all(
42
+ ["ERC721", "ERC1155"].map(
43
+ (standard) => client.api.collections.list({ standard, hideEmpty: true, limit: 1 })
44
+ )
45
+ );
46
+ return { single: single.meta?.total, multi: multi.meta?.total };
47
+ },
48
+ { revalidateOnFocus: false, dedupingInterval: 6e4 }
49
+ );
50
+ return data ?? null;
51
+ }
52
+ function CollectionSearch() {
53
+ const router = useRouter();
54
+ const [value, setValue] = useState("");
55
+ const [query, setQuery] = useState("");
56
+ const [open, setOpen] = useState(false);
57
+ const { results } = useSearch(query, { limit: 6 });
58
+ const matches = results?.collections ?? [];
59
+ useEffect(() => {
60
+ const timer = setTimeout(() => setQuery(value), 300);
61
+ return () => clearTimeout(timer);
62
+ }, [value]);
63
+ const clear = () => {
64
+ setValue("");
65
+ setQuery("");
66
+ setOpen(false);
67
+ };
68
+ return /* @__PURE__ */ jsxs("div", { className: "relative w-full sm:max-w-sm sm:flex-1", children: [
69
+ /* @__PURE__ */ jsx(Search, { className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
70
+ /* @__PURE__ */ jsx(
71
+ Input,
72
+ {
73
+ className: "h-9 pl-9 pr-9 text-sm",
74
+ placeholder: "Search collections",
75
+ "aria-label": "Search collections",
76
+ value,
77
+ onChange: (e) => {
78
+ setValue(e.target.value);
79
+ setOpen(true);
80
+ },
81
+ onFocus: () => setOpen(true),
82
+ onBlur: () => setTimeout(() => setOpen(false), 200),
83
+ onKeyDown: (e) => {
84
+ if (e.key === "Enter" && value.trim().length >= SEARCH_MIN_LENGTH) {
85
+ router.push(`/search?q=${encodeURIComponent(value.trim())}`);
86
+ }
87
+ }
88
+ }
89
+ ),
90
+ value && /* @__PURE__ */ jsx(
91
+ "button",
92
+ {
93
+ "aria-label": "Clear search",
94
+ className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
95
+ onClick: clear,
96
+ children: /* @__PURE__ */ jsx(X, { className: "h-3.5 w-3.5" })
97
+ }
98
+ ),
99
+ open && matches.length > 0 && /* @__PURE__ */ 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) => {
100
+ const label = col.name ?? "Untitled";
101
+ return /* @__PURE__ */ jsxs(
102
+ Link,
103
+ {
104
+ href: collectionHref("STARKNET", col.contractAddress),
105
+ className: "flex items-center gap-3 px-3 py-2.5 transition-colors hover:bg-muted/50",
106
+ children: [
107
+ /* @__PURE__ */ jsx(ResultThumbnail, { src: col.image, label }),
108
+ /* @__PURE__ */ jsx("span", { className: "truncate text-sm font-medium", children: label })
109
+ ]
110
+ },
111
+ col.contractAddress
112
+ );
113
+ }) })
114
+ ] });
115
+ }
27
116
  function CollectionsPage() {
28
- const { stats } = usePlatformStats();
117
+ const counts = useStandardCounts();
29
118
  const [sort, setSort] = useState("recent");
30
- const [featured, setFeatured] = useState(false);
31
119
  const [hideEmpty, setHideEmpty] = useState(true);
32
- const [exclusive, setExclusive] = useState(false);
33
120
  const [service, setService] = useState(void 0);
34
121
  const [filtersOpen, setFiltersOpen] = useState(false);
35
122
  const [page, setPage] = useState(1);
@@ -37,21 +124,30 @@ function CollectionsPage() {
37
124
  const { collections, meta, isLoading } = useCollections(
38
125
  page,
39
126
  PAGE_SIZE,
40
- featured ? true : void 0,
127
+ void 0,
41
128
  sort,
42
129
  service === "pop-protocol" || service === "drop-collection" ? false : hideEmpty,
43
130
  service,
44
131
  "ERC721,ERC1155"
45
132
  );
46
- const prevFilters = useRef({ sort, featured, hideEmpty, service });
133
+ const { collections: featuredCollections, isLoading: featuredLoading } = useCollections(
134
+ 1,
135
+ 8,
136
+ true,
137
+ "recent",
138
+ true,
139
+ void 0,
140
+ "ERC721,ERC1155"
141
+ );
142
+ const prevFilters = useRef({ sort, hideEmpty, service });
47
143
  useEffect(() => {
48
144
  const f = prevFilters.current;
49
- if (f.sort !== sort || f.featured !== featured || f.hideEmpty !== hideEmpty || f.service !== service) {
50
- prevFilters.current = { sort, featured, hideEmpty, service };
145
+ if (f.sort !== sort || f.hideEmpty !== hideEmpty || f.service !== service) {
146
+ prevFilters.current = { sort, hideEmpty, service };
51
147
  setPage(1);
52
148
  setAllCollections([]);
53
149
  }
54
- }, [sort, featured, hideEmpty, service]);
150
+ }, [sort, hideEmpty, service]);
55
151
  useEffect(() => {
56
152
  if (isLoading || collections.length === 0) return;
57
153
  setAllCollections((prev) => {
@@ -62,13 +158,9 @@ function CollectionsPage() {
62
158
  }, [collections, isLoading, page]);
63
159
  const hasMore = meta?.total != null ? allCollections.length < meta.total : false;
64
160
  const isInitialLoading = isLoading && allCollections.length === 0;
65
- const activeFilters = [sort !== "recent", featured, !hideEmpty, exclusive].filter(Boolean).length;
66
- const displayCollections = exclusive ? allCollections.filter((c) => !!c.profile?.hasGatedContent) : allCollections;
161
+ const activeFilters = [!hideEmpty].filter(Boolean).length;
67
162
  const resetAll = () => {
68
- setSort("recent");
69
- setFeatured(false);
70
163
  setHideEmpty(true);
71
- setExclusive(false);
72
164
  };
73
165
  const handleServiceChange = (val) => {
74
166
  setService(val);
@@ -77,58 +169,63 @@ function CollectionsPage() {
77
169
  /* @__PURE__ */ jsxs("div", { className: "space-y-2 pt-8", children: [
78
170
  /* @__PURE__ */ jsx("h1", { className: "text-3xl font-bold", children: "Onchain Collections" }),
79
171
  /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2 mt-1", children: [
80
- meta?.total != null && /* @__PURE__ */ 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: [
81
- /* @__PURE__ */ jsx("span", { className: "font-bold tabular-nums", children: (meta.total ?? 0).toLocaleString() }),
82
- /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Collections" })
83
- ] }),
84
- stats?.tokens != null && /* @__PURE__ */ 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: [
85
- /* @__PURE__ */ jsx("span", { className: "font-bold tabular-nums", children: stats.tokens.toLocaleString() }),
86
- /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Assets" })
172
+ counts?.single != null && /* @__PURE__ */ 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: [
173
+ /* @__PURE__ */ jsx("span", { className: "font-bold tabular-nums", children: counts.single.toLocaleString() }),
174
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Single NFTs" })
87
175
  ] }),
88
- stats?.sales != null && /* @__PURE__ */ 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: [
89
- /* @__PURE__ */ jsx("span", { className: "font-bold tabular-nums", children: stats.sales.toLocaleString() }),
90
- /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Sales" })
176
+ counts?.multi != null && /* @__PURE__ */ 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: [
177
+ /* @__PURE__ */ jsx("span", { className: "font-bold tabular-nums", children: counts.multi.toLocaleString() }),
178
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Multi editions" })
91
179
  ] })
92
180
  ] })
93
181
  ] }),
94
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 pb-3 border-b border-border/60 flex-wrap", children: [
95
- /* @__PURE__ */ jsxs(
96
- "button",
97
- {
98
- onClick: () => setFiltersOpen(true),
99
- className: cn(
100
- "relative flex items-center gap-1.5 h-9 px-3 rounded-lg border text-xs font-medium transition-colors",
101
- activeFilters > 0 || service !== void 0 ? "border-primary bg-primary/10 text-primary" : "border-border text-muted-foreground hover:border-primary/50 hover:text-foreground"
102
- ),
103
- children: [
104
- /* @__PURE__ */ jsx(SlidersHorizontal, { className: "h-3.5 w-3.5" }),
105
- "Filters",
106
- (activeFilters > 0 || service !== void 0) && /* @__PURE__ */ 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) })
107
- ]
108
- }
109
- ),
110
- service !== void 0 && /* @__PURE__ */ 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: [
111
- service === "drop-collection" ? /* @__PURE__ */ jsx(Package, { className: "h-3 w-3" }) : /* @__PURE__ */ jsx(Award, { className: "h-3 w-3" }),
112
- SERVICE_TABS.find((t) => t.value === service)?.label,
113
- /* @__PURE__ */ jsx("button", { onClick: () => setService(void 0), className: "ml-0.5 hover:text-primary/60", children: "\xD7" })
114
- ] }),
115
- sort !== "recent" && /* @__PURE__ */ 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: [
116
- SORT_OPTIONS.find((o) => o.value === sort)?.label,
117
- /* @__PURE__ */ jsx("button", { onClick: () => setSort("recent"), className: "ml-0.5 hover:text-primary/60", children: "\xD7" })
118
- ] }),
119
- featured && /* @__PURE__ */ 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: [
120
- /* @__PURE__ */ jsx(BadgeCheck, { className: "h-3 w-3" }),
121
- "Featured",
122
- /* @__PURE__ */ jsx("button", { onClick: () => setFeatured(false), className: "ml-0.5 hover:text-primary/60", children: "\xD7" })
123
- ] }),
124
- !hideEmpty && /* @__PURE__ */ 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: [
125
- "Show empty",
126
- /* @__PURE__ */ jsx("button", { onClick: () => setHideEmpty(true), className: "ml-0.5 hover:text-primary/60", children: "\xD7" })
182
+ (featuredLoading || featuredCollections.length > 0) && /* @__PURE__ */ jsx(
183
+ ScrollSection,
184
+ {
185
+ icon: /* @__PURE__ */ jsx(BadgeCheck, { className: "h-3.5 w-3.5 text-white" }),
186
+ iconBg: "bg-gradient-to-br from-brand-blue to-indigo-600 shadow-md shadow-brand-blue/20",
187
+ title: "Featured",
188
+ children: featuredLoading ? Array.from({ length: 4 }).map((_, i) => /* @__PURE__ */ jsx("div", { className: "w-56 shrink-0 snap-start sm:w-64", children: /* @__PURE__ */ jsx(CollectionCardSkeleton, {}) }, i)) : featuredCollections.map((col) => /* @__PURE__ */ jsx("div", { className: "w-56 shrink-0 snap-start sm:w-64", children: /* @__PURE__ */ jsx(CollectionCard, { collection: col }) }, col.contractAddress))
189
+ }
190
+ ),
191
+ /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
192
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
193
+ /* @__PURE__ */ jsx(CollectionSearch, {}),
194
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 sm:ml-auto", children: [
195
+ /* @__PURE__ */ jsxs(Select, { value: sort, onValueChange: (v) => setSort(v), children: [
196
+ /* @__PURE__ */ jsxs(SelectTrigger, { className: "h-9 w-auto gap-1.5 text-xs", "aria-label": "Sort collections", children: [
197
+ /* @__PURE__ */ jsx(ArrowDownUp, { className: "h-3.5 w-3.5 text-muted-foreground" }),
198
+ /* @__PURE__ */ jsx(SelectValue, {})
199
+ ] }),
200
+ /* @__PURE__ */ jsx(SelectContent, { children: SORT_OPTIONS.map((opt) => /* @__PURE__ */ jsx(SelectItem, { value: opt.value, className: "text-xs", children: opt.label }, opt.value)) })
201
+ ] }),
202
+ /* @__PURE__ */ jsxs(
203
+ "button",
204
+ {
205
+ onClick: () => setFiltersOpen(true),
206
+ className: cn(
207
+ "relative flex items-center gap-1.5 h-9 px-3 rounded-lg border text-xs font-medium transition-colors",
208
+ activeFilters > 0 || service !== void 0 ? "border-primary bg-primary/10 text-primary" : "border-border text-muted-foreground hover:border-primary/50 hover:text-foreground"
209
+ ),
210
+ children: [
211
+ /* @__PURE__ */ jsx(SlidersHorizontal, { className: "h-3.5 w-3.5" }),
212
+ "Filters",
213
+ (activeFilters > 0 || service !== void 0) && /* @__PURE__ */ 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) })
214
+ ]
215
+ }
216
+ )
217
+ ] })
127
218
  ] }),
128
- exclusive && /* @__PURE__ */ 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: [
129
- /* @__PURE__ */ jsx(Sparkles, { className: "h-3 w-3" }),
130
- "Exclusive",
131
- /* @__PURE__ */ jsx("button", { onClick: () => setExclusive(false), className: "ml-0.5 hover:text-primary/60", children: "\xD7" })
219
+ (service !== void 0 || !hideEmpty) && /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
220
+ service !== void 0 && /* @__PURE__ */ 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: [
221
+ service === "drop-collection" ? /* @__PURE__ */ jsx(Package, { className: "h-3 w-3" }) : /* @__PURE__ */ jsx(Award, { className: "h-3 w-3" }),
222
+ SERVICE_TABS.find((t) => t.value === service)?.label,
223
+ /* @__PURE__ */ jsx("button", { onClick: () => setService(void 0), className: "ml-0.5 hover:text-primary/60", "aria-label": "Remove source filter", children: "\xD7" })
224
+ ] }),
225
+ !hideEmpty && /* @__PURE__ */ 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: [
226
+ "Show empty",
227
+ /* @__PURE__ */ jsx("button", { onClick: () => setHideEmpty(true), className: "ml-0.5 hover:text-primary/60", "aria-label": "Remove show empty filter", children: "\xD7" })
228
+ ] })
132
229
  ] })
133
230
  ] }),
134
231
  /* @__PURE__ */ jsx(Dialog, { open: filtersOpen, onOpenChange: setFiltersOpen, children: /* @__PURE__ */ jsxs(DialogContent, { className: "w-full max-w-sm sm:max-w-md p-0 overflow-hidden gap-0 flex flex-col max-h-[85svh]", children: [
@@ -162,92 +259,36 @@ function CollectionsPage() {
162
259
  label
163
260
  )) })
164
261
  ] }),
165
- /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
166
- /* @__PURE__ */ jsx("p", { className: "text-2xs font-semibold text-muted-foreground", children: "Sort" }),
167
- /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1.5", children: SORT_OPTIONS.map((opt) => /* @__PURE__ */ jsx(
168
- "button",
169
- {
170
- onClick: () => setSort(opt.value),
171
- className: cn(
172
- "text-xs px-3 py-1.5 rounded-full border transition-colors whitespace-nowrap",
173
- sort === opt.value ? "border-primary bg-primary/10 text-primary font-medium" : "border-border text-muted-foreground hover:border-primary/50"
174
- ),
175
- children: opt.label
176
- },
177
- opt.value
178
- )) })
179
- ] }),
180
262
  /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
181
263
  /* @__PURE__ */ jsx("p", { className: "text-2xs font-semibold text-muted-foreground", children: "Show" }),
182
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
183
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
184
- /* @__PURE__ */ jsxs(
185
- "button",
186
- {
187
- onClick: () => setFeatured((v) => !v),
188
- className: cn(
189
- "flex flex-1 items-center gap-2 text-sm px-3 py-2 rounded-lg border transition-colors text-left",
190
- featured ? "border-primary bg-primary/10 text-primary" : "border-border text-muted-foreground hover:border-primary/50"
191
- ),
192
- children: [
193
- /* @__PURE__ */ jsx(BadgeCheck, { className: "h-4 w-4 shrink-0" }),
194
- "Featured only"
195
- ]
196
- }
197
- ),
198
- /* @__PURE__ */ jsx(HelpIcon, { content: "Show only collections featured by Medialane", side: "left" })
199
- ] }),
200
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
201
- /* @__PURE__ */ jsxs(
202
- "button",
203
- {
204
- onClick: () => setHideEmpty((v) => !v),
205
- className: cn(
206
- "flex flex-1 items-center gap-2 text-sm px-3 py-2 rounded-lg border transition-colors text-left",
207
- !hideEmpty ? "border-primary bg-primary/10 text-primary" : "border-border text-muted-foreground hover:border-primary/50"
208
- ),
209
- children: [
210
- /* @__PURE__ */ jsx(Eye, { className: "h-4 w-4 shrink-0" }),
211
- "Show empty collections"
212
- ]
213
- }
214
- ),
215
- /* @__PURE__ */ jsx(HelpIcon, { content: "Include collections with no minted assets yet \u2014 hidden by default to keep the feed clean", side: "left" })
216
- ] }),
217
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
218
- /* @__PURE__ */ jsxs(
219
- "button",
220
- {
221
- onClick: () => setExclusive((v) => !v),
222
- className: cn(
223
- "flex flex-1 items-center gap-2 text-sm px-3 py-2 rounded-lg border transition-colors text-left",
224
- exclusive ? "border-primary bg-primary/10 text-primary" : "border-border text-muted-foreground hover:border-primary/50"
225
- ),
226
- children: [
227
- /* @__PURE__ */ jsx(Sparkles, { className: "h-4 w-4 shrink-0" }),
228
- "Exclusive content only"
229
- ]
230
- }
231
- ),
232
- /* @__PURE__ */ jsx(HelpIcon, { content: "Show only collections with holder-exclusive content", side: "left" })
233
- ] })
234
- ] })
264
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
265
+ /* @__PURE__ */ jsxs(
266
+ "button",
267
+ {
268
+ onClick: () => setHideEmpty((v) => !v),
269
+ className: cn(
270
+ "flex flex-1 items-center gap-2 text-sm px-3 py-2 rounded-lg border transition-colors text-left",
271
+ !hideEmpty ? "border-primary bg-primary/10 text-primary" : "border-border text-muted-foreground hover:border-primary/50"
272
+ ),
273
+ children: [
274
+ /* @__PURE__ */ jsx(Eye, { className: "h-4 w-4 shrink-0" }),
275
+ "Show empty collections"
276
+ ]
277
+ }
278
+ ),
279
+ /* @__PURE__ */ jsx(HelpIcon, { content: "Include collections with no minted assets yet \u2014 hidden by default to keep the feed clean", side: "left" })
280
+ ] }) })
235
281
  ] })
236
282
  ] }),
237
- /* @__PURE__ */ jsx("div", { className: "px-5 py-3 border-t border-border/60", children: /* @__PURE__ */ jsx(Button, { className: "w-full", onClick: () => setFiltersOpen(false), children: "Apply filters" }) })
283
+ /* @__PURE__ */ jsx("div", { className: "px-5 py-3 border-t border-border/60", children: /* @__PURE__ */ jsx(Button, { className: "w-full", onClick: () => setFiltersOpen(false), children: "Show results" }) })
238
284
  ] }) }),
239
- isInitialLoading ? /* @__PURE__ */ 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__ */ jsx(CollectionCardSkeleton, {}, i)) }) : allCollections.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center py-24 gap-4 text-center", children: [
285
+ isInitialLoading ? /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 lg:grid-cols-4 gap-4 sm:gap-5", children: Array.from({ length: 8 }).map((_, i) => /* @__PURE__ */ jsx(CollectionCardSkeleton, {}, i)) }) : allCollections.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center py-24 gap-4 text-center", children: [
240
286
  /* @__PURE__ */ jsx(Layers, { className: "h-12 w-12 text-muted-foreground/30" }),
241
287
  /* @__PURE__ */ jsx("p", { className: "text-2xl font-bold", children: "No collections found" }),
242
- /* @__PURE__ */ 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." }),
288
+ /* @__PURE__ */ jsx("p", { className: "text-muted-foreground max-w-sm", children: hideEmpty ? "No collections with assets yet." : "Deploy the first collection on Medialane." }),
243
289
  activeFilters > 0 && /* @__PURE__ */ jsx(Button, { variant: "outline", size: "sm", onClick: resetAll, children: "Clear filters" })
244
290
  ] }) : /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
245
- exclusive && displayCollections.length === 0 && /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center py-16 gap-3 text-center", children: [
246
- /* @__PURE__ */ jsx(Sparkles, { className: "h-10 w-10 text-muted-foreground/30" }),
247
- /* @__PURE__ */ jsx("p", { className: "text-base font-semibold text-muted-foreground", children: "No exclusive collections in this batch" }),
248
- /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground/70 max-w-xs", children: "Load more collections below, then the filter will catch them." })
249
- ] }),
250
- /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-5", children: displayCollections.map((col) => /* @__PURE__ */ jsx(CollectionCard, { collection: col }, col.contractAddress)) }),
291
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 lg:grid-cols-4 gap-4 sm:gap-5", children: allCollections.map((col) => /* @__PURE__ */ jsx(CollectionCard, { collection: col }, col.contractAddress)) }),
251
292
  /* @__PURE__ */ jsx(
252
293
  LoadMoreSentinel,
253
294
  {
@@ -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":[]}
@@ -175,7 +175,7 @@ function CreatorPage({ address: addressProp, username, useAssetActions, useMarke
175
175
  `${t.contractAddress}-${t.tokenId}`
176
176
  );
177
177
  }) })),
178
- activeTab === "collections" && (collectionsLoading ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2 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-1 gap-4 sm:grid-cols-2 lg:grid-cols-3", children: collections.map((c) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_collection_card.CollectionCard, { collection: c }, c.contractAddress)) })),
178
+ 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)) })),
179
179
  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)) })),
180
180
  activeTab === "analytics" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "max-w-2xl", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react.Suspense, { fallback: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-64 w-full animate-pulse rounded-xl bg-muted/40" }), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CreatorAnalytics, { activities, isLoading: activitiesLoading }) }) }),
181
181
  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)) }) })