@medialane/ui 0.163.0 → 0.165.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/activities-feed.cjs +211 -0
- package/dist/components/activities-feed.cjs.map +1 -0
- package/dist/components/activities-feed.d.cts +9 -0
- package/dist/components/activities-feed.d.ts +9 -0
- package/dist/components/activities-feed.js +177 -0
- package/dist/components/activities-feed.js.map +1 -0
- package/dist/components/button.d.cts +1 -1
- package/dist/components/button.d.ts +1 -1
- package/dist/index.cjs +14 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -2
- package/dist/index.d.ts +4 -2
- package/dist/index.js +14 -2
- package/dist/index.js.map +1 -1
- package/dist/utils/describe-error.cjs +130 -0
- package/dist/utils/describe-error.cjs.map +1 -0
- package/dist/utils/describe-error.d.cts +15 -0
- package/dist/utils/describe-error.d.ts +15 -0
- package/dist/utils/describe-error.js +107 -0
- package/dist/utils/describe-error.js.map +1 -0
- package/dist/utils/wallet-error.cjs +2 -82
- package/dist/utils/wallet-error.cjs.map +1 -1
- package/dist/utils/wallet-error.d.cts +2 -8
- package/dist/utils/wallet-error.d.ts +2 -8
- package/dist/utils/wallet-error.js +1 -81
- package/dist/utils/wallet-error.js.map +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
"use client";
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __export = (target, all) => {
|
|
10
|
+
for (var name in all)
|
|
11
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
12
|
+
};
|
|
13
|
+
var __copyProps = (to, from, except, desc) => {
|
|
14
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
+
for (let key of __getOwnPropNames(from))
|
|
16
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
17
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
18
|
+
}
|
|
19
|
+
return to;
|
|
20
|
+
};
|
|
21
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
22
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
23
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
24
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
25
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
26
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
27
|
+
mod
|
|
28
|
+
));
|
|
29
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
30
|
+
var activities_feed_exports = {};
|
|
31
|
+
__export(activities_feed_exports, {
|
|
32
|
+
ActivitiesFeed: () => ActivitiesFeed
|
|
33
|
+
});
|
|
34
|
+
module.exports = __toCommonJS(activities_feed_exports);
|
|
35
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
36
|
+
var import_react = require("react");
|
|
37
|
+
var import_swr = __toESM(require("swr"), 1);
|
|
38
|
+
var import_link = __toESM(require("next/link"), 1);
|
|
39
|
+
var import_use_activities = require("../utils/use-activities.js");
|
|
40
|
+
var import_use_rewards = require("../utils/use-rewards.js");
|
|
41
|
+
var import_skeleton = require("./skeleton.js");
|
|
42
|
+
var import_load_more_sentinel = require("./load-more-sentinel.js");
|
|
43
|
+
var import_lucide_react = require("lucide-react");
|
|
44
|
+
var import_activity = require("../data/activity.js");
|
|
45
|
+
var import_activity_row = require("./activity-row.js");
|
|
46
|
+
var import_cn = require("../utils/cn.js");
|
|
47
|
+
async function fetchAnnouncements() {
|
|
48
|
+
const res = await fetch("/api/announcements");
|
|
49
|
+
if (!res.ok) return [];
|
|
50
|
+
return res.json();
|
|
51
|
+
}
|
|
52
|
+
function AnnouncementsBanner({ announcements }) {
|
|
53
|
+
const pinned = announcements.filter((a) => a.pinned);
|
|
54
|
+
if (pinned.length === 0) return null;
|
|
55
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "space-y-2", children: pinned.map((ann) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
56
|
+
import_link.default,
|
|
57
|
+
{
|
|
58
|
+
href: ann.href,
|
|
59
|
+
className: "flex items-start gap-3 rounded-xl border border-brand-purple/20 bg-brand-purple/5 px-4 py-3 hover:bg-brand-purple/10 transition-colors group",
|
|
60
|
+
children: [
|
|
61
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-8 w-8 rounded-lg bg-brand-purple/10 flex items-center justify-center shrink-0 mt-0.5", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Megaphone, { className: "h-3.5 w-3.5 text-brand-purple" }) }),
|
|
62
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex-1 min-w-0", children: [
|
|
63
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-1.5 mb-0.5", children: [
|
|
64
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Pin, { className: "h-2.5 w-2.5 text-brand-purple/60" }),
|
|
65
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-[10px] font-bold uppercase tracking-widest text-brand-purple/60", children: "Announcement" })
|
|
66
|
+
] }),
|
|
67
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-sm font-semibold leading-snug", children: ann.title }),
|
|
68
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-xs text-muted-foreground mt-0.5 truncate", children: ann.body })
|
|
69
|
+
] }),
|
|
70
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.ArrowRight, { className: "h-4 w-4 text-muted-foreground group-hover:text-foreground transition-colors shrink-0 mt-1" })
|
|
71
|
+
]
|
|
72
|
+
},
|
|
73
|
+
ann.id
|
|
74
|
+
)) });
|
|
75
|
+
}
|
|
76
|
+
const PAGE_SIZE = 30;
|
|
77
|
+
function ActivitiesFeed({ getClient }) {
|
|
78
|
+
const [page, setPage] = (0, import_react.useState)(1);
|
|
79
|
+
const [typeFilter, setTypeFilter] = (0, import_react.useState)("");
|
|
80
|
+
const [allActivities, setAllActivities] = (0, import_react.useState)([]);
|
|
81
|
+
const { data: announcements = [] } = (0, import_swr.default)(
|
|
82
|
+
"announcements",
|
|
83
|
+
fetchAnnouncements,
|
|
84
|
+
{ revalidateOnFocus: false }
|
|
85
|
+
);
|
|
86
|
+
const prevType = (0, import_react.useRef)(typeFilter);
|
|
87
|
+
(0, import_react.useEffect)(() => {
|
|
88
|
+
if (prevType.current !== typeFilter) {
|
|
89
|
+
prevType.current = typeFilter;
|
|
90
|
+
setPage(1);
|
|
91
|
+
setAllActivities([]);
|
|
92
|
+
}
|
|
93
|
+
}, [typeFilter]);
|
|
94
|
+
const { activities, meta, isLoading } = (0, import_use_activities.useActivities)(getClient, {
|
|
95
|
+
limit: PAGE_SIZE,
|
|
96
|
+
page,
|
|
97
|
+
type: typeFilter || void 0
|
|
98
|
+
});
|
|
99
|
+
(0, import_react.useEffect)(() => {
|
|
100
|
+
if (isLoading) return;
|
|
101
|
+
if (page === 1) {
|
|
102
|
+
setAllActivities(activities);
|
|
103
|
+
} else {
|
|
104
|
+
setAllActivities((prev) => {
|
|
105
|
+
const existing = new Set(
|
|
106
|
+
prev.map((a) => `${a.txHash}-${a.type}-${a.nftTokenId ?? ""}`)
|
|
107
|
+
);
|
|
108
|
+
const newItems = activities.filter(
|
|
109
|
+
(a) => !existing.has(`${a.txHash}-${a.type}-${a.nftTokenId ?? ""}`)
|
|
110
|
+
);
|
|
111
|
+
return newItems.length > 0 ? [...prev, ...newItems] : prev;
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}, [activities, isLoading, page]);
|
|
115
|
+
const pageActors = allActivities.map((a) => a.offerer ?? a.fulfiller ?? (a.type === "mint" ? a.to : a.from)).filter((a) => Boolean(a));
|
|
116
|
+
const { data: actorLevels } = (0, import_use_rewards.useRewardsBatch)(getClient, pageActors);
|
|
117
|
+
const isInitialLoading = isLoading && allActivities.length === 0;
|
|
118
|
+
const isLoadingMore = isLoading && allActivities.length > 0;
|
|
119
|
+
const hasMore = meta?.total != null ? allActivities.length < meta.total : false;
|
|
120
|
+
const total = meta?.total ?? null;
|
|
121
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-5", children: [
|
|
122
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(AnnouncementsBanner, { announcements }),
|
|
123
|
+
total != null && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [
|
|
124
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "flex items-center gap-1.5", children: [
|
|
125
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "h-1.5 w-1.5 rounded-full bg-emerald-500 animate-pulse" }),
|
|
126
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "font-semibold text-foreground tabular-nums", children: total.toLocaleString() }),
|
|
127
|
+
typeFilter ? `${typeFilter} events` : "total events"
|
|
128
|
+
] }),
|
|
129
|
+
typeFilter && allActivities.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
130
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-muted-foreground/40", children: "\xB7" }),
|
|
131
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
|
|
132
|
+
allActivities.length.toLocaleString(),
|
|
133
|
+
" loaded"
|
|
134
|
+
] })
|
|
135
|
+
] })
|
|
136
|
+
] }),
|
|
137
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex flex-wrap gap-2", children: import_activity.TYPE_FILTERS.map((f) => {
|
|
138
|
+
const typeConfig = f.value ? import_activity.ACTIVITY_TYPE_CONFIG[f.value] : null;
|
|
139
|
+
const Icon = typeConfig?.icon;
|
|
140
|
+
const isActive = typeFilter === f.value;
|
|
141
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
142
|
+
"button",
|
|
143
|
+
{
|
|
144
|
+
onClick: () => setTypeFilter(f.value),
|
|
145
|
+
className: (0, import_cn.cn)(
|
|
146
|
+
"flex items-center gap-1.5 text-xs px-3 py-1.5 rounded-full border transition-all font-medium",
|
|
147
|
+
isActive ? "border-primary bg-primary/10 text-primary shadow-sm" : "border-border text-muted-foreground hover:border-primary/40 hover:text-foreground hover:bg-muted/50"
|
|
148
|
+
),
|
|
149
|
+
children: [
|
|
150
|
+
Icon && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
151
|
+
Icon,
|
|
152
|
+
{
|
|
153
|
+
className: (0, import_cn.cn)(
|
|
154
|
+
"h-3 w-3",
|
|
155
|
+
isActive ? typeConfig?.colorClass : ""
|
|
156
|
+
)
|
|
157
|
+
}
|
|
158
|
+
),
|
|
159
|
+
f.label
|
|
160
|
+
]
|
|
161
|
+
},
|
|
162
|
+
f.value
|
|
163
|
+
);
|
|
164
|
+
}) }),
|
|
165
|
+
isInitialLoading ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "divide-y divide-border/50 rounded-xl border border-border overflow-hidden", children: Array.from({ length: 10 }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-3 px-4 py-3.5 bg-card", children: [
|
|
166
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_skeleton.Skeleton, { className: "h-8 w-8 rounded-lg shrink-0" }),
|
|
167
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_skeleton.Skeleton, { className: "h-9 w-9 rounded-md shrink-0" }),
|
|
168
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex-1 space-y-2", children: [
|
|
169
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_skeleton.Skeleton, { className: "h-3.5 w-40" }),
|
|
170
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_skeleton.Skeleton, { className: "h-2.5 w-24" })
|
|
171
|
+
] }),
|
|
172
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-2.5", children: [
|
|
173
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-1 text-right", children: [
|
|
174
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_skeleton.Skeleton, { className: "h-4 w-16" }),
|
|
175
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_skeleton.Skeleton, { className: "h-2.5 w-8" })
|
|
176
|
+
] }),
|
|
177
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_skeleton.Skeleton, { className: "h-2.5 w-12 hidden sm:block" })
|
|
178
|
+
] })
|
|
179
|
+
] }, i)) }) : allActivities.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "py-20 flex flex-col items-center gap-3 text-center", children: [
|
|
180
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-12 w-12 rounded-full bg-muted flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Zap, { className: "h-5 w-5 text-muted-foreground" }) }),
|
|
181
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-muted-foreground", children: typeFilter ? `No ${typeFilter} events yet.` : "No activity yet." })
|
|
182
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-4", children: [
|
|
183
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "divide-y divide-border/50 rounded-xl border border-border overflow-hidden", children: allActivities.map((activity, i) => {
|
|
184
|
+
const actor = activity.offerer ?? activity.fulfiller ?? (activity.type === "mint" ? activity.to : activity.from);
|
|
185
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
186
|
+
import_activity_row.ActivityRow,
|
|
187
|
+
{
|
|
188
|
+
activity,
|
|
189
|
+
showActor: true,
|
|
190
|
+
showExplorer: true,
|
|
191
|
+
actorLevel: actor ? actorLevels?.get(actor) : void 0
|
|
192
|
+
},
|
|
193
|
+
`${activity.txHash}-${activity.type}-${activity.nftTokenId ?? i}`
|
|
194
|
+
);
|
|
195
|
+
}) }),
|
|
196
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
197
|
+
import_load_more_sentinel.LoadMoreSentinel,
|
|
198
|
+
{
|
|
199
|
+
hasMore,
|
|
200
|
+
isLoading: isLoadingMore,
|
|
201
|
+
onLoadMore: () => setPage((p) => p + 1)
|
|
202
|
+
}
|
|
203
|
+
)
|
|
204
|
+
] })
|
|
205
|
+
] });
|
|
206
|
+
}
|
|
207
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
208
|
+
0 && (module.exports = {
|
|
209
|
+
ActivitiesFeed
|
|
210
|
+
});
|
|
211
|
+
//# sourceMappingURL=activities-feed.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/activities-feed.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState, useEffect, useRef } from \"react\";\nimport useSWR from \"swr\";\nimport Link from \"next/link\";\nimport { useActivities } from \"../utils/use-activities.js\";\nimport { useRewardsBatch } from \"../utils/use-rewards.js\";\nimport type { ApiActivitiesQuery, ApiActivity } from \"@medialane/sdk\";\nimport type { MedialaneClient } from \"@medialane/sdk/starknet\";\nimport { Skeleton } from \"./skeleton.js\";\nimport { LoadMoreSentinel } from \"./load-more-sentinel.js\";\nimport { Zap, Megaphone, ArrowRight, Pin } from \"lucide-react\";\nimport { ACTIVITY_TYPE_CONFIG, TYPE_FILTERS } from \"../data/activity.js\";\nimport { ActivityRow } from \"./activity-row.js\";\nimport { cn } from \"../utils/cn.js\";\nimport type { Announcement } from \"../data/notification.js\";\n\nasync function fetchAnnouncements(): Promise<Announcement[]> {\n const res = await fetch(\"/api/announcements\");\n if (!res.ok) return [];\n return res.json();\n}\n\nfunction AnnouncementsBanner({ announcements }: { announcements: Announcement[] }) {\n const pinned = announcements.filter((a) => a.pinned);\n if (pinned.length === 0) return null;\n return (\n <div className=\"space-y-2\">\n {pinned.map((ann) => (\n <Link\n key={ann.id}\n href={ann.href}\n className=\"flex items-start gap-3 rounded-xl border border-brand-purple/20 bg-brand-purple/5 px-4 py-3 hover:bg-brand-purple/10 transition-colors group\"\n >\n <div className=\"h-8 w-8 rounded-lg bg-brand-purple/10 flex items-center justify-center shrink-0 mt-0.5\">\n <Megaphone className=\"h-3.5 w-3.5 text-brand-purple\" />\n </div>\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-1.5 mb-0.5\">\n <Pin className=\"h-2.5 w-2.5 text-brand-purple/60\" />\n <span className=\"text-[10px] font-bold uppercase tracking-widest text-brand-purple/60\">Announcement</span>\n </div>\n <p className=\"text-sm font-semibold leading-snug\">{ann.title}</p>\n <p className=\"text-xs text-muted-foreground mt-0.5 truncate\">{ann.body}</p>\n </div>\n <ArrowRight className=\"h-4 w-4 text-muted-foreground group-hover:text-foreground transition-colors shrink-0 mt-1\" />\n </Link>\n ))}\n </div>\n );\n}\n\nconst PAGE_SIZE = 30;\n\nexport interface ActivitiesFeedProps {\n getClient: () => MedialaneClient;\n}\n\nexport function ActivitiesFeed({ getClient }: ActivitiesFeedProps) {\n const [page, setPage] = useState(1);\n const [typeFilter, setTypeFilter] = useState(\"\");\n const [allActivities, setAllActivities] = useState<ApiActivity[]>([]);\n const { data: announcements = [] } = useSWR<Announcement[]>(\n \"announcements\",\n fetchAnnouncements,\n { revalidateOnFocus: false }\n );\n\n const prevType = useRef(typeFilter);\n useEffect(() => {\n if (prevType.current !== typeFilter) {\n prevType.current = typeFilter;\n setPage(1);\n setAllActivities([]);\n }\n }, [typeFilter]);\n\n const { activities, meta, isLoading } = useActivities(getClient, {\n limit: PAGE_SIZE,\n page,\n type: (typeFilter as ApiActivitiesQuery[\"type\"]) || undefined,\n });\n\n useEffect(() => {\n if (isLoading) return;\n if (page === 1) {\n setAllActivities(activities);\n } else {\n setAllActivities((prev) => {\n const existing = new Set(\n prev.map((a) => `${a.txHash}-${a.type}-${a.nftTokenId ?? \"\"}`)\n );\n const newItems = activities.filter(\n (a) => !existing.has(`${a.txHash}-${a.type}-${a.nftTokenId ?? \"\"}`)\n );\n return newItems.length > 0 ? [...prev, ...newItems] : prev;\n });\n }\n }, [activities, isLoading, page]);\n\n const pageActors = allActivities\n .map((a) => a.offerer ?? a.fulfiller ?? (a.type === \"mint\" ? a.to : a.from))\n .filter((a): a is string => Boolean(a));\n const { data: actorLevels } = useRewardsBatch(getClient, pageActors);\n\n const isInitialLoading = isLoading && allActivities.length === 0;\n const isLoadingMore = isLoading && allActivities.length > 0;\n const hasMore = meta?.total != null ? allActivities.length < meta.total : false;\n const total = meta?.total ?? null;\n\n return (\n <div className=\"space-y-5\">\n <AnnouncementsBanner announcements={announcements} />\n\n {total != null && (\n <div className=\"flex items-center gap-2 text-sm text-muted-foreground\">\n <span className=\"flex items-center gap-1.5\">\n <span className=\"h-1.5 w-1.5 rounded-full bg-emerald-500 animate-pulse\" />\n <span className=\"font-semibold text-foreground tabular-nums\">\n {total.toLocaleString()}\n </span>\n {typeFilter ? `${typeFilter} events` : \"total events\"}\n </span>\n {typeFilter && allActivities.length > 0 && (\n <>\n <span className=\"text-muted-foreground/40\">·</span>\n <span>{allActivities.length.toLocaleString()} loaded</span>\n </>\n )}\n </div>\n )}\n\n <div className=\"flex flex-wrap gap-2\">\n {TYPE_FILTERS.map((f) => {\n const typeConfig = f.value ? ACTIVITY_TYPE_CONFIG[f.value] : null;\n const Icon = typeConfig?.icon;\n const isActive = typeFilter === f.value;\n return (\n <button\n key={f.value}\n onClick={() => setTypeFilter(f.value)}\n className={cn(\n \"flex items-center gap-1.5 text-xs px-3 py-1.5 rounded-full border transition-all font-medium\",\n isActive\n ? \"border-primary bg-primary/10 text-primary shadow-sm\"\n : \"border-border text-muted-foreground hover:border-primary/40 hover:text-foreground hover:bg-muted/50\"\n )}\n >\n {Icon && (\n <Icon\n className={cn(\n \"h-3 w-3\",\n isActive ? typeConfig?.colorClass : \"\"\n )}\n />\n )}\n {f.label}\n </button>\n );\n })}\n </div>\n\n {isInitialLoading ? (\n <div className=\"divide-y divide-border/50 rounded-xl border border-border overflow-hidden\">\n {Array.from({ length: 10 }).map((_, i) => (\n <div key={i} className=\"flex items-center gap-3 px-4 py-3.5 bg-card\">\n <Skeleton className=\"h-8 w-8 rounded-lg shrink-0\" />\n <Skeleton className=\"h-9 w-9 rounded-md shrink-0\" />\n <div className=\"flex-1 space-y-2\">\n <Skeleton className=\"h-3.5 w-40\" />\n <Skeleton className=\"h-2.5 w-24\" />\n </div>\n <div className=\"flex items-center gap-2.5\">\n <div className=\"space-y-1 text-right\">\n <Skeleton className=\"h-4 w-16\" />\n <Skeleton className=\"h-2.5 w-8\" />\n </div>\n <Skeleton className=\"h-2.5 w-12 hidden sm:block\" />\n </div>\n </div>\n ))}\n </div>\n ) : allActivities.length === 0 ? (\n <div className=\"py-20 flex flex-col items-center gap-3 text-center\">\n <div className=\"h-12 w-12 rounded-full bg-muted flex items-center justify-center\">\n <Zap className=\"h-5 w-5 text-muted-foreground\" />\n </div>\n <p className=\"text-muted-foreground\">\n {typeFilter ? `No ${typeFilter} events yet.` : \"No activity yet.\"}\n </p>\n </div>\n ) : (\n <div className=\"space-y-4\">\n <div className=\"divide-y divide-border/50 rounded-xl border border-border overflow-hidden\">\n {allActivities.map((activity, i) => {\n const actor = activity.offerer ?? activity.fulfiller ?? (activity.type === \"mint\" ? activity.to : activity.from);\n return (\n <ActivityRow\n key={`${activity.txHash}-${activity.type}-${activity.nftTokenId ?? i}`}\n activity={activity}\n showActor\n showExplorer\n actorLevel={actor ? actorLevels?.get(actor) : undefined}\n />\n );\n })}\n </div>\n\n <LoadMoreSentinel\n hasMore={hasMore}\n isLoading={isLoadingMore}\n onLoadMore={() => setPage((p) => p + 1)}\n />\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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","names":["Link","useSWR"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { MedialaneClient } from '@medialane/sdk/starknet';
|
|
3
|
+
|
|
4
|
+
interface ActivitiesFeedProps {
|
|
5
|
+
getClient: () => MedialaneClient;
|
|
6
|
+
}
|
|
7
|
+
declare function ActivitiesFeed({ getClient }: ActivitiesFeedProps): react_jsx_runtime.JSX.Element;
|
|
8
|
+
|
|
9
|
+
export { ActivitiesFeed, type ActivitiesFeedProps };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { MedialaneClient } from '@medialane/sdk/starknet';
|
|
3
|
+
|
|
4
|
+
interface ActivitiesFeedProps {
|
|
5
|
+
getClient: () => MedialaneClient;
|
|
6
|
+
}
|
|
7
|
+
declare function ActivitiesFeed({ getClient }: ActivitiesFeedProps): react_jsx_runtime.JSX.Element;
|
|
8
|
+
|
|
9
|
+
export { ActivitiesFeed, type ActivitiesFeedProps };
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useState, useEffect, useRef } from "react";
|
|
4
|
+
import useSWR from "swr";
|
|
5
|
+
import Link from "next/link";
|
|
6
|
+
import { useActivities } from "../utils/use-activities.js";
|
|
7
|
+
import { useRewardsBatch } from "../utils/use-rewards.js";
|
|
8
|
+
import { Skeleton } from "./skeleton.js";
|
|
9
|
+
import { LoadMoreSentinel } from "./load-more-sentinel.js";
|
|
10
|
+
import { Zap, Megaphone, ArrowRight, Pin } from "lucide-react";
|
|
11
|
+
import { ACTIVITY_TYPE_CONFIG, TYPE_FILTERS } from "../data/activity.js";
|
|
12
|
+
import { ActivityRow } from "./activity-row.js";
|
|
13
|
+
import { cn } from "../utils/cn.js";
|
|
14
|
+
async function fetchAnnouncements() {
|
|
15
|
+
const res = await fetch("/api/announcements");
|
|
16
|
+
if (!res.ok) return [];
|
|
17
|
+
return res.json();
|
|
18
|
+
}
|
|
19
|
+
function AnnouncementsBanner({ announcements }) {
|
|
20
|
+
const pinned = announcements.filter((a) => a.pinned);
|
|
21
|
+
if (pinned.length === 0) return null;
|
|
22
|
+
return /* @__PURE__ */ jsx("div", { className: "space-y-2", children: pinned.map((ann) => /* @__PURE__ */ jsxs(
|
|
23
|
+
Link,
|
|
24
|
+
{
|
|
25
|
+
href: ann.href,
|
|
26
|
+
className: "flex items-start gap-3 rounded-xl border border-brand-purple/20 bg-brand-purple/5 px-4 py-3 hover:bg-brand-purple/10 transition-colors group",
|
|
27
|
+
children: [
|
|
28
|
+
/* @__PURE__ */ jsx("div", { className: "h-8 w-8 rounded-lg bg-brand-purple/10 flex items-center justify-center shrink-0 mt-0.5", children: /* @__PURE__ */ jsx(Megaphone, { className: "h-3.5 w-3.5 text-brand-purple" }) }),
|
|
29
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
30
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 mb-0.5", children: [
|
|
31
|
+
/* @__PURE__ */ jsx(Pin, { className: "h-2.5 w-2.5 text-brand-purple/60" }),
|
|
32
|
+
/* @__PURE__ */ jsx("span", { className: "text-[10px] font-bold uppercase tracking-widest text-brand-purple/60", children: "Announcement" })
|
|
33
|
+
] }),
|
|
34
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-semibold leading-snug", children: ann.title }),
|
|
35
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-0.5 truncate", children: ann.body })
|
|
36
|
+
] }),
|
|
37
|
+
/* @__PURE__ */ jsx(ArrowRight, { className: "h-4 w-4 text-muted-foreground group-hover:text-foreground transition-colors shrink-0 mt-1" })
|
|
38
|
+
]
|
|
39
|
+
},
|
|
40
|
+
ann.id
|
|
41
|
+
)) });
|
|
42
|
+
}
|
|
43
|
+
const PAGE_SIZE = 30;
|
|
44
|
+
function ActivitiesFeed({ getClient }) {
|
|
45
|
+
const [page, setPage] = useState(1);
|
|
46
|
+
const [typeFilter, setTypeFilter] = useState("");
|
|
47
|
+
const [allActivities, setAllActivities] = useState([]);
|
|
48
|
+
const { data: announcements = [] } = useSWR(
|
|
49
|
+
"announcements",
|
|
50
|
+
fetchAnnouncements,
|
|
51
|
+
{ revalidateOnFocus: false }
|
|
52
|
+
);
|
|
53
|
+
const prevType = useRef(typeFilter);
|
|
54
|
+
useEffect(() => {
|
|
55
|
+
if (prevType.current !== typeFilter) {
|
|
56
|
+
prevType.current = typeFilter;
|
|
57
|
+
setPage(1);
|
|
58
|
+
setAllActivities([]);
|
|
59
|
+
}
|
|
60
|
+
}, [typeFilter]);
|
|
61
|
+
const { activities, meta, isLoading } = useActivities(getClient, {
|
|
62
|
+
limit: PAGE_SIZE,
|
|
63
|
+
page,
|
|
64
|
+
type: typeFilter || void 0
|
|
65
|
+
});
|
|
66
|
+
useEffect(() => {
|
|
67
|
+
if (isLoading) return;
|
|
68
|
+
if (page === 1) {
|
|
69
|
+
setAllActivities(activities);
|
|
70
|
+
} else {
|
|
71
|
+
setAllActivities((prev) => {
|
|
72
|
+
const existing = new Set(
|
|
73
|
+
prev.map((a) => `${a.txHash}-${a.type}-${a.nftTokenId ?? ""}`)
|
|
74
|
+
);
|
|
75
|
+
const newItems = activities.filter(
|
|
76
|
+
(a) => !existing.has(`${a.txHash}-${a.type}-${a.nftTokenId ?? ""}`)
|
|
77
|
+
);
|
|
78
|
+
return newItems.length > 0 ? [...prev, ...newItems] : prev;
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}, [activities, isLoading, page]);
|
|
82
|
+
const pageActors = allActivities.map((a) => a.offerer ?? a.fulfiller ?? (a.type === "mint" ? a.to : a.from)).filter((a) => Boolean(a));
|
|
83
|
+
const { data: actorLevels } = useRewardsBatch(getClient, pageActors);
|
|
84
|
+
const isInitialLoading = isLoading && allActivities.length === 0;
|
|
85
|
+
const isLoadingMore = isLoading && allActivities.length > 0;
|
|
86
|
+
const hasMore = meta?.total != null ? allActivities.length < meta.total : false;
|
|
87
|
+
const total = meta?.total ?? null;
|
|
88
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-5", children: [
|
|
89
|
+
/* @__PURE__ */ jsx(AnnouncementsBanner, { announcements }),
|
|
90
|
+
total != null && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [
|
|
91
|
+
/* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5", children: [
|
|
92
|
+
/* @__PURE__ */ jsx("span", { className: "h-1.5 w-1.5 rounded-full bg-emerald-500 animate-pulse" }),
|
|
93
|
+
/* @__PURE__ */ jsx("span", { className: "font-semibold text-foreground tabular-nums", children: total.toLocaleString() }),
|
|
94
|
+
typeFilter ? `${typeFilter} events` : "total events"
|
|
95
|
+
] }),
|
|
96
|
+
typeFilter && allActivities.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
97
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground/40", children: "\xB7" }),
|
|
98
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
99
|
+
allActivities.length.toLocaleString(),
|
|
100
|
+
" loaded"
|
|
101
|
+
] })
|
|
102
|
+
] })
|
|
103
|
+
] }),
|
|
104
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2", children: TYPE_FILTERS.map((f) => {
|
|
105
|
+
const typeConfig = f.value ? ACTIVITY_TYPE_CONFIG[f.value] : null;
|
|
106
|
+
const Icon = typeConfig?.icon;
|
|
107
|
+
const isActive = typeFilter === f.value;
|
|
108
|
+
return /* @__PURE__ */ jsxs(
|
|
109
|
+
"button",
|
|
110
|
+
{
|
|
111
|
+
onClick: () => setTypeFilter(f.value),
|
|
112
|
+
className: cn(
|
|
113
|
+
"flex items-center gap-1.5 text-xs px-3 py-1.5 rounded-full border transition-all font-medium",
|
|
114
|
+
isActive ? "border-primary bg-primary/10 text-primary shadow-sm" : "border-border text-muted-foreground hover:border-primary/40 hover:text-foreground hover:bg-muted/50"
|
|
115
|
+
),
|
|
116
|
+
children: [
|
|
117
|
+
Icon && /* @__PURE__ */ jsx(
|
|
118
|
+
Icon,
|
|
119
|
+
{
|
|
120
|
+
className: cn(
|
|
121
|
+
"h-3 w-3",
|
|
122
|
+
isActive ? typeConfig?.colorClass : ""
|
|
123
|
+
)
|
|
124
|
+
}
|
|
125
|
+
),
|
|
126
|
+
f.label
|
|
127
|
+
]
|
|
128
|
+
},
|
|
129
|
+
f.value
|
|
130
|
+
);
|
|
131
|
+
}) }),
|
|
132
|
+
isInitialLoading ? /* @__PURE__ */ jsx("div", { className: "divide-y divide-border/50 rounded-xl border border-border overflow-hidden", children: Array.from({ length: 10 }).map((_, i) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 px-4 py-3.5 bg-card", children: [
|
|
133
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-8 w-8 rounded-lg shrink-0" }),
|
|
134
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-9 w-9 rounded-md shrink-0" }),
|
|
135
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 space-y-2", children: [
|
|
136
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-3.5 w-40" }),
|
|
137
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-2.5 w-24" })
|
|
138
|
+
] }),
|
|
139
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2.5", children: [
|
|
140
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-1 text-right", children: [
|
|
141
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-16" }),
|
|
142
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-2.5 w-8" })
|
|
143
|
+
] }),
|
|
144
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-2.5 w-12 hidden sm:block" })
|
|
145
|
+
] })
|
|
146
|
+
] }, i)) }) : allActivities.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "py-20 flex flex-col items-center gap-3 text-center", children: [
|
|
147
|
+
/* @__PURE__ */ jsx("div", { className: "h-12 w-12 rounded-full bg-muted flex items-center justify-center", children: /* @__PURE__ */ jsx(Zap, { className: "h-5 w-5 text-muted-foreground" }) }),
|
|
148
|
+
/* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: typeFilter ? `No ${typeFilter} events yet.` : "No activity yet." })
|
|
149
|
+
] }) : /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
150
|
+
/* @__PURE__ */ jsx("div", { className: "divide-y divide-border/50 rounded-xl border border-border overflow-hidden", children: allActivities.map((activity, i) => {
|
|
151
|
+
const actor = activity.offerer ?? activity.fulfiller ?? (activity.type === "mint" ? activity.to : activity.from);
|
|
152
|
+
return /* @__PURE__ */ jsx(
|
|
153
|
+
ActivityRow,
|
|
154
|
+
{
|
|
155
|
+
activity,
|
|
156
|
+
showActor: true,
|
|
157
|
+
showExplorer: true,
|
|
158
|
+
actorLevel: actor ? actorLevels?.get(actor) : void 0
|
|
159
|
+
},
|
|
160
|
+
`${activity.txHash}-${activity.type}-${activity.nftTokenId ?? i}`
|
|
161
|
+
);
|
|
162
|
+
}) }),
|
|
163
|
+
/* @__PURE__ */ jsx(
|
|
164
|
+
LoadMoreSentinel,
|
|
165
|
+
{
|
|
166
|
+
hasMore,
|
|
167
|
+
isLoading: isLoadingMore,
|
|
168
|
+
onLoadMore: () => setPage((p) => p + 1)
|
|
169
|
+
}
|
|
170
|
+
)
|
|
171
|
+
] })
|
|
172
|
+
] });
|
|
173
|
+
}
|
|
174
|
+
export {
|
|
175
|
+
ActivitiesFeed
|
|
176
|
+
};
|
|
177
|
+
//# sourceMappingURL=activities-feed.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/activities-feed.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState, useEffect, useRef } from \"react\";\nimport useSWR from \"swr\";\nimport Link from \"next/link\";\nimport { useActivities } from \"../utils/use-activities.js\";\nimport { useRewardsBatch } from \"../utils/use-rewards.js\";\nimport type { ApiActivitiesQuery, ApiActivity } from \"@medialane/sdk\";\nimport type { MedialaneClient } from \"@medialane/sdk/starknet\";\nimport { Skeleton } from \"./skeleton.js\";\nimport { LoadMoreSentinel } from \"./load-more-sentinel.js\";\nimport { Zap, Megaphone, ArrowRight, Pin } from \"lucide-react\";\nimport { ACTIVITY_TYPE_CONFIG, TYPE_FILTERS } from \"../data/activity.js\";\nimport { ActivityRow } from \"./activity-row.js\";\nimport { cn } from \"../utils/cn.js\";\nimport type { Announcement } from \"../data/notification.js\";\n\nasync function fetchAnnouncements(): Promise<Announcement[]> {\n const res = await fetch(\"/api/announcements\");\n if (!res.ok) return [];\n return res.json();\n}\n\nfunction AnnouncementsBanner({ announcements }: { announcements: Announcement[] }) {\n const pinned = announcements.filter((a) => a.pinned);\n if (pinned.length === 0) return null;\n return (\n <div className=\"space-y-2\">\n {pinned.map((ann) => (\n <Link\n key={ann.id}\n href={ann.href}\n className=\"flex items-start gap-3 rounded-xl border border-brand-purple/20 bg-brand-purple/5 px-4 py-3 hover:bg-brand-purple/10 transition-colors group\"\n >\n <div className=\"h-8 w-8 rounded-lg bg-brand-purple/10 flex items-center justify-center shrink-0 mt-0.5\">\n <Megaphone className=\"h-3.5 w-3.5 text-brand-purple\" />\n </div>\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-1.5 mb-0.5\">\n <Pin className=\"h-2.5 w-2.5 text-brand-purple/60\" />\n <span className=\"text-[10px] font-bold uppercase tracking-widest text-brand-purple/60\">Announcement</span>\n </div>\n <p className=\"text-sm font-semibold leading-snug\">{ann.title}</p>\n <p className=\"text-xs text-muted-foreground mt-0.5 truncate\">{ann.body}</p>\n </div>\n <ArrowRight className=\"h-4 w-4 text-muted-foreground group-hover:text-foreground transition-colors shrink-0 mt-1\" />\n </Link>\n ))}\n </div>\n );\n}\n\nconst PAGE_SIZE = 30;\n\nexport interface ActivitiesFeedProps {\n getClient: () => MedialaneClient;\n}\n\nexport function ActivitiesFeed({ getClient }: ActivitiesFeedProps) {\n const [page, setPage] = useState(1);\n const [typeFilter, setTypeFilter] = useState(\"\");\n const [allActivities, setAllActivities] = useState<ApiActivity[]>([]);\n const { data: announcements = [] } = useSWR<Announcement[]>(\n \"announcements\",\n fetchAnnouncements,\n { revalidateOnFocus: false }\n );\n\n const prevType = useRef(typeFilter);\n useEffect(() => {\n if (prevType.current !== typeFilter) {\n prevType.current = typeFilter;\n setPage(1);\n setAllActivities([]);\n }\n }, [typeFilter]);\n\n const { activities, meta, isLoading } = useActivities(getClient, {\n limit: PAGE_SIZE,\n page,\n type: (typeFilter as ApiActivitiesQuery[\"type\"]) || undefined,\n });\n\n useEffect(() => {\n if (isLoading) return;\n if (page === 1) {\n setAllActivities(activities);\n } else {\n setAllActivities((prev) => {\n const existing = new Set(\n prev.map((a) => `${a.txHash}-${a.type}-${a.nftTokenId ?? \"\"}`)\n );\n const newItems = activities.filter(\n (a) => !existing.has(`${a.txHash}-${a.type}-${a.nftTokenId ?? \"\"}`)\n );\n return newItems.length > 0 ? [...prev, ...newItems] : prev;\n });\n }\n }, [activities, isLoading, page]);\n\n const pageActors = allActivities\n .map((a) => a.offerer ?? a.fulfiller ?? (a.type === \"mint\" ? a.to : a.from))\n .filter((a): a is string => Boolean(a));\n const { data: actorLevels } = useRewardsBatch(getClient, pageActors);\n\n const isInitialLoading = isLoading && allActivities.length === 0;\n const isLoadingMore = isLoading && allActivities.length > 0;\n const hasMore = meta?.total != null ? allActivities.length < meta.total : false;\n const total = meta?.total ?? null;\n\n return (\n <div className=\"space-y-5\">\n <AnnouncementsBanner announcements={announcements} />\n\n {total != null && (\n <div className=\"flex items-center gap-2 text-sm text-muted-foreground\">\n <span className=\"flex items-center gap-1.5\">\n <span className=\"h-1.5 w-1.5 rounded-full bg-emerald-500 animate-pulse\" />\n <span className=\"font-semibold text-foreground tabular-nums\">\n {total.toLocaleString()}\n </span>\n {typeFilter ? `${typeFilter} events` : \"total events\"}\n </span>\n {typeFilter && allActivities.length > 0 && (\n <>\n <span className=\"text-muted-foreground/40\">·</span>\n <span>{allActivities.length.toLocaleString()} loaded</span>\n </>\n )}\n </div>\n )}\n\n <div className=\"flex flex-wrap gap-2\">\n {TYPE_FILTERS.map((f) => {\n const typeConfig = f.value ? ACTIVITY_TYPE_CONFIG[f.value] : null;\n const Icon = typeConfig?.icon;\n const isActive = typeFilter === f.value;\n return (\n <button\n key={f.value}\n onClick={() => setTypeFilter(f.value)}\n className={cn(\n \"flex items-center gap-1.5 text-xs px-3 py-1.5 rounded-full border transition-all font-medium\",\n isActive\n ? \"border-primary bg-primary/10 text-primary shadow-sm\"\n : \"border-border text-muted-foreground hover:border-primary/40 hover:text-foreground hover:bg-muted/50\"\n )}\n >\n {Icon && (\n <Icon\n className={cn(\n \"h-3 w-3\",\n isActive ? typeConfig?.colorClass : \"\"\n )}\n />\n )}\n {f.label}\n </button>\n );\n })}\n </div>\n\n {isInitialLoading ? (\n <div className=\"divide-y divide-border/50 rounded-xl border border-border overflow-hidden\">\n {Array.from({ length: 10 }).map((_, i) => (\n <div key={i} className=\"flex items-center gap-3 px-4 py-3.5 bg-card\">\n <Skeleton className=\"h-8 w-8 rounded-lg shrink-0\" />\n <Skeleton className=\"h-9 w-9 rounded-md shrink-0\" />\n <div className=\"flex-1 space-y-2\">\n <Skeleton className=\"h-3.5 w-40\" />\n <Skeleton className=\"h-2.5 w-24\" />\n </div>\n <div className=\"flex items-center gap-2.5\">\n <div className=\"space-y-1 text-right\">\n <Skeleton className=\"h-4 w-16\" />\n <Skeleton className=\"h-2.5 w-8\" />\n </div>\n <Skeleton className=\"h-2.5 w-12 hidden sm:block\" />\n </div>\n </div>\n ))}\n </div>\n ) : allActivities.length === 0 ? (\n <div className=\"py-20 flex flex-col items-center gap-3 text-center\">\n <div className=\"h-12 w-12 rounded-full bg-muted flex items-center justify-center\">\n <Zap className=\"h-5 w-5 text-muted-foreground\" />\n </div>\n <p className=\"text-muted-foreground\">\n {typeFilter ? `No ${typeFilter} events yet.` : \"No activity yet.\"}\n </p>\n </div>\n ) : (\n <div className=\"space-y-4\">\n <div className=\"divide-y divide-border/50 rounded-xl border border-border overflow-hidden\">\n {allActivities.map((activity, i) => {\n const actor = activity.offerer ?? activity.fulfiller ?? (activity.type === \"mint\" ? activity.to : activity.from);\n return (\n <ActivityRow\n key={`${activity.txHash}-${activity.type}-${activity.nftTokenId ?? i}`}\n activity={activity}\n showActor\n showExplorer\n actorLevel={actor ? actorLevels?.get(actor) : undefined}\n />\n );\n })}\n </div>\n\n <LoadMoreSentinel\n hasMore={hasMore}\n isLoading={isLoadingMore}\n onLoadMore={() => setPage((p) => p + 1)}\n />\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -3,7 +3,7 @@ import * as React from 'react';
|
|
|
3
3
|
import { VariantProps } from 'class-variance-authority';
|
|
4
4
|
|
|
5
5
|
declare const buttonVariants: (props?: ({
|
|
6
|
-
variant?: "
|
|
6
|
+
variant?: "link" | "default" | "destructive" | "outline" | "ghost" | "secondary" | "premium" | "tonal" | "gradient-border" | "gradient-fill" | null | undefined;
|
|
7
7
|
size?: "icon" | "default" | "sm" | "lg" | null | undefined;
|
|
8
8
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
9
9
|
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
|
|
@@ -3,7 +3,7 @@ import * as React from 'react';
|
|
|
3
3
|
import { VariantProps } from 'class-variance-authority';
|
|
4
4
|
|
|
5
5
|
declare const buttonVariants: (props?: ({
|
|
6
|
-
variant?: "
|
|
6
|
+
variant?: "link" | "default" | "destructive" | "outline" | "ghost" | "secondary" | "premium" | "tonal" | "gradient-border" | "gradient-fill" | null | undefined;
|
|
7
7
|
size?: "icon" | "default" | "sm" | "lg" | null | undefined;
|
|
8
8
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
9
9
|
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
|
package/dist/index.cjs
CHANGED
|
@@ -23,6 +23,7 @@ __export(index_exports, {
|
|
|
23
23
|
AI_POLICIES: () => import_ip.AI_POLICIES,
|
|
24
24
|
ActionButton: () => import_action_button.ActionButton,
|
|
25
25
|
ActionDialog: () => import_action_dialog.ActionDialog,
|
|
26
|
+
ActivitiesFeed: () => import_activities_feed.ActivitiesFeed,
|
|
26
27
|
ActivityCard: () => import_activity_card.ActivityCard,
|
|
27
28
|
ActivityCardSkeleton: () => import_activity_card.ActivityCardSkeleton,
|
|
28
29
|
ActivityFeedShell: () => import_activity_feed_shell.ActivityFeedShell,
|
|
@@ -153,6 +154,7 @@ __export(index_exports, {
|
|
|
153
154
|
FormMessage: () => import_form.FormMessage,
|
|
154
155
|
GATED_CONTENT_TYPES: () => import_gated_content_types.GATED_CONTENT_TYPES,
|
|
155
156
|
GATED_CONTENT_TYPE_FALLBACK: () => import_gated_content_types.GATED_CONTENT_TYPE_FALLBACK,
|
|
157
|
+
GENERIC: () => import_describe_error.GENERIC,
|
|
156
158
|
GEOGRAPHIC_SCOPES: () => import_ip.GEOGRAPHIC_SCOPES,
|
|
157
159
|
GradientButton: () => import_gradient_button.GradientButton,
|
|
158
160
|
HelpIcon: () => import_help_icon.HelpIcon,
|
|
@@ -204,9 +206,11 @@ __export(index_exports, {
|
|
|
204
206
|
MedialaneCollectionCard: () => import_medialane_collection_card.MedialaneCollectionCard,
|
|
205
207
|
MedialaneLogoFull: () => import_brand_logo.MedialaneLogoFull,
|
|
206
208
|
MotionCard: () => import_motion_primitives.MotionCard,
|
|
209
|
+
NETWORK_BUSY: () => import_describe_error.NETWORK_BUSY,
|
|
207
210
|
NOTIFICATION_COLOR: () => import_notification_meta.NOTIFICATION_COLOR,
|
|
208
211
|
NOTIFICATION_ICON: () => import_notification_meta.NOTIFICATION_ICON,
|
|
209
212
|
NOTIFICATION_LABEL: () => import_notification_meta.NOTIFICATION_LABEL,
|
|
213
|
+
NOT_SUBMITTED: () => import_describe_error.NOT_SUBMITTED,
|
|
210
214
|
NavAccountSheet: () => import_nav_shell.NavAccountSheet,
|
|
211
215
|
NavBrandButton: () => import_nav_shell.NavBrandButton,
|
|
212
216
|
NavCommandMenu: () => import_nav_command_menu.NavCommandMenu,
|
|
@@ -285,6 +289,7 @@ __export(index_exports, {
|
|
|
285
289
|
TokenCard: () => import_token_card.TokenCard,
|
|
286
290
|
TokenCardSkeleton: () => import_token_card.TokenCardSkeleton,
|
|
287
291
|
TokenGlyph: () => import_token_glyph.TokenGlyph,
|
|
292
|
+
UserFacingError: () => import_describe_error.UserFacingError,
|
|
288
293
|
WrongNetworkError: () => import_wallet_error.WrongNetworkError,
|
|
289
294
|
XpEarned: () => import_xp_earned.XpEarned,
|
|
290
295
|
XpProgress: () => import_xp_progress.XpProgress,
|
|
@@ -302,6 +307,7 @@ __export(index_exports, {
|
|
|
302
307
|
coinSupply: () => import_coins.coinSupply,
|
|
303
308
|
createRewardEarned: () => import_reward_earned.createRewardEarned,
|
|
304
309
|
derivePortfolioCounts: () => import_portfolio_counts.derivePortfolioCounts,
|
|
310
|
+
describeError: () => import_describe_error.describeError,
|
|
305
311
|
dropCreateSchema: () => import_drop_create_schema.dropCreateSchema,
|
|
306
312
|
fdvUsd: () => import_coins.fdvUsd,
|
|
307
313
|
feeLabelFor: () => import_self_fund_consent_dialog.feeLabelFor,
|
|
@@ -318,7 +324,6 @@ __export(index_exports, {
|
|
|
318
324
|
getDefaultClaimWindow: () => import_launchpad_defaults.getDefaultClaimWindow,
|
|
319
325
|
getDefaultDropSchedule: () => import_launchpad_defaults.getDefaultDropSchedule,
|
|
320
326
|
getDropStatus: () => import_drop_status.getDropStatus,
|
|
321
|
-
getFriendlyWalletError: () => import_wallet_error.getFriendlyWalletError,
|
|
322
327
|
getReadIds: () => import_notification_storage.getReadIds,
|
|
323
328
|
ipfsToHttp: () => import_ipfs.ipfsToHttp,
|
|
324
329
|
isBareExecuteFailure: () => import_wallet_error.isBareExecuteFailure,
|
|
@@ -400,6 +405,7 @@ var import_use_intersection_active = require("./utils/use-intersection-active.js
|
|
|
400
405
|
var import_notification_storage = require("./utils/notification-storage.js");
|
|
401
406
|
var import_license_summary = require("./utils/license-summary.js");
|
|
402
407
|
var import_wallet_error = require("./utils/wallet-error.js");
|
|
408
|
+
var import_describe_error = require("./utils/describe-error.js");
|
|
403
409
|
var import_ip_types = require("./data/ip-types.js");
|
|
404
410
|
var import_ip = require("./data/ip.js");
|
|
405
411
|
var import_ip_templates = require("./data/ip-templates.js");
|
|
@@ -495,6 +501,7 @@ var import_badge_catalog = require("./components/rewards/badge-catalog.js");
|
|
|
495
501
|
var import_xp_earned = require("./components/rewards/xp-earned.js");
|
|
496
502
|
var import_reward_earned = require("./components/rewards/reward-earned.js");
|
|
497
503
|
var import_load_more_sentinel = require("./components/load-more-sentinel.js");
|
|
504
|
+
var import_activities_feed = require("./components/activities-feed.js");
|
|
498
505
|
var import_rewards_section = require("./components/rewards-section.js");
|
|
499
506
|
var import_action_button = require("./components/action-button.js");
|
|
500
507
|
var import_gradient_button = require("./components/gradient-button.js");
|
|
@@ -572,6 +579,7 @@ var import_export_key_section = require("./components/wallet/export-key-section.
|
|
|
572
579
|
AI_POLICIES,
|
|
573
580
|
ActionButton,
|
|
574
581
|
ActionDialog,
|
|
582
|
+
ActivitiesFeed,
|
|
575
583
|
ActivityCard,
|
|
576
584
|
ActivityCardSkeleton,
|
|
577
585
|
ActivityFeedShell,
|
|
@@ -702,6 +710,7 @@ var import_export_key_section = require("./components/wallet/export-key-section.
|
|
|
702
710
|
FormMessage,
|
|
703
711
|
GATED_CONTENT_TYPES,
|
|
704
712
|
GATED_CONTENT_TYPE_FALLBACK,
|
|
713
|
+
GENERIC,
|
|
705
714
|
GEOGRAPHIC_SCOPES,
|
|
706
715
|
GradientButton,
|
|
707
716
|
HelpIcon,
|
|
@@ -753,9 +762,11 @@ var import_export_key_section = require("./components/wallet/export-key-section.
|
|
|
753
762
|
MedialaneCollectionCard,
|
|
754
763
|
MedialaneLogoFull,
|
|
755
764
|
MotionCard,
|
|
765
|
+
NETWORK_BUSY,
|
|
756
766
|
NOTIFICATION_COLOR,
|
|
757
767
|
NOTIFICATION_ICON,
|
|
758
768
|
NOTIFICATION_LABEL,
|
|
769
|
+
NOT_SUBMITTED,
|
|
759
770
|
NavAccountSheet,
|
|
760
771
|
NavBrandButton,
|
|
761
772
|
NavCommandMenu,
|
|
@@ -834,6 +845,7 @@ var import_export_key_section = require("./components/wallet/export-key-section.
|
|
|
834
845
|
TokenCard,
|
|
835
846
|
TokenCardSkeleton,
|
|
836
847
|
TokenGlyph,
|
|
848
|
+
UserFacingError,
|
|
837
849
|
WrongNetworkError,
|
|
838
850
|
XpEarned,
|
|
839
851
|
XpProgress,
|
|
@@ -851,6 +863,7 @@ var import_export_key_section = require("./components/wallet/export-key-section.
|
|
|
851
863
|
coinSupply,
|
|
852
864
|
createRewardEarned,
|
|
853
865
|
derivePortfolioCounts,
|
|
866
|
+
describeError,
|
|
854
867
|
dropCreateSchema,
|
|
855
868
|
fdvUsd,
|
|
856
869
|
feeLabelFor,
|
|
@@ -867,7 +880,6 @@ var import_export_key_section = require("./components/wallet/export-key-section.
|
|
|
867
880
|
getDefaultClaimWindow,
|
|
868
881
|
getDefaultDropSchedule,
|
|
869
882
|
getDropStatus,
|
|
870
|
-
getFriendlyWalletError,
|
|
871
883
|
getReadIds,
|
|
872
884
|
ipfsToHttp,
|
|
873
885
|
isBareExecuteFailure,
|