muzhiyu-ui 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 (96) hide show
  1. package/README.md +202 -0
  2. package/components/muzhiyu/mu-action-sheet/mu-action-sheet.vue +335 -0
  3. package/components/muzhiyu/mu-alert/mu-alert.vue +220 -0
  4. package/components/muzhiyu/mu-back-top/mu-back-top.vue +161 -0
  5. package/components/muzhiyu/mu-badge/mu-badge.vue +150 -0
  6. package/components/muzhiyu/mu-barcode/mu-barcode.vue +100 -0
  7. package/components/muzhiyu/mu-blank/mu-blank.vue +30 -0
  8. package/components/muzhiyu/mu-bottom-nav/mu-bottom-nav.vue +331 -0
  9. package/components/muzhiyu/mu-bubble/mu-bubble.vue +316 -0
  10. package/components/muzhiyu/mu-button/mu-button.vue +431 -0
  11. package/components/muzhiyu/mu-calendar/mu-calendar.vue +429 -0
  12. package/components/muzhiyu/mu-car-input/mu-car-input.vue +209 -0
  13. package/components/muzhiyu/mu-card/mu-card.vue +317 -0
  14. package/components/muzhiyu/mu-cascader/mu-cascader.vue +336 -0
  15. package/components/muzhiyu/mu-cell/mu-cell.vue +368 -0
  16. package/components/muzhiyu/mu-checkbox/mu-checkbox.vue +116 -0
  17. package/components/muzhiyu/mu-checkbox-group/mu-checkbox-group.vue +40 -0
  18. package/components/muzhiyu/mu-code-input/mu-code-input.vue +264 -0
  19. package/components/muzhiyu/mu-collapse/mu-collapse.vue +316 -0
  20. package/components/muzhiyu/mu-color-picker/mu-color-picker.vue +466 -0
  21. package/components/muzhiyu/mu-config/index.js +34 -0
  22. package/components/muzhiyu/mu-config/mu-config.vue +54 -0
  23. package/components/muzhiyu/mu-countdown/mu-countdown.vue +338 -0
  24. package/components/muzhiyu/mu-cropper/mu-cropper.vue +415 -0
  25. package/components/muzhiyu/mu-date-picker/mu-date-picker.vue +290 -0
  26. package/components/muzhiyu/mu-datetime/mu-datetime.vue +262 -0
  27. package/components/muzhiyu/mu-divider/mu-divider.vue +229 -0
  28. package/components/muzhiyu/mu-drawer/mu-drawer.vue +172 -0
  29. package/components/muzhiyu/mu-dropdown/mu-dropdown.vue +215 -0
  30. package/components/muzhiyu/mu-dropdown-top/mu-dropdown-top.vue +243 -0
  31. package/components/muzhiyu/mu-empty/mu-empty.vue +217 -0
  32. package/components/muzhiyu/mu-fab/mu-fab.vue +324 -0
  33. package/components/muzhiyu/mu-footer/mu-footer.vue +21 -0
  34. package/components/muzhiyu/mu-form/mu-form.vue +170 -0
  35. package/components/muzhiyu/mu-grid/mu-grid.vue +95 -0
  36. package/components/muzhiyu/mu-grid-item/mu-grid-item.vue +247 -0
  37. package/components/muzhiyu/mu-html/mu-html.vue +145 -0
  38. package/components/muzhiyu/mu-icon/mu-icon.vue +822 -0
  39. package/components/muzhiyu/mu-image-grid/mu-image-grid.vue +225 -0
  40. package/components/muzhiyu/mu-image-preview/mu-image-preview.vue +286 -0
  41. package/components/muzhiyu/mu-index-list/mu-index-list.vue +381 -0
  42. package/components/muzhiyu/mu-input/mu-input.vue +570 -0
  43. package/components/muzhiyu/mu-input-number/mu-input-number.vue +193 -0
  44. package/components/muzhiyu/mu-keyboard/mu-keyboard.vue +415 -0
  45. package/components/muzhiyu/mu-list/mu-list.vue +89 -0
  46. package/components/muzhiyu/mu-loading/mu-loading.vue +124 -0
  47. package/components/muzhiyu/mu-loading-page/mu-loading-page.vue +529 -0
  48. package/components/muzhiyu/mu-loadmore/mu-loadmore.vue +26 -0
  49. package/components/muzhiyu/mu-modal/mu-modal.vue +298 -0
  50. package/components/muzhiyu/mu-navbar/mu-navbar.vue +223 -0
  51. package/components/muzhiyu/mu-nomore/mu-nomore.vue +107 -0
  52. package/components/muzhiyu/mu-notice-bar/mu-notice-bar.vue +284 -0
  53. package/components/muzhiyu/mu-notify/mu-notify.vue +202 -0
  54. package/components/muzhiyu/mu-overlay/mu-overlay.vue +94 -0
  55. package/components/muzhiyu/mu-pagination/mu-pagination.vue +330 -0
  56. package/components/muzhiyu/mu-password-input/mu-password-input.vue +119 -0
  57. package/components/muzhiyu/mu-picker/mu-picker.vue +297 -0
  58. package/components/muzhiyu/mu-popup/mu-popup.vue +297 -0
  59. package/components/muzhiyu/mu-progress/mu-progress.vue +156 -0
  60. package/components/muzhiyu/mu-pull-refresh/mu-pull-refresh.vue +54 -0
  61. package/components/muzhiyu/mu-qrcode/mu-qrcode.vue +340 -0
  62. package/components/muzhiyu/mu-qrcode/qrcode.js +2237 -0
  63. package/components/muzhiyu/mu-radio/mu-radio.vue +125 -0
  64. package/components/muzhiyu/mu-radio-group/mu-radio-group.vue +37 -0
  65. package/components/muzhiyu/mu-rate/mu-rate.vue +103 -0
  66. package/components/muzhiyu/mu-search/mu-search.vue +320 -0
  67. package/components/muzhiyu/mu-section/mu-section.vue +206 -0
  68. package/components/muzhiyu/mu-select/mu-select.vue +440 -0
  69. package/components/muzhiyu/mu-share-sheet/mu-share-sheet.vue +269 -0
  70. package/components/muzhiyu/mu-sidebar/mu-sidebar.vue +304 -0
  71. package/components/muzhiyu/mu-signature/mu-signature.vue +449 -0
  72. package/components/muzhiyu/mu-skeleton/mu-skeleton.vue +225 -0
  73. package/components/muzhiyu/mu-slider/mu-slider.vue +228 -0
  74. package/components/muzhiyu/mu-space/mu-space.vue +84 -0
  75. package/components/muzhiyu/mu-steps/mu-steps.vue +311 -0
  76. package/components/muzhiyu/mu-sticky/mu-sticky.vue +57 -0
  77. package/components/muzhiyu/mu-swipe-cell/mu-swipe-cell.vue +281 -0
  78. package/components/muzhiyu/mu-swiper/mu-swiper.vue +107 -0
  79. package/components/muzhiyu/mu-switch/mu-switch.vue +99 -0
  80. package/components/muzhiyu/mu-tabbar/mu-tabbar.vue +382 -0
  81. package/components/muzhiyu/mu-table/mu-table.vue +420 -0
  82. package/components/muzhiyu/mu-tabs/mu-tabs.vue +339 -0
  83. package/components/muzhiyu/mu-tag/mu-tag.vue +65 -0
  84. package/components/muzhiyu/mu-text-ellipsis/mu-text-ellipsis.vue +54 -0
  85. package/components/muzhiyu/mu-timeline/mu-timeline.vue +166 -0
  86. package/components/muzhiyu/mu-tips/mu-tips.vue +36 -0
  87. package/components/muzhiyu/mu-toast/mu-toast.vue +151 -0
  88. package/components/muzhiyu/mu-transfer/mu-transfer.vue +114 -0
  89. package/components/muzhiyu/mu-tree/mu-tree.vue +263 -0
  90. package/components/muzhiyu/mu-upload/mu-upload.vue +415 -0
  91. package/components/muzhiyu/mu-waterfall/mu-waterfall.vue +321 -0
  92. package/components/muzhiyu/mu-watermark/mu-watermark.vue +60 -0
  93. package/index.js +83 -0
  94. package/package.json +38 -0
  95. package/utils/index.js +600 -0
  96. package/utils/request.js +265 -0
