@oddsmith/ui 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eleventy.cjs +14 -0
- package/LICENSE +28 -0
- package/README.md +118 -0
- package/custom-elements.json +1539 -0
- package/docs/_README/index.html +4 -0
- package/docs/api/index.html +2100 -0
- package/docs/components.bundle.js +1669 -0
- package/docs/components.bundle.js.map +1 -0
- package/docs/docs.css +162 -0
- package/docs/examples/index.html +56 -0
- package/docs/index.html +53 -0
- package/docs/install/index.html +45 -0
- package/docs/prism-okaidia.css +123 -0
- package/docs-src/.nojekyll +0 -0
- package/docs-src/_README.md +7 -0
- package/docs-src/_data/api.11tydata.js +8 -0
- package/docs-src/_includes/example.11ty.js +35 -0
- package/docs-src/_includes/footer.11ty.js +6 -0
- package/docs-src/_includes/header.11ty.js +7 -0
- package/docs-src/_includes/nav.11ty.js +11 -0
- package/docs-src/_includes/page.11ty.js +32 -0
- package/docs-src/_includes/relative-path.cjs +9 -0
- package/docs-src/api.11ty.js +85 -0
- package/docs-src/bundle.ts +9 -0
- package/docs-src/docs.css +162 -0
- package/docs-src/examples/index.md +15 -0
- package/docs-src/index.md +39 -0
- package/docs-src/install.md +28 -0
- package/docs-src/package.json +3 -0
- package/index.html +19 -0
- package/karma.conf.cjs +24 -0
- package/main.css +210 -0
- package/main.ts +124 -0
- package/package.json +86 -0
- package/previews/casino.ts +12 -0
- package/previews/catalog.ts +94 -0
- package/previews/leaderboard-v1.ts +12 -0
- package/previews/leaderboard-v2.ts +17 -0
- package/previews/sample-data.ts +101 -0
- package/previews/sf-leaderboard.ts +100 -0
- package/previews/sf-live-feed.ts +15 -0
- package/previews/streaks.ts +40 -0
- package/previews/types.ts +18 -0
- package/src/components/README.md +16 -0
- package/src/components/casino-leaderboard/casino-leaderboard.html +80 -0
- package/src/components/casino-leaderboard/casino-leaderboard.scss +585 -0
- package/src/components/casino-leaderboard/casino-leaderboard.ts +136 -0
- package/src/components/casino-leaderboard/data.ts +111 -0
- package/src/components/casino-leaderboard/index.ts +5 -0
- package/src/components/casino-leaderboard/todo.txt +2 -0
- package/src/components/casino-leaderboard/types.ts +19 -0
- package/src/components/leaderboard/components/leaderboard.ts +373 -0
- package/src/components/leaderboard/components/player-card.ts +342 -0
- package/src/components/leaderboard/components/ui.ts +452 -0
- package/src/components/leaderboard/data.ts +152 -0
- package/src/components/leaderboard/index.ts +2 -0
- package/src/components/leaderboard/main.ts +42 -0
- package/src/components/leaderboard/styles.ts +67 -0
- package/src/components/leaderboard/types.ts +28 -0
- package/src/components/leaderboard-v2/components/sf-leaderboard-player.ts +451 -0
- package/src/components/leaderboard-v2/components/sf-leaderboard-ui.ts +512 -0
- package/src/components/leaderboard-v2/components/sf-leaderboard.ts +205 -0
- package/src/components/leaderboard-v2/constants.ts +16 -0
- package/src/components/leaderboard-v2/demo/sample-data.ts +152 -0
- package/src/components/leaderboard-v2/events.ts +13 -0
- package/src/components/leaderboard-v2/icons.ts +22 -0
- package/src/components/leaderboard-v2/index.ts +23 -0
- package/src/components/leaderboard-v2/sf-leaderboard.html +1 -0
- package/src/components/leaderboard-v2/sf-leaderboard.scss +382 -0
- package/src/components/leaderboard-v2/tokens.ts +35 -0
- package/src/components/leaderboard-v2/types.ts +30 -0
- package/src/components/sf-leaderboard/index.ts +77 -0
- package/src/components/sf-leaderboard/sections/footer-section/footer-section.host.ts +3 -0
- package/src/components/sf-leaderboard/sections/footer-section/footer-section.html +3 -0
- package/src/components/sf-leaderboard/sections/footer-section/footer-section.scss +18 -0
- package/src/components/sf-leaderboard/sections/footer-section/footer-section.ts +22 -0
- package/src/components/sf-leaderboard/sections/header-section/header-section.host.ts +14 -0
- package/src/components/sf-leaderboard/sections/header-section/header-section.html +27 -0
- package/src/components/sf-leaderboard/sections/header-section/header-section.scss +189 -0
- package/src/components/sf-leaderboard/sections/header-section/header-section.ts +70 -0
- package/src/components/sf-leaderboard/sections/ranking-section/ranking-section.host.ts +22 -0
- package/src/components/sf-leaderboard/sections/ranking-section/ranking-section.html +38 -0
- package/src/components/sf-leaderboard/sections/ranking-section/ranking-section.scss +99 -0
- package/src/components/sf-leaderboard/sections/ranking-section/ranking-section.ts +121 -0
- package/src/components/sf-leaderboard/sections/stats-section/stats-section.host.ts +8 -0
- package/src/components/sf-leaderboard/sections/stats-section/stats-section.html +6 -0
- package/src/components/sf-leaderboard/sections/stats-section/stats-section.scss +44 -0
- package/src/components/sf-leaderboard/sections/stats-section/stats-section.ts +41 -0
- package/src/components/sf-leaderboard/sections/table-section/table-section.host.ts +17 -0
- package/src/components/sf-leaderboard/sections/table-section/table-section.html +19 -0
- package/src/components/sf-leaderboard/sections/table-section/table-section.scss +37 -0
- package/src/components/sf-leaderboard/sections/table-section/table-section.ts +108 -0
- package/src/components/sf-leaderboard/services/index.ts +22 -0
- package/src/components/sf-leaderboard/services/sf-leaderboard-data.service.ts +54 -0
- package/src/components/sf-leaderboard/services/sf-leaderboard.state.ts +160 -0
- package/src/components/sf-leaderboard/shared/components/activity-feed/activity-feed.host.ts +7 -0
- package/src/components/sf-leaderboard/shared/components/activity-feed/activity-feed.html +10 -0
- package/src/components/sf-leaderboard/shared/components/activity-feed/activity-feed.scss +180 -0
- package/src/components/sf-leaderboard/shared/components/activity-feed/activity-feed.ts +88 -0
- package/src/components/sf-leaderboard/shared/components/filters/filters.host.ts +12 -0
- package/src/components/sf-leaderboard/shared/components/filters/filters.html +22 -0
- package/src/components/sf-leaderboard/shared/components/filters/filters.scss +122 -0
- package/src/components/sf-leaderboard/shared/components/filters/filters.ts +75 -0
- package/src/components/sf-leaderboard/shared/components/player-avatar/player-avatar.host.ts +9 -0
- package/src/components/sf-leaderboard/shared/components/player-avatar/player-avatar.html +5 -0
- package/src/components/sf-leaderboard/shared/components/player-avatar/player-avatar.scss +81 -0
- package/src/components/sf-leaderboard/shared/components/player-avatar/player-avatar.ts +34 -0
- package/src/components/sf-leaderboard/shared/components/podium/map-players.ts +24 -0
- package/src/components/sf-leaderboard/shared/components/podium/podium.host.ts +10 -0
- package/src/components/sf-leaderboard/shared/components/podium/podium.html +53 -0
- package/src/components/sf-leaderboard/shared/components/podium/podium.scss +580 -0
- package/src/components/sf-leaderboard/shared/components/podium/podium.ts +49 -0
- package/src/components/sf-leaderboard/shared/components/podium/podium.types.ts +9 -0
- package/src/components/sf-leaderboard/shared/components/rank-badge/rank-badge.host.ts +11 -0
- package/src/components/sf-leaderboard/shared/components/rank-badge/rank-badge.html +9 -0
- package/src/components/sf-leaderboard/shared/components/rank-badge/rank-badge.scss +98 -0
- package/src/components/sf-leaderboard/shared/components/rank-badge/rank-badge.ts +63 -0
- package/src/components/sf-leaderboard/shared/components/stat-card/stat-card.host.ts +9 -0
- package/src/components/sf-leaderboard/shared/components/stat-card/stat-card.html +15 -0
- package/src/components/sf-leaderboard/shared/components/stat-card/stat-card.scss +210 -0
- package/src/components/sf-leaderboard/shared/components/stat-card/stat-card.ts +36 -0
- package/src/components/sf-leaderboard/shared/components/table/table.host.ts +5 -0
- package/src/components/sf-leaderboard/shared/components/table/table.html +11 -0
- package/src/components/sf-leaderboard/shared/components/table/table.scss +212 -0
- package/src/components/sf-leaderboard/shared/components/table/table.ts +111 -0
- package/src/components/sf-leaderboard/shared/constants/defaults.ts +7 -0
- package/src/components/sf-leaderboard/shared/constants/filters.ts +16 -0
- package/src/components/sf-leaderboard/shared/constants/index.ts +5 -0
- package/src/components/sf-leaderboard/shared/constants/player-stats.ts +3 -0
- package/src/components/sf-leaderboard/shared/constants/stats-overview.ts +38 -0
- package/src/components/sf-leaderboard/shared/constants/tags.ts +16 -0
- package/src/components/sf-leaderboard/shared/styles/_section.scss +35 -0
- package/src/components/sf-leaderboard/shared/types/data.ts +29 -0
- package/src/components/sf-leaderboard/shared/types/events.ts +30 -0
- package/src/components/sf-leaderboard/shared/types/player-stats.ts +3 -0
- package/src/components/sf-leaderboard/shared/types/sections.ts +100 -0
- package/src/components/sf-leaderboard/shared/utils/utils.ts +17 -0
- package/src/components/sf-leaderboard/theme/THEMING.md +54 -0
- package/src/components/sf-leaderboard/theme/context.ts +16 -0
- package/src/components/sf-leaderboard/theme/default-theme.ts +4 -0
- package/src/components/sf-leaderboard/theme/hex-to-rgb.ts +25 -0
- package/src/components/sf-leaderboard/theme/index.ts +18 -0
- package/src/components/sf-leaderboard/theme/inject-theme.ts +39 -0
- package/src/components/sf-leaderboard/theme/load-theme.ts +26 -0
- package/src/components/sf-leaderboard/theme/merge-theme.ts +59 -0
- package/src/components/sf-leaderboard/theme/scss/_colors.scss +101 -0
- package/src/components/sf-leaderboard/theme/scss/shared.scss +123 -0
- package/src/components/sf-leaderboard/theme/styles.ts +6 -0
- package/src/components/sf-leaderboard/theme/theme-to-css-vars.ts +99 -0
- package/src/components/sf-leaderboard/theme/themes/fallback.json +62 -0
- package/src/components/sf-leaderboard/theme/themes/red.json +62 -0
- package/src/components/sf-leaderboard/theme/types.ts +71 -0
- package/src/components/sf-live-feed/components/avatar/avatar.host.ts +5 -0
- package/src/components/sf-live-feed/components/avatar/avatar.html +3 -0
- package/src/components/sf-live-feed/components/avatar/avatar.scss +24 -0
- package/src/components/sf-live-feed/components/avatar/avatar.ts +27 -0
- package/src/components/sf-live-feed/components/sf-live-feed/sf-live-feed.host.ts +8 -0
- package/src/components/sf-live-feed/components/sf-live-feed/sf-live-feed.html +10 -0
- package/src/components/sf-live-feed/components/sf-live-feed/sf-live-feed.scss +177 -0
- package/src/components/sf-live-feed/components/sf-live-feed/sf-live-feed.ts +65 -0
- package/src/components/sf-live-feed/constants.ts +4 -0
- package/src/components/sf-live-feed/demo/sample-data.ts +34 -0
- package/src/components/sf-live-feed/index.ts +19 -0
- package/src/components/sf-live-feed/styles/theme.scss +19 -0
- package/src/components/sf-live-feed/styles/theme.ts +5 -0
- package/src/components/sf-live-feed/types.ts +19 -0
- package/src/components/sf-live-feed/utils.ts +17 -0
- package/src/components/streaks/constants.ts +17 -0
- package/src/components/streaks/demo/sample-steps.ts +10 -0
- package/src/components/streaks/events.ts +8 -0
- package/src/components/streaks/index.ts +16 -0
- package/src/components/streaks/sf-streaks.html +26 -0
- package/src/components/streaks/sf-streaks.scss +351 -0
- package/src/components/streaks/sf-streaks.ts +235 -0
- package/src/components/streaks/types.ts +7 -0
- package/src/lib/lit/component.ts +10 -0
- package/src/lib/lit/safe-custom-element.ts +12 -0
- package/src/lib/lit/scss.ts +6 -0
- package/src/vite-env.d.ts +18 -0
- package/styles/global.css +125 -0
- package/todo.txt +54 -0
- package/tsconfig.json +31 -0
- package/vite.config.ts +56 -0
- package/vite.docs.config.ts +33 -0
- package/vite.lit-html-plugin.ts +43 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { LbPlayer, LbStats } from './types.js';
|
|
2
|
+
|
|
3
|
+
export const SF_LEADERBOARD_TAG = 'sf-leaderboard';
|
|
4
|
+
|
|
5
|
+
export const DEFAULT_LB_TITLE = 'ARENA RANKINGS';
|
|
6
|
+
export const DEFAULT_LB_SUBTITLE = 'Climb the grid. Claim the crown.';
|
|
7
|
+
|
|
8
|
+
export const DEFAULT_LB_STATS: LbStats = {
|
|
9
|
+
totalPlayers: 12847,
|
|
10
|
+
yourRank: 156,
|
|
11
|
+
topScore: 2847500,
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
/** Empty defaults — use demo data or set via properties. */
|
|
15
|
+
export const DEFAULT_LB_PLAYERS: LbPlayer[] = [];
|
|
16
|
+
export const DEFAULT_LB_CURRENT_USER: LbPlayer | undefined = undefined;
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { LbPlayer, LbBadge, LbStats } from '../types.js';
|
|
2
|
+
|
|
3
|
+
export const badges: LbBadge[] = [
|
|
4
|
+
{ id: '1', name: 'First Win', icon: 'trophy', rarity: 'common' },
|
|
5
|
+
{ id: '2', name: 'Streak Master', icon: 'flame', rarity: 'rare' },
|
|
6
|
+
{ id: '3', name: 'Top 10', icon: 'star', rarity: 'epic' },
|
|
7
|
+
{ id: '4', name: 'Legend', icon: 'crown', rarity: 'legendary' },
|
|
8
|
+
{ id: '5', name: 'Speed Demon', icon: 'zap', rarity: 'rare' },
|
|
9
|
+
{ id: '6', name: 'Perfectionist', icon: 'gem', rarity: 'epic' },
|
|
10
|
+
];
|
|
11
|
+
|
|
12
|
+
export const players: LbPlayer[] = [
|
|
13
|
+
{
|
|
14
|
+
id: '1',
|
|
15
|
+
rank: 1,
|
|
16
|
+
username: 'ShadowNinja',
|
|
17
|
+
avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=shadow',
|
|
18
|
+
level: 99,
|
|
19
|
+
xp: 45000,
|
|
20
|
+
xpToNextLevel: 50000,
|
|
21
|
+
score: 2847500,
|
|
22
|
+
wins: 342,
|
|
23
|
+
streak: 15,
|
|
24
|
+
badges: [badges[3], badges[2], badges[5]],
|
|
25
|
+
trend: 'same',
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
id: '2',
|
|
29
|
+
rank: 2,
|
|
30
|
+
username: 'CyberPhoenix',
|
|
31
|
+
avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=phoenix',
|
|
32
|
+
level: 95,
|
|
33
|
+
xp: 38000,
|
|
34
|
+
xpToNextLevel: 45000,
|
|
35
|
+
score: 2654200,
|
|
36
|
+
wins: 298,
|
|
37
|
+
streak: 8,
|
|
38
|
+
badges: [badges[2], badges[1], badges[4]],
|
|
39
|
+
trend: 'up',
|
|
40
|
+
rankChange: 2,
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
id: '3',
|
|
44
|
+
rank: 3,
|
|
45
|
+
username: 'NeonBlade',
|
|
46
|
+
avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=blade',
|
|
47
|
+
level: 92,
|
|
48
|
+
xp: 41000,
|
|
49
|
+
xpToNextLevel: 44000,
|
|
50
|
+
score: 2501800,
|
|
51
|
+
wins: 276,
|
|
52
|
+
streak: 5,
|
|
53
|
+
badges: [badges[2], badges[0], badges[1]],
|
|
54
|
+
trend: 'down',
|
|
55
|
+
rankChange: 1,
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
id: '4',
|
|
59
|
+
rank: 4,
|
|
60
|
+
username: 'StormWatcher',
|
|
61
|
+
avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=storm',
|
|
62
|
+
level: 88,
|
|
63
|
+
xp: 22000,
|
|
64
|
+
xpToNextLevel: 42000,
|
|
65
|
+
score: 2234500,
|
|
66
|
+
wins: 245,
|
|
67
|
+
streak: 12,
|
|
68
|
+
badges: [badges[1], badges[4]],
|
|
69
|
+
trend: 'up',
|
|
70
|
+
rankChange: 3,
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
id: '5',
|
|
74
|
+
rank: 5,
|
|
75
|
+
username: 'VoidRunner',
|
|
76
|
+
avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=void',
|
|
77
|
+
level: 85,
|
|
78
|
+
xp: 35000,
|
|
79
|
+
xpToNextLevel: 40000,
|
|
80
|
+
score: 2087300,
|
|
81
|
+
wins: 218,
|
|
82
|
+
streak: 3,
|
|
83
|
+
badges: [badges[0], badges[5]],
|
|
84
|
+
trend: 'same',
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
id: '6',
|
|
88
|
+
rank: 6,
|
|
89
|
+
username: 'PixelHunter',
|
|
90
|
+
avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=pixel',
|
|
91
|
+
level: 82,
|
|
92
|
+
xp: 18000,
|
|
93
|
+
xpToNextLevel: 38000,
|
|
94
|
+
score: 1956700,
|
|
95
|
+
wins: 195,
|
|
96
|
+
streak: 7,
|
|
97
|
+
badges: [badges[1], badges[0]],
|
|
98
|
+
trend: 'up',
|
|
99
|
+
rankChange: 1,
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
id: '7',
|
|
103
|
+
rank: 7,
|
|
104
|
+
username: 'GhostCoder',
|
|
105
|
+
avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=ghost',
|
|
106
|
+
level: 79,
|
|
107
|
+
xp: 28000,
|
|
108
|
+
xpToNextLevel: 36000,
|
|
109
|
+
score: 1823400,
|
|
110
|
+
wins: 178,
|
|
111
|
+
streak: 2,
|
|
112
|
+
badges: [badges[4], badges[0]],
|
|
113
|
+
trend: 'down',
|
|
114
|
+
rankChange: 2,
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
id: '8',
|
|
118
|
+
rank: 8,
|
|
119
|
+
username: 'ThunderFist',
|
|
120
|
+
avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=thunder',
|
|
121
|
+
level: 76,
|
|
122
|
+
xp: 12000,
|
|
123
|
+
xpToNextLevel: 34000,
|
|
124
|
+
score: 1678900,
|
|
125
|
+
wins: 156,
|
|
126
|
+
streak: 4,
|
|
127
|
+
badges: [badges[0]],
|
|
128
|
+
trend: 'same',
|
|
129
|
+
},
|
|
130
|
+
];
|
|
131
|
+
|
|
132
|
+
export const stats: LbStats = {
|
|
133
|
+
totalPlayers: 12847,
|
|
134
|
+
yourRank: 156,
|
|
135
|
+
topScore: 2847500,
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
export const currentUser: LbPlayer = {
|
|
139
|
+
id: 'current',
|
|
140
|
+
rank: 156,
|
|
141
|
+
username: 'YourLbPlayer',
|
|
142
|
+
avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=current',
|
|
143
|
+
level: 45,
|
|
144
|
+
xp: 12500,
|
|
145
|
+
xpToNextLevel: 20000,
|
|
146
|
+
score: 456780,
|
|
147
|
+
wins: 42,
|
|
148
|
+
streak: 3,
|
|
149
|
+
badges: [badges[0], badges[1]],
|
|
150
|
+
trend: 'up',
|
|
151
|
+
rankChange: 12,
|
|
152
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { LbPlayer, LbTabId } from './types.js';
|
|
2
|
+
|
|
3
|
+
export const LB_TAB_CHANGE = 'tab-change';
|
|
4
|
+
export const LB_PLAYER_SELECT = 'player-select';
|
|
5
|
+
export const LB_LOAD_MORE = 'load-more';
|
|
6
|
+
|
|
7
|
+
export interface LbTabChangeDetail {
|
|
8
|
+
tab: LbTabId;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface LbPlayerSelectDetail {
|
|
12
|
+
player: LbPlayer;
|
|
13
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export const icons = {
|
|
2
|
+
trophy: `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M6 9H4.5a2.5 2.5 0 0 1 0-5H6"/><path d="M18 9h1.5a2.5 2.5 0 0 0 0-5H18"/><path d="M4 22h16"/><path d="M10 14.66V17c0 .55-.47.98-.97 1.21C7.85 18.75 7 20.24 7 22"/><path d="M14 14.66V17c0 .55.47.98.97 1.21C16.15 18.75 17 20.24 17 22"/><path d="M18 2H6v7a6 6 0 0 0 12 0V2Z"/></svg>`,
|
|
3
|
+
crown: `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M11.562 3.266a.5.5 0 0 1 .876 0L15.39 8.87a1 1 0 0 0 1.516.294L21.183 5.5a.5.5 0 0 1 .798.519l-2.834 10.246a1 1 0 0 1-.956.734H5.81a1 1 0 0 1-.957-.734L2.02 6.02a.5.5 0 0 1 .798-.519l4.276 3.664a1 1 0 0 0 1.516-.294z"/><path d="M5 21h14"/></svg>`,
|
|
4
|
+
flame: `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M8.5 14.5A2.5 2.5 0 0 0 11 12c0-1.38-.5-2-1-3-1.072-2.143-.224-4.054 2-6 .5 2.5 2 4.9 4 6.5 2 1.6 3 3.5 3 5.5a7 7 0 1 1-14 0c0-1.153.433-2.294 1-3a2.5 2.5 0 0 0 2.5 2.5z"/></svg>`,
|
|
5
|
+
star: `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z"/></svg>`,
|
|
6
|
+
zap: `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z"/></svg>`,
|
|
7
|
+
gem: `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M6 3h12l4 6-10 13L2 9Z"/><path d="M11 3 8 9l4 13 4-13-3-6"/><path d="M2 9h20"/></svg>`,
|
|
8
|
+
users: `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>`,
|
|
9
|
+
target: `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><circle cx="12" cy="12" r="6"/><circle cx="12" cy="12" r="2"/></svg>`,
|
|
10
|
+
trendingUp: `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="22 7 13.5 15.5 8.5 10.5 2 17"/><polyline points="16 7 22 7 22 13"/></svg>`,
|
|
11
|
+
trendingDown: `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="22 17 13.5 8.5 8.5 13.5 2 7"/><polyline points="16 17 22 17 22 11"/></svg>`,
|
|
12
|
+
minus: `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M5 12h14"/></svg>`,
|
|
13
|
+
} as const;
|
|
14
|
+
|
|
15
|
+
export type LbIconName = keyof typeof icons;
|
|
16
|
+
|
|
17
|
+
export function getIcon(name: LbIconName, size = 16): string {
|
|
18
|
+
const icon = icons[name] || '';
|
|
19
|
+
return icon
|
|
20
|
+
.replace(/width="\d+"/, `width="${size}"`)
|
|
21
|
+
.replace(/height="\d+"/, `height="${size}"`);
|
|
22
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Leaderboard v2 — public API.
|
|
3
|
+
* Import: `import '@skinforge/leaderboard-v2'`
|
|
4
|
+
*/
|
|
5
|
+
export type { LbPlayer, LbBadge, LbStats, LbTabId } from './types.js';
|
|
6
|
+
export {
|
|
7
|
+
SF_LEADERBOARD_TAG,
|
|
8
|
+
DEFAULT_LB_TITLE,
|
|
9
|
+
DEFAULT_LB_SUBTITLE,
|
|
10
|
+
DEFAULT_LB_STATS,
|
|
11
|
+
} from './constants.js';
|
|
12
|
+
export {
|
|
13
|
+
LB_TAB_CHANGE,
|
|
14
|
+
LB_PLAYER_SELECT,
|
|
15
|
+
LB_LOAD_MORE,
|
|
16
|
+
} from './events.js';
|
|
17
|
+
export type {
|
|
18
|
+
LbTabChangeDetail,
|
|
19
|
+
LbPlayerSelectDetail,
|
|
20
|
+
} from './events.js';
|
|
21
|
+
export { SfLeaderboard } from './components/sf-leaderboard.js';
|
|
22
|
+
|
|
23
|
+
import './components/sf-leaderboard.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
${this.renderContent()}
|
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
:host {
|
|
2
|
+
display: block;
|
|
3
|
+
width: 100%;
|
|
4
|
+
max-width: 920px;
|
|
5
|
+
margin: 0 auto;
|
|
6
|
+
position: relative;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.shell {
|
|
10
|
+
position: relative;
|
|
11
|
+
padding: 2rem 1.5rem 2.5rem;
|
|
12
|
+
border-radius: 24px;
|
|
13
|
+
background: linear-gradient(
|
|
14
|
+
160deg,
|
|
15
|
+
rgba(8, 10, 24, 0.98) 0%,
|
|
16
|
+
rgba(5, 5, 16, 0.99) 50%,
|
|
17
|
+
rgba(12, 8, 32, 0.98) 100%
|
|
18
|
+
);
|
|
19
|
+
border: 1px solid var(--lb-border);
|
|
20
|
+
box-shadow:
|
|
21
|
+
var(--lb-glow-cyan),
|
|
22
|
+
inset 0 1px 0 rgba(255, 255, 255, 0.06);
|
|
23
|
+
overflow: hidden;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.shell::before {
|
|
27
|
+
content: '';
|
|
28
|
+
position: absolute;
|
|
29
|
+
inset: 0;
|
|
30
|
+
background-image:
|
|
31
|
+
linear-gradient(rgba(0, 245, 255, 0.03) 1px, transparent 1px),
|
|
32
|
+
linear-gradient(90deg, rgba(0, 245, 255, 0.03) 1px, transparent 1px);
|
|
33
|
+
background-size: 32px 32px;
|
|
34
|
+
pointer-events: none;
|
|
35
|
+
mask-image: linear-gradient(180deg, black 0%, transparent 85%);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.shell::after {
|
|
39
|
+
content: '';
|
|
40
|
+
position: absolute;
|
|
41
|
+
top: -40%;
|
|
42
|
+
left: -20%;
|
|
43
|
+
width: 60%;
|
|
44
|
+
height: 60%;
|
|
45
|
+
background: radial-gradient(
|
|
46
|
+
circle,
|
|
47
|
+
rgba(139, 92, 246, 0.2) 0%,
|
|
48
|
+
transparent 70%
|
|
49
|
+
);
|
|
50
|
+
animation: aurora 12s ease-in-out infinite;
|
|
51
|
+
pointer-events: none;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
@keyframes aurora {
|
|
55
|
+
0%, 100% { transform: translate(0, 0) scale(1); opacity: 0.6; }
|
|
56
|
+
50% { transform: translate(20%, 10%) scale(1.1); opacity: 1; }
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.live-badge {
|
|
60
|
+
position: absolute;
|
|
61
|
+
top: 1rem;
|
|
62
|
+
right: 1rem;
|
|
63
|
+
display: flex;
|
|
64
|
+
align-items: center;
|
|
65
|
+
gap: 0.4rem;
|
|
66
|
+
padding: 0.35rem 0.75rem;
|
|
67
|
+
border-radius: 999px;
|
|
68
|
+
font-size: 0.65rem;
|
|
69
|
+
font-weight: 700;
|
|
70
|
+
letter-spacing: 0.12em;
|
|
71
|
+
text-transform: uppercase;
|
|
72
|
+
color: var(--lb-success);
|
|
73
|
+
background: rgba(34, 255, 154, 0.1);
|
|
74
|
+
border: 1px solid rgba(34, 255, 154, 0.35);
|
|
75
|
+
z-index: 2;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.live-dot {
|
|
79
|
+
width: 6px;
|
|
80
|
+
height: 6px;
|
|
81
|
+
border-radius: 50%;
|
|
82
|
+
background: var(--lb-success);
|
|
83
|
+
box-shadow: 0 0 10px var(--lb-success);
|
|
84
|
+
animation: pulse-live 1.5s ease-in-out infinite;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
@keyframes pulse-live {
|
|
88
|
+
0%, 100% { opacity: 1; transform: scale(1); }
|
|
89
|
+
50% { opacity: 0.5; transform: scale(0.85); }
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.header {
|
|
93
|
+
text-align: center;
|
|
94
|
+
margin-bottom: 2rem;
|
|
95
|
+
position: relative;
|
|
96
|
+
z-index: 1;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.title-row {
|
|
100
|
+
display: flex;
|
|
101
|
+
align-items: center;
|
|
102
|
+
justify-content: center;
|
|
103
|
+
gap: 0.75rem;
|
|
104
|
+
margin-bottom: 0.5rem;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.crown-icon {
|
|
108
|
+
color: var(--lb-gold);
|
|
109
|
+
display: flex;
|
|
110
|
+
filter: drop-shadow(0 0 12px rgba(255, 213, 74, 0.6));
|
|
111
|
+
animation: float-crown 3s ease-in-out infinite;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.crown-icon:last-child {
|
|
115
|
+
animation-delay: -1.5s;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
@keyframes float-crown {
|
|
119
|
+
0%, 100% { transform: translateY(0); }
|
|
120
|
+
50% { transform: translateY(-4px); }
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.title {
|
|
124
|
+
font-family: var(--lb-font);
|
|
125
|
+
font-size: clamp(1.5rem, 4vw, 2.25rem);
|
|
126
|
+
font-weight: 900;
|
|
127
|
+
letter-spacing: 0.08em;
|
|
128
|
+
background: linear-gradient(
|
|
129
|
+
90deg,
|
|
130
|
+
var(--lb-cyan) 0%,
|
|
131
|
+
#fff 40%,
|
|
132
|
+
var(--lb-magenta) 100%
|
|
133
|
+
);
|
|
134
|
+
-webkit-background-clip: text;
|
|
135
|
+
-webkit-text-fill-color: transparent;
|
|
136
|
+
background-clip: text;
|
|
137
|
+
text-shadow: 0 0 40px rgba(0, 245, 255, 0.3);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.subtitle {
|
|
141
|
+
font-size: 0.875rem;
|
|
142
|
+
color: var(--lb-muted);
|
|
143
|
+
letter-spacing: 0.2em;
|
|
144
|
+
text-transform: uppercase;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.stats-grid {
|
|
148
|
+
display: grid;
|
|
149
|
+
grid-template-columns: repeat(3, 1fr);
|
|
150
|
+
gap: 0.75rem;
|
|
151
|
+
margin-bottom: 1.75rem;
|
|
152
|
+
position: relative;
|
|
153
|
+
z-index: 1;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
.hero-card {
|
|
157
|
+
margin-bottom: 1.75rem;
|
|
158
|
+
padding: 1.5rem;
|
|
159
|
+
border-radius: var(--lb-radius);
|
|
160
|
+
background: linear-gradient(
|
|
161
|
+
135deg,
|
|
162
|
+
rgba(0, 245, 255, 0.08) 0%,
|
|
163
|
+
rgba(255, 43, 214, 0.06) 100%
|
|
164
|
+
);
|
|
165
|
+
border: 1px solid rgba(0, 245, 255, 0.25);
|
|
166
|
+
box-shadow: var(--lb-glow-cyan);
|
|
167
|
+
position: relative;
|
|
168
|
+
z-index: 1;
|
|
169
|
+
overflow: hidden;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
.hero-card::before {
|
|
173
|
+
content: '';
|
|
174
|
+
position: absolute;
|
|
175
|
+
inset: 0;
|
|
176
|
+
background: linear-gradient(
|
|
177
|
+
90deg,
|
|
178
|
+
transparent,
|
|
179
|
+
rgba(255, 255, 255, 0.04),
|
|
180
|
+
transparent
|
|
181
|
+
);
|
|
182
|
+
animation: scan 4s linear infinite;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
@keyframes scan {
|
|
186
|
+
0% { transform: translateX(-100%); }
|
|
187
|
+
100% { transform: translateX(100%); }
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.hero-header {
|
|
191
|
+
display: flex;
|
|
192
|
+
align-items: center;
|
|
193
|
+
justify-content: space-between;
|
|
194
|
+
margin-bottom: 1rem;
|
|
195
|
+
position: relative;
|
|
196
|
+
z-index: 1;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
.hero-info {
|
|
200
|
+
display: flex;
|
|
201
|
+
align-items: center;
|
|
202
|
+
gap: 1rem;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
.hero-avatar-wrap {
|
|
206
|
+
position: relative;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
.hero-avatar {
|
|
210
|
+
width: 68px;
|
|
211
|
+
height: 68px;
|
|
212
|
+
border-radius: 50%;
|
|
213
|
+
border: 2px solid var(--lb-cyan);
|
|
214
|
+
box-shadow: 0 0 20px rgba(0, 245, 255, 0.4);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
.hero-level {
|
|
218
|
+
position: absolute;
|
|
219
|
+
bottom: -4px;
|
|
220
|
+
right: -4px;
|
|
221
|
+
width: 26px;
|
|
222
|
+
height: 26px;
|
|
223
|
+
border-radius: 50%;
|
|
224
|
+
display: flex;
|
|
225
|
+
align-items: center;
|
|
226
|
+
justify-content: center;
|
|
227
|
+
font-size: 0.7rem;
|
|
228
|
+
font-weight: 800;
|
|
229
|
+
background: linear-gradient(135deg, var(--lb-violet), var(--lb-magenta));
|
|
230
|
+
border: 2px solid var(--lb-bg);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
.hero-name {
|
|
234
|
+
font-family: var(--lb-font);
|
|
235
|
+
font-size: 1.2rem;
|
|
236
|
+
font-weight: 700;
|
|
237
|
+
display: flex;
|
|
238
|
+
align-items: center;
|
|
239
|
+
gap: 0.5rem;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
.you-chip {
|
|
243
|
+
font-size: 0.65rem;
|
|
244
|
+
padding: 3px 8px;
|
|
245
|
+
border-radius: 4px;
|
|
246
|
+
background: var(--lb-cyan);
|
|
247
|
+
color: var(--lb-bg);
|
|
248
|
+
font-weight: 800;
|
|
249
|
+
letter-spacing: 0.05em;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
.hero-meta {
|
|
253
|
+
font-size: 0.8rem;
|
|
254
|
+
color: var(--lb-muted);
|
|
255
|
+
margin-top: 0.25rem;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
.hero-score-block {
|
|
259
|
+
text-align: right;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
.hero-score {
|
|
263
|
+
font-family: var(--lb-font);
|
|
264
|
+
font-size: 1.75rem;
|
|
265
|
+
font-weight: 900;
|
|
266
|
+
color: var(--lb-cyan);
|
|
267
|
+
text-shadow: 0 0 20px rgba(0, 245, 255, 0.5);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
.hero-streak {
|
|
271
|
+
display: flex;
|
|
272
|
+
align-items: center;
|
|
273
|
+
justify-content: flex-end;
|
|
274
|
+
gap: 0.25rem;
|
|
275
|
+
font-size: 0.8rem;
|
|
276
|
+
color: var(--lb-magenta);
|
|
277
|
+
margin-top: 0.25rem;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
.tabs {
|
|
281
|
+
display: flex;
|
|
282
|
+
gap: 0.35rem;
|
|
283
|
+
margin-bottom: 1.5rem;
|
|
284
|
+
padding: 0.35rem;
|
|
285
|
+
background: rgba(0, 0, 0, 0.4);
|
|
286
|
+
border-radius: 12px;
|
|
287
|
+
border: 1px solid var(--lb-border);
|
|
288
|
+
position: relative;
|
|
289
|
+
z-index: 1;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
.tab {
|
|
293
|
+
flex: 1;
|
|
294
|
+
display: flex;
|
|
295
|
+
align-items: center;
|
|
296
|
+
justify-content: center;
|
|
297
|
+
gap: 0.4rem;
|
|
298
|
+
padding: 0.65rem;
|
|
299
|
+
border: none;
|
|
300
|
+
border-radius: 8px;
|
|
301
|
+
background: transparent;
|
|
302
|
+
color: var(--lb-muted);
|
|
303
|
+
font-family: inherit;
|
|
304
|
+
font-size: 0.8rem;
|
|
305
|
+
font-weight: 600;
|
|
306
|
+
cursor: pointer;
|
|
307
|
+
transition: all 0.25s ease;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
.tab:hover {
|
|
311
|
+
color: var(--lb-foreground);
|
|
312
|
+
background: rgba(255, 255, 255, 0.05);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
.tab.active {
|
|
316
|
+
color: var(--lb-bg);
|
|
317
|
+
background: linear-gradient(135deg, var(--lb-cyan), var(--lb-violet));
|
|
318
|
+
box-shadow: 0 4px 20px rgba(0, 245, 255, 0.35);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
.tab-label {
|
|
322
|
+
display: none;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
@media (min-width: 640px) {
|
|
326
|
+
.tab-label {
|
|
327
|
+
display: inline;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
.toggle-btn {
|
|
332
|
+
width: 100%;
|
|
333
|
+
margin-bottom: 1rem;
|
|
334
|
+
padding: 0.5rem;
|
|
335
|
+
border: none;
|
|
336
|
+
background: transparent;
|
|
337
|
+
color: var(--lb-muted);
|
|
338
|
+
font-size: 0.7rem;
|
|
339
|
+
letter-spacing: 0.1em;
|
|
340
|
+
text-transform: uppercase;
|
|
341
|
+
cursor: pointer;
|
|
342
|
+
font-family: inherit;
|
|
343
|
+
transition: color 0.2s;
|
|
344
|
+
position: relative;
|
|
345
|
+
z-index: 1;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
.toggle-btn:hover {
|
|
349
|
+
color: var(--lb-cyan);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
.players-list {
|
|
353
|
+
display: flex;
|
|
354
|
+
flex-direction: column;
|
|
355
|
+
gap: 0.65rem;
|
|
356
|
+
position: relative;
|
|
357
|
+
z-index: 1;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
.load-more {
|
|
361
|
+
width: 100%;
|
|
362
|
+
margin-top: 1.25rem;
|
|
363
|
+
padding: 0.85rem;
|
|
364
|
+
border-radius: var(--lb-radius);
|
|
365
|
+
border: 1px solid var(--lb-border);
|
|
366
|
+
background: rgba(0, 245, 255, 0.06);
|
|
367
|
+
color: var(--lb-cyan);
|
|
368
|
+
font-family: var(--lb-font);
|
|
369
|
+
font-size: 0.75rem;
|
|
370
|
+
font-weight: 700;
|
|
371
|
+
letter-spacing: 0.15em;
|
|
372
|
+
text-transform: uppercase;
|
|
373
|
+
cursor: pointer;
|
|
374
|
+
transition: all 0.25s;
|
|
375
|
+
position: relative;
|
|
376
|
+
z-index: 1;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
.load-more:hover {
|
|
380
|
+
background: rgba(0, 245, 255, 0.12);
|
|
381
|
+
box-shadow: var(--lb-glow-cyan);
|
|
382
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { css } from 'lit';
|
|
2
|
+
|
|
3
|
+
/** Design tokens + base reset for all v2 leaderboard child components. */
|
|
4
|
+
export const lbTokens = css`
|
|
5
|
+
:host {
|
|
6
|
+
--lb-bg: #050510;
|
|
7
|
+
--lb-surface: rgba(12, 14, 28, 0.85);
|
|
8
|
+
--lb-surface-hover: rgba(20, 24, 48, 0.95);
|
|
9
|
+
--lb-foreground: #f0f4ff;
|
|
10
|
+
--lb-muted: #7b8499;
|
|
11
|
+
--lb-cyan: #00f5ff;
|
|
12
|
+
--lb-magenta: #ff2bd6;
|
|
13
|
+
--lb-violet: #8b5cf6;
|
|
14
|
+
--lb-gold: #ffd54a;
|
|
15
|
+
--lb-silver: #c0d4e8;
|
|
16
|
+
--lb-bronze: #cd7f32;
|
|
17
|
+
--lb-success: #22ff9a;
|
|
18
|
+
--lb-danger: #ff4466;
|
|
19
|
+
--lb-border: rgba(0, 245, 255, 0.15);
|
|
20
|
+
--lb-glow-cyan: 0 0 24px rgba(0, 245, 255, 0.35);
|
|
21
|
+
--lb-glow-gold: 0 0 32px rgba(255, 213, 74, 0.45);
|
|
22
|
+
--lb-radius: 14px;
|
|
23
|
+
--lb-font: 'Orbitron', 'Inter', system-ui, sans-serif;
|
|
24
|
+
--lb-font-body: 'Inter', system-ui, sans-serif;
|
|
25
|
+
|
|
26
|
+
font-family: var(--lb-font-body);
|
|
27
|
+
color: var(--lb-foreground);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
* {
|
|
31
|
+
box-sizing: border-box;
|
|
32
|
+
margin: 0;
|
|
33
|
+
padding: 0;
|
|
34
|
+
}
|
|
35
|
+
`;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export interface LbPlayer {
|
|
2
|
+
id: string;
|
|
3
|
+
rank: number;
|
|
4
|
+
username: string;
|
|
5
|
+
avatar: string;
|
|
6
|
+
level: number;
|
|
7
|
+
xp: number;
|
|
8
|
+
xpToNextLevel: number;
|
|
9
|
+
score: number;
|
|
10
|
+
wins: number;
|
|
11
|
+
streak: number;
|
|
12
|
+
badges: LbBadge[];
|
|
13
|
+
trend: 'up' | 'down' | 'same';
|
|
14
|
+
rankChange?: number;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface LbBadge {
|
|
18
|
+
id: string;
|
|
19
|
+
name: string;
|
|
20
|
+
icon: string;
|
|
21
|
+
rarity: 'common' | 'rare' | 'epic' | 'legendary';
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface LbStats {
|
|
25
|
+
totalPlayers: number;
|
|
26
|
+
yourRank: number;
|
|
27
|
+
topScore: number;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export type LbTabId = 'global' | 'weekly' | 'friends';
|