@didaoktv/didaoui-uniapp 1.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.
Files changed (73) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +89 -0
  3. package/components/dd-action-sheet/dd-action-sheet.vue +207 -0
  4. package/components/dd-alert/dd-alert.vue +240 -0
  5. package/components/dd-avatar/dd-avatar.vue +168 -0
  6. package/components/dd-backtop/dd-backtop.vue +75 -0
  7. package/components/dd-badge/dd-badge.vue +150 -0
  8. package/components/dd-button/dd-button.vue +215 -0
  9. package/components/dd-capsule-button/dd-capsule-button.vue +109 -0
  10. package/components/dd-card/dd-card.vue +155 -0
  11. package/components/dd-cell/dd-cell.vue +201 -0
  12. package/components/dd-cell-group/dd-cell-group.vue +56 -0
  13. package/components/dd-champion-card/dd-champion-card.vue +258 -0
  14. package/components/dd-checkbox/dd-checkbox.vue +145 -0
  15. package/components/dd-collapse/dd-collapse.vue +63 -0
  16. package/components/dd-collapse-item/dd-collapse-item.vue +154 -0
  17. package/components/dd-count-down/dd-count-down.vue +163 -0
  18. package/components/dd-date-picker/dd-date-picker.vue +253 -0
  19. package/components/dd-dialog/dd-dialog.vue +264 -0
  20. package/components/dd-divider/dd-divider.vue +104 -0
  21. package/components/dd-drawer/dd-drawer.vue +214 -0
  22. package/components/dd-dropdown-item/dd-dropdown-item.vue +203 -0
  23. package/components/dd-dropdown-menu/dd-dropdown-menu.vue +177 -0
  24. package/components/dd-empty-state/dd-empty-state.vue +140 -0
  25. package/components/dd-feature-grid/dd-feature-grid.vue +139 -0
  26. package/components/dd-field/dd-field.vue +240 -0
  27. package/components/dd-icon/dd-icon.vue +464 -0
  28. package/components/dd-image/dd-image.vue +158 -0
  29. package/components/dd-input/dd-input.vue +172 -0
  30. package/components/dd-list-cell/dd-list-cell.vue +152 -0
  31. package/components/dd-loading/dd-loading.vue +187 -0
  32. package/components/dd-loadmore/dd-loadmore.vue +152 -0
  33. package/components/dd-mini-program-navbar/dd-mini-program-navbar.vue +245 -0
  34. package/components/dd-modal/dd-modal.vue +286 -0
  35. package/components/dd-navigation/dd-navigation.vue +134 -0
  36. package/components/dd-overlay/dd-overlay.vue +114 -0
  37. package/components/dd-picker/dd-picker.vue +203 -0
  38. package/components/dd-popover/dd-popover.vue +190 -0
  39. package/components/dd-popover-item/dd-popover-item.vue +88 -0
  40. package/components/dd-popup/dd-popup.vue +243 -0
  41. package/components/dd-progress/dd-progress.vue +255 -0
  42. package/components/dd-pull-refresh/dd-pull-refresh.vue +232 -0
  43. package/components/dd-radio/dd-radio.vue +129 -0
  44. package/components/dd-rate/dd-rate.vue +133 -0
  45. package/components/dd-room-card/dd-room-card.vue +309 -0
  46. package/components/dd-search-bar/dd-search-bar.vue +176 -0
  47. package/components/dd-segmented-tab/dd-segmented-tab.vue +187 -0
  48. package/components/dd-skeleton/dd-skeleton.vue +184 -0
  49. package/components/dd-slider/dd-slider.vue +227 -0
  50. package/components/dd-stat-card/dd-stat-card.vue +174 -0
  51. package/components/dd-step/dd-step.vue +188 -0
  52. package/components/dd-stepper/dd-stepper.vue +171 -0
  53. package/components/dd-steps/dd-steps.vue +61 -0
  54. package/components/dd-sticky/dd-sticky.vue +132 -0
  55. package/components/dd-swipe/dd-swipe.vue +146 -0
  56. package/components/dd-swipe-action/dd-swipe-action.vue +248 -0
  57. package/components/dd-swipe-item/dd-swipe-item.vue +27 -0
  58. package/components/dd-swipeable-tab/dd-swipeable-tab.vue +202 -0
  59. package/components/dd-switch/dd-switch.vue +106 -0
  60. package/components/dd-tabbar/dd-tabbar.vue +112 -0
  61. package/components/dd-tabbar-item/dd-tabbar-item.vue +122 -0
  62. package/components/dd-tag/dd-tag.vue +178 -0
  63. package/components/dd-toast/dd-toast.vue +195 -0
  64. package/components/dd-top-navbar/dd-top-navbar.vue +184 -0
  65. package/components/dd-upload/dd-upload.vue +187 -0
  66. package/index.ts +127 -0
  67. package/libs/utils.ts +106 -0
  68. package/package.json +58 -0
  69. package/scss/_functions.scss +68 -0
  70. package/scss/_mixins.scss +154 -0
  71. package/scss/_reset.scss +30 -0
  72. package/scss/_variables.scss +317 -0
  73. package/uni.scss +4 -0
