@medialane/ui 0.35.1 → 0.36.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/badge-shelf.cjs +90 -0
- package/dist/components/rewards/badge-shelf.cjs.map +1 -0
- package/dist/components/rewards/badge-shelf.d.cts +24 -0
- package/dist/components/rewards/badge-shelf.d.ts +24 -0
- package/dist/components/rewards/badge-shelf.js +56 -0
- package/dist/components/rewards/badge-shelf.js.map +1 -0
- package/dist/components/rewards/leaderboard-table.cjs +96 -0
- package/dist/components/rewards/leaderboard-table.cjs.map +1 -0
- package/dist/components/rewards/leaderboard-table.d.cts +34 -0
- package/dist/components/rewards/leaderboard-table.d.ts +34 -0
- package/dist/components/rewards/leaderboard-table.js +71 -0
- package/dist/components/rewards/leaderboard-table.js.map +1 -0
- package/dist/components/rewards/level-badge.cjs +60 -0
- package/dist/components/rewards/level-badge.cjs.map +1 -0
- package/dist/components/rewards/level-badge.d.cts +14 -0
- package/dist/components/rewards/level-badge.d.ts +14 -0
- package/dist/components/rewards/level-badge.js +36 -0
- package/dist/components/rewards/level-badge.js.map +1 -0
- package/dist/components/rewards/level-ladder.cjs +54 -0
- package/dist/components/rewards/level-ladder.cjs.map +1 -0
- package/dist/components/rewards/level-ladder.d.cts +17 -0
- package/dist/components/rewards/level-ladder.d.ts +17 -0
- package/dist/components/rewards/level-ladder.js +30 -0
- package/dist/components/rewards/level-ladder.js.map +1 -0
- package/dist/components/rewards/score-summary-card.cjs +83 -0
- package/dist/components/rewards/score-summary-card.cjs.map +1 -0
- package/dist/components/rewards/score-summary-card.d.cts +26 -0
- package/dist/components/rewards/score-summary-card.d.ts +26 -0
- package/dist/components/rewards/score-summary-card.js +59 -0
- package/dist/components/rewards/score-summary-card.js.map +1 -0
- package/dist/components/rewards/xp-progress.cjs +81 -0
- package/dist/components/rewards/xp-progress.cjs.map +1 -0
- package/dist/components/rewards/xp-progress.d.cts +18 -0
- package/dist/components/rewards/xp-progress.d.ts +18 -0
- package/dist/components/rewards/xp-progress.js +57 -0
- package/dist/components/rewards/xp-progress.js.map +1 -0
- package/dist/components/rewards/xp-toast-content.cjs +49 -0
- package/dist/components/rewards/xp-toast-content.cjs.map +1 -0
- package/dist/components/rewards/xp-toast-content.d.cts +14 -0
- package/dist/components/rewards/xp-toast-content.d.ts +14 -0
- package/dist/components/rewards/xp-toast-content.js +25 -0
- package/dist/components/rewards/xp-toast-content.js.map +1 -0
- package/dist/index.cjs +23 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,90 @@
|
|
|
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 badge_shelf_exports = {};
|
|
31
|
+
__export(badge_shelf_exports, {
|
|
32
|
+
BadgeShelf: () => BadgeShelf
|
|
33
|
+
});
|
|
34
|
+
module.exports = __toCommonJS(badge_shelf_exports);
|
|
35
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
36
|
+
var import_react = __toESM(require("react"), 1);
|
|
37
|
+
var import_cn = require("../../utils/cn.js");
|
|
38
|
+
const iconCache = /* @__PURE__ */ new Map();
|
|
39
|
+
function BadgeIcon({ name, color, className }) {
|
|
40
|
+
const [Icon, setIcon] = import_react.default.useState(
|
|
41
|
+
() => iconCache.get(name) ?? null
|
|
42
|
+
);
|
|
43
|
+
import_react.default.useEffect(() => {
|
|
44
|
+
if (iconCache.has(name)) {
|
|
45
|
+
setIcon(() => iconCache.get(name));
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
import("lucide-react").then((mod) => {
|
|
49
|
+
const C = mod[name];
|
|
50
|
+
if (C) {
|
|
51
|
+
iconCache.set(name, C);
|
|
52
|
+
setIcon(() => C);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
}, [name]);
|
|
56
|
+
if (!Icon) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: (0, import_cn.cn)("rounded-full", className), style: { backgroundColor: color } });
|
|
57
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Icon, { className, style: { color } });
|
|
58
|
+
}
|
|
59
|
+
function BadgeShelf({ badges, earnedKeys, showLocked = false, className }) {
|
|
60
|
+
const earned = earnedKeys ? new Set(earnedKeys) : null;
|
|
61
|
+
const visible = badges.filter((b) => showLocked || !earned || earned.has(b.key));
|
|
62
|
+
if (visible.length === 0) return null;
|
|
63
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: (0, import_cn.cn)("flex flex-wrap gap-2", className), children: visible.map((badge) => {
|
|
64
|
+
const isLocked = earned ? !earned.has(badge.key) : false;
|
|
65
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
66
|
+
"div",
|
|
67
|
+
{
|
|
68
|
+
title: isLocked ? `${badge.description} \u2014 keep going to earn this` : badge.description,
|
|
69
|
+
className: (0, import_cn.cn)(
|
|
70
|
+
"flex h-7 select-none items-center gap-1.5 rounded-full border px-2.5",
|
|
71
|
+
isLocked && "opacity-45 grayscale"
|
|
72
|
+
),
|
|
73
|
+
style: {
|
|
74
|
+
borderColor: `${badge.color}60`,
|
|
75
|
+
backgroundColor: `${badge.color}14`
|
|
76
|
+
},
|
|
77
|
+
children: [
|
|
78
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(BadgeIcon, { name: badge.icon, color: badge.color, className: "h-3.5 w-3.5 shrink-0" }),
|
|
79
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-xs font-semibold", style: { color: badge.color }, children: badge.name })
|
|
80
|
+
]
|
|
81
|
+
},
|
|
82
|
+
badge.key
|
|
83
|
+
);
|
|
84
|
+
}) });
|
|
85
|
+
}
|
|
86
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
87
|
+
0 && (module.exports = {
|
|
88
|
+
BadgeShelf
|
|
89
|
+
});
|
|
90
|
+
//# sourceMappingURL=badge-shelf.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/rewards/badge-shelf.tsx"],"sourcesContent":["\"use client\";\n\nimport React from \"react\";\nimport type { LucideProps } from \"lucide-react\";\nimport { cn } from \"../../utils/cn.js\";\n\nexport interface BadgeShelfBadge {\n key: string;\n name: string;\n description: string;\n icon: string;\n color: string;\n category: string;\n}\n\nexport interface BadgeShelfProps {\n /** The badges to render — the earned set, or the full catalog with `earnedKeys`. */\n badges: BadgeShelfBadge[];\n /** When set, badges outside this set render locked (grayscale, reduced opacity). */\n earnedKeys?: string[];\n /** Render locked badges too (requires `earnedKeys`); default hides them. */\n showLocked?: boolean;\n className?: string;\n}\n\n// Lazily resolve lucide icons by name at runtime (icon names come from the API).\nconst iconCache = new Map<string, React.ComponentType<LucideProps>>();\n\nfunction BadgeIcon({ name, color, className }: { name: string; color: string; className?: string }) {\n const [Icon, setIcon] = React.useState<React.ComponentType<LucideProps> | null>(\n () => iconCache.get(name) ?? null\n );\n\n React.useEffect(() => {\n if (iconCache.has(name)) {\n setIcon(() => iconCache.get(name)!);\n return;\n }\n import(\"lucide-react\").then((mod) => {\n const C = (mod as Record<string, unknown>)[name] as React.ComponentType<LucideProps> | undefined;\n if (C) {\n iconCache.set(name, C);\n setIcon(() => C);\n }\n });\n }, [name]);\n\n if (!Icon) return <span className={cn(\"rounded-full\", className)} style={{ backgroundColor: color }} />;\n return <Icon className={className} style={{ color }} />;\n}\n\n/** Badge chips with native tooltips. Earned badges render in their color;\n * locked ones (present in `badges` but not `earnedKeys`) render muted. */\nexport function BadgeShelf({ badges, earnedKeys, showLocked = false, className }: BadgeShelfProps) {\n const earned = earnedKeys ? new Set(earnedKeys) : null;\n const visible = badges.filter((b) => showLocked || !earned || earned.has(b.key));\n if (visible.length === 0) return null;\n\n return (\n <div className={cn(\"flex flex-wrap gap-2\", className)}>\n {visible.map((badge) => {\n const isLocked = earned ? !earned.has(badge.key) : false;\n return (\n <div\n key={badge.key}\n title={isLocked ? `${badge.description} — keep going to earn this` : badge.description}\n className={cn(\n \"flex h-7 select-none items-center gap-1.5 rounded-full border px-2.5\",\n isLocked && \"opacity-45 grayscale\"\n )}\n style={{\n borderColor: `${badge.color}60`,\n backgroundColor: `${badge.color}14`,\n }}\n >\n <BadgeIcon name={badge.icon} color={badge.color} className=\"h-3.5 w-3.5 shrink-0\" />\n <span className=\"text-xs font-semibold\" style={{ color: badge.color }}>\n {badge.name}\n </span>\n </div>\n );\n })}\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA+CoB;AA7CpB,mBAAkB;AAElB,gBAAmB;AAsBnB,MAAM,YAAY,oBAAI,IAA8C;AAEpE,SAAS,UAAU,EAAE,MAAM,OAAO,UAAU,GAAwD;AAClG,QAAM,CAAC,MAAM,OAAO,IAAI,aAAAA,QAAM;AAAA,IAC5B,MAAM,UAAU,IAAI,IAAI,KAAK;AAAA,EAC/B;AAEA,eAAAA,QAAM,UAAU,MAAM;AACpB,QAAI,UAAU,IAAI,IAAI,GAAG;AACvB,cAAQ,MAAM,UAAU,IAAI,IAAI,CAAE;AAClC;AAAA,IACF;AACA,WAAO,cAAc,EAAE,KAAK,CAAC,QAAQ;AACnC,YAAM,IAAK,IAAgC,IAAI;AAC/C,UAAI,GAAG;AACL,kBAAU,IAAI,MAAM,CAAC;AACrB,gBAAQ,MAAM,CAAC;AAAA,MACjB;AAAA,IACF,CAAC;AAAA,EACH,GAAG,CAAC,IAAI,CAAC;AAET,MAAI,CAAC,KAAM,QAAO,4CAAC,UAAK,eAAW,cAAG,gBAAgB,SAAS,GAAG,OAAO,EAAE,iBAAiB,MAAM,GAAG;AACrG,SAAO,4CAAC,QAAK,WAAsB,OAAO,EAAE,MAAM,GAAG;AACvD;AAIO,SAAS,WAAW,EAAE,QAAQ,YAAY,aAAa,OAAO,UAAU,GAAoB;AACjG,QAAM,SAAS,aAAa,IAAI,IAAI,UAAU,IAAI;AAClD,QAAM,UAAU,OAAO,OAAO,CAAC,MAAM,cAAc,CAAC,UAAU,OAAO,IAAI,EAAE,GAAG,CAAC;AAC/E,MAAI,QAAQ,WAAW,EAAG,QAAO;AAEjC,SACE,4CAAC,SAAI,eAAW,cAAG,wBAAwB,SAAS,GACjD,kBAAQ,IAAI,CAAC,UAAU;AACtB,UAAM,WAAW,SAAS,CAAC,OAAO,IAAI,MAAM,GAAG,IAAI;AACnD,WACE;AAAA,MAAC;AAAA;AAAA,QAEC,OAAO,WAAW,GAAG,MAAM,WAAW,oCAA+B,MAAM;AAAA,QAC3E,eAAW;AAAA,UACT;AAAA,UACA,YAAY;AAAA,QACd;AAAA,QACA,OAAO;AAAA,UACL,aAAa,GAAG,MAAM,KAAK;AAAA,UAC3B,iBAAiB,GAAG,MAAM,KAAK;AAAA,QACjC;AAAA,QAEA;AAAA,sDAAC,aAAU,MAAM,MAAM,MAAM,OAAO,MAAM,OAAO,WAAU,wBAAuB;AAAA,UAClF,4CAAC,UAAK,WAAU,yBAAwB,OAAO,EAAE,OAAO,MAAM,MAAM,GACjE,gBAAM,MACT;AAAA;AAAA;AAAA,MAdK,MAAM;AAAA,IAeb;AAAA,EAEJ,CAAC,GACH;AAEJ;","names":["React"]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
interface BadgeShelfBadge {
|
|
4
|
+
key: string;
|
|
5
|
+
name: string;
|
|
6
|
+
description: string;
|
|
7
|
+
icon: string;
|
|
8
|
+
color: string;
|
|
9
|
+
category: string;
|
|
10
|
+
}
|
|
11
|
+
interface BadgeShelfProps {
|
|
12
|
+
/** The badges to render — the earned set, or the full catalog with `earnedKeys`. */
|
|
13
|
+
badges: BadgeShelfBadge[];
|
|
14
|
+
/** When set, badges outside this set render locked (grayscale, reduced opacity). */
|
|
15
|
+
earnedKeys?: string[];
|
|
16
|
+
/** Render locked badges too (requires `earnedKeys`); default hides them. */
|
|
17
|
+
showLocked?: boolean;
|
|
18
|
+
className?: string;
|
|
19
|
+
}
|
|
20
|
+
/** Badge chips with native tooltips. Earned badges render in their color;
|
|
21
|
+
* locked ones (present in `badges` but not `earnedKeys`) render muted. */
|
|
22
|
+
declare function BadgeShelf({ badges, earnedKeys, showLocked, className }: BadgeShelfProps): react_jsx_runtime.JSX.Element | null;
|
|
23
|
+
|
|
24
|
+
export { BadgeShelf, type BadgeShelfBadge, type BadgeShelfProps };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
interface BadgeShelfBadge {
|
|
4
|
+
key: string;
|
|
5
|
+
name: string;
|
|
6
|
+
description: string;
|
|
7
|
+
icon: string;
|
|
8
|
+
color: string;
|
|
9
|
+
category: string;
|
|
10
|
+
}
|
|
11
|
+
interface BadgeShelfProps {
|
|
12
|
+
/** The badges to render — the earned set, or the full catalog with `earnedKeys`. */
|
|
13
|
+
badges: BadgeShelfBadge[];
|
|
14
|
+
/** When set, badges outside this set render locked (grayscale, reduced opacity). */
|
|
15
|
+
earnedKeys?: string[];
|
|
16
|
+
/** Render locked badges too (requires `earnedKeys`); default hides them. */
|
|
17
|
+
showLocked?: boolean;
|
|
18
|
+
className?: string;
|
|
19
|
+
}
|
|
20
|
+
/** Badge chips with native tooltips. Earned badges render in their color;
|
|
21
|
+
* locked ones (present in `badges` but not `earnedKeys`) render muted. */
|
|
22
|
+
declare function BadgeShelf({ badges, earnedKeys, showLocked, className }: BadgeShelfProps): react_jsx_runtime.JSX.Element | null;
|
|
23
|
+
|
|
24
|
+
export { BadgeShelf, type BadgeShelfBadge, type BadgeShelfProps };
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { cn } from "../../utils/cn.js";
|
|
5
|
+
const iconCache = /* @__PURE__ */ new Map();
|
|
6
|
+
function BadgeIcon({ name, color, className }) {
|
|
7
|
+
const [Icon, setIcon] = React.useState(
|
|
8
|
+
() => iconCache.get(name) ?? null
|
|
9
|
+
);
|
|
10
|
+
React.useEffect(() => {
|
|
11
|
+
if (iconCache.has(name)) {
|
|
12
|
+
setIcon(() => iconCache.get(name));
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
import("lucide-react").then((mod) => {
|
|
16
|
+
const C = mod[name];
|
|
17
|
+
if (C) {
|
|
18
|
+
iconCache.set(name, C);
|
|
19
|
+
setIcon(() => C);
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
}, [name]);
|
|
23
|
+
if (!Icon) return /* @__PURE__ */ jsx("span", { className: cn("rounded-full", className), style: { backgroundColor: color } });
|
|
24
|
+
return /* @__PURE__ */ jsx(Icon, { className, style: { color } });
|
|
25
|
+
}
|
|
26
|
+
function BadgeShelf({ badges, earnedKeys, showLocked = false, className }) {
|
|
27
|
+
const earned = earnedKeys ? new Set(earnedKeys) : null;
|
|
28
|
+
const visible = badges.filter((b) => showLocked || !earned || earned.has(b.key));
|
|
29
|
+
if (visible.length === 0) return null;
|
|
30
|
+
return /* @__PURE__ */ jsx("div", { className: cn("flex flex-wrap gap-2", className), children: visible.map((badge) => {
|
|
31
|
+
const isLocked = earned ? !earned.has(badge.key) : false;
|
|
32
|
+
return /* @__PURE__ */ jsxs(
|
|
33
|
+
"div",
|
|
34
|
+
{
|
|
35
|
+
title: isLocked ? `${badge.description} \u2014 keep going to earn this` : badge.description,
|
|
36
|
+
className: cn(
|
|
37
|
+
"flex h-7 select-none items-center gap-1.5 rounded-full border px-2.5",
|
|
38
|
+
isLocked && "opacity-45 grayscale"
|
|
39
|
+
),
|
|
40
|
+
style: {
|
|
41
|
+
borderColor: `${badge.color}60`,
|
|
42
|
+
backgroundColor: `${badge.color}14`
|
|
43
|
+
},
|
|
44
|
+
children: [
|
|
45
|
+
/* @__PURE__ */ jsx(BadgeIcon, { name: badge.icon, color: badge.color, className: "h-3.5 w-3.5 shrink-0" }),
|
|
46
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-semibold", style: { color: badge.color }, children: badge.name })
|
|
47
|
+
]
|
|
48
|
+
},
|
|
49
|
+
badge.key
|
|
50
|
+
);
|
|
51
|
+
}) });
|
|
52
|
+
}
|
|
53
|
+
export {
|
|
54
|
+
BadgeShelf
|
|
55
|
+
};
|
|
56
|
+
//# sourceMappingURL=badge-shelf.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/rewards/badge-shelf.tsx"],"sourcesContent":["\"use client\";\n\nimport React from \"react\";\nimport type { LucideProps } from \"lucide-react\";\nimport { cn } from \"../../utils/cn.js\";\n\nexport interface BadgeShelfBadge {\n key: string;\n name: string;\n description: string;\n icon: string;\n color: string;\n category: string;\n}\n\nexport interface BadgeShelfProps {\n /** The badges to render — the earned set, or the full catalog with `earnedKeys`. */\n badges: BadgeShelfBadge[];\n /** When set, badges outside this set render locked (grayscale, reduced opacity). */\n earnedKeys?: string[];\n /** Render locked badges too (requires `earnedKeys`); default hides them. */\n showLocked?: boolean;\n className?: string;\n}\n\n// Lazily resolve lucide icons by name at runtime (icon names come from the API).\nconst iconCache = new Map<string, React.ComponentType<LucideProps>>();\n\nfunction BadgeIcon({ name, color, className }: { name: string; color: string; className?: string }) {\n const [Icon, setIcon] = React.useState<React.ComponentType<LucideProps> | null>(\n () => iconCache.get(name) ?? null\n );\n\n React.useEffect(() => {\n if (iconCache.has(name)) {\n setIcon(() => iconCache.get(name)!);\n return;\n }\n import(\"lucide-react\").then((mod) => {\n const C = (mod as Record<string, unknown>)[name] as React.ComponentType<LucideProps> | undefined;\n if (C) {\n iconCache.set(name, C);\n setIcon(() => C);\n }\n });\n }, [name]);\n\n if (!Icon) return <span className={cn(\"rounded-full\", className)} style={{ backgroundColor: color }} />;\n return <Icon className={className} style={{ color }} />;\n}\n\n/** Badge chips with native tooltips. Earned badges render in their color;\n * locked ones (present in `badges` but not `earnedKeys`) render muted. */\nexport function BadgeShelf({ badges, earnedKeys, showLocked = false, className }: BadgeShelfProps) {\n const earned = earnedKeys ? new Set(earnedKeys) : null;\n const visible = badges.filter((b) => showLocked || !earned || earned.has(b.key));\n if (visible.length === 0) return null;\n\n return (\n <div className={cn(\"flex flex-wrap gap-2\", className)}>\n {visible.map((badge) => {\n const isLocked = earned ? !earned.has(badge.key) : false;\n return (\n <div\n key={badge.key}\n title={isLocked ? `${badge.description} — keep going to earn this` : badge.description}\n className={cn(\n \"flex h-7 select-none items-center gap-1.5 rounded-full border px-2.5\",\n isLocked && \"opacity-45 grayscale\"\n )}\n style={{\n borderColor: `${badge.color}60`,\n backgroundColor: `${badge.color}14`,\n }}\n >\n <BadgeIcon name={badge.icon} color={badge.color} className=\"h-3.5 w-3.5 shrink-0\" />\n <span className=\"text-xs font-semibold\" style={{ color: badge.color }}>\n {badge.name}\n </span>\n </div>\n );\n })}\n </div>\n );\n}\n"],"mappings":";AA+CoB,cAgBV,YAhBU;AA7CpB,OAAO,WAAW;AAElB,SAAS,UAAU;AAsBnB,MAAM,YAAY,oBAAI,IAA8C;AAEpE,SAAS,UAAU,EAAE,MAAM,OAAO,UAAU,GAAwD;AAClG,QAAM,CAAC,MAAM,OAAO,IAAI,MAAM;AAAA,IAC5B,MAAM,UAAU,IAAI,IAAI,KAAK;AAAA,EAC/B;AAEA,QAAM,UAAU,MAAM;AACpB,QAAI,UAAU,IAAI,IAAI,GAAG;AACvB,cAAQ,MAAM,UAAU,IAAI,IAAI,CAAE;AAClC;AAAA,IACF;AACA,WAAO,cAAc,EAAE,KAAK,CAAC,QAAQ;AACnC,YAAM,IAAK,IAAgC,IAAI;AAC/C,UAAI,GAAG;AACL,kBAAU,IAAI,MAAM,CAAC;AACrB,gBAAQ,MAAM,CAAC;AAAA,MACjB;AAAA,IACF,CAAC;AAAA,EACH,GAAG,CAAC,IAAI,CAAC;AAET,MAAI,CAAC,KAAM,QAAO,oBAAC,UAAK,WAAW,GAAG,gBAAgB,SAAS,GAAG,OAAO,EAAE,iBAAiB,MAAM,GAAG;AACrG,SAAO,oBAAC,QAAK,WAAsB,OAAO,EAAE,MAAM,GAAG;AACvD;AAIO,SAAS,WAAW,EAAE,QAAQ,YAAY,aAAa,OAAO,UAAU,GAAoB;AACjG,QAAM,SAAS,aAAa,IAAI,IAAI,UAAU,IAAI;AAClD,QAAM,UAAU,OAAO,OAAO,CAAC,MAAM,cAAc,CAAC,UAAU,OAAO,IAAI,EAAE,GAAG,CAAC;AAC/E,MAAI,QAAQ,WAAW,EAAG,QAAO;AAEjC,SACE,oBAAC,SAAI,WAAW,GAAG,wBAAwB,SAAS,GACjD,kBAAQ,IAAI,CAAC,UAAU;AACtB,UAAM,WAAW,SAAS,CAAC,OAAO,IAAI,MAAM,GAAG,IAAI;AACnD,WACE;AAAA,MAAC;AAAA;AAAA,QAEC,OAAO,WAAW,GAAG,MAAM,WAAW,oCAA+B,MAAM;AAAA,QAC3E,WAAW;AAAA,UACT;AAAA,UACA,YAAY;AAAA,QACd;AAAA,QACA,OAAO;AAAA,UACL,aAAa,GAAG,MAAM,KAAK;AAAA,UAC3B,iBAAiB,GAAG,MAAM,KAAK;AAAA,QACjC;AAAA,QAEA;AAAA,8BAAC,aAAU,MAAM,MAAM,MAAM,OAAO,MAAM,OAAO,WAAU,wBAAuB;AAAA,UAClF,oBAAC,UAAK,WAAU,yBAAwB,OAAO,EAAE,OAAO,MAAM,MAAM,GACjE,gBAAM,MACT;AAAA;AAAA;AAAA,MAdK,MAAM;AAAA,IAeb;AAAA,EAEJ,CAAC,GACH;AAEJ;","names":[]}
|
|
@@ -0,0 +1,96 @@
|
|
|
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 leaderboard_table_exports = {};
|
|
20
|
+
__export(leaderboard_table_exports, {
|
|
21
|
+
LeaderboardTable: () => LeaderboardTable,
|
|
22
|
+
LeaderboardWidget: () => LeaderboardWidget
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(leaderboard_table_exports);
|
|
25
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
26
|
+
var import_cn = require("../../utils/cn.js");
|
|
27
|
+
var import_address = require("../../utils/address.js");
|
|
28
|
+
var import_level_badge = require("./level-badge.js");
|
|
29
|
+
function rankAccent(rank) {
|
|
30
|
+
if (rank === 1) return "#f59e0b";
|
|
31
|
+
if (rank === 2) return "#94a3b8";
|
|
32
|
+
if (rank === 3) return "#b45309";
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
function LeaderboardTable({ entries, highlightAddress, renderAddress, className }) {
|
|
36
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: (0, import_cn.cn)("overflow-hidden rounded-xl border border-border", className), children: entries.map((e) => {
|
|
37
|
+
const accent = rankAccent(e.rank);
|
|
38
|
+
const isViewer = highlightAddress != null && e.address === highlightAddress;
|
|
39
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
40
|
+
"div",
|
|
41
|
+
{
|
|
42
|
+
className: (0, import_cn.cn)(
|
|
43
|
+
"flex items-center gap-3 border-b border-border/60 bg-card px-3 py-2.5 last:border-b-0 sm:px-4",
|
|
44
|
+
isViewer && "bg-primary/10"
|
|
45
|
+
),
|
|
46
|
+
children: [
|
|
47
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
48
|
+
"span",
|
|
49
|
+
{
|
|
50
|
+
className: "w-8 shrink-0 text-center text-sm font-black tabular-nums",
|
|
51
|
+
style: accent ? { color: accent } : void 0,
|
|
52
|
+
children: e.rank
|
|
53
|
+
}
|
|
54
|
+
),
|
|
55
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "min-w-0 flex-1 truncate text-sm font-medium", children: [
|
|
56
|
+
renderAddress ? renderAddress(e.address) : (0, import_address.shortenAddress)(e.address),
|
|
57
|
+
isViewer && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "ml-1.5 text-xs text-muted-foreground", children: "(you)" })
|
|
58
|
+
] }),
|
|
59
|
+
/* @__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" }),
|
|
60
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "shrink-0 text-sm font-semibold tabular-nums", children: [
|
|
61
|
+
e.totalXp.toLocaleString(),
|
|
62
|
+
" XP"
|
|
63
|
+
] })
|
|
64
|
+
]
|
|
65
|
+
},
|
|
66
|
+
e.address
|
|
67
|
+
);
|
|
68
|
+
}) });
|
|
69
|
+
}
|
|
70
|
+
function LeaderboardWidget({ entries, title = "Top Creators", href, renderAddress, className }) {
|
|
71
|
+
if (entries.length === 0) return null;
|
|
72
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: (0, import_cn.cn)("rounded-xl border border-border bg-card p-4 sm:p-5", className), children: [
|
|
73
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mb-3 flex items-center justify-between", children: [
|
|
74
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { className: "text-base font-black", children: title }),
|
|
75
|
+
href && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href, className: "text-xs font-semibold text-muted-foreground active:opacity-70", children: "View leaderboard \u2192" })
|
|
76
|
+
] }),
|
|
77
|
+
/* @__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: [
|
|
78
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
79
|
+
"span",
|
|
80
|
+
{
|
|
81
|
+
className: "w-5 shrink-0 text-center text-sm font-black tabular-nums",
|
|
82
|
+
style: rankAccent(e.rank) ? { color: rankAccent(e.rank) } : void 0,
|
|
83
|
+
children: e.rank
|
|
84
|
+
}
|
|
85
|
+
),
|
|
86
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "min-w-0 flex-1 truncate text-sm font-medium", children: renderAddress ? renderAddress(e.address) : (0, import_address.shortenAddress)(e.address) }),
|
|
87
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_level_badge.LevelBadge, { level: e.currentLevel, name: e.currentLevelName, badgeColor: e.badgeColor, size: "sm" })
|
|
88
|
+
] }, e.address)) })
|
|
89
|
+
] });
|
|
90
|
+
}
|
|
91
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
92
|
+
0 && (module.exports = {
|
|
93
|
+
LeaderboardTable,
|
|
94
|
+
LeaderboardWidget
|
|
95
|
+
});
|
|
96
|
+
//# sourceMappingURL=leaderboard-table.cjs.map
|
|
@@ -0,0 +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 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\nfunction rankAccent(rank: number): string | null {\n if (rank === 1) return \"#f59e0b\";\n if (rank === 2) return \"#94a3b8\";\n if (rank === 3) return \"#b45309\";\n return null;\n}\n\n/** Full leaderboard rows: rank, address, level chip, XP. */\nexport function LeaderboardTable({ entries, highlightAddress, renderAddress, className }: LeaderboardTableProps) {\n return (\n <div className={cn(\"overflow-hidden rounded-xl border border-border\", className)}>\n {entries.map((e) => {\n const accent = rankAccent(e.rank);\n const isViewer = highlightAddress != null && e.address === highlightAddress;\n return (\n <div\n key={e.address}\n className={cn(\n \"flex items-center gap-3 border-b border-border/60 bg-card px-3 py-2.5 last:border-b-0 sm:px-4\",\n isViewer && \"bg-primary/10\"\n )}\n >\n <span\n className=\"w-8 shrink-0 text-center text-sm font-black tabular-nums\"\n style={accent ? { color: accent } : undefined}\n >\n {e.rank}\n </span>\n <span className=\"min-w-0 flex-1 truncate text-sm font-medium\">\n {renderAddress ? renderAddress(e.address) : shortenAddress(e.address)}\n {isViewer && <span className=\"ml-1.5 text-xs text-muted-foreground\">(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-sm font-semibold tabular-nums\">{e.totalXp.toLocaleString()} XP</span>\n </div>\n );\n })}\n </div>\n );\n}\n\nexport interface LeaderboardWidgetProps {\n entries: LeaderboardEntryLike[];\n title?: string;\n /** Link to the full leaderboard (\"/rewards\"). */\n href?: string;\n renderAddress?: (address: string) => ReactNode;\n className?: string;\n}\n\n/** Compact top-N card for homepage/discover rails. */\nexport function LeaderboardWidget({ entries, title = \"Top Creators\", href, renderAddress, className }: LeaderboardWidgetProps) {\n if (entries.length === 0) return null;\n return (\n <section className={cn(\"rounded-xl border border-border bg-card p-4 sm:p-5\", className)}>\n <div className=\"mb-3 flex items-center justify-between\">\n <h2 className=\"text-base font-black\">{title}</h2>\n {href && (\n <a href={href} className=\"text-xs font-semibold text-muted-foreground active:opacity-70\">\n View leaderboard →\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\n className=\"w-5 shrink-0 text-center text-sm font-black tabular-nums\"\n style={rankAccent(e.rank) ? { color: rankAccent(e.rank)! } : undefined}\n >\n {e.rank}\n </span>\n <span className=\"min-w-0 flex-1 truncate text-sm font-medium\">\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;AA8CY;AA7CZ,gBAAmB;AACnB,qBAA+B;AAC/B,yBAA2B;AAqB3B,SAAS,WAAW,MAA6B;AAC/C,MAAI,SAAS,EAAG,QAAO;AACvB,MAAI,SAAS,EAAG,QAAO;AACvB,MAAI,SAAS,EAAG,QAAO;AACvB,SAAO;AACT;AAGO,SAAS,iBAAiB,EAAE,SAAS,kBAAkB,eAAe,UAAU,GAA0B;AAC/G,SACE,4CAAC,SAAI,eAAW,cAAG,mDAAmD,SAAS,GAC5E,kBAAQ,IAAI,CAAC,MAAM;AAClB,UAAM,SAAS,WAAW,EAAE,IAAI;AAChC,UAAM,WAAW,oBAAoB,QAAQ,EAAE,YAAY;AAC3D,WACE;AAAA,MAAC;AAAA;AAAA,QAEC,eAAW;AAAA,UACT;AAAA,UACA,YAAY;AAAA,QACd;AAAA,QAEA;AAAA;AAAA,YAAC;AAAA;AAAA,cACC,WAAU;AAAA,cACV,OAAO,SAAS,EAAE,OAAO,OAAO,IAAI;AAAA,cAEnC,YAAE;AAAA;AAAA,UACL;AAAA,UACA,6CAAC,UAAK,WAAU,+CACb;AAAA,4BAAgB,cAAc,EAAE,OAAO,QAAI,+BAAe,EAAE,OAAO;AAAA,YACnE,YAAY,4CAAC,UAAK,WAAU,wCAAuC,mBAAK;AAAA,aAC3E;AAAA,UACA,4CAAC,iCAAW,OAAO,EAAE,cAAc,MAAM,EAAE,kBAAkB,YAAY,EAAE,YAAY,MAAK,MAAK,WAAU,yBAAwB;AAAA,UACnI,6CAAC,UAAK,WAAU,+CAA+C;AAAA,cAAE,QAAQ,eAAe;AAAA,YAAE;AAAA,aAAG;AAAA;AAAA;AAAA,MAjBxF,EAAE;AAAA,IAkBT;AAAA,EAEJ,CAAC,GACH;AAEJ;AAYO,SAAS,kBAAkB,EAAE,SAAS,QAAQ,gBAAgB,MAAM,eAAe,UAAU,GAA2B;AAC7H,MAAI,QAAQ,WAAW,EAAG,QAAO;AACjC,SACE,6CAAC,aAAQ,eAAW,cAAG,sDAAsD,SAAS,GACpF;AAAA,iDAAC,SAAI,WAAU,0CACb;AAAA,kDAAC,QAAG,WAAU,wBAAwB,iBAAM;AAAA,MAC3C,QACC,4CAAC,OAAE,MAAY,WAAU,iEAAgE,qCAEzF;AAAA,OAEJ;AAAA,IACA,4CAAC,QAAG,WAAU,eACX,kBAAQ,IAAI,CAAC,MACZ,6CAAC,QAAmB,WAAU,6BAC5B;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,WAAU;AAAA,UACV,OAAO,WAAW,EAAE,IAAI,IAAI,EAAE,OAAO,WAAW,EAAE,IAAI,EAAG,IAAI;AAAA,UAE5D,YAAE;AAAA;AAAA,MACL;AAAA,MACA,4CAAC,UAAK,WAAU,+CACb,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,SAV1F,EAAE,OAWX,CACD,GACH;AAAA,KACF;AAEJ;","names":[]}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
interface LeaderboardEntryLike {
|
|
5
|
+
rank: number;
|
|
6
|
+
address: string;
|
|
7
|
+
publicId?: string | null;
|
|
8
|
+
totalXp: number;
|
|
9
|
+
currentLevel: number;
|
|
10
|
+
currentLevelName: string;
|
|
11
|
+
badgeColor: string;
|
|
12
|
+
}
|
|
13
|
+
interface LeaderboardTableProps {
|
|
14
|
+
entries: LeaderboardEntryLike[];
|
|
15
|
+
/** The viewer's address — its row gets highlighted. */
|
|
16
|
+
highlightAddress?: string | null;
|
|
17
|
+
/** Render the address cell (e.g. a profile link). Defaults to a shortened address. */
|
|
18
|
+
renderAddress?: (address: string) => ReactNode;
|
|
19
|
+
className?: string;
|
|
20
|
+
}
|
|
21
|
+
/** Full leaderboard rows: rank, address, level chip, XP. */
|
|
22
|
+
declare function LeaderboardTable({ entries, highlightAddress, renderAddress, className }: LeaderboardTableProps): react_jsx_runtime.JSX.Element;
|
|
23
|
+
interface LeaderboardWidgetProps {
|
|
24
|
+
entries: LeaderboardEntryLike[];
|
|
25
|
+
title?: string;
|
|
26
|
+
/** Link to the full leaderboard ("/rewards"). */
|
|
27
|
+
href?: string;
|
|
28
|
+
renderAddress?: (address: string) => ReactNode;
|
|
29
|
+
className?: string;
|
|
30
|
+
}
|
|
31
|
+
/** Compact top-N card for homepage/discover rails. */
|
|
32
|
+
declare function LeaderboardWidget({ entries, title, href, renderAddress, className }: LeaderboardWidgetProps): react_jsx_runtime.JSX.Element | null;
|
|
33
|
+
|
|
34
|
+
export { type LeaderboardEntryLike, LeaderboardTable, type LeaderboardTableProps, LeaderboardWidget, type LeaderboardWidgetProps };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
interface LeaderboardEntryLike {
|
|
5
|
+
rank: number;
|
|
6
|
+
address: string;
|
|
7
|
+
publicId?: string | null;
|
|
8
|
+
totalXp: number;
|
|
9
|
+
currentLevel: number;
|
|
10
|
+
currentLevelName: string;
|
|
11
|
+
badgeColor: string;
|
|
12
|
+
}
|
|
13
|
+
interface LeaderboardTableProps {
|
|
14
|
+
entries: LeaderboardEntryLike[];
|
|
15
|
+
/** The viewer's address — its row gets highlighted. */
|
|
16
|
+
highlightAddress?: string | null;
|
|
17
|
+
/** Render the address cell (e.g. a profile link). Defaults to a shortened address. */
|
|
18
|
+
renderAddress?: (address: string) => ReactNode;
|
|
19
|
+
className?: string;
|
|
20
|
+
}
|
|
21
|
+
/** Full leaderboard rows: rank, address, level chip, XP. */
|
|
22
|
+
declare function LeaderboardTable({ entries, highlightAddress, renderAddress, className }: LeaderboardTableProps): react_jsx_runtime.JSX.Element;
|
|
23
|
+
interface LeaderboardWidgetProps {
|
|
24
|
+
entries: LeaderboardEntryLike[];
|
|
25
|
+
title?: string;
|
|
26
|
+
/** Link to the full leaderboard ("/rewards"). */
|
|
27
|
+
href?: string;
|
|
28
|
+
renderAddress?: (address: string) => ReactNode;
|
|
29
|
+
className?: string;
|
|
30
|
+
}
|
|
31
|
+
/** Compact top-N card for homepage/discover rails. */
|
|
32
|
+
declare function LeaderboardWidget({ entries, title, href, renderAddress, className }: LeaderboardWidgetProps): react_jsx_runtime.JSX.Element | null;
|
|
33
|
+
|
|
34
|
+
export { type LeaderboardEntryLike, LeaderboardTable, type LeaderboardTableProps, LeaderboardWidget, type LeaderboardWidgetProps };
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../../utils/cn.js";
|
|
3
|
+
import { shortenAddress } from "../../utils/address.js";
|
|
4
|
+
import { LevelBadge } from "./level-badge.js";
|
|
5
|
+
function rankAccent(rank) {
|
|
6
|
+
if (rank === 1) return "#f59e0b";
|
|
7
|
+
if (rank === 2) return "#94a3b8";
|
|
8
|
+
if (rank === 3) return "#b45309";
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
function LeaderboardTable({ entries, highlightAddress, renderAddress, className }) {
|
|
12
|
+
return /* @__PURE__ */ jsx("div", { className: cn("overflow-hidden rounded-xl border border-border", className), children: entries.map((e) => {
|
|
13
|
+
const accent = rankAccent(e.rank);
|
|
14
|
+
const isViewer = highlightAddress != null && e.address === highlightAddress;
|
|
15
|
+
return /* @__PURE__ */ jsxs(
|
|
16
|
+
"div",
|
|
17
|
+
{
|
|
18
|
+
className: cn(
|
|
19
|
+
"flex items-center gap-3 border-b border-border/60 bg-card px-3 py-2.5 last:border-b-0 sm:px-4",
|
|
20
|
+
isViewer && "bg-primary/10"
|
|
21
|
+
),
|
|
22
|
+
children: [
|
|
23
|
+
/* @__PURE__ */ jsx(
|
|
24
|
+
"span",
|
|
25
|
+
{
|
|
26
|
+
className: "w-8 shrink-0 text-center text-sm font-black tabular-nums",
|
|
27
|
+
style: accent ? { color: accent } : void 0,
|
|
28
|
+
children: e.rank
|
|
29
|
+
}
|
|
30
|
+
),
|
|
31
|
+
/* @__PURE__ */ jsxs("span", { className: "min-w-0 flex-1 truncate text-sm font-medium", children: [
|
|
32
|
+
renderAddress ? renderAddress(e.address) : shortenAddress(e.address),
|
|
33
|
+
isViewer && /* @__PURE__ */ jsx("span", { className: "ml-1.5 text-xs text-muted-foreground", children: "(you)" })
|
|
34
|
+
] }),
|
|
35
|
+
/* @__PURE__ */ jsx(LevelBadge, { level: e.currentLevel, name: e.currentLevelName, badgeColor: e.badgeColor, size: "sm", className: "hidden sm:inline-flex" }),
|
|
36
|
+
/* @__PURE__ */ jsxs("span", { className: "shrink-0 text-sm font-semibold tabular-nums", children: [
|
|
37
|
+
e.totalXp.toLocaleString(),
|
|
38
|
+
" XP"
|
|
39
|
+
] })
|
|
40
|
+
]
|
|
41
|
+
},
|
|
42
|
+
e.address
|
|
43
|
+
);
|
|
44
|
+
}) });
|
|
45
|
+
}
|
|
46
|
+
function LeaderboardWidget({ entries, title = "Top Creators", href, renderAddress, className }) {
|
|
47
|
+
if (entries.length === 0) return null;
|
|
48
|
+
return /* @__PURE__ */ jsxs("section", { className: cn("rounded-xl border border-border bg-card p-4 sm:p-5", className), children: [
|
|
49
|
+
/* @__PURE__ */ jsxs("div", { className: "mb-3 flex items-center justify-between", children: [
|
|
50
|
+
/* @__PURE__ */ jsx("h2", { className: "text-base font-black", children: title }),
|
|
51
|
+
href && /* @__PURE__ */ jsx("a", { href, className: "text-xs font-semibold text-muted-foreground active:opacity-70", children: "View leaderboard \u2192" })
|
|
52
|
+
] }),
|
|
53
|
+
/* @__PURE__ */ jsx("ol", { className: "space-y-2.5", children: entries.map((e) => /* @__PURE__ */ jsxs("li", { className: "flex items-center gap-2.5", children: [
|
|
54
|
+
/* @__PURE__ */ jsx(
|
|
55
|
+
"span",
|
|
56
|
+
{
|
|
57
|
+
className: "w-5 shrink-0 text-center text-sm font-black tabular-nums",
|
|
58
|
+
style: rankAccent(e.rank) ? { color: rankAccent(e.rank) } : void 0,
|
|
59
|
+
children: e.rank
|
|
60
|
+
}
|
|
61
|
+
),
|
|
62
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate text-sm font-medium", children: renderAddress ? renderAddress(e.address) : shortenAddress(e.address) }),
|
|
63
|
+
/* @__PURE__ */ jsx(LevelBadge, { level: e.currentLevel, name: e.currentLevelName, badgeColor: e.badgeColor, size: "sm" })
|
|
64
|
+
] }, e.address)) })
|
|
65
|
+
] });
|
|
66
|
+
}
|
|
67
|
+
export {
|
|
68
|
+
LeaderboardTable,
|
|
69
|
+
LeaderboardWidget
|
|
70
|
+
};
|
|
71
|
+
//# sourceMappingURL=leaderboard-table.js.map
|
|
@@ -0,0 +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 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\nfunction rankAccent(rank: number): string | null {\n if (rank === 1) return \"#f59e0b\";\n if (rank === 2) return \"#94a3b8\";\n if (rank === 3) return \"#b45309\";\n return null;\n}\n\n/** Full leaderboard rows: rank, address, level chip, XP. */\nexport function LeaderboardTable({ entries, highlightAddress, renderAddress, className }: LeaderboardTableProps) {\n return (\n <div className={cn(\"overflow-hidden rounded-xl border border-border\", className)}>\n {entries.map((e) => {\n const accent = rankAccent(e.rank);\n const isViewer = highlightAddress != null && e.address === highlightAddress;\n return (\n <div\n key={e.address}\n className={cn(\n \"flex items-center gap-3 border-b border-border/60 bg-card px-3 py-2.5 last:border-b-0 sm:px-4\",\n isViewer && \"bg-primary/10\"\n )}\n >\n <span\n className=\"w-8 shrink-0 text-center text-sm font-black tabular-nums\"\n style={accent ? { color: accent } : undefined}\n >\n {e.rank}\n </span>\n <span className=\"min-w-0 flex-1 truncate text-sm font-medium\">\n {renderAddress ? renderAddress(e.address) : shortenAddress(e.address)}\n {isViewer && <span className=\"ml-1.5 text-xs text-muted-foreground\">(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-sm font-semibold tabular-nums\">{e.totalXp.toLocaleString()} XP</span>\n </div>\n );\n })}\n </div>\n );\n}\n\nexport interface LeaderboardWidgetProps {\n entries: LeaderboardEntryLike[];\n title?: string;\n /** Link to the full leaderboard (\"/rewards\"). */\n href?: string;\n renderAddress?: (address: string) => ReactNode;\n className?: string;\n}\n\n/** Compact top-N card for homepage/discover rails. */\nexport function LeaderboardWidget({ entries, title = \"Top Creators\", href, renderAddress, className }: LeaderboardWidgetProps) {\n if (entries.length === 0) return null;\n return (\n <section className={cn(\"rounded-xl border border-border bg-card p-4 sm:p-5\", className)}>\n <div className=\"mb-3 flex items-center justify-between\">\n <h2 className=\"text-base font-black\">{title}</h2>\n {href && (\n <a href={href} className=\"text-xs font-semibold text-muted-foreground active:opacity-70\">\n View leaderboard →\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\n className=\"w-5 shrink-0 text-center text-sm font-black tabular-nums\"\n style={rankAccent(e.rank) ? { color: rankAccent(e.rank)! } : undefined}\n >\n {e.rank}\n </span>\n <span className=\"min-w-0 flex-1 truncate text-sm font-medium\">\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":"AA8CY,cAMA,YANA;AA7CZ,SAAS,UAAU;AACnB,SAAS,sBAAsB;AAC/B,SAAS,kBAAkB;AAqB3B,SAAS,WAAW,MAA6B;AAC/C,MAAI,SAAS,EAAG,QAAO;AACvB,MAAI,SAAS,EAAG,QAAO;AACvB,MAAI,SAAS,EAAG,QAAO;AACvB,SAAO;AACT;AAGO,SAAS,iBAAiB,EAAE,SAAS,kBAAkB,eAAe,UAAU,GAA0B;AAC/G,SACE,oBAAC,SAAI,WAAW,GAAG,mDAAmD,SAAS,GAC5E,kBAAQ,IAAI,CAAC,MAAM;AAClB,UAAM,SAAS,WAAW,EAAE,IAAI;AAChC,UAAM,WAAW,oBAAoB,QAAQ,EAAE,YAAY;AAC3D,WACE;AAAA,MAAC;AAAA;AAAA,QAEC,WAAW;AAAA,UACT;AAAA,UACA,YAAY;AAAA,QACd;AAAA,QAEA;AAAA;AAAA,YAAC;AAAA;AAAA,cACC,WAAU;AAAA,cACV,OAAO,SAAS,EAAE,OAAO,OAAO,IAAI;AAAA,cAEnC,YAAE;AAAA;AAAA,UACL;AAAA,UACA,qBAAC,UAAK,WAAU,+CACb;AAAA,4BAAgB,cAAc,EAAE,OAAO,IAAI,eAAe,EAAE,OAAO;AAAA,YACnE,YAAY,oBAAC,UAAK,WAAU,wCAAuC,mBAAK;AAAA,aAC3E;AAAA,UACA,oBAAC,cAAW,OAAO,EAAE,cAAc,MAAM,EAAE,kBAAkB,YAAY,EAAE,YAAY,MAAK,MAAK,WAAU,yBAAwB;AAAA,UACnI,qBAAC,UAAK,WAAU,+CAA+C;AAAA,cAAE,QAAQ,eAAe;AAAA,YAAE;AAAA,aAAG;AAAA;AAAA;AAAA,MAjBxF,EAAE;AAAA,IAkBT;AAAA,EAEJ,CAAC,GACH;AAEJ;AAYO,SAAS,kBAAkB,EAAE,SAAS,QAAQ,gBAAgB,MAAM,eAAe,UAAU,GAA2B;AAC7H,MAAI,QAAQ,WAAW,EAAG,QAAO;AACjC,SACE,qBAAC,aAAQ,WAAW,GAAG,sDAAsD,SAAS,GACpF;AAAA,yBAAC,SAAI,WAAU,0CACb;AAAA,0BAAC,QAAG,WAAU,wBAAwB,iBAAM;AAAA,MAC3C,QACC,oBAAC,OAAE,MAAY,WAAU,iEAAgE,qCAEzF;AAAA,OAEJ;AAAA,IACA,oBAAC,QAAG,WAAU,eACX,kBAAQ,IAAI,CAAC,MACZ,qBAAC,QAAmB,WAAU,6BAC5B;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,WAAU;AAAA,UACV,OAAO,WAAW,EAAE,IAAI,IAAI,EAAE,OAAO,WAAW,EAAE,IAAI,EAAG,IAAI;AAAA,UAE5D,YAAE;AAAA;AAAA,MACL;AAAA,MACA,oBAAC,UAAK,WAAU,+CACb,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,SAV1F,EAAE,OAWX,CACD,GACH;AAAA,KACF;AAEJ;","names":[]}
|
|
@@ -0,0 +1,60 @@
|
|
|
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_badge_exports = {};
|
|
20
|
+
__export(level_badge_exports, {
|
|
21
|
+
LevelBadge: () => LevelBadge
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(level_badge_exports);
|
|
24
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
25
|
+
var import_cn = require("../../utils/cn.js");
|
|
26
|
+
function LevelBadge({ level, name, badgeColor, size = "md", className }) {
|
|
27
|
+
const sizeClasses = {
|
|
28
|
+
sm: "h-5 px-1.5 gap-1 text-[10px]",
|
|
29
|
+
md: "h-6 px-2 gap-1.5 text-xs",
|
|
30
|
+
lg: "h-8 px-3 gap-2 text-sm"
|
|
31
|
+
};
|
|
32
|
+
const dotSizes = {
|
|
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)(
|
|
38
|
+
"span",
|
|
39
|
+
{
|
|
40
|
+
className: (0, import_cn.cn)(
|
|
41
|
+
"inline-flex items-center rounded-full border font-semibold tracking-tight whitespace-nowrap",
|
|
42
|
+
sizeClasses[size],
|
|
43
|
+
className
|
|
44
|
+
),
|
|
45
|
+
style: { borderColor: `${badgeColor}60`, backgroundColor: `${badgeColor}18`, color: badgeColor },
|
|
46
|
+
children: [
|
|
47
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: (0, import_cn.cn)("rounded-full shrink-0", dotSizes[size]), style: { backgroundColor: badgeColor } }),
|
|
48
|
+
"Lv.",
|
|
49
|
+
level,
|
|
50
|
+
" ",
|
|
51
|
+
name
|
|
52
|
+
]
|
|
53
|
+
}
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
57
|
+
0 && (module.exports = {
|
|
58
|
+
LevelBadge
|
|
59
|
+
});
|
|
60
|
+
//# sourceMappingURL=level-badge.cjs.map
|
|
@@ -0,0 +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/** Color-coded level chip (\"Lv.6 Voyager\"). Pure presentation — the consuming\n * app supplies level data from the rewards API. */\nexport function LevelBadge({ level, name, badgeColor, size = \"md\", className }: LevelBadgeProps) {\n const sizeClasses = {\n sm: \"h-5 px-1.5 gap-1 text-[10px]\",\n md: \"h-6 px-2 gap-1.5 text-xs\",\n lg: \"h-8 px-3 gap-2 text-sm\",\n };\n\n const dotSizes = {\n sm: \"h-1.5 w-1.5\",\n md: \"h-2 w-2\",\n lg: \"h-2.5 w-2.5\",\n };\n\n return (\n <span\n className={cn(\n \"inline-flex items-center rounded-full border font-semibold tracking-tight whitespace-nowrap\",\n sizeClasses[size],\n className\n )}\n style={{ borderColor: `${badgeColor}60`, backgroundColor: `${badgeColor}18`, color: badgeColor }}\n >\n <span className={cn(\"rounded-full shrink-0\", dotSizes[size])} style={{ backgroundColor: badgeColor }} />\n Lv.{level} {name}\n </span>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA0BI;AA1BJ,gBAAmB;AAYZ,SAAS,WAAW,EAAE,OAAO,MAAM,YAAY,OAAO,MAAM,UAAU,GAAoB;AAC/F,QAAM,cAAc;AAAA,IAClB,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,EACN;AAEA,QAAM,WAAW;AAAA,IACf,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,EACN;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,eAAW;AAAA,QACT;AAAA,QACA,YAAY,IAAI;AAAA,QAChB;AAAA,MACF;AAAA,MACA,OAAO,EAAE,aAAa,GAAG,UAAU,MAAM,iBAAiB,GAAG,UAAU,MAAM,OAAO,WAAW;AAAA,MAE/F;AAAA,oDAAC,UAAK,eAAW,cAAG,yBAAyB,SAAS,IAAI,CAAC,GAAG,OAAO,EAAE,iBAAiB,WAAW,GAAG;AAAA,QAAE;AAAA,QACpG;AAAA,QAAM;AAAA,QAAE;AAAA;AAAA;AAAA,EACd;AAEJ;","names":[]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
interface LevelBadgeProps {
|
|
4
|
+
level: number;
|
|
5
|
+
name: string;
|
|
6
|
+
badgeColor: string;
|
|
7
|
+
size?: "sm" | "md" | "lg";
|
|
8
|
+
className?: string;
|
|
9
|
+
}
|
|
10
|
+
/** Color-coded level chip ("Lv.6 Voyager"). Pure presentation — the consuming
|
|
11
|
+
* app supplies level data from the rewards API. */
|
|
12
|
+
declare function LevelBadge({ level, name, badgeColor, size, className }: LevelBadgeProps): react_jsx_runtime.JSX.Element;
|
|
13
|
+
|
|
14
|
+
export { LevelBadge, type LevelBadgeProps };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
interface LevelBadgeProps {
|
|
4
|
+
level: number;
|
|
5
|
+
name: string;
|
|
6
|
+
badgeColor: string;
|
|
7
|
+
size?: "sm" | "md" | "lg";
|
|
8
|
+
className?: string;
|
|
9
|
+
}
|
|
10
|
+
/** Color-coded level chip ("Lv.6 Voyager"). Pure presentation — the consuming
|
|
11
|
+
* app supplies level data from the rewards API. */
|
|
12
|
+
declare function LevelBadge({ level, name, badgeColor, size, className }: LevelBadgeProps): react_jsx_runtime.JSX.Element;
|
|
13
|
+
|
|
14
|
+
export { LevelBadge, type LevelBadgeProps };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../../utils/cn.js";
|
|
3
|
+
function LevelBadge({ level, name, badgeColor, size = "md", className }) {
|
|
4
|
+
const sizeClasses = {
|
|
5
|
+
sm: "h-5 px-1.5 gap-1 text-[10px]",
|
|
6
|
+
md: "h-6 px-2 gap-1.5 text-xs",
|
|
7
|
+
lg: "h-8 px-3 gap-2 text-sm"
|
|
8
|
+
};
|
|
9
|
+
const dotSizes = {
|
|
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(
|
|
15
|
+
"span",
|
|
16
|
+
{
|
|
17
|
+
className: cn(
|
|
18
|
+
"inline-flex items-center rounded-full border font-semibold tracking-tight whitespace-nowrap",
|
|
19
|
+
sizeClasses[size],
|
|
20
|
+
className
|
|
21
|
+
),
|
|
22
|
+
style: { borderColor: `${badgeColor}60`, backgroundColor: `${badgeColor}18`, color: badgeColor },
|
|
23
|
+
children: [
|
|
24
|
+
/* @__PURE__ */ jsx("span", { className: cn("rounded-full shrink-0", dotSizes[size]), style: { backgroundColor: badgeColor } }),
|
|
25
|
+
"Lv.",
|
|
26
|
+
level,
|
|
27
|
+
" ",
|
|
28
|
+
name
|
|
29
|
+
]
|
|
30
|
+
}
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
export {
|
|
34
|
+
LevelBadge
|
|
35
|
+
};
|
|
36
|
+
//# sourceMappingURL=level-badge.js.map
|
|
@@ -0,0 +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/** Color-coded level chip (\"Lv.6 Voyager\"). Pure presentation — the consuming\n * app supplies level data from the rewards API. */\nexport function LevelBadge({ level, name, badgeColor, size = \"md\", className }: LevelBadgeProps) {\n const sizeClasses = {\n sm: \"h-5 px-1.5 gap-1 text-[10px]\",\n md: \"h-6 px-2 gap-1.5 text-xs\",\n lg: \"h-8 px-3 gap-2 text-sm\",\n };\n\n const dotSizes = {\n sm: \"h-1.5 w-1.5\",\n md: \"h-2 w-2\",\n lg: \"h-2.5 w-2.5\",\n };\n\n return (\n <span\n className={cn(\n \"inline-flex items-center rounded-full border font-semibold tracking-tight whitespace-nowrap\",\n sizeClasses[size],\n className\n )}\n style={{ borderColor: `${badgeColor}60`, backgroundColor: `${badgeColor}18`, color: badgeColor }}\n >\n <span className={cn(\"rounded-full shrink-0\", dotSizes[size])} style={{ backgroundColor: badgeColor }} />\n Lv.{level} {name}\n </span>\n );\n}\n"],"mappings":"AA0BI,SAQE,KARF;AA1BJ,SAAS,UAAU;AAYZ,SAAS,WAAW,EAAE,OAAO,MAAM,YAAY,OAAO,MAAM,UAAU,GAAoB;AAC/F,QAAM,cAAc;AAAA,IAClB,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,EACN;AAEA,QAAM,WAAW;AAAA,IACf,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,EACN;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW;AAAA,QACT;AAAA,QACA,YAAY,IAAI;AAAA,QAChB;AAAA,MACF;AAAA,MACA,OAAO,EAAE,aAAa,GAAG,UAAU,MAAM,iBAAiB,GAAG,UAAU,MAAM,OAAO,WAAW;AAAA,MAE/F;AAAA,4BAAC,UAAK,WAAW,GAAG,yBAAyB,SAAS,IAAI,CAAC,GAAG,OAAO,EAAE,iBAAiB,WAAW,GAAG;AAAA,QAAE;AAAA,QACpG;AAAA,QAAM;AAAA,QAAE;AAAA;AAAA;AAAA,EACd;AAEJ;","names":[]}
|