@@ -0,0 +1,281 @@
1
+ <template>
2
+ <view class="mu-swipe-cell" :class="[disabled && 'mu-swipe-cell--disabled']">
3
+ <view
4
+ class="mu-swipe-cell__wrapper"
5
+ :style="wrapperStyle"
6
+ @touchstart="onTouchStart"
7
+ @touchmove="onTouchMove"
8
+ @touchend="onTouchEnd"
9
+ >
10
+ <!-- 左侧侧滑区 -->
11
+ <view
12
+ v-if="$slots.left || leftActions.length"
13
+ class="mu-swipe-cell__left"
14
+ :style="leftStyle"
15
+ @tap.stop
16
+ >
17
+ <slot name="left">
18
+ <view
19
+ v-for="(act, i) in leftActions"
20
+ :key="'left-' + i"
21
+ class="mu-swipe-cell__action mu-touchable-flat"
22
+ :style="getActionStyle(act)"
23
+ @tap="handleActionClick(act, i, 'left')"
24
+ >
25
+ <mu-icon v-if="act.icon" :name="act.icon" :size="18" :color="act.color || '#FFFFFF'" style="margin-right: 6rpx;" />
26
+ <text class="mu-swipe-cell__action-text" :style="{ color: act.color || '#FFFFFF' }">{{ act.text }}</text>
27
+ </view>
28
+ </slot>
29
+ </view>
30
+
31
+ <!-- 中间主体内容区 -->
32
+ <view class="mu-swipe-cell__content" @tap="handleContentClick">
33
+ <slot></slot>
34
+ </view>
35
+
36
+ <!-- 右侧侧滑区 -->
37
+ <view
38
+ v-if="$slots.right || rightActions.length"
39
+ class="mu-swipe-cell__right"
40
+ :style="rightStyle"
41
+ @tap.stop
42
+ >
43
+ <slot name="right">
44
+ <view
45
+ v-for="(act, i) in rightActions"
46
+ :key="'right-' + i"
47
+ class="mu-swipe-cell__action mu-touchable-flat"
48
+ :style="getActionStyle(act)"
49
+ @tap="handleActionClick(act, i, 'right')"
50
+ >
51
+ <mu-icon v-if="act.icon" :name="act.icon" :size="18" :color="act.color || '#FFFFFF'" style="margin-right: 6rpx;" />
52
+ <text class="mu-swipe-cell__action-text" :style="{ color: act.color || '#FFFFFF' }">{{ act.text }}</text>
53
+ </view>
54
+ </slot>
55
+ </view>
56
+ </view>
57
+ </view>
58
+ </template>
59
+
60
+ <script setup>
61
+ import { ref, computed } from 'vue'
62
+
63
+ const props = defineProps({
64
+ leftActions: { type: Array, default: () => [] },
65
+ rightActions: { type: Array, default: () => [] },
66
+ buttonWidth: { type: [Number, String], default: 130 }, // 单个按钮默认宽度(rpx)
67
+ disabled: { type: Boolean, default: false },
68
+ autoClose: { type: Boolean, default: true },
69
+ threshold: { type: Number, default: 0.3 } // 触发展开阈值比例 (0.3 代表滑动达到 30% 释放即自动开)
70
+ })
71
+
72
+ const emit = defineEmits(['open', 'close', 'click-action', 'click'])
73
+
74
+ const offset = ref(0)
75
+ const touchStartX = ref(0)
76
+ const touchStartY = ref(0)
77
+ const isSwiping = ref(false)
78
+ const openedPosition = ref('') // '' | 'left' | 'right'
79
+
80
+ // 计算侧滑最大展开距离 (rpx)
81
+ const maxLeftOffset = computed(() => {
82
+ if (props.leftActions && props.leftActions.length) {
83
+ return props.leftActions.reduce((total, item) => {
84
+ const w = item.width ? parseSize(item.width) : parseSize(props.buttonWidth)
85
+ return total + w
86
+ }, 0)
87
+ }
88
+ return 260
89
+ })
90
+
91
+ const maxRightOffset = computed(() => {
92
+ if (props.rightActions && props.rightActions.length) {
93
+ return props.rightActions.reduce((total, item) => {
94
+ const w = item.width ? parseSize(item.width) : parseSize(props.buttonWidth)
95
+ return total + w
96
+ }, 0)
97
+ }
98
+ return 260
99
+ })
100
+
101
+ const wrapperStyle = computed(() => ({
102
+ transform: `translateX(${offset.value}rpx)`,
103
+ transition: isSwiping.value ? 'none' : 'transform 0.25s cubic-bezier(0.25, 1, 0.5, 1)'
104
+ }))
105
+
106
+ const leftStyle = computed(() => ({
107
+ width: `${maxLeftOffset.value}rpx`
108
+ }))
109
+
110
+ const rightStyle = computed(() => ({
111
+ width: `${maxRightOffset.value}rpx`
112
+ }))
113
+
114
+ function parseSize(val) {
115
+ if (typeof val === 'number') return val
116
+ if (typeof val === 'string') {
117
+ const num = parseInt(val)
118
+ return isNaN(num) ? 130 : num
119
+ }
120
+ return 130
121
+ }
122
+
123
+ function getActionStyle(act) {
124
+ const w = act.width ? parseSize(act.width) : parseSize(props.buttonWidth)
125
+ return {
126
+ width: `${w}rpx`,
127
+ background: act.bg || act.bgColor || act.color || '#F43F5E'
128
+ }
129
+ }
130
+
131
+ function onTouchStart(e) {
132
+ if (props.disabled || !e || !e.touches || !e.touches[0]) return
133
+ const touch = e.touches[0]
134
+ touchStartX.value = touch.clientX
135
+ touchStartY.value = touch.clientY
136
+ isSwiping.value = true
137
+ }
138
+
139
+ function onTouchMove(e) {
140
+ if (props.disabled || !e || !e.touches || !e.touches[0]) return
141
+ const touch = e.touches[0]
142
+ const diffX = (touch.clientX - touchStartX.value) * 2 // 转换为 rpx 缩放比例
143
+ const diffY = Math.abs(touch.clientY - touchStartY.value) * 2
144
+
145
+ // 纵向滚动避让
146
+ if (diffY > Math.abs(diffX)) return
147
+
148
+ let newOffset = 0
149
+ if (openedPosition.value === 'left') {
150
+ newOffset = maxLeftOffset.value + diffX
151
+ } else if (openedPosition.value === 'right') {
152
+ newOffset = -maxRightOffset.value + diffX
153
+ } else {
154
+ newOffset = diffX
155
+ }
156
+
157
+ // 阻尼约束
158
+ if (newOffset > 0) {
159
+ if (!props.leftActions.length && !hasSlot('left')) return
160
+ offset.value = Math.min(maxLeftOffset.value * 1.2, newOffset)
161
+ } else if (newOffset < 0) {
162
+ if (!props.rightActions.length && !hasSlot('right')) return
163
+ offset.value = Math.max(-maxRightOffset.value * 1.2, newOffset)
164
+ }
165
+ }
166
+
167
+ function hasSlot(name) {
168
+ return false // 辅助防报错
169
+ }
170
+
171
+ function onTouchEnd() {
172
+ if (props.disabled) return
173
+ isSwiping.value = false
174
+
175
+ if (offset.value > maxLeftOffset.value * props.threshold) {
176
+ open('left')
177
+ } else if (offset.value < -maxRightOffset.value * props.threshold) {
178
+ open('right')
179
+ } else {
180
+ close()
181
+ }
182
+ }
183
+
184
+ function open(position = 'right') {
185
+ openedPosition.value = position
186
+ if (position === 'left') {
187
+ offset.value = maxLeftOffset.value
188
+ } else {
189
+ offset.value = -maxRightOffset.value
190
+ }
191
+ emit('open', position)
192
+ }
193
+
194
+ function close() {
195
+ openedPosition.value = ''
196
+ offset.value = 0
197
+ emit('close')
198
+ }
199
+
200
+ function handleActionClick(action, index, position) {
201
+ emit('click-action', { action, index, position })
202
+ if (props.autoClose) {
203
+ close()
204
+ }
205
+ }
206
+
207
+ function handleContentClick(e) {
208
+ if (openedPosition.value) {
209
+ close()
210
+ return
211
+ }
212
+ emit('click', e)
213
+ }
214
+
215
+ defineExpose({ open, close })
216
+ </script>
217
+
218
+ <style lang="scss" scoped>
219
+ @import "@/uni.scss";
220
+
221
+ .mu-swipe-cell {
222
+ position: relative;
223
+ width: 100%;
224
+ overflow: hidden;
225
+ box-sizing: border-box;
226
+
227
+ &--disabled {
228
+ opacity: 0.5;
229
+ pointer-events: none;
230
+ }
231
+
232
+ &__wrapper {
233
+ position: relative;
234
+ width: 100%;
235
+ display: flex;
236
+ align-items: stretch;
237
+ box-sizing: border-box;
238
+ }
239
+
240
+ &__content {
241
+ width: 100%;
242
+ flex-shrink: 0;
243
+ box-sizing: border-box;
244
+ }
245
+
246
+ &__left {
247
+ position: absolute;
248
+ top: 0;
249
+ bottom: 0;
250
+ right: 100%;
251
+ display: flex;
252
+ align-items: stretch;
253
+ z-index: 2;
254
+ }
255
+
256
+ &__right {
257
+ position: absolute;
258
+ top: 0;
259
+ bottom: 0;
260
+ left: 100%;
261
+ display: flex;
262
+ align-items: stretch;
263
+ z-index: 2;
264
+ }
265
+
266
+ &__action {
267
+ display: flex;
268
+ align-items: center;
269
+ justify-content: center;
270
+ height: 100%;
271
+ box-sizing: border-box;
272
+ cursor: pointer;
273
+
274
+ &-text {
275
+ font-size: 26rpx;
276
+ font-weight: 700;
277
+ white-space: nowrap;
278
+ }
279
+ }
280
+ }
281
+ </style>
@@ -0,0 +1,107 @@
1
+ <template>
2
+ <view class="mu-swiper" :style="{ height: formattedHeight }">
3
+ <swiper class="mu-swiper__inner" :current="current" :interval="interval" :duration="duration"
4
+ :autoplay="autoplay" :circular="loop" :indicator-dots="false"
5
+ @change="onChange">
6
+ <swiper-item v-for="(item, i) in list" :key="i" @tap="onTap(i)">
7
+ <slot :item="item" :index="i">
8
+ <view class="mu-swiper__item">
9
+ <image class="mu-swiper__image" :src="typeof item === 'string' ? item : (item && item.image ? item.image : '')" :mode="imageMode" />
10
+ <view v-if="item && item.title" class="mu-swiper__title">
11
+ <text class="mu-swiper__title-text">{{ item.title }}</text>
12
+ </view>
13
+ </view>
14
+ </slot>
15
+ </swiper-item>
16
+ </swiper>
17
+ <view v-if="indicator && list && list.length" class="mu-swiper__indicator">
18
+ <view v-for="(item, i) in list" :key="i" class="mu-swiper__dot"
19
+ :class="{ 'mu-swiper__dot--active': i === activeIndex }"></view>
20
+ </view>
21
+ </view>
22
+ </template>
23
+
24
+ <script setup>
25
+ /**
26
+ * mu-swiper 轮播图
27
+ * @description 循环轮播展示图片或内容
28
+ * @property {Array} list - 数据列表(字符串为图片URL,对象可插槽)
29
+ * @property {number|string} current - 当前索引
30
+ * @property {number|string} height - 高度rpx
31
+ * @property {number} interval - 自动播放间隔ms
32
+ * @property {number} duration - 切换动画时长ms
33
+ * @property {boolean} autoplay - 自动播放
34
+ * @property {boolean} loop - 循环播放
35
+ * @property {boolean} indicator - 显示指示器
36
+ * @property {string} imageMode - 图片裁剪模式
37
+ */
38
+ import { ref, computed, watch } from 'vue'
39
+
40
+ const props = defineProps({
41
+ list: { type: Array, default: () => [] },
42
+ current: { type: Number, default: 0 },
43
+ height: { type: [Number, String], default: 360 },
44
+ interval: { type: Number, default: 3000 },
45
+ duration: { type: Number, default: 300 },
46
+ autoplay: { type: Boolean, default: true },
47
+ loop: { type: Boolean, default: true },
48
+ indicator: { type: Boolean, default: true },
49
+ imageMode: { type: String, default: 'aspectFill' }
50
+ })
51
+
52
+ const emit = defineEmits(['change', 'click'])
53
+ const activeIndex = ref(props.current)
54
+
55
+ const formattedHeight = computed(() => {
56
+ if (typeof props.height === 'number') return `${props.height}rpx`
57
+ if (typeof props.height === 'string') {
58
+ if (props.height.endsWith('rpx') || props.height.endsWith('px')) return props.height
59
+ return `${props.height}rpx`
60
+ }
61
+ return '360rpx'
62
+ })
63
+
64
+ watch(() => props.current, (v) => { activeIndex.value = v })
65
+
66
+ function onChange(e) {
67
+ const cur = e.detail ? e.detail.current : 0
68
+ activeIndex.value = cur
69
+ emit('change', cur)
70
+ }
71
+
72
+ function onTap(index) {
73
+ emit('click', index)
74
+ }
75
+ </script>
76
+
77
+ <style lang="scss" scoped>
78
+ @import "@/uni.scss";
79
+
80
+ .mu-swiper {
81
+ position: relative; width: 100%; overflow: hidden;
82
+ border-radius: $mu-radius-md;
83
+ &__inner { width: 100%; height: 100%; }
84
+ &__item { position: relative; width: 100%; height: 100%; }
85
+ &__image { width: 100%; height: 100%; }
86
+ &__title {
87
+ position: absolute; left: 0; right: 0; bottom: 0;
88
+ padding: $mu-space-3 $mu-space-4;
89
+ background: linear-gradient(to top, rgba(0,0,0,0.4), transparent);
90
+ &-text { font-size: $mu-font-sm; color: #fff; }
91
+ }
92
+ &__indicator {
93
+ position: absolute; bottom: 16rpx; left: 50%;
94
+ transform: translateX(-50%);
95
+ display: flex; gap: 8rpx; z-index: 2;
96
+ }
97
+ &__dot {
98
+ width: 12rpx; height: 12rpx; border-radius: 50%;
99
+ background: rgba(255, 255, 255, 0.5);
100
+ transition: all $mu-duration $mu-ease;
101
+ &--active {
102
+ width: 32rpx; border-radius: 6rpx;
103
+ background: #fff;
104
+ }
105
+ }
106
+ }
107
+ </style>
@@ -0,0 +1,99 @@
1
+ <template>
2
+ <view class="mu-switch" :class="{ 'mu-switch--on': modelValue, 'mu-switch--disabled': disabled }" @tap="toggle">
3
+ <view class="mu-switch__track" :style="trackStyle">
4
+ <view class="mu-switch__thumb" :style="{ transform: modelValue ? 'translateX(38rpx)' : 'translateX(0)' }"></view>
5
+ </view>
6
+ <text v-if="label" class="mu-switch__label">{{ label }}</text>
7
+ </view>
8
+ </template>
9
+
10
+ <script setup>
11
+ import { computed } from 'vue'
12
+
13
+ const props = defineProps({
14
+ modelValue: { type: Boolean, default: false },
15
+ disabled: { type: Boolean, default: false },
16
+ label: { type: String, default: '' },
17
+ activeColor: { type: String, default: '' },
18
+ inactiveColor: { type: String, default: '' }
19
+ })
20
+
21
+ const emit = defineEmits(['update:modelValue', 'change'])
22
+
23
+ const trackStyle = computed(() => {
24
+ if (props.modelValue) {
25
+ return { background: props.activeColor || '' }
26
+ } else {
27
+ return { background: props.inactiveColor || '' }
28
+ }
29
+ })
30
+
31
+ function toggle() {
32
+ if (props.disabled) return
33
+ const val = !props.modelValue
34
+ emit('update:modelValue', val)
35
+ emit('change', val)
36
+ }
37
+ </script>
38
+
39
+ <style lang="scss" scoped>
40
+ @import "@/uni.scss";
41
+
42
+ .mu-switch {
43
+ display: inline-flex;
44
+ align-items: center;
45
+ cursor: pointer;
46
+
47
+ &--disabled { opacity: $mu-opacity-disabled; cursor: not-allowed; }
48
+
49
+ &__track {
50
+ width: 84rpx;
51
+ height: 46rpx;
52
+ border-radius: $mu-radius-full;
53
+ position: relative;
54
+ background: $mu-border;
55
+ transition: all $mu-duration $mu-ease;
56
+ padding: 4rpx;
57
+ display: flex;
58
+ align-items: center;
59
+ box-sizing: border-box;
60
+ }
61
+
62
+ &--on &__track {
63
+ background: $mu-primary-gradient;
64
+ box-shadow: 0 4rpx 14rpx rgba(99, 102, 241, 0.3);
65
+ }
66
+
67
+ &__thumb {
68
+ width: 38rpx;
69
+ height: 38rpx;
70
+ border-radius: 50%;
71
+ background: #ffffff;
72
+ box-shadow: 0 2rpx 8rpx rgba(15, 23, 42, 0.2);
73
+ transition: transform $mu-duration $mu-ease-spring;
74
+ }
75
+
76
+ &__label {
77
+ margin-left: 16rpx;
78
+ font-size: 28rpx;
79
+ font-weight: 600;
80
+ color: $mu-text-primary;
81
+ }
82
+ }
83
+
84
+ .mu-dark, page.mu-dark {
85
+
86
+ .mu-switch {
87
+ &__track { background: rgba(255, 255, 255, 0.12); }
88
+ &__label { color: $mu-dark-text-primary; }
89
+ }
90
+ }
91
+
92
+ @media (prefers-color-scheme: dark) {
93
+
94
+ .mu-switch {
95
+ &__track { background: rgba(255, 255, 255, 0.12); }
96
+ &__label { color: $mu-dark-text-primary; }
97
+ }
98
+ }
99
+ </style>