@medialane/ui 0.100.0 → 0.100.1
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/rewards/leaderboard-table.cjs +11 -11
- package/dist/components/rewards/leaderboard-table.cjs.map +1 -1
- package/dist/components/rewards/leaderboard-table.d.cts +3 -1
- package/dist/components/rewards/leaderboard-table.d.ts +3 -1
- package/dist/components/rewards/leaderboard-table.js +11 -11
- package/dist/components/rewards/leaderboard-table.js.map +1 -1
- package/package.json +1 -1
|
@@ -27,24 +27,24 @@ var import_cn = require("../../utils/cn.js");
|
|
|
27
27
|
var import_address = require("../../utils/address.js");
|
|
28
28
|
var import_level_badge = require("./level-badge.js");
|
|
29
29
|
function LeaderboardTable({ entries, highlightAddress, renderAddress, className }) {
|
|
30
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: (0, import_cn.cn)("
|
|
30
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: (0, import_cn.cn)("space-y-1.5", className), children: entries.map((e) => {
|
|
31
31
|
const isViewer = highlightAddress != null && e.address === highlightAddress;
|
|
32
32
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
33
33
|
"div",
|
|
34
34
|
{
|
|
35
35
|
className: (0, import_cn.cn)(
|
|
36
|
-
"flex items-center gap-
|
|
37
|
-
isViewer
|
|
36
|
+
"flex items-center gap-4 rounded-2xl px-4 py-3.5 transition-colors",
|
|
37
|
+
isViewer ? "bg-brand-rose/10" : "bg-foreground/[0.04] hover:bg-foreground/[0.07]"
|
|
38
38
|
),
|
|
39
39
|
children: [
|
|
40
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "min-w-0 flex-1 truncate text-
|
|
40
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "min-w-0 flex-1 truncate text-base font-bold", children: [
|
|
41
41
|
renderAddress ? renderAddress(e.address) : (0, import_address.shortenAddress)(e.address),
|
|
42
|
-
isViewer && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "ml-1.5 text-xs text-
|
|
42
|
+
isViewer && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "ml-1.5 text-xs font-medium text-foreground/50", children: "(you)" })
|
|
43
43
|
] }),
|
|
44
44
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_level_badge.LevelBadge, { level: e.currentLevel, name: e.currentLevelName, badgeColor: e.badgeColor, size: "sm", className: "hidden sm:inline-flex" }),
|
|
45
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "shrink-0 text-
|
|
45
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "shrink-0 text-lg font-black tabular-nums", children: [
|
|
46
46
|
e.totalXp.toLocaleString(),
|
|
47
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "ml-1 text-xs font-
|
|
47
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "ml-1 text-xs font-bold text-foreground/40", children: "XP" })
|
|
48
48
|
] })
|
|
49
49
|
]
|
|
50
50
|
},
|
|
@@ -54,13 +54,13 @@ function LeaderboardTable({ entries, highlightAddress, renderAddress, className
|
|
|
54
54
|
}
|
|
55
55
|
function LeaderboardWidget({ entries, title = "Community Rewards", href, renderAddress, className }) {
|
|
56
56
|
if (entries.length === 0) return null;
|
|
57
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: (0, import_cn.cn)("rounded-
|
|
57
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: (0, import_cn.cn)("rounded-2xl bg-foreground/[0.04] p-5", className), children: [
|
|
58
58
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mb-3 flex items-center justify-between", children: [
|
|
59
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { className: "text-
|
|
60
|
-
href && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href, className: "text-xs font-
|
|
59
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { className: "text-lg font-black", children: title }),
|
|
60
|
+
href && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href, className: "text-xs font-bold text-foreground/50 hover:text-foreground active:opacity-70", children: "View scoreboard \u2192" })
|
|
61
61
|
] }),
|
|
62
62
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("ol", { className: "space-y-2.5", children: entries.map((e) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { className: "flex items-center gap-2.5", children: [
|
|
63
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "min-w-0 flex-1 truncate text-sm font-
|
|
63
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "min-w-0 flex-1 truncate text-sm font-bold", children: renderAddress ? renderAddress(e.address) : (0, import_address.shortenAddress)(e.address) }),
|
|
64
64
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_level_badge.LevelBadge, { level: e.currentLevel, name: e.currentLevelName, badgeColor: e.badgeColor, size: "sm" })
|
|
65
65
|
] }, e.address)) })
|
|
66
66
|
] });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/rewards/leaderboard-table.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { cn } from \"../../utils/cn.js\";\nimport { shortenAddress } from \"../../utils/address.js\";\nimport { LevelBadge } from \"./level-badge.js\";\n\nexport interface LeaderboardEntryLike {\n /** Kept for API compatibility with the backend's ordered response — not\n * rendered. This is a scoreboard, not a ranking: no \"#1/#2/#3\", no podium\n * colors. Order in the array is still the sort order the caller gets. */\n rank: number;\n address: string;\n publicId?: string | null;\n totalXp: number;\n currentLevel: number;\n currentLevelName: string;\n badgeColor: string;\n}\n\nexport interface LeaderboardTableProps {\n entries: LeaderboardEntryLike[];\n /** The viewer's address — its row gets highlighted. */\n highlightAddress?: string | null;\n /** Render the address cell (e.g. a profile link). Defaults to a shortened address. */\n renderAddress?: (address: string) => ReactNode;\n className?: string;\n}\n\n/** Scoreboard rows: address, level chip, points. No position number or\n * podium coloring — this celebrates participation, not competition. */\nexport function LeaderboardTable({ entries, highlightAddress, renderAddress, className }: LeaderboardTableProps) {\n return (\n <div className={cn(\"
|
|
1
|
+
{"version":3,"sources":["../../../src/components/rewards/leaderboard-table.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { cn } from \"../../utils/cn.js\";\nimport { shortenAddress } from \"../../utils/address.js\";\nimport { LevelBadge } from \"./level-badge.js\";\n\nexport interface LeaderboardEntryLike {\n /** Kept for API compatibility with the backend's ordered response — not\n * rendered. This is a scoreboard, not a ranking: no \"#1/#2/#3\", no podium\n * colors. Order in the array is still the sort order the caller gets. */\n rank: number;\n address: string;\n publicId?: string | null;\n totalXp: number;\n currentLevel: number;\n currentLevelName: string;\n badgeColor: string;\n}\n\nexport interface LeaderboardTableProps {\n entries: LeaderboardEntryLike[];\n /** The viewer's address — its row gets highlighted. */\n highlightAddress?: string | null;\n /** Render the address cell (e.g. a profile link). Defaults to a shortened address. */\n renderAddress?: (address: string) => ReactNode;\n className?: string;\n}\n\n/** Scoreboard rows: address, level chip, points. No position number or\n * podium coloring — this celebrates participation, not competition.\n * Each row is its own rounded tile with real padding, not a bordered\n * list with hairline dividers. */\nexport function LeaderboardTable({ entries, highlightAddress, renderAddress, className }: LeaderboardTableProps) {\n return (\n <div className={cn(\"space-y-1.5\", className)}>\n {entries.map((e) => {\n const isViewer = highlightAddress != null && e.address === highlightAddress;\n return (\n <div\n key={e.address}\n className={cn(\n \"flex items-center gap-4 rounded-2xl px-4 py-3.5 transition-colors\",\n isViewer ? \"bg-brand-rose/10\" : \"bg-foreground/[0.04] hover:bg-foreground/[0.07]\"\n )}\n >\n <span className=\"min-w-0 flex-1 truncate text-base font-bold\">\n {renderAddress ? renderAddress(e.address) : shortenAddress(e.address)}\n {isViewer && <span className=\"ml-1.5 text-xs font-medium text-foreground/50\">(you)</span>}\n </span>\n <LevelBadge level={e.currentLevel} name={e.currentLevelName} badgeColor={e.badgeColor} size=\"sm\" className=\"hidden sm:inline-flex\" />\n <span className=\"shrink-0 text-lg font-black tabular-nums\">\n {e.totalXp.toLocaleString()}\n <span className=\"ml-1 text-xs font-bold text-foreground/40\">XP</span>\n </span>\n </div>\n );\n })}\n </div>\n );\n}\n\nexport interface LeaderboardWidgetProps {\n entries: LeaderboardEntryLike[];\n title?: string;\n /** Link to the full scoreboard (\"/rewards\"). */\n href?: string;\n renderAddress?: (address: string) => ReactNode;\n className?: string;\n}\n\n/** Compact card for homepage/discover rails — same no-ranking scoreboard rows. */\nexport function LeaderboardWidget({ entries, title = \"Community Rewards\", href, renderAddress, className }: LeaderboardWidgetProps) {\n if (entries.length === 0) return null;\n return (\n <section className={cn(\"rounded-2xl bg-foreground/[0.04] p-5\", className)}>\n <div className=\"mb-3 flex items-center justify-between\">\n <h2 className=\"text-lg font-black\">{title}</h2>\n {href && (\n <a href={href} className=\"text-xs font-bold text-foreground/50 hover:text-foreground active:opacity-70\">\n View scoreboard →\n </a>\n )}\n </div>\n <ol className=\"space-y-2.5\">\n {entries.map((e) => (\n <li key={e.address} className=\"flex items-center gap-2.5\">\n <span className=\"min-w-0 flex-1 truncate text-sm font-bold\">\n {renderAddress ? renderAddress(e.address) : shortenAddress(e.address)}\n </span>\n <LevelBadge level={e.currentLevel} name={e.currentLevelName} badgeColor={e.badgeColor} size=\"sm\" />\n </li>\n ))}\n </ol>\n </section>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA4CY;AA3CZ,gBAAmB;AACnB,qBAA+B;AAC/B,yBAA2B;AA4BpB,SAAS,iBAAiB,EAAE,SAAS,kBAAkB,eAAe,UAAU,GAA0B;AAC/G,SACE,4CAAC,SAAI,eAAW,cAAG,eAAe,SAAS,GACxC,kBAAQ,IAAI,CAAC,MAAM;AAClB,UAAM,WAAW,oBAAoB,QAAQ,EAAE,YAAY;AAC3D,WACE;AAAA,MAAC;AAAA;AAAA,QAEC,eAAW;AAAA,UACT;AAAA,UACA,WAAW,qBAAqB;AAAA,QAClC;AAAA,QAEA;AAAA,uDAAC,UAAK,WAAU,+CACb;AAAA,4BAAgB,cAAc,EAAE,OAAO,QAAI,+BAAe,EAAE,OAAO;AAAA,YACnE,YAAY,4CAAC,UAAK,WAAU,iDAAgD,mBAAK;AAAA,aACpF;AAAA,UACA,4CAAC,iCAAW,OAAO,EAAE,cAAc,MAAM,EAAE,kBAAkB,YAAY,EAAE,YAAY,MAAK,MAAK,WAAU,yBAAwB;AAAA,UACnI,6CAAC,UAAK,WAAU,4CACb;AAAA,cAAE,QAAQ,eAAe;AAAA,YAC1B,4CAAC,UAAK,WAAU,6CAA4C,gBAAE;AAAA,aAChE;AAAA;AAAA;AAAA,MAdK,EAAE;AAAA,IAeT;AAAA,EAEJ,CAAC,GACH;AAEJ;AAYO,SAAS,kBAAkB,EAAE,SAAS,QAAQ,qBAAqB,MAAM,eAAe,UAAU,GAA2B;AAClI,MAAI,QAAQ,WAAW,EAAG,QAAO;AACjC,SACE,6CAAC,aAAQ,eAAW,cAAG,wCAAwC,SAAS,GACtE;AAAA,iDAAC,SAAI,WAAU,0CACb;AAAA,kDAAC,QAAG,WAAU,sBAAsB,iBAAM;AAAA,MACzC,QACC,4CAAC,OAAE,MAAY,WAAU,gFAA+E,oCAExG;AAAA,OAEJ;AAAA,IACA,4CAAC,QAAG,WAAU,eACX,kBAAQ,IAAI,CAAC,MACZ,6CAAC,QAAmB,WAAU,6BAC5B;AAAA,kDAAC,UAAK,WAAU,6CACb,0BAAgB,cAAc,EAAE,OAAO,QAAI,+BAAe,EAAE,OAAO,GACtE;AAAA,MACA,4CAAC,iCAAW,OAAO,EAAE,cAAc,MAAM,EAAE,kBAAkB,YAAY,EAAE,YAAY,MAAK,MAAK;AAAA,SAJ1F,EAAE,OAKX,CACD,GACH;AAAA,KACF;AAEJ;","names":[]}
|
|
@@ -22,7 +22,9 @@ interface LeaderboardTableProps {
|
|
|
22
22
|
className?: string;
|
|
23
23
|
}
|
|
24
24
|
/** Scoreboard rows: address, level chip, points. No position number or
|
|
25
|
-
* podium coloring — this celebrates participation, not competition.
|
|
25
|
+
* podium coloring — this celebrates participation, not competition.
|
|
26
|
+
* Each row is its own rounded tile with real padding, not a bordered
|
|
27
|
+
* list with hairline dividers. */
|
|
26
28
|
declare function LeaderboardTable({ entries, highlightAddress, renderAddress, className }: LeaderboardTableProps): react_jsx_runtime.JSX.Element;
|
|
27
29
|
interface LeaderboardWidgetProps {
|
|
28
30
|
entries: LeaderboardEntryLike[];
|
|
@@ -22,7 +22,9 @@ interface LeaderboardTableProps {
|
|
|
22
22
|
className?: string;
|
|
23
23
|
}
|
|
24
24
|
/** Scoreboard rows: address, level chip, points. No position number or
|
|
25
|
-
* podium coloring — this celebrates participation, not competition.
|
|
25
|
+
* podium coloring — this celebrates participation, not competition.
|
|
26
|
+
* Each row is its own rounded tile with real padding, not a bordered
|
|
27
|
+
* list with hairline dividers. */
|
|
26
28
|
declare function LeaderboardTable({ entries, highlightAddress, renderAddress, className }: LeaderboardTableProps): react_jsx_runtime.JSX.Element;
|
|
27
29
|
interface LeaderboardWidgetProps {
|
|
28
30
|
entries: LeaderboardEntryLike[];
|
|
@@ -3,24 +3,24 @@ import { cn } from "../../utils/cn.js";
|
|
|
3
3
|
import { shortenAddress } from "../../utils/address.js";
|
|
4
4
|
import { LevelBadge } from "./level-badge.js";
|
|
5
5
|
function LeaderboardTable({ entries, highlightAddress, renderAddress, className }) {
|
|
6
|
-
return /* @__PURE__ */ jsx("div", { className: cn("
|
|
6
|
+
return /* @__PURE__ */ jsx("div", { className: cn("space-y-1.5", className), children: entries.map((e) => {
|
|
7
7
|
const isViewer = highlightAddress != null && e.address === highlightAddress;
|
|
8
8
|
return /* @__PURE__ */ jsxs(
|
|
9
9
|
"div",
|
|
10
10
|
{
|
|
11
11
|
className: cn(
|
|
12
|
-
"flex items-center gap-
|
|
13
|
-
isViewer
|
|
12
|
+
"flex items-center gap-4 rounded-2xl px-4 py-3.5 transition-colors",
|
|
13
|
+
isViewer ? "bg-brand-rose/10" : "bg-foreground/[0.04] hover:bg-foreground/[0.07]"
|
|
14
14
|
),
|
|
15
15
|
children: [
|
|
16
|
-
/* @__PURE__ */ jsxs("span", { className: "min-w-0 flex-1 truncate text-
|
|
16
|
+
/* @__PURE__ */ jsxs("span", { className: "min-w-0 flex-1 truncate text-base font-bold", children: [
|
|
17
17
|
renderAddress ? renderAddress(e.address) : shortenAddress(e.address),
|
|
18
|
-
isViewer && /* @__PURE__ */ jsx("span", { className: "ml-1.5 text-xs text-
|
|
18
|
+
isViewer && /* @__PURE__ */ jsx("span", { className: "ml-1.5 text-xs font-medium text-foreground/50", children: "(you)" })
|
|
19
19
|
] }),
|
|
20
20
|
/* @__PURE__ */ jsx(LevelBadge, { level: e.currentLevel, name: e.currentLevelName, badgeColor: e.badgeColor, size: "sm", className: "hidden sm:inline-flex" }),
|
|
21
|
-
/* @__PURE__ */ jsxs("span", { className: "shrink-0 text-
|
|
21
|
+
/* @__PURE__ */ jsxs("span", { className: "shrink-0 text-lg font-black tabular-nums", children: [
|
|
22
22
|
e.totalXp.toLocaleString(),
|
|
23
|
-
/* @__PURE__ */ jsx("span", { className: "ml-1 text-xs font-
|
|
23
|
+
/* @__PURE__ */ jsx("span", { className: "ml-1 text-xs font-bold text-foreground/40", children: "XP" })
|
|
24
24
|
] })
|
|
25
25
|
]
|
|
26
26
|
},
|
|
@@ -30,13 +30,13 @@ function LeaderboardTable({ entries, highlightAddress, renderAddress, className
|
|
|
30
30
|
}
|
|
31
31
|
function LeaderboardWidget({ entries, title = "Community Rewards", href, renderAddress, className }) {
|
|
32
32
|
if (entries.length === 0) return null;
|
|
33
|
-
return /* @__PURE__ */ jsxs("section", { className: cn("rounded-
|
|
33
|
+
return /* @__PURE__ */ jsxs("section", { className: cn("rounded-2xl bg-foreground/[0.04] p-5", className), children: [
|
|
34
34
|
/* @__PURE__ */ jsxs("div", { className: "mb-3 flex items-center justify-between", children: [
|
|
35
|
-
/* @__PURE__ */ jsx("h2", { className: "text-
|
|
36
|
-
href && /* @__PURE__ */ jsx("a", { href, className: "text-xs font-
|
|
35
|
+
/* @__PURE__ */ jsx("h2", { className: "text-lg font-black", children: title }),
|
|
36
|
+
href && /* @__PURE__ */ jsx("a", { href, className: "text-xs font-bold text-foreground/50 hover:text-foreground active:opacity-70", children: "View scoreboard \u2192" })
|
|
37
37
|
] }),
|
|
38
38
|
/* @__PURE__ */ jsx("ol", { className: "space-y-2.5", children: entries.map((e) => /* @__PURE__ */ jsxs("li", { className: "flex items-center gap-2.5", children: [
|
|
39
|
-
/* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate text-sm font-
|
|
39
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate text-sm font-bold", children: renderAddress ? renderAddress(e.address) : shortenAddress(e.address) }),
|
|
40
40
|
/* @__PURE__ */ jsx(LevelBadge, { level: e.currentLevel, name: e.currentLevelName, badgeColor: e.badgeColor, size: "sm" })
|
|
41
41
|
] }, e.address)) })
|
|
42
42
|
] });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/rewards/leaderboard-table.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { cn } from \"../../utils/cn.js\";\nimport { shortenAddress } from \"../../utils/address.js\";\nimport { LevelBadge } from \"./level-badge.js\";\n\nexport interface LeaderboardEntryLike {\n /** Kept for API compatibility with the backend's ordered response — not\n * rendered. This is a scoreboard, not a ranking: no \"#1/#2/#3\", no podium\n * colors. Order in the array is still the sort order the caller gets. */\n rank: number;\n address: string;\n publicId?: string | null;\n totalXp: number;\n currentLevel: number;\n currentLevelName: string;\n badgeColor: string;\n}\n\nexport interface LeaderboardTableProps {\n entries: LeaderboardEntryLike[];\n /** The viewer's address — its row gets highlighted. */\n highlightAddress?: string | null;\n /** Render the address cell (e.g. a profile link). Defaults to a shortened address. */\n renderAddress?: (address: string) => ReactNode;\n className?: string;\n}\n\n/** Scoreboard rows: address, level chip, points. No position number or\n * podium coloring — this celebrates participation, not competition. */\nexport function LeaderboardTable({ entries, highlightAddress, renderAddress, className }: LeaderboardTableProps) {\n return (\n <div className={cn(\"
|
|
1
|
+
{"version":3,"sources":["../../../src/components/rewards/leaderboard-table.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { cn } from \"../../utils/cn.js\";\nimport { shortenAddress } from \"../../utils/address.js\";\nimport { LevelBadge } from \"./level-badge.js\";\n\nexport interface LeaderboardEntryLike {\n /** Kept for API compatibility with the backend's ordered response — not\n * rendered. This is a scoreboard, not a ranking: no \"#1/#2/#3\", no podium\n * colors. Order in the array is still the sort order the caller gets. */\n rank: number;\n address: string;\n publicId?: string | null;\n totalXp: number;\n currentLevel: number;\n currentLevelName: string;\n badgeColor: string;\n}\n\nexport interface LeaderboardTableProps {\n entries: LeaderboardEntryLike[];\n /** The viewer's address — its row gets highlighted. */\n highlightAddress?: string | null;\n /** Render the address cell (e.g. a profile link). Defaults to a shortened address. */\n renderAddress?: (address: string) => ReactNode;\n className?: string;\n}\n\n/** Scoreboard rows: address, level chip, points. No position number or\n * podium coloring — this celebrates participation, not competition.\n * Each row is its own rounded tile with real padding, not a bordered\n * list with hairline dividers. */\nexport function LeaderboardTable({ entries, highlightAddress, renderAddress, className }: LeaderboardTableProps) {\n return (\n <div className={cn(\"space-y-1.5\", className)}>\n {entries.map((e) => {\n const isViewer = highlightAddress != null && e.address === highlightAddress;\n return (\n <div\n key={e.address}\n className={cn(\n \"flex items-center gap-4 rounded-2xl px-4 py-3.5 transition-colors\",\n isViewer ? \"bg-brand-rose/10\" : \"bg-foreground/[0.04] hover:bg-foreground/[0.07]\"\n )}\n >\n <span className=\"min-w-0 flex-1 truncate text-base font-bold\">\n {renderAddress ? renderAddress(e.address) : shortenAddress(e.address)}\n {isViewer && <span className=\"ml-1.5 text-xs font-medium text-foreground/50\">(you)</span>}\n </span>\n <LevelBadge level={e.currentLevel} name={e.currentLevelName} badgeColor={e.badgeColor} size=\"sm\" className=\"hidden sm:inline-flex\" />\n <span className=\"shrink-0 text-lg font-black tabular-nums\">\n {e.totalXp.toLocaleString()}\n <span className=\"ml-1 text-xs font-bold text-foreground/40\">XP</span>\n </span>\n </div>\n );\n })}\n </div>\n );\n}\n\nexport interface LeaderboardWidgetProps {\n entries: LeaderboardEntryLike[];\n title?: string;\n /** Link to the full scoreboard (\"/rewards\"). */\n href?: string;\n renderAddress?: (address: string) => ReactNode;\n className?: string;\n}\n\n/** Compact card for homepage/discover rails — same no-ranking scoreboard rows. */\nexport function LeaderboardWidget({ entries, title = \"Community Rewards\", href, renderAddress, className }: LeaderboardWidgetProps) {\n if (entries.length === 0) return null;\n return (\n <section className={cn(\"rounded-2xl bg-foreground/[0.04] p-5\", className)}>\n <div className=\"mb-3 flex items-center justify-between\">\n <h2 className=\"text-lg font-black\">{title}</h2>\n {href && (\n <a href={href} className=\"text-xs font-bold text-foreground/50 hover:text-foreground active:opacity-70\">\n View scoreboard →\n </a>\n )}\n </div>\n <ol className=\"space-y-2.5\">\n {entries.map((e) => (\n <li key={e.address} className=\"flex items-center gap-2.5\">\n <span className=\"min-w-0 flex-1 truncate text-sm font-bold\">\n {renderAddress ? renderAddress(e.address) : shortenAddress(e.address)}\n </span>\n <LevelBadge level={e.currentLevel} name={e.currentLevelName} badgeColor={e.badgeColor} size=\"sm\" />\n </li>\n ))}\n </ol>\n </section>\n );\n}\n"],"mappings":"AA4CY,SAEe,KAFf;AA3CZ,SAAS,UAAU;AACnB,SAAS,sBAAsB;AAC/B,SAAS,kBAAkB;AA4BpB,SAAS,iBAAiB,EAAE,SAAS,kBAAkB,eAAe,UAAU,GAA0B;AAC/G,SACE,oBAAC,SAAI,WAAW,GAAG,eAAe,SAAS,GACxC,kBAAQ,IAAI,CAAC,MAAM;AAClB,UAAM,WAAW,oBAAoB,QAAQ,EAAE,YAAY;AAC3D,WACE;AAAA,MAAC;AAAA;AAAA,QAEC,WAAW;AAAA,UACT;AAAA,UACA,WAAW,qBAAqB;AAAA,QAClC;AAAA,QAEA;AAAA,+BAAC,UAAK,WAAU,+CACb;AAAA,4BAAgB,cAAc,EAAE,OAAO,IAAI,eAAe,EAAE,OAAO;AAAA,YACnE,YAAY,oBAAC,UAAK,WAAU,iDAAgD,mBAAK;AAAA,aACpF;AAAA,UACA,oBAAC,cAAW,OAAO,EAAE,cAAc,MAAM,EAAE,kBAAkB,YAAY,EAAE,YAAY,MAAK,MAAK,WAAU,yBAAwB;AAAA,UACnI,qBAAC,UAAK,WAAU,4CACb;AAAA,cAAE,QAAQ,eAAe;AAAA,YAC1B,oBAAC,UAAK,WAAU,6CAA4C,gBAAE;AAAA,aAChE;AAAA;AAAA;AAAA,MAdK,EAAE;AAAA,IAeT;AAAA,EAEJ,CAAC,GACH;AAEJ;AAYO,SAAS,kBAAkB,EAAE,SAAS,QAAQ,qBAAqB,MAAM,eAAe,UAAU,GAA2B;AAClI,MAAI,QAAQ,WAAW,EAAG,QAAO;AACjC,SACE,qBAAC,aAAQ,WAAW,GAAG,wCAAwC,SAAS,GACtE;AAAA,yBAAC,SAAI,WAAU,0CACb;AAAA,0BAAC,QAAG,WAAU,sBAAsB,iBAAM;AAAA,MACzC,QACC,oBAAC,OAAE,MAAY,WAAU,gFAA+E,oCAExG;AAAA,OAEJ;AAAA,IACA,oBAAC,QAAG,WAAU,eACX,kBAAQ,IAAI,CAAC,MACZ,qBAAC,QAAmB,WAAU,6BAC5B;AAAA,0BAAC,UAAK,WAAU,6CACb,0BAAgB,cAAc,EAAE,OAAO,IAAI,eAAe,EAAE,OAAO,GACtE;AAAA,MACA,oBAAC,cAAW,OAAO,EAAE,cAAc,MAAM,EAAE,kBAAkB,YAAY,EAAE,YAAY,MAAK,MAAK;AAAA,SAJ1F,EAAE,OAKX,CACD,GACH;AAAA,KACF;AAEJ;","names":[]}
|