@medialane/ui 0.100.0 → 0.100.3
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/coin-launch-preview.cjs +1 -1
- package/dist/components/coin-launch-preview.cjs.map +1 -1
- package/dist/components/coin-launch-preview.js +1 -1
- package/dist/components/coin-launch-preview.js.map +1 -1
- package/dist/components/launchpad-services.cjs +4 -4
- package/dist/components/launchpad-services.cjs.map +1 -1
- package/dist/components/launchpad-services.js +4 -4
- package/dist/components/launchpad-services.js.map +1 -1
- package/dist/components/launchpad-strip.cjs +4 -4
- package/dist/components/launchpad-strip.cjs.map +1 -1
- package/dist/components/launchpad-strip.js +4 -4
- package/dist/components/launchpad-strip.js.map +1 -1
- package/dist/components/rewards/badge-catalog.cjs +49 -0
- package/dist/components/rewards/badge-catalog.cjs.map +1 -0
- package/dist/components/rewards/badge-catalog.d.cts +22 -0
- package/dist/components/rewards/badge-catalog.d.ts +22 -0
- package/dist/components/rewards/badge-catalog.js +25 -0
- package/dist/components/rewards/badge-catalog.js.map +1 -0
- 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/dist/components/rewards/level-badge.cjs +7 -16
- package/dist/components/rewards/level-badge.cjs.map +1 -1
- package/dist/components/rewards/level-badge.d.cts +10 -4
- package/dist/components/rewards/level-badge.d.ts +10 -4
- package/dist/components/rewards/level-badge.js +8 -17
- package/dist/components/rewards/level-badge.js.map +1 -1
- package/dist/components/rewards/level-journey-list.cjs +52 -0
- package/dist/components/rewards/level-journey-list.cjs.map +1 -0
- package/dist/components/rewards/level-journey-list.d.cts +22 -0
- package/dist/components/rewards/level-journey-list.d.ts +22 -0
- package/dist/components/rewards/level-journey-list.js +28 -0
- package/dist/components/rewards/level-journey-list.js.map +1 -0
- package/dist/components/token-glyph.cjs.map +1 -1
- package/dist/components/token-glyph.d.cts +1 -1
- package/dist/components/token-glyph.d.ts +1 -1
- package/dist/components/token-glyph.js.map +1 -1
- package/dist/data/brand.cjs +4 -4
- package/dist/data/brand.cjs.map +1 -1
- package/dist/data/brand.d.cts +4 -4
- package/dist/data/brand.d.ts +4 -4
- package/dist/data/brand.js +4 -4
- package/dist/data/brand.js.map +1 -1
- package/dist/index.cjs +6 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/preset/tailwind.cjs +1 -1
- package/dist/preset/tailwind.cjs.map +1 -1
- package/dist/preset/tailwind.js +1 -1
- package/dist/preset/tailwind.js.map +1 -1
- package/package.json +1 -1
- package/dist/components/rewards/level-ladder.cjs +0 -54
- package/dist/components/rewards/level-ladder.cjs.map +0 -1
- package/dist/components/rewards/level-ladder.d.cts +0 -17
- package/dist/components/rewards/level-ladder.d.ts +0 -17
- package/dist/components/rewards/level-ladder.js +0 -30
- package/dist/components/rewards/level-ladder.js.map +0 -1
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
interface BadgeCatalogBadge {
|
|
4
|
+
key: string;
|
|
5
|
+
name: string;
|
|
6
|
+
description: string;
|
|
7
|
+
icon: string;
|
|
8
|
+
color: string;
|
|
9
|
+
category: string;
|
|
10
|
+
}
|
|
11
|
+
interface BadgeCatalogProps {
|
|
12
|
+
badges: BadgeCatalogBadge[];
|
|
13
|
+
className?: string;
|
|
14
|
+
}
|
|
15
|
+
/** Full badge catalog, grouped by category — "what's achievable," not
|
|
16
|
+
* "what you've done" (no earned/locked state; that's BadgeShelf's job on
|
|
17
|
+
* /rewards, which stays exactly as-is for the viewer's own progress).
|
|
18
|
+
* Groups render in whatever categories are actually present in the data,
|
|
19
|
+
* not a hardcoded list — new categories show up automatically. */
|
|
20
|
+
declare function BadgeCatalog({ badges, className }: BadgeCatalogProps): react_jsx_runtime.JSX.Element;
|
|
21
|
+
|
|
22
|
+
export { BadgeCatalog, type BadgeCatalogBadge, type BadgeCatalogProps };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
interface BadgeCatalogBadge {
|
|
4
|
+
key: string;
|
|
5
|
+
name: string;
|
|
6
|
+
description: string;
|
|
7
|
+
icon: string;
|
|
8
|
+
color: string;
|
|
9
|
+
category: string;
|
|
10
|
+
}
|
|
11
|
+
interface BadgeCatalogProps {
|
|
12
|
+
badges: BadgeCatalogBadge[];
|
|
13
|
+
className?: string;
|
|
14
|
+
}
|
|
15
|
+
/** Full badge catalog, grouped by category — "what's achievable," not
|
|
16
|
+
* "what you've done" (no earned/locked state; that's BadgeShelf's job on
|
|
17
|
+
* /rewards, which stays exactly as-is for the viewer's own progress).
|
|
18
|
+
* Groups render in whatever categories are actually present in the data,
|
|
19
|
+
* not a hardcoded list — new categories show up automatically. */
|
|
20
|
+
declare function BadgeCatalog({ badges, className }: BadgeCatalogProps): react_jsx_runtime.JSX.Element;
|
|
21
|
+
|
|
22
|
+
export { BadgeCatalog, type BadgeCatalogBadge, type BadgeCatalogProps };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../../utils/cn.js";
|
|
3
|
+
import { BadgeIcon } from "./badge-shelf.js";
|
|
4
|
+
const CATEGORY_LABELS = {
|
|
5
|
+
creator: "Creator",
|
|
6
|
+
collector: "Collector",
|
|
7
|
+
community: "Community"
|
|
8
|
+
};
|
|
9
|
+
function BadgeCatalog({ badges, className }) {
|
|
10
|
+
const categories = [...new Set(badges.map((b) => b.category))];
|
|
11
|
+
return /* @__PURE__ */ jsx("div", { className: cn("space-y-8", className), children: categories.map((cat) => /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
12
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-black uppercase tracking-wide text-foreground/50", children: CATEGORY_LABELS[cat] ?? cat }),
|
|
13
|
+
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-3", children: badges.filter((b) => b.category === cat).map((badge) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 rounded-2xl bg-foreground/[0.04] p-4", children: [
|
|
14
|
+
/* @__PURE__ */ jsx("span", { className: "flex h-10 w-10 items-center justify-center rounded-xl shrink-0 bg-gradient-to-br from-brand-orange to-brand-maeve", children: /* @__PURE__ */ jsx(BadgeIcon, { name: badge.icon, color: "#ffffff", className: "h-5 w-5" }) }),
|
|
15
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
16
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-bold", children: badge.name }),
|
|
17
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-foreground/60 truncate", children: badge.description })
|
|
18
|
+
] })
|
|
19
|
+
] }, badge.key)) })
|
|
20
|
+
] }, cat)) });
|
|
21
|
+
}
|
|
22
|
+
export {
|
|
23
|
+
BadgeCatalog
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=badge-catalog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/rewards/badge-catalog.tsx"],"sourcesContent":["import { cn } from \"../../utils/cn.js\";\nimport { BadgeIcon } from \"./badge-shelf.js\";\n\nexport interface BadgeCatalogBadge {\n key: string;\n name: string;\n description: string;\n icon: string;\n color: string;\n category: string;\n}\n\nexport interface BadgeCatalogProps {\n badges: BadgeCatalogBadge[];\n className?: string;\n}\n\nconst CATEGORY_LABELS: Record<string, string> = {\n creator: \"Creator\",\n collector: \"Collector\",\n community: \"Community\",\n};\n\n/** Full badge catalog, grouped by category — \"what's achievable,\" not\n * \"what you've done\" (no earned/locked state; that's BadgeShelf's job on\n * /rewards, which stays exactly as-is for the viewer's own progress).\n * Groups render in whatever categories are actually present in the data,\n * not a hardcoded list — new categories show up automatically. */\nexport function BadgeCatalog({ badges, className }: BadgeCatalogProps) {\n const categories = [...new Set(badges.map((b) => b.category))];\n\n return (\n <div className={cn(\"space-y-8\", className)}>\n {categories.map((cat) => (\n <div key={cat} className=\"space-y-3\">\n <p className=\"text-sm font-black uppercase tracking-wide text-foreground/50\">\n {CATEGORY_LABELS[cat] ?? cat}\n </p>\n <div className=\"grid grid-cols-1 sm:grid-cols-2 gap-3\">\n {badges\n .filter((b) => b.category === cat)\n .map((badge) => (\n <div key={badge.key} className=\"flex items-center gap-3 rounded-2xl bg-foreground/[0.04] p-4\">\n <span className=\"flex h-10 w-10 items-center justify-center rounded-xl shrink-0 bg-gradient-to-br from-brand-orange to-brand-maeve\">\n <BadgeIcon name={badge.icon} color=\"#ffffff\" className=\"h-5 w-5\" />\n </span>\n <div className=\"min-w-0\">\n <p className=\"text-sm font-bold\">{badge.name}</p>\n <p className=\"text-xs text-foreground/60 truncate\">{badge.description}</p>\n </div>\n </div>\n ))}\n </div>\n </div>\n ))}\n </div>\n );\n}\n"],"mappings":"AAmCU,cAWQ,YAXR;AAnCV,SAAS,UAAU;AACnB,SAAS,iBAAiB;AAgB1B,MAAM,kBAA0C;AAAA,EAC9C,SAAS;AAAA,EACT,WAAW;AAAA,EACX,WAAW;AACb;AAOO,SAAS,aAAa,EAAE,QAAQ,UAAU,GAAsB;AACrE,QAAM,aAAa,CAAC,GAAG,IAAI,IAAI,OAAO,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;AAE7D,SACE,oBAAC,SAAI,WAAW,GAAG,aAAa,SAAS,GACtC,qBAAW,IAAI,CAAC,QACf,qBAAC,SAAc,WAAU,aACvB;AAAA,wBAAC,OAAE,WAAU,iEACV,0BAAgB,GAAG,KAAK,KAC3B;AAAA,IACA,oBAAC,SAAI,WAAU,yCACZ,iBACE,OAAO,CAAC,MAAM,EAAE,aAAa,GAAG,EAChC,IAAI,CAAC,UACJ,qBAAC,SAAoB,WAAU,gEAC7B;AAAA,0BAAC,UAAK,WAAU,qHACd,8BAAC,aAAU,MAAM,MAAM,MAAM,OAAM,WAAU,WAAU,WAAU,GACnE;AAAA,MACA,qBAAC,SAAI,WAAU,WACb;AAAA,4BAAC,OAAE,WAAU,qBAAqB,gBAAM,MAAK;AAAA,QAC7C,oBAAC,OAAE,WAAU,uCAAuC,gBAAM,aAAY;AAAA,SACxE;AAAA,SAPQ,MAAM,GAQhB,CACD,GACL;AAAA,OAlBQ,GAmBV,CACD,GACH;AAEJ;","names":[]}
|
|
@@ -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":[]}
|
|
@@ -23,31 +23,22 @@ __export(level_badge_exports, {
|
|
|
23
23
|
module.exports = __toCommonJS(level_badge_exports);
|
|
24
24
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
25
25
|
var import_cn = require("../../utils/cn.js");
|
|
26
|
-
function LevelBadge({ level, name,
|
|
26
|
+
function LevelBadge({ level, name, size = "md", className }) {
|
|
27
27
|
const sizeClasses = {
|
|
28
|
-
sm: "h-5 px-
|
|
29
|
-
md: "h-6 px-
|
|
30
|
-
lg: "h-8 px-
|
|
28
|
+
sm: "h-5 px-2.5 text-2xs",
|
|
29
|
+
md: "h-6 px-3 text-xs",
|
|
30
|
+
lg: "h-8 px-4 text-sm"
|
|
31
31
|
};
|
|
32
|
-
|
|
33
|
-
sm: "h-1.5 w-1.5",
|
|
34
|
-
md: "h-2 w-2",
|
|
35
|
-
lg: "h-2.5 w-2.5"
|
|
36
|
-
};
|
|
37
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
32
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
38
33
|
"span",
|
|
39
34
|
{
|
|
40
35
|
title: `Level ${level}`,
|
|
41
36
|
className: (0, import_cn.cn)(
|
|
42
|
-
"inline-flex items-center rounded-full
|
|
37
|
+
"inline-flex items-center rounded-full font-bold tracking-tight whitespace-nowrap text-white bg-gradient-to-r from-brand-orange to-brand-maeve",
|
|
43
38
|
sizeClasses[size],
|
|
44
39
|
className
|
|
45
40
|
),
|
|
46
|
-
|
|
47
|
-
children: [
|
|
48
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: (0, import_cn.cn)("rounded-full shrink-0", dotSizes[size]), style: { backgroundColor: badgeColor } }),
|
|
49
|
-
name
|
|
50
|
-
]
|
|
41
|
+
children: name
|
|
51
42
|
}
|
|
52
43
|
);
|
|
53
44
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/rewards/level-badge.tsx"],"sourcesContent":["import { cn } from \"../../utils/cn.js\";\n\nexport interface LevelBadgeProps {\n level: number;\n name: string;\n badgeColor: string;\n size?: \"sm\" | \"md\" | \"lg\";\n className?: string;\n}\n\n/**
|
|
1
|
+
{"version":3,"sources":["../../../src/components/rewards/level-badge.tsx"],"sourcesContent":["import { cn } from \"../../utils/cn.js\";\n\nexport interface LevelBadgeProps {\n level: number;\n name: string;\n /** Kept for interface consistency with other rewards components that do\n * use per-level color (XpProgress, LevelUpCelebration, JourneyPath) —\n * this component intentionally ignores it in favor of one signature\n * brand gradient across every level, not 20+ flat per-level colors. */\n badgeColor: string;\n size?: \"sm\" | \"md\" | \"lg\";\n className?: string;\n}\n\n/** Level chip — shows the level's title only (\"Voyager\"), not the raw\n * number (\"Lv.6 Voyager\" read as UI noise). The level is still available\n * on hover via the native title tooltip. One signature orange->maeve\n * gradient fill, white text — vivid and consistent regardless of level,\n * rather than a washed-out per-level tint. Pure presentation — the\n * consuming app supplies level data from the rewards API. */\nexport function LevelBadge({ level, name, size = \"md\", className }: LevelBadgeProps) {\n const sizeClasses = {\n sm: \"h-5 px-2.5 text-2xs\",\n md: \"h-6 px-3 text-xs\",\n lg: \"h-8 px-4 text-sm\",\n };\n\n return (\n <span\n title={`Level ${level}`}\n className={cn(\n \"inline-flex items-center rounded-full font-bold tracking-tight whitespace-nowrap text-white bg-gradient-to-r from-brand-orange to-brand-maeve\",\n sizeClasses[size],\n className\n )}\n >\n {name}\n </span>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA4BI;AA5BJ,gBAAmB;AAoBZ,SAAS,WAAW,EAAE,OAAO,MAAM,OAAO,MAAM,UAAU,GAAoB;AACnF,QAAM,cAAc;AAAA,IAClB,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,EACN;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO,SAAS,KAAK;AAAA,MACrB,eAAW;AAAA,QACT;AAAA,QACA,YAAY,IAAI;AAAA,QAChB;AAAA,MACF;AAAA,MAEC;AAAA;AAAA,EACH;AAEJ;","names":[]}
|
|
@@ -3,14 +3,20 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
|
3
3
|
interface LevelBadgeProps {
|
|
4
4
|
level: number;
|
|
5
5
|
name: string;
|
|
6
|
+
/** Kept for interface consistency with other rewards components that do
|
|
7
|
+
* use per-level color (XpProgress, LevelUpCelebration, JourneyPath) —
|
|
8
|
+
* this component intentionally ignores it in favor of one signature
|
|
9
|
+
* brand gradient across every level, not 20+ flat per-level colors. */
|
|
6
10
|
badgeColor: string;
|
|
7
11
|
size?: "sm" | "md" | "lg";
|
|
8
12
|
className?: string;
|
|
9
13
|
}
|
|
10
|
-
/**
|
|
11
|
-
*
|
|
12
|
-
*
|
|
14
|
+
/** Level chip — shows the level's title only ("Voyager"), not the raw
|
|
15
|
+
* number ("Lv.6 Voyager" read as UI noise). The level is still available
|
|
16
|
+
* on hover via the native title tooltip. One signature orange->maeve
|
|
17
|
+
* gradient fill, white text — vivid and consistent regardless of level,
|
|
18
|
+
* rather than a washed-out per-level tint. Pure presentation — the
|
|
13
19
|
* consuming app supplies level data from the rewards API. */
|
|
14
|
-
declare function LevelBadge({ level, name,
|
|
20
|
+
declare function LevelBadge({ level, name, size, className }: LevelBadgeProps): react_jsx_runtime.JSX.Element;
|
|
15
21
|
|
|
16
22
|
export { LevelBadge, type LevelBadgeProps };
|
|
@@ -3,14 +3,20 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
|
3
3
|
interface LevelBadgeProps {
|
|
4
4
|
level: number;
|
|
5
5
|
name: string;
|
|
6
|
+
/** Kept for interface consistency with other rewards components that do
|
|
7
|
+
* use per-level color (XpProgress, LevelUpCelebration, JourneyPath) —
|
|
8
|
+
* this component intentionally ignores it in favor of one signature
|
|
9
|
+
* brand gradient across every level, not 20+ flat per-level colors. */
|
|
6
10
|
badgeColor: string;
|
|
7
11
|
size?: "sm" | "md" | "lg";
|
|
8
12
|
className?: string;
|
|
9
13
|
}
|
|
10
|
-
/**
|
|
11
|
-
*
|
|
12
|
-
*
|
|
14
|
+
/** Level chip — shows the level's title only ("Voyager"), not the raw
|
|
15
|
+
* number ("Lv.6 Voyager" read as UI noise). The level is still available
|
|
16
|
+
* on hover via the native title tooltip. One signature orange->maeve
|
|
17
|
+
* gradient fill, white text — vivid and consistent regardless of level,
|
|
18
|
+
* rather than a washed-out per-level tint. Pure presentation — the
|
|
13
19
|
* consuming app supplies level data from the rewards API. */
|
|
14
|
-
declare function LevelBadge({ level, name,
|
|
20
|
+
declare function LevelBadge({ level, name, size, className }: LevelBadgeProps): react_jsx_runtime.JSX.Element;
|
|
15
21
|
|
|
16
22
|
export { LevelBadge, type LevelBadgeProps };
|
|
@@ -1,30 +1,21 @@
|
|
|
1
|
-
import { jsx
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
2
|
import { cn } from "../../utils/cn.js";
|
|
3
|
-
function LevelBadge({ level, name,
|
|
3
|
+
function LevelBadge({ level, name, size = "md", className }) {
|
|
4
4
|
const sizeClasses = {
|
|
5
|
-
sm: "h-5 px-
|
|
6
|
-
md: "h-6 px-
|
|
7
|
-
lg: "h-8 px-
|
|
5
|
+
sm: "h-5 px-2.5 text-2xs",
|
|
6
|
+
md: "h-6 px-3 text-xs",
|
|
7
|
+
lg: "h-8 px-4 text-sm"
|
|
8
8
|
};
|
|
9
|
-
|
|
10
|
-
sm: "h-1.5 w-1.5",
|
|
11
|
-
md: "h-2 w-2",
|
|
12
|
-
lg: "h-2.5 w-2.5"
|
|
13
|
-
};
|
|
14
|
-
return /* @__PURE__ */ jsxs(
|
|
9
|
+
return /* @__PURE__ */ jsx(
|
|
15
10
|
"span",
|
|
16
11
|
{
|
|
17
12
|
title: `Level ${level}`,
|
|
18
13
|
className: cn(
|
|
19
|
-
"inline-flex items-center rounded-full
|
|
14
|
+
"inline-flex items-center rounded-full font-bold tracking-tight whitespace-nowrap text-white bg-gradient-to-r from-brand-orange to-brand-maeve",
|
|
20
15
|
sizeClasses[size],
|
|
21
16
|
className
|
|
22
17
|
),
|
|
23
|
-
|
|
24
|
-
children: [
|
|
25
|
-
/* @__PURE__ */ jsx("span", { className: cn("rounded-full shrink-0", dotSizes[size]), style: { backgroundColor: badgeColor } }),
|
|
26
|
-
name
|
|
27
|
-
]
|
|
18
|
+
children: name
|
|
28
19
|
}
|
|
29
20
|
);
|
|
30
21
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/rewards/level-badge.tsx"],"sourcesContent":["import { cn } from \"../../utils/cn.js\";\n\nexport interface LevelBadgeProps {\n level: number;\n name: string;\n badgeColor: string;\n size?: \"sm\" | \"md\" | \"lg\";\n className?: string;\n}\n\n/**
|
|
1
|
+
{"version":3,"sources":["../../../src/components/rewards/level-badge.tsx"],"sourcesContent":["import { cn } from \"../../utils/cn.js\";\n\nexport interface LevelBadgeProps {\n level: number;\n name: string;\n /** Kept for interface consistency with other rewards components that do\n * use per-level color (XpProgress, LevelUpCelebration, JourneyPath) —\n * this component intentionally ignores it in favor of one signature\n * brand gradient across every level, not 20+ flat per-level colors. */\n badgeColor: string;\n size?: \"sm\" | \"md\" | \"lg\";\n className?: string;\n}\n\n/** Level chip — shows the level's title only (\"Voyager\"), not the raw\n * number (\"Lv.6 Voyager\" read as UI noise). The level is still available\n * on hover via the native title tooltip. One signature orange->maeve\n * gradient fill, white text — vivid and consistent regardless of level,\n * rather than a washed-out per-level tint. Pure presentation — the\n * consuming app supplies level data from the rewards API. */\nexport function LevelBadge({ level, name, size = \"md\", className }: LevelBadgeProps) {\n const sizeClasses = {\n sm: \"h-5 px-2.5 text-2xs\",\n md: \"h-6 px-3 text-xs\",\n lg: \"h-8 px-4 text-sm\",\n };\n\n return (\n <span\n title={`Level ${level}`}\n className={cn(\n \"inline-flex items-center rounded-full font-bold tracking-tight whitespace-nowrap text-white bg-gradient-to-r from-brand-orange to-brand-maeve\",\n sizeClasses[size],\n className\n )}\n >\n {name}\n </span>\n );\n}\n"],"mappings":"AA4BI;AA5BJ,SAAS,UAAU;AAoBZ,SAAS,WAAW,EAAE,OAAO,MAAM,OAAO,MAAM,UAAU,GAAoB;AACnF,QAAM,cAAc;AAAA,IAClB,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,EACN;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO,SAAS,KAAK;AAAA,MACrB,WAAW;AAAA,QACT;AAAA,QACA,YAAY,IAAI;AAAA,QAChB;AAAA,MACF;AAAA,MAEC;AAAA;AAAA,EACH;AAEJ;","names":[]}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var level_journey_list_exports = {};
|
|
20
|
+
__export(level_journey_list_exports, {
|
|
21
|
+
LevelJourneyList: () => LevelJourneyList
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(level_journey_list_exports);
|
|
24
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
25
|
+
var import_cn = require("../../utils/cn.js");
|
|
26
|
+
function LevelJourneyList({ levels, className }) {
|
|
27
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ol", { className: (0, import_cn.cn)("divide-y divide-foreground/[0.06]", className), children: levels.map((l, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { className: "flex items-start gap-4 py-4", children: [
|
|
28
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "flex items-center gap-1.5 w-8 shrink-0 pt-0.5", children: [
|
|
29
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-xs font-bold text-foreground/30 tabular-nums", children: l.level }),
|
|
30
|
+
(i + 1) % 10 === 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
31
|
+
"span",
|
|
32
|
+
{
|
|
33
|
+
"aria-hidden": true,
|
|
34
|
+
className: "h-1.5 w-1.5 rounded-full bg-gradient-to-r from-brand-orange to-brand-maeve"
|
|
35
|
+
}
|
|
36
|
+
)
|
|
37
|
+
] }),
|
|
38
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex-1 min-w-0", children: [
|
|
39
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-base font-bold", children: l.name }),
|
|
40
|
+
l.description && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-sm text-foreground/60 mt-0.5 leading-relaxed", children: l.description })
|
|
41
|
+
] }),
|
|
42
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "text-sm font-black tabular-nums text-foreground/70 shrink-0", children: [
|
|
43
|
+
l.xpRequired.toLocaleString(),
|
|
44
|
+
" XP"
|
|
45
|
+
] })
|
|
46
|
+
] }, l.level)) });
|
|
47
|
+
}
|
|
48
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
49
|
+
0 && (module.exports = {
|
|
50
|
+
LevelJourneyList
|
|
51
|
+
});
|
|
52
|
+
//# sourceMappingURL=level-journey-list.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/rewards/level-journey-list.tsx"],"sourcesContent":["import { cn } from \"../../utils/cn.js\";\n\nexport interface LevelJourneyListLevel {\n level: number;\n name: string;\n xpRequired: number;\n description: string | null;\n}\n\nexport interface LevelJourneyListProps {\n levels: LevelJourneyListLevel[];\n className?: string;\n}\n\n/** The full level ladder as a vertical showcase list — not the old\n * horizontal chip rail, which doesn't scale past a handful of items and\n * was built for a dashboard strip, not a 50-row standalone page. No\n * current-level state: this is the system-wide view, not \"where am I.\"\n * Every 10th level gets a small gradient marker as a milestone cue;\n * colors are otherwise uniform (one signature identity, not 50 flat\n * per-level colors) — badgeColor is deliberately not consumed here. */\nexport function LevelJourneyList({ levels, className }: LevelJourneyListProps) {\n return (\n <ol className={cn(\"divide-y divide-foreground/[0.06]\", className)}>\n {levels.map((l, i) => (\n <li key={l.level} className=\"flex items-start gap-4 py-4\">\n <span className=\"flex items-center gap-1.5 w-8 shrink-0 pt-0.5\">\n <span className=\"text-xs font-bold text-foreground/30 tabular-nums\">{l.level}</span>\n {(i + 1) % 10 === 0 && (\n <span\n aria-hidden\n className=\"h-1.5 w-1.5 rounded-full bg-gradient-to-r from-brand-orange to-brand-maeve\"\n />\n )}\n </span>\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-base font-bold\">{l.name}</p>\n {l.description && (\n <p className=\"text-sm text-foreground/60 mt-0.5 leading-relaxed\">{l.description}</p>\n )}\n </div>\n <span className=\"text-sm font-black tabular-nums text-foreground/70 shrink-0\">\n {l.xpRequired.toLocaleString()} XP\n </span>\n </li>\n ))}\n </ol>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA0BU;AA1BV,gBAAmB;AAqBZ,SAAS,iBAAiB,EAAE,QAAQ,UAAU,GAA0B;AAC7E,SACE,4CAAC,QAAG,eAAW,cAAG,qCAAqC,SAAS,GAC7D,iBAAO,IAAI,CAAC,GAAG,MACd,6CAAC,QAAiB,WAAU,+BAC1B;AAAA,iDAAC,UAAK,WAAU,iDACd;AAAA,kDAAC,UAAK,WAAU,qDAAqD,YAAE,OAAM;AAAA,OAC3E,IAAI,KAAK,OAAO,KAChB;AAAA,QAAC;AAAA;AAAA,UACC,eAAW;AAAA,UACX,WAAU;AAAA;AAAA,MACZ;AAAA,OAEJ;AAAA,IACA,6CAAC,SAAI,WAAU,kBACb;AAAA,kDAAC,OAAE,WAAU,uBAAuB,YAAE,MAAK;AAAA,MAC1C,EAAE,eACD,4CAAC,OAAE,WAAU,qDAAqD,YAAE,aAAY;AAAA,OAEpF;AAAA,IACA,6CAAC,UAAK,WAAU,+DACb;AAAA,QAAE,WAAW,eAAe;AAAA,MAAE;AAAA,OACjC;AAAA,OAlBO,EAAE,KAmBX,CACD,GACH;AAEJ;","names":[]}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
interface LevelJourneyListLevel {
|
|
4
|
+
level: number;
|
|
5
|
+
name: string;
|
|
6
|
+
xpRequired: number;
|
|
7
|
+
description: string | null;
|
|
8
|
+
}
|
|
9
|
+
interface LevelJourneyListProps {
|
|
10
|
+
levels: LevelJourneyListLevel[];
|
|
11
|
+
className?: string;
|
|
12
|
+
}
|
|
13
|
+
/** The full level ladder as a vertical showcase list — not the old
|
|
14
|
+
* horizontal chip rail, which doesn't scale past a handful of items and
|
|
15
|
+
* was built for a dashboard strip, not a 50-row standalone page. No
|
|
16
|
+
* current-level state: this is the system-wide view, not "where am I."
|
|
17
|
+
* Every 10th level gets a small gradient marker as a milestone cue;
|
|
18
|
+
* colors are otherwise uniform (one signature identity, not 50 flat
|
|
19
|
+
* per-level colors) — badgeColor is deliberately not consumed here. */
|
|
20
|
+
declare function LevelJourneyList({ levels, className }: LevelJourneyListProps): react_jsx_runtime.JSX.Element;
|
|
21
|
+
|
|
22
|
+
export { LevelJourneyList, type LevelJourneyListLevel, type LevelJourneyListProps };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
interface LevelJourneyListLevel {
|
|
4
|
+
level: number;
|
|
5
|
+
name: string;
|
|
6
|
+
xpRequired: number;
|
|
7
|
+
description: string | null;
|
|
8
|
+
}
|
|
9
|
+
interface LevelJourneyListProps {
|
|
10
|
+
levels: LevelJourneyListLevel[];
|
|
11
|
+
className?: string;
|
|
12
|
+
}
|
|
13
|
+
/** The full level ladder as a vertical showcase list — not the old
|
|
14
|
+
* horizontal chip rail, which doesn't scale past a handful of items and
|
|
15
|
+
* was built for a dashboard strip, not a 50-row standalone page. No
|
|
16
|
+
* current-level state: this is the system-wide view, not "where am I."
|
|
17
|
+
* Every 10th level gets a small gradient marker as a milestone cue;
|
|
18
|
+
* colors are otherwise uniform (one signature identity, not 50 flat
|
|
19
|
+
* per-level colors) — badgeColor is deliberately not consumed here. */
|
|
20
|
+
declare function LevelJourneyList({ levels, className }: LevelJourneyListProps): react_jsx_runtime.JSX.Element;
|
|
21
|
+
|
|
22
|
+
export { LevelJourneyList, type LevelJourneyListLevel, type LevelJourneyListProps };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../../utils/cn.js";
|
|
3
|
+
function LevelJourneyList({ levels, className }) {
|
|
4
|
+
return /* @__PURE__ */ jsx("ol", { className: cn("divide-y divide-foreground/[0.06]", className), children: levels.map((l, i) => /* @__PURE__ */ jsxs("li", { className: "flex items-start gap-4 py-4", children: [
|
|
5
|
+
/* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5 w-8 shrink-0 pt-0.5", children: [
|
|
6
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-bold text-foreground/30 tabular-nums", children: l.level }),
|
|
7
|
+
(i + 1) % 10 === 0 && /* @__PURE__ */ jsx(
|
|
8
|
+
"span",
|
|
9
|
+
{
|
|
10
|
+
"aria-hidden": true,
|
|
11
|
+
className: "h-1.5 w-1.5 rounded-full bg-gradient-to-r from-brand-orange to-brand-maeve"
|
|
12
|
+
}
|
|
13
|
+
)
|
|
14
|
+
] }),
|
|
15
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
16
|
+
/* @__PURE__ */ jsx("p", { className: "text-base font-bold", children: l.name }),
|
|
17
|
+
l.description && /* @__PURE__ */ jsx("p", { className: "text-sm text-foreground/60 mt-0.5 leading-relaxed", children: l.description })
|
|
18
|
+
] }),
|
|
19
|
+
/* @__PURE__ */ jsxs("span", { className: "text-sm font-black tabular-nums text-foreground/70 shrink-0", children: [
|
|
20
|
+
l.xpRequired.toLocaleString(),
|
|
21
|
+
" XP"
|
|
22
|
+
] })
|
|
23
|
+
] }, l.level)) });
|
|
24
|
+
}
|
|
25
|
+
export {
|
|
26
|
+
LevelJourneyList
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=level-journey-list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/rewards/level-journey-list.tsx"],"sourcesContent":["import { cn } from \"../../utils/cn.js\";\n\nexport interface LevelJourneyListLevel {\n level: number;\n name: string;\n xpRequired: number;\n description: string | null;\n}\n\nexport interface LevelJourneyListProps {\n levels: LevelJourneyListLevel[];\n className?: string;\n}\n\n/** The full level ladder as a vertical showcase list — not the old\n * horizontal chip rail, which doesn't scale past a handful of items and\n * was built for a dashboard strip, not a 50-row standalone page. No\n * current-level state: this is the system-wide view, not \"where am I.\"\n * Every 10th level gets a small gradient marker as a milestone cue;\n * colors are otherwise uniform (one signature identity, not 50 flat\n * per-level colors) — badgeColor is deliberately not consumed here. */\nexport function LevelJourneyList({ levels, className }: LevelJourneyListProps) {\n return (\n <ol className={cn(\"divide-y divide-foreground/[0.06]\", className)}>\n {levels.map((l, i) => (\n <li key={l.level} className=\"flex items-start gap-4 py-4\">\n <span className=\"flex items-center gap-1.5 w-8 shrink-0 pt-0.5\">\n <span className=\"text-xs font-bold text-foreground/30 tabular-nums\">{l.level}</span>\n {(i + 1) % 10 === 0 && (\n <span\n aria-hidden\n className=\"h-1.5 w-1.5 rounded-full bg-gradient-to-r from-brand-orange to-brand-maeve\"\n />\n )}\n </span>\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-base font-bold\">{l.name}</p>\n {l.description && (\n <p className=\"text-sm text-foreground/60 mt-0.5 leading-relaxed\">{l.description}</p>\n )}\n </div>\n <span className=\"text-sm font-black tabular-nums text-foreground/70 shrink-0\">\n {l.xpRequired.toLocaleString()} XP\n </span>\n </li>\n ))}\n </ol>\n );\n}\n"],"mappings":"AA0BU,SACE,KADF;AA1BV,SAAS,UAAU;AAqBZ,SAAS,iBAAiB,EAAE,QAAQ,UAAU,GAA0B;AAC7E,SACE,oBAAC,QAAG,WAAW,GAAG,qCAAqC,SAAS,GAC7D,iBAAO,IAAI,CAAC,GAAG,MACd,qBAAC,QAAiB,WAAU,+BAC1B;AAAA,yBAAC,UAAK,WAAU,iDACd;AAAA,0BAAC,UAAK,WAAU,qDAAqD,YAAE,OAAM;AAAA,OAC3E,IAAI,KAAK,OAAO,KAChB;AAAA,QAAC;AAAA;AAAA,UACC,eAAW;AAAA,UACX,WAAU;AAAA;AAAA,MACZ;AAAA,OAEJ;AAAA,IACA,qBAAC,SAAI,WAAU,kBACb;AAAA,0BAAC,OAAE,WAAU,uBAAuB,YAAE,MAAK;AAAA,MAC1C,EAAE,eACD,oBAAC,OAAE,WAAU,qDAAqD,YAAE,aAAY;AAAA,OAEpF;AAAA,IACA,qBAAC,UAAK,WAAU,+DACb;AAAA,QAAE,WAAW,eAAe;AAAA,MAAE;AAAA,OACjC;AAAA,OAlBO,EAAE,KAmBX,CACD,GACH;AAEJ;","names":[]}
|