@@ -0,0 +1,155 @@
1
+ <template>
2
+ <view
3
+ class="dd-card"
4
+ :class="[
5
+ `dd-card--${variant}`,
6
+ {
7
+ 'dd-card--border': border,
8
+ 'dd-card--active': active,
9
+ 'dd-card--hover': hover,
10
+ },
11
+ ]"
12
+ :hover-class="hoverable ? 'dd-card--hover-state' : ''"
13
+ :hover-stay-time="120"
14
+ @click="onClick"
15
+ >
16
+ <view v-if="$slots.header || $slots.extra" class="dd-card__header">
17
+ <view class="dd-card__header-inner"><slot name="header"></slot></view>
18
+ <view v-if="$slots.extra" class="dd-card__extra"><slot name="extra"></slot></view>
19
+ </view>
20
+ <view class="dd-card__body"><slot></slot></view>
21
+ <view v-if="$slots.footer" class="dd-card__footer"><slot name="footer"></slot></view>
22
+ </view>
23
+ </template>
24
+
25
+ <script setup lang="ts">
26
+ import { useSlots } from 'vue'
27
+
28
+ interface Props {
29
+ variant?: 'vertical' | 'horizontal' | 'compact'
30
+ border?: boolean
31
+ active?: boolean
32
+ hover?: boolean
33
+ hoverable?: boolean
34
+ }
35
+
36
+ const props = withDefaults(defineProps<Props>(), {
37
+ variant: 'vertical',
38
+ border: true,
39
+ active: false,
40
+ hover: false,
41
+ hoverable: false,
42
+ })
43
+
44
+ const emit = defineEmits<{ (e: 'click', val: Event): void }>()
45
+
46
+ const slots = useSlots()
47
+ void slots
48
+
49
+ function onClick(e: Event) {
50
+ emit('click', e)
51
+ }
52
+ </script>
53
+
54
+ <style lang="scss" scoped>
55
+ @import '../../scss/variables';
56
+ @import '../../scss/mixins';
57
+
58
+ .dd-card {
59
+ box-sizing: border-box;
60
+ background: $dd-bg-elevated;
61
+ border-radius: $dd-radius-lg;
62
+ box-shadow: $dd-shadow-1;
63
+ overflow: hidden;
64
+ @include dd-transition(all 0.3s ease);
65
+
66
+ &__header {
67
+ @include dd-flex-between;
68
+ padding: $dd-space-4 $dd-space-5;
69
+ box-sizing: border-box;
70
+ @include dd-hairline-bottom($dd-border-default);
71
+
72
+ &-inner {
73
+ flex: 1;
74
+ min-width: 0;
75
+ }
76
+ }
77
+
78
+ &__extra {
79
+ flex-shrink: 0;
80
+ margin-left: $dd-space-3;
81
+ }
82
+
83
+ &__body {
84
+ padding: $dd-space-5;
85
+ box-sizing: border-box;
86
+ }
87
+
88
+ &__footer {
89
+ padding: $dd-space-4 $dd-space-5;
90
+ box-sizing: border-box;
91
+ @include dd-hairline-top($dd-border-default);
92
+ }
93
+
94
+ &--border {
95
+ border: 1px solid $dd-border-default;
96
+ }
97
+
98
+ &--hover,
99
+ &--hover-state {
100
+ transform: translateY(-4rpx);
101
+ box-shadow: $dd-shadow-2;
102
+ }
103
+
104
+ &--active {
105
+ border: 2px solid $dd-primary-500;
106
+ box-shadow: $dd-shadow-glow-gold-lg;
107
+ }
108
+ }
109
+
110
+ // horizontal: 去除 header/footer 分隔线, body flex
111
+ .dd-card--horizontal {
112
+ display: flex;
113
+ flex-direction: row;
114
+
115
+ .dd-card__header,
116
+ .dd-card__footer {
117
+ &::after,
118
+ &::before {
119
+ display: none;
120
+ }
121
+ }
122
+
123
+ .dd-card__body {
124
+ flex: 1;
125
+ padding: $dd-space-4;
126
+ }
127
+
128
+ // horizontal 不堆叠 header/footer, 整体作为 row
129
+ .dd-card__header,
130
+ .dd-card__footer {
131
+ padding: $dd-space-4;
132
+ }
133
+ }
134
+
135
+ // compact: 更小圆角 + 更紧凑 padding
136
+ .dd-card--compact {
137
+ border-radius: $dd-radius-md;
138
+
139
+ .dd-card__body {
140
+ padding: $dd-space-3 $dd-space-4;
141
+ }
142
+
143
+ .dd-card__header {
144
+ padding: $dd-space-3 $dd-space-4;
145
+ }
146
+
147
+ .dd-card__footer {
148
+ padding: $dd-space-3 $dd-space-4;
149
+ }
150
+ }
151
+
152
+ .dd-card--horizontal.dd-card--active {
153
+ border: 2px solid $dd-primary-500;
154
+ }
155
+ </style>
@@ -0,0 +1,201 @@
1
+ <template>
2
+ <view
3
+ class="dd-cell"
4
+ :class="[
5
+ `dd-cell--${size}`,
6
+ {
7
+ 'dd-cell--center': center,
8
+ 'dd-cell--required': required,
9
+ 'dd-cell--borderless': borderless,
10
+ 'dd-cell--link': isLink,
11
+ },
12
+ ]"
13
+ :hover-class="isLink ? 'dd-cell--active' : ''"
14
+ :hover-stay-time="100"
15
+ @click="handleClick"
16
+ >
17
+ <view v-if="$slots.icon || icon" class="dd-cell__icon">
18
+ <slot name="icon">
19
+ <dd-icon v-if="icon" :name="icon" class="dd-cell__icon-text" />
20
+ </slot>
21
+ </view>
22
+ <view v-if="required" class="dd-cell__required"><text>*</text></view>
23
+ <view class="dd-cell__content">
24
+ <text v-if="title" class="dd-cell__title">{{ title }}</text>
25
+ <text v-if="label || $slots.label" class="dd-cell__label">
26
+ <slot name="label">{{ label }}</slot>
27
+ </text>
28
+ </view>
29
+ <view class="dd-cell__right">
30
+ <slot name="value">
31
+ <text v-if="value" class="dd-cell__value">{{ value }}</text>
32
+ </slot>
33
+ <slot name="right-icon"></slot>
34
+ <view
35
+ v-if="isLink"
36
+ class="dd-cell__arrow"
37
+ :class="`dd-cell__arrow--${arrowDirection}`"
38
+ ><dd-icon name="arrow" /></view>
39
+ </view>
40
+ </view>
41
+ </template>
42
+
43
+ <script setup lang="ts">
44
+ import { useSlots } from 'vue'
45
+ import DdIcon from '../dd-icon/dd-icon.vue'
46
+
47
+ interface Props {
48
+ title?: string
49
+ label?: string
50
+ value?: string
51
+ icon?: string
52
+ size?: 'sm' | 'md'
53
+ isLink?: boolean
54
+ arrowDirection?: 'left' | 'right' | 'up' | 'down'
55
+ required?: boolean
56
+ center?: boolean
57
+ borderless?: boolean
58
+ }
59
+
60
+ const props = withDefaults(defineProps<Props>(), {
61
+ title: '',
62
+ label: '',
63
+ value: '',
64
+ icon: '',
65
+ size: 'md',
66
+ isLink: false,
67
+ arrowDirection: 'right',
68
+ required: false,
69
+ center: false,
70
+ borderless: false,
71
+ })
72
+
73
+ const emit = defineEmits<{ (e: 'click', val: Event): void }>()
74
+
75
+ const slots = useSlots()
76
+ void slots
77
+
78
+ // 仅当 isLink 时才向外抛 click
79
+ function handleClick(e: Event) {
80
+ if (!props.isLink) return
81
+ emit('click', e)
82
+ }
83
+ </script>
84
+
85
+ <style lang="scss" scoped>
86
+ @import '../../scss/variables';
87
+ @import '../../scss/mixins';
88
+
89
+ .dd-cell {
90
+ display: flex;
91
+ flex-direction: row;
92
+ align-items: flex-start;
93
+ box-sizing: border-box;
94
+ width: 100%;
95
+ padding: 0 24rpx 0 32rpx;
96
+ background: $dd-bg-elevated;
97
+ font-size: $dd-font-size-body;
98
+ color: $dd-text-primary;
99
+ @include dd-hairline-bottom($dd-border-subtle);
100
+
101
+ &--sm {
102
+ min-height: 96rpx;
103
+ }
104
+
105
+ &--md {
106
+ min-height: 112rpx;
107
+ }
108
+
109
+ &--center {
110
+ align-items: center;
111
+ }
112
+
113
+ &--borderless {
114
+ &::after {
115
+ display: none;
116
+ }
117
+ }
118
+
119
+ &--active {
120
+ background: $dd-surface-container-high;
121
+ }
122
+
123
+ &__icon {
124
+ flex-shrink: 0;
125
+ margin-right: $dd-space-2;
126
+ display: flex;
127
+ align-items: center;
128
+ height: 100%;
129
+ }
130
+
131
+ &__icon-text {
132
+ font-size: 36rpx;
133
+ line-height: 1;
134
+ color: $dd-primary-400;
135
+ }
136
+
137
+ &__required {
138
+ color: $dd-error-500;
139
+ font-size: $dd-font-size-body;
140
+ margin-right: 4rpx;
141
+ line-height: 1.5;
142
+ text {
143
+ line-height: 1;
144
+ }
145
+ }
146
+
147
+ &__content {
148
+ flex: 1;
149
+ min-width: 0;
150
+ display: flex;
151
+ flex-direction: column;
152
+ justify-content: center;
153
+ padding: $dd-space-2 0;
154
+ }
155
+
156
+ &__title {
157
+ font-size: $dd-font-size-body;
158
+ color: $dd-text-primary;
159
+ @include dd-ellipsis(1);
160
+ }
161
+
162
+ &__label {
163
+ margin-top: 4rpx;
164
+ font-size: $dd-font-size-caption;
165
+ color: $dd-text-tertiary;
166
+ @include dd-ellipsis(1);
167
+ }
168
+
169
+ &__right {
170
+ flex-shrink: 0;
171
+ display: flex;
172
+ align-items: center;
173
+ gap: $dd-space-1;
174
+ margin-left: $dd-space-2;
175
+ }
176
+
177
+ &__value {
178
+ font-size: $dd-font-size-body;
179
+ color: $dd-text-tertiary;
180
+ }
181
+
182
+ &__arrow {
183
+ font-size: 32rpx;
184
+ color: $dd-text-tertiary;
185
+ line-height: 1;
186
+
187
+ &--right {
188
+ transform: rotate(0deg);
189
+ }
190
+ &--left {
191
+ transform: rotate(180deg);
192
+ }
193
+ &--up {
194
+ transform: rotate(-90deg);
195
+ }
196
+ &--down {
197
+ transform: rotate(90deg);
198
+ }
199
+ }
200
+ }
201
+ </style>
@@ -0,0 +1,56 @@
1
+ <template>
2
+ <view class="dd-cell-group">
3
+ <view v-if="title || $slots.title" class="dd-cell-group__title">
4
+ <slot name="title">{{ title }}</slot>
5
+ </view>
6
+ <view class="dd-cell-group__body">
7
+ <slot></slot>
8
+ </view>
9
+ </view>
10
+ </template>
11
+
12
+ <script setup lang="ts">
13
+ import { useSlots } from 'vue'
14
+
15
+ interface Props {
16
+ title?: string
17
+ }
18
+
19
+ withDefaults(defineProps<Props>(), {
20
+ title: '',
21
+ })
22
+
23
+ const slots = useSlots()
24
+ void slots
25
+ </script>
26
+
27
+ <style lang="scss" scoped>
28
+ @import '../../scss/variables';
29
+ @import '../../scss/mixins';
30
+
31
+ .dd-cell-group {
32
+ display: flex;
33
+ flex-direction: column;
34
+ width: 100%;
35
+
36
+ &__title {
37
+ padding: 32rpx 32rpx 16rpx;
38
+ font-size: $dd-font-size-caption;
39
+ color: $dd-text-tertiary;
40
+ }
41
+
42
+ &__body {
43
+ background: $dd-bg-elevated;
44
+ border-radius: $dd-radius-lg;
45
+ overflow: hidden;
46
+
47
+ // 去除最后一个子元素的底边框, 避免溢出到圆角外
48
+ :deep(.dd-cell:last-child),
49
+ :deep(.dd-list-cell:last-child) {
50
+ &::after {
51
+ display: none;
52
+ }
53
+ }
54
+ }
55
+ }
56
+ </style>
@@ -0,0 +1,258 @@
1
+ <template>
2
+ <view
3
+ class="dd-champ"
4
+ :class="[`dd-champ--${variant}`, `dd-champ--rank${rank}`]"
5
+ @click="onClick"
6
+ >
7
+ <!-- PODIUM: 居中列, 头像按 rank 缩放, rank1 带弹跳皇冠 -->
8
+ <template v-if="variant === 'podium'">
9
+ <view v-if="rank === 1" class="dd-champ__crown">👑</view>
10
+ <view class="dd-champ__avatar" :style="avatarStyle">
11
+ <image v-if="avatar" class="dd-champ__avatar-img" :src="avatar" mode="aspectFill" />
12
+ <text v-else class="dd-champ__avatar-text">{{ initial }}</text>
13
+ </view>
14
+ <text class="dd-champ__name">{{ name }}</text>
15
+ <text class="dd-champ__score">{{ score }}</text>
16
+ <view class="dd-champ__rank-badge" :style="rankBadgeStyle">
17
+ <text class="dd-champ__rank-num">{{ rank }}</text>
18
+ </view>
19
+ </template>
20
+
21
+ <!-- HORIZONTAL: 行式, 排名号+头像+名字+分数 -->
22
+ <template v-else-if="variant === 'horizontal'">
23
+ <text class="dd-champ__rank-inline">{{ rank }}</text>
24
+ <view class="dd-champ__avatar dd-champ__avatar--sm" :style="avatarStyle">
25
+ <image v-if="avatar" class="dd-champ__avatar-img" :src="avatar" mode="aspectFill" />
26
+ <text v-else class="dd-champ__avatar-text">{{ initial }}</text>
27
+ </view>
28
+ <text class="dd-champ__name dd-champ__name--inline">{{ name }}</text>
29
+ <text class="dd-champ__score dd-champ__score--inline">{{ score }}</text>
30
+ </template>
31
+
32
+ <!-- LIST: 无边框行, 小排名徽标+头像+名字+右对齐分数 -->
33
+ <template v-else>
34
+ <view class="dd-champ__rank-badge dd-champ__rank-badge--sm" :style="rankBadgeStyle">
35
+ <text class="dd-champ__rank-num">{{ rank }}</text>
36
+ </view>
37
+ <view class="dd-champ__avatar dd-champ__avatar--sm" :style="avatarStyle">
38
+ <image v-if="avatar" class="dd-champ__avatar-img" :src="avatar" mode="aspectFill" />
39
+ <text v-else class="dd-champ__avatar-text">{{ initial }}</text>
40
+ </view>
41
+ <text class="dd-champ__name dd-champ__name--inline">{{ name }}</text>
42
+ <text class="dd-champ__score dd-champ__score--inline dd-champ__score--right">{{ score }}</text>
43
+ </template>
44
+ </view>
45
+ </template>
46
+
47
+ <script setup lang="ts">
48
+ import { computed } from 'vue'
49
+
50
+ interface Props {
51
+ variant?: 'podium' | 'horizontal' | 'list'
52
+ rank?: number
53
+ name?: string
54
+ score?: string | number
55
+ avatar?: string
56
+ }
57
+
58
+ const props = withDefaults(defineProps<Props>(), {
59
+ variant: 'podium',
60
+ rank: 1,
61
+ name: '',
62
+ score: '',
63
+ avatar: '',
64
+ })
65
+
66
+ const emit = defineEmits<{ (e: 'click', val: { rank: number }): void }>()
67
+
68
+ // 金/银/铜 字面量色
69
+ const tierColors: Record<number, { border: string; glow: string; score: string; badgeStart: string; badgeEnd: string }> = {
70
+ 1: { border: '#FFD700', glow: '0 0 40rpx rgba(255,215,0,0.4)', score: '#FFD700', badgeStart: '#FFD700', badgeEnd: '#B8860B' },
71
+ 2: { border: '#C0C0C0', glow: '0 0 32rpx rgba(192,192,192,0.4)', score: '#C0C0C0', badgeStart: '#C0C0C0', badgeEnd: '#808080' },
72
+ 3: { border: '#CD7F32', glow: '0 0 24rpx rgba(205,127,50,0.4)', score: '#CD7F32', badgeStart: '#CD7F32', badgeEnd: '#8B4513' },
73
+ }
74
+
75
+ // podium 头像尺寸: rank1=72, rank2=60, rank3=52
76
+ const podiumSizeMap: Record<number, number> = { 1: 144, 2: 120, 3: 104 }
77
+
78
+ const tier = computed(() => tierColors[props.rank] || tierColors[1])
79
+
80
+ const avatarStyle = computed(() => {
81
+ const size = props.variant === 'podium' ? (podiumSizeMap[props.rank] || 144) : 80
82
+ return {
83
+ width: `${size}rpx`,
84
+ height: `${size}rpx`,
85
+ borderColor: tier.value.border,
86
+ boxShadow: tier.value.glow,
87
+ }
88
+ })
89
+
90
+ const rankBadgeStyle = computed(() => ({
91
+ background: `linear-gradient(135deg, ${tier.value.badgeStart} 0%, ${tier.value.badgeEnd} 100%)`,
92
+ }))
93
+
94
+ const initial = computed(() => {
95
+ if (!props.name) return ''
96
+ return props.name.charAt(0).toUpperCase()
97
+ })
98
+
99
+ function onClick() {
100
+ emit('click', { rank: props.rank })
101
+ }
102
+ </script>
103
+
104
+ <style lang="scss" scoped>
105
+ @import '../../scss/variables';
106
+ @import '../../scss/mixins';
107
+
108
+ .dd-champ {
109
+ box-sizing: border-box;
110
+ }
111
+
112
+ // === PODIUM ===
113
+ .dd-champ--podium {
114
+ display: flex;
115
+ flex-direction: column;
116
+ align-items: center;
117
+ justify-content: center;
118
+ gap: $dd-space-2;
119
+ position: relative;
120
+ padding: $dd-space-4 $dd-space-2;
121
+ }
122
+
123
+ .dd-champ__crown {
124
+ font-size: 56rpx;
125
+ line-height: 1;
126
+ animation: dd-champ-bounce 1.6s ease-in-out infinite;
127
+ }
128
+
129
+ @keyframes dd-champ-bounce {
130
+ 0%, 100% { transform: translateY(0); }
131
+ 50% { transform: translateY(-12rpx); }
132
+ }
133
+
134
+ .dd-champ__avatar {
135
+ border-radius: 50%;
136
+ display: flex;
137
+ align-items: center;
138
+ justify-content: center;
139
+ overflow: hidden;
140
+ border-width: 6rpx;
141
+ border-style: solid;
142
+ background: $dd-surface-container-high;
143
+ box-sizing: border-box;
144
+
145
+ &--sm {
146
+ border-width: 4rpx;
147
+ }
148
+ }
149
+
150
+ .dd-champ__avatar-img {
151
+ width: 100%;
152
+ height: 100%;
153
+ }
154
+
155
+ .dd-champ__avatar-text {
156
+ font-size: $dd-font-size-h3;
157
+ font-weight: 700;
158
+ color: $dd-color-white;
159
+ }
160
+
161
+ .dd-champ__name {
162
+ font-size: $dd-font-size-body;
163
+ font-weight: 600;
164
+ color: $dd-text-primary;
165
+ @include dd-ellipsis(1);
166
+
167
+ &--inline {
168
+ flex: 1;
169
+ min-width: 0;
170
+ margin-left: $dd-space-2;
171
+ }
172
+ }
173
+
174
+ .dd-champ__score {
175
+ font-size: $dd-font-size-caption;
176
+ color: $dd-primary-400;
177
+
178
+ &--inline {
179
+ flex-shrink: 0;
180
+ margin-left: $dd-space-2;
181
+ }
182
+
183
+ &--right {
184
+ margin-left: auto;
185
+ text-align: right;
186
+ }
187
+ }
188
+
189
+ .dd-champ--rank1 .dd-champ__score {
190
+ color: #FFD700;
191
+ }
192
+ .dd-champ--rank2 .dd-champ__score {
193
+ color: #C0C0C0;
194
+ }
195
+ .dd-champ--rank3 .dd-champ__score {
196
+ color: #CD7F32;
197
+ }
198
+
199
+ .dd-champ__rank-badge {
200
+ position: absolute;
201
+ bottom: -$dd-space-1;
202
+ right: 50%;
203
+ transform: translateX(50%);
204
+ width: 56rpx;
205
+ height: 56rpx;
206
+ border-radius: 50%;
207
+ display: flex;
208
+ align-items: center;
209
+ justify-content: center;
210
+
211
+ &--sm {
212
+ position: static;
213
+ transform: none;
214
+ width: 48rpx;
215
+ height: 48rpx;
216
+ flex-shrink: 0;
217
+ }
218
+ }
219
+
220
+ .dd-champ__rank-num {
221
+ font-size: $dd-font-size-caption;
222
+ font-weight: 800;
223
+ color: $dd-neutral-900;
224
+ line-height: 1;
225
+ }
226
+
227
+ .dd-champ__rank-inline {
228
+ font-size: $dd-font-size-h3;
229
+ font-weight: 800;
230
+ color: #FFD700;
231
+ flex-shrink: 0;
232
+ width: 48rpx;
233
+ text-align: center;
234
+ }
235
+
236
+ // === HORIZONTAL ===
237
+ .dd-champ--horizontal {
238
+ display: flex;
239
+ flex-direction: row;
240
+ align-items: center;
241
+ gap: $dd-space-2;
242
+ background: $dd-bg-elevated;
243
+ border: 1px solid $dd-border-default;
244
+ border-radius: $dd-radius-lg;
245
+ padding: $dd-space-3 $dd-space-4;
246
+ }
247
+
248
+ // === LIST ===
249
+ .dd-champ--list {
250
+ display: flex;
251
+ flex-direction: row;
252
+ align-items: center;
253
+ gap: $dd-space-2;
254
+ background: $dd-bg-elevated;
255
+ border-bottom: 1px solid $dd-border-default;
256
+ padding: $dd-space-3 $dd-space-4;
257
+ }
258
+ </style>