@medialane/ui 0.317.0 → 0.318.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.
- package/dist/components/account/input-otp.d.cts +2 -2
- package/dist/components/account/input-otp.d.ts +2 -2
- package/dist/components/button.d.cts +2 -2
- package/dist/components/button.d.ts +2 -2
- package/dist/components/collections-page.cjs +5 -5
- package/dist/components/collections-page.cjs.map +1 -1
- package/dist/components/collections-page.js +5 -5
- package/dist/components/collections-page.js.map +1 -1
- package/dist/components/launchpad/edition-mint-schema.d.cts +4 -4
- package/dist/components/launchpad/edition-mint-schema.d.ts +4 -4
- package/dist/utils/media-wallet/use-erc20-balance.d.cts +1 -1
- package/dist/utils/media-wallet/use-erc20-balance.d.ts +1 -1
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as input_otp from 'input-otp';
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
|
|
4
|
-
declare const InputOTP: React.ForwardRefExoticComponent<(Omit<Omit<React.InputHTMLAttributes<HTMLInputElement>, "
|
|
4
|
+
declare const InputOTP: React.ForwardRefExoticComponent<(Omit<Omit<React.InputHTMLAttributes<HTMLInputElement>, "onChange" | "value" | "maxLength" | "textAlign" | "onComplete" | "pushPasswordManagerStrategy" | "pasteTransformer" | "containerClassName" | "noScriptCSSFallback"> & {
|
|
5
5
|
value?: string;
|
|
6
6
|
onChange?: (newValue: string) => unknown;
|
|
7
7
|
maxLength: number;
|
|
@@ -14,7 +14,7 @@ declare const InputOTP: React.ForwardRefExoticComponent<(Omit<Omit<React.InputHT
|
|
|
14
14
|
} & {
|
|
15
15
|
render: (props: input_otp.RenderProps) => React.ReactNode;
|
|
16
16
|
children?: never;
|
|
17
|
-
} & React.RefAttributes<HTMLInputElement>, "ref"> | Omit<Omit<React.InputHTMLAttributes<HTMLInputElement>, "
|
|
17
|
+
} & React.RefAttributes<HTMLInputElement>, "ref"> | Omit<Omit<React.InputHTMLAttributes<HTMLInputElement>, "onChange" | "value" | "maxLength" | "textAlign" | "onComplete" | "pushPasswordManagerStrategy" | "pasteTransformer" | "containerClassName" | "noScriptCSSFallback"> & {
|
|
18
18
|
value?: string;
|
|
19
19
|
onChange?: (newValue: string) => unknown;
|
|
20
20
|
maxLength: number;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as input_otp from 'input-otp';
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
|
|
4
|
-
declare const InputOTP: React.ForwardRefExoticComponent<(Omit<Omit<React.InputHTMLAttributes<HTMLInputElement>, "
|
|
4
|
+
declare const InputOTP: React.ForwardRefExoticComponent<(Omit<Omit<React.InputHTMLAttributes<HTMLInputElement>, "onChange" | "value" | "maxLength" | "textAlign" | "onComplete" | "pushPasswordManagerStrategy" | "pasteTransformer" | "containerClassName" | "noScriptCSSFallback"> & {
|
|
5
5
|
value?: string;
|
|
6
6
|
onChange?: (newValue: string) => unknown;
|
|
7
7
|
maxLength: number;
|
|
@@ -14,7 +14,7 @@ declare const InputOTP: React.ForwardRefExoticComponent<(Omit<Omit<React.InputHT
|
|
|
14
14
|
} & {
|
|
15
15
|
render: (props: input_otp.RenderProps) => React.ReactNode;
|
|
16
16
|
children?: never;
|
|
17
|
-
} & React.RefAttributes<HTMLInputElement>, "ref"> | Omit<Omit<React.InputHTMLAttributes<HTMLInputElement>, "
|
|
17
|
+
} & React.RefAttributes<HTMLInputElement>, "ref"> | Omit<Omit<React.InputHTMLAttributes<HTMLInputElement>, "onChange" | "value" | "maxLength" | "textAlign" | "onComplete" | "pushPasswordManagerStrategy" | "pasteTransformer" | "containerClassName" | "noScriptCSSFallback"> & {
|
|
18
18
|
value?: string;
|
|
19
19
|
onChange?: (newValue: string) => unknown;
|
|
20
20
|
maxLength: number;
|
|
@@ -3,8 +3,8 @@ import * as React from 'react';
|
|
|
3
3
|
import { VariantProps } from 'class-variance-authority';
|
|
4
4
|
|
|
5
5
|
declare const buttonVariants: (props?: ({
|
|
6
|
-
variant?: "
|
|
7
|
-
size?: "
|
|
6
|
+
variant?: "default" | "link" | "destructive" | "outline" | "secondary" | "ghost" | "premium" | "tonal" | "gradient-border" | "gradient-fill" | null | undefined;
|
|
7
|
+
size?: "default" | "icon" | "sm" | "lg" | null | undefined;
|
|
8
8
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
9
9
|
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
|
|
10
10
|
asChild?: boolean;
|
|
@@ -3,8 +3,8 @@ import * as React from 'react';
|
|
|
3
3
|
import { VariantProps } from 'class-variance-authority';
|
|
4
4
|
|
|
5
5
|
declare const buttonVariants: (props?: ({
|
|
6
|
-
variant?: "
|
|
7
|
-
size?: "
|
|
6
|
+
variant?: "default" | "link" | "destructive" | "outline" | "secondary" | "ghost" | "premium" | "tonal" | "gradient-border" | "gradient-fill" | null | undefined;
|
|
7
|
+
size?: "default" | "icon" | "sm" | "lg" | null | undefined;
|
|
8
8
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
9
9
|
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
|
|
10
10
|
asChild?: boolean;
|
|
@@ -52,7 +52,7 @@ var import_use_collections = require("../utils/use-collections.js");
|
|
|
52
52
|
var import_use_medialane_client = require("../utils/use-medialane-client.js");
|
|
53
53
|
var import_use_search = require("../utils/use-search.js");
|
|
54
54
|
var import_sdk = require("@medialane/sdk");
|
|
55
|
-
const PAGE_SIZE =
|
|
55
|
+
const PAGE_SIZE = 25;
|
|
56
56
|
const SORT_OPTIONS = [
|
|
57
57
|
{ label: "Recent", value: "recent" },
|
|
58
58
|
{ label: "Most assets", value: "supply" },
|
|
@@ -164,7 +164,7 @@ function CollectionsPage() {
|
|
|
164
164
|
);
|
|
165
165
|
const { collections: featuredCollections, isLoading: featuredLoading } = (0, import_use_collections.useCollections)(
|
|
166
166
|
1,
|
|
167
|
-
|
|
167
|
+
10,
|
|
168
168
|
true,
|
|
169
169
|
"recent",
|
|
170
170
|
true,
|
|
@@ -211,7 +211,7 @@ function CollectionsPage() {
|
|
|
211
211
|
] })
|
|
212
212
|
] })
|
|
213
213
|
] }),
|
|
214
|
-
(featuredLoading || featuredCollections.length > 0) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "grid grid-cols-2 lg:grid-cols-
|
|
214
|
+
(featuredLoading || featuredCollections.length > 0) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "grid grid-cols-2 lg:grid-cols-5 gap-4 sm:gap-5", children: featuredLoading ? Array.from({ length: 10 }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_collection_card.CollectionCardSkeleton, {}, i)) : featuredCollections.map((col) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_collection_card.CollectionCard, { collection: col }, col.contractAddress)) }),
|
|
215
215
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-3", children: [
|
|
216
216
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
217
217
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CollectionSearch, {}),
|
|
@@ -306,13 +306,13 @@ function CollectionsPage() {
|
|
|
306
306
|
] }),
|
|
307
307
|
/* @__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" }) })
|
|
308
308
|
] }) }),
|
|
309
|
-
isInitialLoading ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "grid grid-cols-2 lg:grid-cols-
|
|
309
|
+
isInitialLoading ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "grid grid-cols-2 lg:grid-cols-5 gap-4 sm:gap-5", children: Array.from({ length: 10 }).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: [
|
|
310
310
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Layers, { className: "h-12 w-12 text-muted-foreground/30" }),
|
|
311
311
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-2xl font-bold", children: "No collections found" }),
|
|
312
312
|
/* @__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." }),
|
|
313
313
|
activeFilters > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_button.Button, { variant: "outline", size: "sm", onClick: resetAll, children: "Clear filters" })
|
|
314
314
|
] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-6", children: [
|
|
315
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "grid grid-cols-2 lg:grid-cols-
|
|
315
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "grid grid-cols-2 lg:grid-cols-5 gap-4 sm:gap-5", children: allCollections.map((col) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_collection_card.CollectionCard, { collection: col }, col.contractAddress)) }),
|
|
316
316
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
317
317
|
import_load_more_sentinel.LoadMoreSentinel,
|
|
318
318
|
{
|
|
@@ -1 +1 @@
|
|
|
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, 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 { 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 && 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.single + counts.multi).toLocaleString()}</span>\n <span className=\"text-muted-foreground\">Collections</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 <div className=\"grid grid-cols-2 lg:grid-cols-4 gap-4 sm:gap-5\">\n {featuredLoading\n ? Array.from({ length: 8 }).map((_, i) => <CollectionCardSkeleton key={i} />)\n : featuredCollections.map((col) => (\n <CollectionCard key={col.contractAddress} collection={col} />\n ))}\n </div>\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"]}
|
|
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, 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 { 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 = 25;\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 10,\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 && 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.single + counts.multi).toLocaleString()}</span>\n <span className=\"text-muted-foreground\">Collections</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 <div className=\"grid grid-cols-2 lg:grid-cols-5 gap-4 sm:gap-5\">\n {featuredLoading\n ? Array.from({ length: 10 }).map((_, i) => <CollectionCardSkeleton key={i} />)\n : featuredCollections.map((col) => (\n <CollectionCard key={col.contractAddress} collection={col} />\n ))}\n </div>\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-5 gap-4 sm:gap-5\">\n {Array.from({ length: 10 }).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-5 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"]}
|
|
@@ -19,7 +19,7 @@ import { useCollections } from "../utils/use-collections.js";
|
|
|
19
19
|
import { useMedialaneClient } from "../utils/use-medialane-client.js";
|
|
20
20
|
import { SEARCH_MIN_LENGTH, useSearch } from "../utils/use-search.js";
|
|
21
21
|
import { collectionHref } from "@medialane/sdk";
|
|
22
|
-
const PAGE_SIZE =
|
|
22
|
+
const PAGE_SIZE = 25;
|
|
23
23
|
const SORT_OPTIONS = [
|
|
24
24
|
{ label: "Recent", value: "recent" },
|
|
25
25
|
{ label: "Most assets", value: "supply" },
|
|
@@ -131,7 +131,7 @@ function CollectionsPage() {
|
|
|
131
131
|
);
|
|
132
132
|
const { collections: featuredCollections, isLoading: featuredLoading } = useCollections(
|
|
133
133
|
1,
|
|
134
|
-
|
|
134
|
+
10,
|
|
135
135
|
true,
|
|
136
136
|
"recent",
|
|
137
137
|
true,
|
|
@@ -178,7 +178,7 @@ function CollectionsPage() {
|
|
|
178
178
|
] })
|
|
179
179
|
] })
|
|
180
180
|
] }),
|
|
181
|
-
(featuredLoading || featuredCollections.length > 0) && /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 lg:grid-cols-
|
|
181
|
+
(featuredLoading || featuredCollections.length > 0) && /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 lg:grid-cols-5 gap-4 sm:gap-5", children: featuredLoading ? Array.from({ length: 10 }).map((_, i) => /* @__PURE__ */ jsx(CollectionCardSkeleton, {}, i)) : featuredCollections.map((col) => /* @__PURE__ */ jsx(CollectionCard, { collection: col }, col.contractAddress)) }),
|
|
182
182
|
/* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
183
183
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
184
184
|
/* @__PURE__ */ jsx(CollectionSearch, {}),
|
|
@@ -273,13 +273,13 @@ function CollectionsPage() {
|
|
|
273
273
|
] }),
|
|
274
274
|
/* @__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" }) })
|
|
275
275
|
] }) }),
|
|
276
|
-
isInitialLoading ? /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 lg:grid-cols-
|
|
276
|
+
isInitialLoading ? /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 lg:grid-cols-5 gap-4 sm:gap-5", children: Array.from({ length: 10 }).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: [
|
|
277
277
|
/* @__PURE__ */ jsx(Layers, { className: "h-12 w-12 text-muted-foreground/30" }),
|
|
278
278
|
/* @__PURE__ */ jsx("p", { className: "text-2xl font-bold", children: "No collections found" }),
|
|
279
279
|
/* @__PURE__ */ jsx("p", { className: "text-muted-foreground max-w-sm", children: hideEmpty ? "No collections with assets yet." : "Deploy the first collection on Medialane." }),
|
|
280
280
|
activeFilters > 0 && /* @__PURE__ */ jsx(Button, { variant: "outline", size: "sm", onClick: resetAll, children: "Clear filters" })
|
|
281
281
|
] }) : /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
|
|
282
|
-
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 lg:grid-cols-
|
|
282
|
+
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 lg:grid-cols-5 gap-4 sm:gap-5", children: allCollections.map((col) => /* @__PURE__ */ jsx(CollectionCard, { collection: col }, col.contractAddress)) }),
|
|
283
283
|
/* @__PURE__ */ jsx(
|
|
284
284
|
LoadMoreSentinel,
|
|
285
285
|
{
|
|
@@ -1 +1 @@
|
|
|
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, 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 { 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 && 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.single + counts.multi).toLocaleString()}</span>\n <span className=\"text-muted-foreground\">Collections</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 <div className=\"grid grid-cols-2 lg:grid-cols-4 gap-4 sm:gap-5\">\n {featuredLoading\n ? Array.from({ length: 8 }).map((_, i) => <CollectionCardSkeleton key={i} />)\n : featuredCollections.map((col) => (\n <CollectionCard key={col.contractAddress} collection={col} />\n ))}\n </div>\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":[]}
|
|
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, 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 { 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 = 25;\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 10,\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 && 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.single + counts.multi).toLocaleString()}</span>\n <span className=\"text-muted-foreground\">Collections</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 <div className=\"grid grid-cols-2 lg:grid-cols-5 gap-4 sm:gap-5\">\n {featuredLoading\n ? Array.from({ length: 10 }).map((_, i) => <CollectionCardSkeleton key={i} />)\n : featuredCollections.map((col) => (\n <CollectionCard key={col.contractAddress} collection={col} />\n ))}\n </div>\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-5 gap-4 sm:gap-5\">\n {Array.from({ length: 10 }).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-5 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":";AA4EM,cA6BQ,YA7BR;AA1EN,SAAS,UAAU,WAAW,cAAc;AAC5C,OAAO,YAAY;AACnB,SAAS,QAAQ,KAAK,mBAAmB,OAAO,SAAS,aAAa,QAAQ,SAAS;AACvF,SAAS,cAAc;AACvB,SAAS,QAAQ,eAAe,mBAAmB;AACnD,SAAS,QAAQ,eAAe,YAAY,eAAe,mBAAmB;AAC9E,SAAS,gBAAgB;AACzB,SAAS,aAAa;AACtB,SAAS,uBAAuB;AAChC,OAAO,UAAU;AACjB,SAAS,iBAAiB;AAC1B,SAAS,qBAAqB;AAC9B,SAAS,gBAAgB,8BAA8B;AACvD,SAAS,wBAAwB;AACjC,SAAS,UAAU;AACnB,SAAS,sBAA2C;AACpD,SAAS,0BAA0B;AACnC,SAAS,mBAAmB,iBAAiB;AAC7C,SAAS,sBAA0C;AAEnD,MAAM,YAAY;AAElB,MAAM,eAA2D;AAAA,EAC/D,EAAE,OAAO,UAAe,OAAO,SAAU;AAAA,EACzC,EAAE,OAAO,eAAe,OAAO,SAAU;AAAA,EACzC,EAAE,OAAO,cAAe,OAAO,SAAU;AAAA,EACzC,EAAE,OAAO,gBAAc,OAAO,QAAU;AAAA,EACxC,EAAE,OAAO,cAAc,OAAO,OAAU;AAC1C;AAEA,MAAM,eAAe;AAAA,EACnB,EAAE,OAAO,OAAc,OAAO,OAAa;AAAA,EAC3C,EAAE,OAAO,cAAc,OAAO,eAAe;AAAA,EAC7C,EAAE,OAAO,SAAc,OAAO,kBAAkB;AAClD;AAEA,SAAS,oBAAoB;AAC3B,QAAM,SAAS,mBAAmB;AAClC,QAAM,EAAE,KAAK,IAAI;AAAA,IACf;AAAA,IACA,YAAY;AACV,YAAM,CAAC,QAAQ,KAAK,IAAI,MAAM,QAAQ;AAAA,QACpC,CAAC,UAAU,SAAS,EAAE;AAAA,UAAI,CAAC,aACzB,OAAO,IAAI,YAAY,KAAK,EAAE,UAAU,WAAW,MAAM,OAAO,EAAE,CAAC;AAAA,QACrE;AAAA,MACF;AACA,aAAO,EAAE,QAAQ,OAAO,MAAM,OAAO,OAAO,MAAM,MAAM,MAAM;AAAA,IAChE;AAAA,IACA,EAAE,mBAAmB,OAAO,kBAAkB,IAAO;AAAA,EACvD;AACA,SAAO,QAAQ;AACjB;AAEA,SAAS,mBAAmB;AAC1B,QAAM,SAAS,UAAU;AACzB,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,EAAE;AACrC,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,EAAE;AACrC,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,KAAK;AACtC,QAAM,EAAE,QAAQ,IAAI,UAAU,OAAO,EAAE,OAAO,EAAE,CAAC;AACjD,QAAM,UAAU,SAAS,eAAe,CAAC;AAEzC,YAAU,MAAM;AACd,UAAM,QAAQ,WAAW,MAAM,SAAS,KAAK,GAAG,GAAG;AACnD,WAAO,MAAM,aAAa,KAAK;AAAA,EACjC,GAAG,CAAC,KAAK,CAAC;AAEV,QAAM,QAAQ,MAAM;AAClB,aAAS,EAAE;AACX,aAAS,EAAE;AACX,YAAQ,KAAK;AAAA,EACf;AAEA,SACE,qBAAC,SAAI,WAAU,yCACb;AAAA,wBAAC,UAAO,WAAU,8FAA6F;AAAA,IAC/G;AAAA,MAAC;AAAA;AAAA,QACC,WAAU;AAAA,QACV,aAAY;AAAA,QACZ,cAAW;AAAA,QACX;AAAA,QACA,UAAU,CAAC,MAAM;AAAE,mBAAS,EAAE,OAAO,KAAK;AAAG,kBAAQ,IAAI;AAAA,QAAG;AAAA,QAC5D,SAAS,MAAM,QAAQ,IAAI;AAAA,QAC3B,QAAQ,MAAM,WAAW,MAAM,QAAQ,KAAK,GAAG,GAAG;AAAA,QAClD,WAAW,CAAC,MAAM;AAChB,cAAI,EAAE,QAAQ,WAAW,MAAM,KAAK,EAAE,UAAU,mBAAmB;AACjE,mBAAO,KAAK,aAAa,mBAAmB,MAAM,KAAK,CAAC,CAAC,EAAE;AAAA,UAC7D;AAAA,QACF;AAAA;AAAA,IACF;AAAA,IACC,SACC;AAAA,MAAC;AAAA;AAAA,QACC,cAAW;AAAA,QACX,WAAU;AAAA,QACV,SAAS;AAAA,QAET,8BAAC,KAAE,WAAU,eAAc;AAAA;AAAA,IAC7B;AAAA,IAED,QAAQ,QAAQ,SAAS,KACxB,oBAAC,SAAI,WAAU,mHACZ,kBAAQ,IAAI,CAAC,QAAQ;AACpB,YAAM,QAAQ,IAAI,QAAQ;AAC1B,aACE;AAAA,QAAC;AAAA;AAAA,UAEC,MAAM,eAAe,YAAY,IAAI,eAAe;AAAA,UACpD,WAAU;AAAA,UAEV;AAAA,gCAAC,mBAAgB,KAAK,IAAI,OAAO,OAAc;AAAA,YAC/C,oBAAC,UAAK,WAAU,gCAAgC,iBAAM;AAAA;AAAA;AAAA,QALjD,IAAI;AAAA,MAMX;AAAA,IAEJ,CAAC,GACH;AAAA,KAEJ;AAEJ;AAEO,SAAS,kBAAkB;AAChC,QAAM,SAAS,kBAAkB;AACjC,QAAM,CAAC,MAAM,OAAO,IAAc,SAAyB,QAAQ;AACnE,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,IAAI;AAC/C,QAAM,CAAC,SAAS,UAAU,IAAQ,SAA6B,MAAS;AACxE,QAAM,CAAC,aAAa,cAAc,IAAI,SAAS,KAAK;AACpD,QAAM,CAAC,MAAM,OAAO,IAAc,SAAS,CAAC;AAC5C,QAAM,CAAC,gBAAgB,iBAAiB,IAAI,SAA0B,CAAC,CAAC;AAExE,QAAM,EAAE,aAAa,MAAM,UAAU,IAAI;AAAA,IACvC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,YAAY,kBAAkB,YAAY,oBAAoB,QAAQ;AAAA,IACtE;AAAA,IACA;AAAA,EACF;AAEA,QAAM,EAAE,aAAa,qBAAqB,WAAW,gBAAgB,IAAI;AAAA,IACvE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,QAAM,cAAc,OAAO,EAAE,MAAM,WAAW,QAAQ,CAAC;AACvD,YAAU,MAAM;AACd,UAAM,IAAI,YAAY;AACtB,QAAI,EAAE,SAAS,QAAQ,EAAE,cAAc,aAAa,EAAE,YAAY,SAAS;AACzE,kBAAY,UAAU,EAAE,MAAM,WAAW,QAAQ;AACjD,cAAQ,CAAC;AACT,wBAAkB,CAAC,CAAC;AAAA,IACtB;AAAA,EACF,GAAG,CAAC,MAAM,WAAW,OAAO,CAAC;AAE7B,YAAU,MAAM;AACd,QAAI,aAAa,YAAY,WAAW,EAAG;AAC3C,sBAAkB,CAAC,SAAS;AAC1B,YAAM,MAAM,IAAI,IAAI,KAAK,IAAI,CAAC,MAAM,EAAE,eAAe,CAAC;AACtD,YAAM,OAAO,YAAY,OAAO,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE,eAAe,CAAC;AAClE,aAAO,SAAS,IAAI,cAAc,CAAC,GAAG,MAAM,GAAG,IAAI;AAAA,IACrD,CAAC;AAAA,EACH,GAAG,CAAC,aAAa,WAAW,IAAI,CAAC;AAEjC,QAAM,UAAU,MAAM,SAAS,OAAO,eAAe,SAAS,KAAK,QAAQ;AAC3E,QAAM,mBAAmB,aAAa,eAAe,WAAW;AAEhE,QAAM,gBAAgB,CAAC,CAAC,SAAS,EAAE,OAAO,OAAO,EAAE;AAEnD,QAAM,WAAW,MAAM;AACrB,iBAAa,IAAI;AAAA,EACnB;AAEA,QAAM,sBAAsB,CAAC,QAA4B;AACvD,eAAW,GAAG;AAAA,EAChB;AAEA,SACE,qBAAC,iBAAc,WAAU,8CAEvB;AAAA,yBAAC,SAAI,WAAU,kBAEb;AAAA,0BAAC,QAAG,WAAU,sBAAqB,iCAAmB;AAAA,MACtD,qBAAC,SAAI,WAAU,0CACZ;AAAA,gBAAQ,UAAU,QAAQ,OAAO,SAAS,QACzC,qBAAC,SAAI,WAAU,6FACb;AAAA,8BAAC,UAAK,WAAU,0BAA2B,kBAAO,SAAS,OAAO,OAAO,eAAe,GAAE;AAAA,UAC1F,oBAAC,UAAK,WAAU,yBAAwB,yBAAW;AAAA,WACrD;AAAA,QAED,QAAQ,SAAS,QAChB,qBAAC,SAAI,WAAU,6FACb;AAAA,8BAAC,UAAK,WAAU,0BAA0B,iBAAO,MAAM,eAAe,GAAE;AAAA,UACxE,oBAAC,UAAK,WAAU,yBAAwB,4BAAc;AAAA,WACxD;AAAA,SAEJ;AAAA,OACF;AAAA,KAEE,mBAAmB,oBAAoB,SAAS,MAChD,oBAAC,SAAI,WAAU,kDACZ,4BACG,MAAM,KAAK,EAAE,QAAQ,GAAG,CAAC,EAAE,IAAI,CAAC,GAAG,MAAM,oBAAC,4BAA4B,CAAG,CAAE,IAC3E,oBAAoB,IAAI,CAAC,QACvB,oBAAC,kBAAyC,YAAY,OAAjC,IAAI,eAAkC,CAC5D,GACP;AAAA,IAGF,qBAAC,SAAI,WAAU,aACb;AAAA,2BAAC,SAAI,WAAU,qCACb;AAAA,4BAAC,oBAAiB;AAAA,QAClB,qBAAC,SAAI,WAAU,sCACb;AAAA,+BAAC,UAAO,OAAO,MAAM,eAAe,CAAC,MAAM,QAAQ,CAAmB,GACpE;AAAA,iCAAC,iBAAc,WAAU,8BAA6B,cAAW,oBAC/D;AAAA,kCAAC,eAAY,WAAU,qCAAoC;AAAA,cAC3D,oBAAC,eAAY;AAAA,eACf;AAAA,YACA,oBAAC,iBACE,uBAAa,IAAI,CAAC,QACjB,oBAAC,cAA2B,OAAO,IAAI,OAAO,WAAU,WAAW,cAAI,SAAtD,IAAI,KAAwD,CAC9E,GACH;AAAA,aACF;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACC,SAAS,MAAM,eAAe,IAAI;AAAA,cAClC,WAAW;AAAA,gBACT;AAAA,gBACA,gBAAgB,KAAK,YAAY,SAC7B,8CACA;AAAA,cACN;AAAA,cAEA;AAAA,oCAAC,qBAAkB,WAAU,eAAc;AAAA,gBAAE;AAAA,iBAE3C,gBAAgB,KAAK,YAAY,WACjC,oBAAC,UAAK,WAAU,+GACb,2BAAiB,YAAY,SAAY,IAAI,IAChD;AAAA;AAAA;AAAA,UAEJ;AAAA,WACF;AAAA,SACF;AAAA,OACE,YAAY,UAAa,CAAC,cAC1B,qBAAC,SAAI,WAAU,qCACZ;AAAA,oBAAY,UACX,qBAAC,UAAK,WAAU,gHACb;AAAA,sBAAY,oBAAoB,oBAAC,WAAQ,WAAU,WAAU,IAAK,oBAAC,SAAM,WAAU,WAAU;AAAA,UAC7F,aAAa,KAAK,CAAC,MAAM,EAAE,UAAU,OAAO,GAAG;AAAA,UAChD,oBAAC,YAAO,SAAS,MAAM,WAAW,MAAS,GAAG,WAAU,gCAA+B,cAAW,wBAAuB,kBAAC;AAAA,WAC5H;AAAA,QAED,CAAC,aACA,qBAAC,UAAK,WAAU,gHAA+G;AAAA;AAAA,UAE7H,oBAAC,YAAO,SAAS,MAAM,aAAa,IAAI,GAAG,WAAU,gCAA+B,cAAW,4BAA2B,kBAAC;AAAA,WAC7H;AAAA,SAEJ;AAAA,OAEJ;AAAA,IAEA,oBAAC,UAAO,MAAM,aAAa,cAAc,gBACvC,+BAAC,iBAAc,WAAU,qFAEvB;AAAA,2BAAC,SAAI,WAAU,+EACb;AAAA,6BAAC,eAAY,WAAU,+CACrB;AAAA,8BAAC,qBAAkB,WAAU,wBAAuB;AAAA,UAAE;AAAA,WAExD;AAAA,SACE,gBAAgB,KAAK,YAAY,WACjC,oBAAC,UAAO,SAAQ,SAAQ,MAAK,MAAK,WAAU,qCAAoC,SAAS,MAAM;AAAE,mBAAS;AAAG,qBAAW,MAAS;AAAA,QAAG,GAAG,uBAEvI;AAAA,SAEJ;AAAA,MAEA,qBAAC,SAAI,WAAU,8CAEb;AAAA,6BAAC,SAAI,WAAU,aACb;AAAA,8BAAC,OAAE,WAAU,gDAA+C,oBAAM;AAAA,UAClE,oBAAC,SAAI,WAAU,0BACZ,uBAAa,IAAI,CAAC,EAAE,OAAO,MAAM,MAChC;AAAA,YAAC;AAAA;AAAA,cAEC,SAAS,MAAM,oBAAoB,KAAK;AAAA,cACxC,WAAW;AAAA,gBACT;AAAA,gBACA,YAAY,QACR,0DACA;AAAA,cACN;AAAA,cAEC;AAAA,0BAAU,kBAAkB,oBAAC,SAAM,WAAU,WAAU;AAAA,gBACvD,UAAU,qBAAqB,oBAAC,WAAQ,WAAU,WAAU;AAAA,gBAC5D;AAAA;AAAA;AAAA,YAXI;AAAA,UAYP,CACD,GACH;AAAA,WACF;AAAA,QAEA,qBAAC,SAAI,WAAU,aACb;AAAA,8BAAC,OAAE,WAAU,gDAA+C,kBAAI;AAAA,UAChE,oBAAC,SAAI,WAAU,uBACb,+BAAC,SAAI,WAAU,2BACb;AAAA;AAAA,cAAC;AAAA;AAAA,gBACC,SAAS,MAAM,aAAa,CAAC,MAAM,CAAC,CAAC;AAAA,gBACrC,WAAW;AAAA,kBACT;AAAA,kBACA,CAAC,YACG,8CACA;AAAA,gBACN;AAAA,gBAEA;AAAA,sCAAC,OAAI,WAAU,oBAAmB;AAAA,kBAAE;AAAA;AAAA;AAAA,YAEtC;AAAA,YACA,oBAAC,YAAS,SAAQ,iGAA2F,MAAK,QAAO;AAAA,aAC3H,GACF;AAAA,WACF;AAAA,SAEF;AAAA,MAEA,oBAAC,SAAI,WAAU,uCACb,8BAAC,UAAO,WAAU,UAAS,SAAS,MAAM,eAAe,KAAK,GAAG,0BAEjE,GACF;AAAA,OAEF,GACF;AAAA,IAEC,mBACC,oBAAC,SAAI,WAAU,kDACZ,gBAAM,KAAK,EAAE,QAAQ,GAAG,CAAC,EAAE,IAAI,CAAC,GAAG,MAAM,oBAAC,4BAA4B,CAAG,CAAE,GAC9E,IACE,eAAe,WAAW,IAC5B,qBAAC,SAAI,WAAU,qEACb;AAAA,0BAAC,UAAO,WAAU,sCAAqC;AAAA,MACvD,oBAAC,OAAE,WAAU,sBAAqB,kCAAoB;AAAA,MACtD,oBAAC,OAAE,WAAU,kCACV,sBACG,oCACA,6CACN;AAAA,MACC,gBAAgB,KACf,oBAAC,UAAO,SAAQ,WAAU,MAAK,MAAK,SAAS,UAAU,2BAEvD;AAAA,OAEJ,IAEA,qBAAC,SAAI,WAAU,aACb;AAAA,0BAAC,SAAI,WAAU,kDACZ,yBAAe,IAAI,CAAC,QACnB,oBAAC,kBAAyC,YAAY,OAAjC,IAAI,eAAkC,CAC5D,GACH;AAAA,MAEA;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA;AAAA,UACA,YAAY,MAAM,QAAQ,CAAC,MAAM,IAAI,CAAC;AAAA;AAAA,MACxC;AAAA,OACF;AAAA,KAEJ;AAEJ;","names":[]}
|
|
@@ -19,13 +19,13 @@ declare const editionMintSchema: z.ZodObject<{
|
|
|
19
19
|
ipType: "Audio" | "Video" | "Art" | "Photography" | "NFT" | "Software" | "RWA" | "Patents" | "Posts" | "Publications" | "Documents" | "Custom";
|
|
20
20
|
licenseType: string;
|
|
21
21
|
commercialUse: "Yes" | "No";
|
|
22
|
-
value: string;
|
|
23
|
-
recipient: string;
|
|
24
22
|
derivatives: "Allowed" | "Not Allowed" | "Share-Alike";
|
|
25
23
|
attribution: "Required" | "Not Required";
|
|
26
24
|
geographicScope: string;
|
|
27
25
|
aiPolicy: "Allowed" | "Not Allowed" | "Training Only";
|
|
28
26
|
royalty: number;
|
|
27
|
+
value: string;
|
|
28
|
+
recipient: string;
|
|
29
29
|
description?: string | undefined;
|
|
30
30
|
external_url?: string | undefined;
|
|
31
31
|
}, {
|
|
@@ -33,13 +33,13 @@ declare const editionMintSchema: z.ZodObject<{
|
|
|
33
33
|
ipType: "Audio" | "Video" | "Art" | "Photography" | "NFT" | "Software" | "RWA" | "Patents" | "Posts" | "Publications" | "Documents" | "Custom";
|
|
34
34
|
licenseType: string;
|
|
35
35
|
commercialUse: "Yes" | "No";
|
|
36
|
-
value: string;
|
|
37
|
-
recipient: string;
|
|
38
36
|
derivatives: "Allowed" | "Not Allowed" | "Share-Alike";
|
|
39
37
|
attribution: "Required" | "Not Required";
|
|
40
38
|
geographicScope: string;
|
|
41
39
|
aiPolicy: "Allowed" | "Not Allowed" | "Training Only";
|
|
42
40
|
royalty: number;
|
|
41
|
+
value: string;
|
|
42
|
+
recipient: string;
|
|
43
43
|
description?: string | undefined;
|
|
44
44
|
external_url?: string | undefined;
|
|
45
45
|
}>;
|
|
@@ -19,13 +19,13 @@ declare const editionMintSchema: z.ZodObject<{
|
|
|
19
19
|
ipType: "Audio" | "Video" | "Art" | "Photography" | "NFT" | "Software" | "RWA" | "Patents" | "Posts" | "Publications" | "Documents" | "Custom";
|
|
20
20
|
licenseType: string;
|
|
21
21
|
commercialUse: "Yes" | "No";
|
|
22
|
-
value: string;
|
|
23
|
-
recipient: string;
|
|
24
22
|
derivatives: "Allowed" | "Not Allowed" | "Share-Alike";
|
|
25
23
|
attribution: "Required" | "Not Required";
|
|
26
24
|
geographicScope: string;
|
|
27
25
|
aiPolicy: "Allowed" | "Not Allowed" | "Training Only";
|
|
28
26
|
royalty: number;
|
|
27
|
+
value: string;
|
|
28
|
+
recipient: string;
|
|
29
29
|
description?: string | undefined;
|
|
30
30
|
external_url?: string | undefined;
|
|
31
31
|
}, {
|
|
@@ -33,13 +33,13 @@ declare const editionMintSchema: z.ZodObject<{
|
|
|
33
33
|
ipType: "Audio" | "Video" | "Art" | "Photography" | "NFT" | "Software" | "RWA" | "Patents" | "Posts" | "Publications" | "Documents" | "Custom";
|
|
34
34
|
licenseType: string;
|
|
35
35
|
commercialUse: "Yes" | "No";
|
|
36
|
-
value: string;
|
|
37
|
-
recipient: string;
|
|
38
36
|
derivatives: "Allowed" | "Not Allowed" | "Share-Alike";
|
|
39
37
|
attribution: "Required" | "Not Required";
|
|
40
38
|
geographicScope: string;
|
|
41
39
|
aiPolicy: "Allowed" | "Not Allowed" | "Training Only";
|
|
42
40
|
royalty: number;
|
|
41
|
+
value: string;
|
|
42
|
+
recipient: string;
|
|
43
43
|
description?: string | undefined;
|
|
44
44
|
external_url?: string | undefined;
|
|
45
45
|
}>;
|
|
@@ -7,7 +7,7 @@ declare function useTokenBalance(symbol: string | null, holderAddress: string |
|
|
|
7
7
|
rawBalance: bigint | null;
|
|
8
8
|
isLoading: boolean;
|
|
9
9
|
error: any;
|
|
10
|
-
decimals:
|
|
10
|
+
decimals: 8 | 6 | 18;
|
|
11
11
|
};
|
|
12
12
|
declare function hasSufficientBalance(rawBalance: bigint | null, requiredHuman: string, decimals: number): boolean | null;
|
|
13
13
|
|
|
@@ -7,7 +7,7 @@ declare function useTokenBalance(symbol: string | null, holderAddress: string |
|
|
|
7
7
|
rawBalance: bigint | null;
|
|
8
8
|
isLoading: boolean;
|
|
9
9
|
error: any;
|
|
10
|
-
decimals:
|
|
10
|
+
decimals: 8 | 6 | 18;
|
|
11
11
|
};
|
|
12
12
|
declare function hasSufficientBalance(rawBalance: bigint | null, requiredHuman: string, decimals: number): boolean | null;
|
|
13
13
|
|