@atooyu/uxto-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 (141) hide show
  1. package/README.md +259 -0
  2. package/dist/index.js +5055 -0
  3. package/dist/index.js.map +1 -0
  4. package/dist/index.mjs +5055 -0
  5. package/dist/index.mjs.map +1 -0
  6. package/dist/style.css +2528 -0
  7. package/package.json +93 -0
  8. package/src/components/index.ts +51 -0
  9. package/src/components/u-avatar/u-avatar.vue +205 -0
  10. package/src/components/u-badge/u-badge.vue +145 -0
  11. package/src/components/u-button/u-button.vue +239 -0
  12. package/src/components/u-cell/u-cell.vue +179 -0
  13. package/src/components/u-cell-group/u-cell-group.vue +46 -0
  14. package/src/components/u-checkbox/u-checkbox.vue +174 -0
  15. package/src/components/u-checkbox-group/u-checkbox-group.vue +72 -0
  16. package/src/components/u-code-input/u-code-input.vue +248 -0
  17. package/src/components/u-count-down/u-count-down.vue +182 -0
  18. package/src/components/u-datetime-picker/u-datetime-picker.vue +377 -0
  19. package/src/components/u-divider/u-divider.vue +71 -0
  20. package/src/components/u-empty/u-empty.vue +98 -0
  21. package/src/components/u-grid/u-grid.vue +63 -0
  22. package/src/components/u-grid-item/u-grid-item.vue +170 -0
  23. package/src/components/u-icon/icons/account.svg +3 -0
  24. package/src/components/u-icon/icons/arrow-down.svg +3 -0
  25. package/src/components/u-icon/icons/arrow-left.svg +3 -0
  26. package/src/components/u-icon/icons/arrow-right.svg +3 -0
  27. package/src/components/u-icon/icons/arrow-up.svg +3 -0
  28. package/src/components/u-icon/icons/bell.svg +3 -0
  29. package/src/components/u-icon/icons/bookmark-o.svg +3 -0
  30. package/src/components/u-icon/icons/bookmark.svg +3 -0
  31. package/src/components/u-icon/icons/chat.svg +3 -0
  32. package/src/components/u-icon/icons/check-circle.svg +3 -0
  33. package/src/components/u-icon/icons/check.svg +3 -0
  34. package/src/components/u-icon/icons/chevron-left.svg +3 -0
  35. package/src/components/u-icon/icons/chevron-right.svg +3 -0
  36. package/src/components/u-icon/icons/clear-o.svg +3 -0
  37. package/src/components/u-icon/icons/clear.svg +3 -0
  38. package/src/components/u-icon/icons/clipboard.svg +3 -0
  39. package/src/components/u-icon/icons/clock.svg +3 -0
  40. package/src/components/u-icon/icons/close.svg +3 -0
  41. package/src/components/u-icon/icons/code.svg +3 -0
  42. package/src/components/u-icon/icons/copy.svg +3 -0
  43. package/src/components/u-icon/icons/delete.svg +3 -0
  44. package/src/components/u-icon/icons/download.svg +3 -0
  45. package/src/components/u-icon/icons/edit.svg +3 -0
  46. package/src/components/u-icon/icons/email.svg +3 -0
  47. package/src/components/u-icon/icons/error-o.svg +3 -0
  48. package/src/components/u-icon/icons/error.svg +3 -0
  49. package/src/components/u-icon/icons/exit-fullscreen.svg +3 -0
  50. package/src/components/u-icon/icons/expand-less.svg +3 -0
  51. package/src/components/u-icon/icons/expand-more.svg +3 -0
  52. package/src/components/u-icon/icons/eye-off.svg +3 -0
  53. package/src/components/u-icon/icons/eye.svg +3 -0
  54. package/src/components/u-icon/icons/flag-o.svg +3 -0
  55. package/src/components/u-icon/icons/flag.svg +3 -0
  56. package/src/components/u-icon/icons/fullscreen.svg +3 -0
  57. package/src/components/u-icon/icons/grid.svg +3 -0
  58. package/src/components/u-icon/icons/group.svg +3 -0
  59. package/src/components/u-icon/icons/heart-o.svg +3 -0
  60. package/src/components/u-icon/icons/heart.svg +3 -0
  61. package/src/components/u-icon/icons/info-o.svg +3 -0
  62. package/src/components/u-icon/icons/info.svg +3 -0
  63. package/src/components/u-icon/icons/keyboard-arrow-down.svg +3 -0
  64. package/src/components/u-icon/icons/keyboard-arrow-left.svg +3 -0
  65. package/src/components/u-icon/icons/keyboard-arrow-right.svg +3 -0
  66. package/src/components/u-icon/icons/keyboard-arrow-up.svg +3 -0
  67. package/src/components/u-icon/icons/like-o.svg +3 -0
  68. package/src/components/u-icon/icons/like.svg +3 -0
  69. package/src/components/u-icon/icons/link.svg +3 -0
  70. package/src/components/u-icon/icons/list.svg +3 -0
  71. package/src/components/u-icon/icons/loading.svg +3 -0
  72. package/src/components/u-icon/icons/lock.svg +3 -0
  73. package/src/components/u-icon/icons/menu-o.svg +3 -0
  74. package/src/components/u-icon/icons/menu.svg +3 -0
  75. package/src/components/u-icon/icons/message.svg +3 -0
  76. package/src/components/u-icon/icons/minus.svg +3 -0
  77. package/src/components/u-icon/icons/notification.svg +3 -0
  78. package/src/components/u-icon/icons/phone.svg +3 -0
  79. package/src/components/u-icon/icons/plus.svg +3 -0
  80. package/src/components/u-icon/icons/question.svg +3 -0
  81. package/src/components/u-icon/icons/redo.svg +3 -0
  82. package/src/components/u-icon/icons/refresh-o.svg +3 -0
  83. package/src/components/u-icon/icons/refresh.svg +3 -0
  84. package/src/components/u-icon/icons/reload.svg +3 -0
  85. package/src/components/u-icon/icons/search-o.svg +3 -0
  86. package/src/components/u-icon/icons/search.svg +3 -0
  87. package/src/components/u-icon/icons/setting.svg +3 -0
  88. package/src/components/u-icon/icons/share.svg +3 -0
  89. package/src/components/u-icon/icons/smile-o.svg +3 -0
  90. package/src/components/u-icon/icons/smile.svg +3 -0
  91. package/src/components/u-icon/icons/star-o.svg +3 -0
  92. package/src/components/u-icon/icons/star.svg +3 -0
  93. package/src/components/u-icon/icons/success-o.svg +3 -0
  94. package/src/components/u-icon/icons/success.svg +3 -0
  95. package/src/components/u-icon/icons/sync.svg +3 -0
  96. package/src/components/u-icon/icons/tick.svg +3 -0
  97. package/src/components/u-icon/icons/undo.svg +3 -0
  98. package/src/components/u-icon/icons/unlock.svg +3 -0
  99. package/src/components/u-icon/icons/upload.svg +3 -0
  100. package/src/components/u-icon/icons/user.svg +3 -0
  101. package/src/components/u-icon/icons/warning-o.svg +3 -0
  102. package/src/components/u-icon/icons/warning.svg +3 -0
  103. package/src/components/u-icon/icons/zoom-in.svg +3 -0
  104. package/src/components/u-icon/icons/zoom-out.svg +3 -0
  105. package/src/components/u-icon/index.ts +219 -0
  106. package/src/components/u-icon/u-icon.vue +117 -0
  107. package/src/components/u-image/u-image.vue +106 -0
  108. package/src/components/u-input/u-input.vue +208 -0
  109. package/src/components/u-keyboard/u-keyboard.vue +213 -0
  110. package/src/components/u-layout/u-layout.vue +58 -0
  111. package/src/components/u-line-progress/u-line-progress.vue +156 -0
  112. package/src/components/u-link/u-link.vue +113 -0
  113. package/src/components/u-list/u-list.vue +148 -0
  114. package/src/components/u-list-item/u-list-item.vue +180 -0
  115. package/src/components/u-loading/u-loading.vue +80 -0
  116. package/src/components/u-loading-page/u-loading-page.vue +94 -0
  117. package/src/components/u-modal/u-modal.vue +159 -0
  118. package/src/components/u-notice-bar/u-notice-bar.vue +113 -0
  119. package/src/components/u-number-box/u-number-box.vue +262 -0
  120. package/src/components/u-parse/u-parse.vue +197 -0
  121. package/src/components/u-picker/u-picker.vue +219 -0
  122. package/src/components/u-popup/u-popup.vue +257 -0
  123. package/src/components/u-radio/u-radio.vue +159 -0
  124. package/src/components/u-radio-group/u-radio-group.vue +61 -0
  125. package/src/components/u-rate/u-rate.vue +187 -0
  126. package/src/components/u-read-more/u-read-more.vue +117 -0
  127. package/src/components/u-search/u-search.vue +238 -0
  128. package/src/components/u-skeleton/u-skeleton.vue +192 -0
  129. package/src/components/u-slider/u-slider.vue +453 -0
  130. package/src/components/u-swiper/u-swiper.vue +301 -0
  131. package/src/components/u-swiper-item/u-swiper-item.vue +82 -0
  132. package/src/components/u-switch/u-switch.vue +105 -0
  133. package/src/components/u-tabbar/u-tabbar.vue +221 -0
  134. package/src/components/u-tag/u-tag.vue +144 -0
  135. package/src/components/u-textarea/u-textarea.vue +189 -0
  136. package/src/components/u-toast/u-toast.vue +186 -0
  137. package/src/components/u-tooltip/u-tooltip.vue +364 -0
  138. package/src/components/u-transition/u-transition.vue +216 -0
  139. package/src/components/u-upload/u-upload.vue +403 -0
  140. package/src/styles/index.scss +59 -0
  141. package/src/styles/variables.scss +68 -0
@@ -0,0 +1,239 @@
1
+ <template>
2
+ <button
3
+ class="u-button"
4
+ :class="[
5
+ `u-button--${type}`,
6
+ `u-button--${size}`,
7
+ {
8
+ 'u-button--plain': plain,
9
+ 'u-button--round': round,
10
+ 'u-button--square': square,
11
+ 'u-button--disabled': disabled,
12
+ 'u-button--loading': loading,
13
+ 'u-button--block': block
14
+ }
15
+ ]"
16
+ :style="buttonStyle"
17
+ :disabled="disabled || loading"
18
+ :hover-class="disabled || loading ? '' : 'u-button--active'"
19
+ @click="handleClick"
20
+ >
21
+ <view v-if="loading" class="u-button__loading">
22
+ <view class="u-button__loading-icon"></view>
23
+ </view>
24
+ <view v-else class="u-button__content">
25
+ <text v-if="icon" class="u-button__icon">{{ icon }}</text>
26
+ <text class="u-button__text"><slot /></text>
27
+ </view>
28
+ </button>
29
+ </template>
30
+
31
+ <script setup lang="ts">
32
+ import { computed } from 'vue'
33
+
34
+ type ButtonType = 'primary' | 'success' | 'warning' | 'danger' | 'default'
35
+ type ButtonSize = 'large' | 'normal' | 'small' | 'mini'
36
+
37
+ interface Props {
38
+ type?: ButtonType
39
+ size?: ButtonSize
40
+ plain?: boolean
41
+ round?: boolean
42
+ square?: boolean
43
+ disabled?: boolean
44
+ loading?: boolean
45
+ block?: boolean
46
+ icon?: string
47
+ color?: string
48
+ }
49
+
50
+ const props = withDefaults(defineProps<Props>(), {
51
+ type: 'default',
52
+ size: 'normal',
53
+ plain: false,
54
+ round: false,
55
+ square: false,
56
+ disabled: false,
57
+ loading: false,
58
+ block: false
59
+ })
60
+
61
+ const emit = defineEmits<{
62
+ click: [event: MouseEvent]
63
+ }>()
64
+
65
+ const buttonStyle = computed(() => {
66
+ if (props.color) {
67
+ return {
68
+ backgroundColor: props.plain ? 'transparent' : props.color,
69
+ borderColor: props.color,
70
+ color: props.plain ? props.color : '#fff'
71
+ }
72
+ }
73
+ return {}
74
+ })
75
+
76
+ const handleClick = (event: MouseEvent) => {
77
+ if (!props.disabled && !props.loading) {
78
+ emit('click', event)
79
+ }
80
+ }
81
+ </script>
82
+
83
+ <script lang="ts">
84
+ export default {
85
+ options: {
86
+ virtualHost: true,
87
+ styleIsolation: 'shared'
88
+ }
89
+ }
90
+ </script>
91
+
92
+ <style lang="scss" scoped>
93
+ .u-button {
94
+ display: inline-flex;
95
+ align-items: center;
96
+ justify-content: center;
97
+ position: relative;
98
+ box-sizing: border-box;
99
+ height: $--button-height;
100
+ padding: 0 $--spacing-lg;
101
+ margin: 0;
102
+ font-size: $--font-size-md;
103
+ line-height: 1.2;
104
+ text-align: center;
105
+ border-radius: $--border-radius-md;
106
+ border: 1px solid transparent;
107
+ transition: all $--transition-duration;
108
+ -webkit-tap-highlight-color: transparent;
109
+
110
+ &::after {
111
+ border: none;
112
+ }
113
+
114
+ &--default {
115
+ color: $--text-color;
116
+ background-color: $--bg-color-2;
117
+ border-color: $--border-color;
118
+ }
119
+
120
+ &--primary {
121
+ color: $--text-color-white;
122
+ background-color: $--color-primary;
123
+ border-color: $--color-primary;
124
+ }
125
+
126
+ &--success {
127
+ color: $--text-color-white;
128
+ background-color: $--color-success;
129
+ border-color: $--color-success;
130
+ }
131
+
132
+ &--warning {
133
+ color: $--text-color-white;
134
+ background-color: $--color-warning;
135
+ border-color: $--color-warning;
136
+ }
137
+
138
+ &--danger {
139
+ color: $--text-color-white;
140
+ background-color: $--color-danger;
141
+ border-color: $--color-danger;
142
+ }
143
+
144
+ &--large {
145
+ height: $--button-height-lg;
146
+ font-size: $--font-size-lg;
147
+ }
148
+
149
+ &--small {
150
+ height: $--button-height-sm;
151
+ padding: 0 $--spacing-md;
152
+ font-size: $--font-size-sm;
153
+ }
154
+
155
+ &--mini {
156
+ height: 24px;
157
+ padding: 0 $--spacing-sm;
158
+ font-size: $--font-size-xs;
159
+ }
160
+
161
+ &--plain {
162
+ background-color: transparent;
163
+
164
+ &.u-button--primary {
165
+ color: $--color-primary;
166
+ }
167
+
168
+ &.u-button--success {
169
+ color: $--color-success;
170
+ }
171
+
172
+ &.u-button--warning {
173
+ color: $--color-warning;
174
+ }
175
+
176
+ &.u-button--danger {
177
+ color: $--color-danger;
178
+ }
179
+ }
180
+
181
+ &--round {
182
+ border-radius: 999px;
183
+ }
184
+
185
+ &--square {
186
+ border-radius: 0;
187
+ }
188
+
189
+ &--disabled {
190
+ opacity: 0.5;
191
+ }
192
+
193
+ &--loading {
194
+ }
195
+
196
+ &--block {
197
+ display: flex;
198
+ width: 100%;
199
+ }
200
+
201
+ &--active {
202
+ opacity: 0.8;
203
+ }
204
+
205
+ &__content {
206
+ display: flex;
207
+ align-items: center;
208
+ justify-content: center;
209
+ }
210
+
211
+ &__icon {
212
+ margin-right: $--spacing-xs;
213
+ }
214
+
215
+ &__loading {
216
+ display: flex;
217
+ align-items: center;
218
+ justify-content: center;
219
+ }
220
+
221
+ &__loading-icon {
222
+ width: 16px;
223
+ height: 16px;
224
+ border: 2px solid currentColor;
225
+ border-top-color: transparent;
226
+ border-radius: 50%;
227
+ animation: u-button-loading 0.8s linear infinite;
228
+ }
229
+ }
230
+
231
+ @keyframes u-button-loading {
232
+ from {
233
+ transform: rotate(0deg);
234
+ }
235
+ to {
236
+ transform: rotate(360deg);
237
+ }
238
+ }
239
+ </style>
@@ -0,0 +1,179 @@
1
+ <template>
2
+ <view
3
+ class="u-cell"
4
+ :class="{
5
+ 'u-cell--clickable': isClickable,
6
+ 'u-cell--disabled': disabled
7
+ }"
8
+ :hover-class="isClickable && !disabled ? 'u-cell--active' : ''"
9
+ @click="handleClick"
10
+ >
11
+ <view v-if="$slots.icon || icon" class="u-cell__icon">
12
+ <slot name="icon">
13
+ <image v-if="icon" class="u-cell__icon-img" :src="icon" mode="aspectFit" />
14
+ </slot>
15
+ </view>
16
+
17
+ <view class="u-cell__content">
18
+ <view class="u-cell__title">
19
+ <text class="u-cell__title-text">{{ title }}</text>
20
+ <text v-if="label" class="u-cell__label">{{ label }}</text>
21
+ </view>
22
+
23
+ <view class="u-cell__value">
24
+ <slot name="value">
25
+ <text class="u-cell__value-text">{{ value }}</text>
26
+ </slot>
27
+ </view>
28
+ </view>
29
+
30
+ <view v-if="isLink" class="u-cell__arrow">
31
+ <text class="u-cell__arrow-icon">›</text>
32
+ </view>
33
+
34
+ <slot name="right-icon" />
35
+ </view>
36
+ </template>
37
+
38
+ <script setup lang="ts">
39
+ import { computed } from 'vue'
40
+
41
+ interface Props {
42
+ title?: string
43
+ value?: string | number
44
+ label?: string
45
+ icon?: string
46
+ isLink?: boolean
47
+ to?: string
48
+ url?: string
49
+ disabled?: boolean
50
+ clickable?: boolean
51
+ }
52
+
53
+ const props = withDefaults(defineProps<Props>(), {
54
+ title: '',
55
+ isLink: false,
56
+ disabled: false,
57
+ clickable: false
58
+ })
59
+
60
+ const emit = defineEmits<{
61
+ click: [event: MouseEvent]
62
+ }>()
63
+
64
+ const isClickable = computed(() => {
65
+ return props.clickable || props.isLink || props.to || props.url
66
+ })
67
+
68
+ const handleClick = (event: MouseEvent) => {
69
+ if (props.disabled) return
70
+
71
+ emit('click', event)
72
+
73
+ if (props.url) {
74
+ uni.navigateTo({ url: props.url })
75
+ } else if (props.to) {
76
+ uni.navigateTo({ url: props.to })
77
+ }
78
+ }
79
+ </script>
80
+
81
+ <script lang="ts">
82
+ export default {
83
+ options: {
84
+ virtualHost: true,
85
+ styleIsolation: 'shared'
86
+ }
87
+ }
88
+ </script>
89
+
90
+ <style lang="scss" scoped>
91
+ .u-cell {
92
+ display: flex;
93
+ align-items: center;
94
+ min-height: $--cell-height;
95
+ padding: $--spacing-md $--spacing-lg;
96
+ background-color: $--bg-color-2;
97
+ position: relative;
98
+
99
+ &::after {
100
+ content: '';
101
+ position: absolute;
102
+ left: $--spacing-lg;
103
+ right: 0;
104
+ bottom: 0;
105
+ height: 1px;
106
+ background-color: $--border-color;
107
+ transform: scaleY(0.5);
108
+ }
109
+
110
+ &:last-child::after {
111
+ display: none;
112
+ }
113
+
114
+ &--clickable {
115
+ }
116
+
117
+ &--disabled {
118
+ opacity: 0.5;
119
+ }
120
+
121
+ &--active {
122
+ background-color: $--bg-color;
123
+ }
124
+
125
+ &__icon {
126
+ margin-right: $--spacing-md;
127
+
128
+ &-img {
129
+ width: 20px;
130
+ height: 20px;
131
+ }
132
+ }
133
+
134
+ &__content {
135
+ flex: 1;
136
+ display: flex;
137
+ align-items: center;
138
+ justify-content: space-between;
139
+ overflow: hidden;
140
+ }
141
+
142
+ &__title {
143
+ flex: 1;
144
+ overflow: hidden;
145
+
146
+ &-text {
147
+ font-size: $--font-size-md;
148
+ color: $--text-color;
149
+ line-height: 24px;
150
+ }
151
+ }
152
+
153
+ &__label {
154
+ display: block;
155
+ margin-top: 2px;
156
+ font-size: $--font-size-sm;
157
+ color: $--text-color-2;
158
+ line-height: 18px;
159
+ }
160
+
161
+ &__value {
162
+ overflow: hidden;
163
+
164
+ &-text {
165
+ font-size: $--font-size-md;
166
+ color: $--text-color-2;
167
+ }
168
+ }
169
+
170
+ &__arrow {
171
+ margin-left: $--spacing-sm;
172
+ color: $--text-color-3;
173
+
174
+ &-icon {
175
+ font-size: 16px;
176
+ }
177
+ }
178
+ }
179
+ </style>
@@ -0,0 +1,46 @@
1
+ <template>
2
+ <view class="u-cell-group">
3
+ <view v-if="title || $slots.title" class="u-cell-group__title">
4
+ <slot name="title">{{ title }}</slot>
5
+ </view>
6
+ <view class="u-cell-group__body">
7
+ <slot />
8
+ </view>
9
+ </view>
10
+ </template>
11
+
12
+ <script setup lang="ts">
13
+ interface Props {
14
+ title?: string
15
+ }
16
+
17
+ withDefaults(defineProps<Props>(), {
18
+ title: ''
19
+ })
20
+ </script>
21
+
22
+ <script lang="ts">
23
+ export default {
24
+ options: {
25
+ virtualHost: true,
26
+ styleIsolation: 'shared'
27
+ }
28
+ }
29
+ </script>
30
+
31
+ <style lang="scss" scoped>
32
+ .u-cell-group {
33
+ background-color: $--bg-color-2;
34
+
35
+ &__title {
36
+ padding: $--spacing-md $--spacing-lg;
37
+ font-size: $--font-size-sm;
38
+ color: $--text-color-2;
39
+ background-color: $--bg-color;
40
+ }
41
+
42
+ &__body {
43
+ position: relative;
44
+ }
45
+ }
46
+ </style>
@@ -0,0 +1,174 @@
1
+ <template>
2
+ <view class="u-checkbox" :class="checkboxClass" @click="handleClick">
3
+ <view class="u-checkbox__icon" :class="iconClass" :style="iconStyle">
4
+ <text v-if="checked" class="u-checkbox__check">✓</text>
5
+ </view>
6
+ <view v-if="label || $slots.default" class="u-checkbox__label">
7
+ <slot>{{ label }}</slot>
8
+ </view>
9
+ </view>
10
+ </template>
11
+
12
+ <script setup lang="ts">
13
+ import { computed, inject } from 'vue'
14
+ import type { ComputedRef, Ref } from 'vue'
15
+
16
+ interface CheckboxGroupContext {
17
+ modelValue: Ref<any[]>
18
+ disabled: ComputedRef<boolean>
19
+ max: ComputedRef<number>
20
+ toggle: (value: any) => void
21
+ }
22
+
23
+ interface Props {
24
+ value?: any
25
+ label?: string
26
+ disabled?: boolean
27
+ checkedColor?: string
28
+ shape?: 'square' | 'circle'
29
+ iconSize?: number
30
+ }
31
+
32
+ const props = withDefaults(defineProps<Props>(), {
33
+ value: '',
34
+ label: '',
35
+ disabled: false,
36
+ checkedColor: '',
37
+ shape: 'square',
38
+ iconSize: 20
39
+ })
40
+
41
+ const emit = defineEmits<{
42
+ 'update:modelValue': [value: boolean]
43
+ change: [checked: boolean]
44
+ }>()
45
+
46
+ const group = inject<CheckboxGroupContext | null>('u-checkbox-group', null)
47
+
48
+ const checked = computed(() => {
49
+ if (group) {
50
+ return group.modelValue.value.includes(props.value)
51
+ }
52
+ return false
53
+ })
54
+
55
+ const isDisabled = computed(() => {
56
+ if (group) {
57
+ return group.disabled.value || props.disabled
58
+ }
59
+ return props.disabled
60
+ })
61
+
62
+ const checkboxClass = computed(() => [
63
+ {
64
+ 'u-checkbox--disabled': isDisabled.value,
65
+ 'u-checkbox--checked': checked.value
66
+ }
67
+ ])
68
+
69
+ const iconClass = computed(() => [
70
+ `u-checkbox__icon--${props.shape}`,
71
+ {
72
+ 'u-checkbox__icon--checked': checked.value,
73
+ 'u-checkbox__icon--disabled': isDisabled.value
74
+ }
75
+ ])
76
+
77
+ const iconStyle = computed(() => {
78
+ const style: Record<string, string> = {}
79
+ style.width = `${props.iconSize}px`
80
+ style.height = `${props.iconSize}px`
81
+
82
+ if (checked.value && props.checkedColor) {
83
+ style.backgroundColor = props.checkedColor
84
+ style.borderColor = props.checkedColor
85
+ }
86
+
87
+ return style
88
+ })
89
+
90
+ const handleClick = () => {
91
+ if (isDisabled.value) return
92
+
93
+ if (group) {
94
+ group.toggle(props.value)
95
+ } else {
96
+ emit('update:modelValue', !checked.value)
97
+ emit('change', !checked.value)
98
+ }
99
+ }
100
+ </script>
101
+
102
+ <script lang="ts">
103
+ export default {
104
+ options: {
105
+ virtualHost: true,
106
+ styleIsolation: 'shared'
107
+ }
108
+ }
109
+ </script>
110
+
111
+ <style lang="scss" scoped>
112
+ .u-checkbox {
113
+ display: inline-flex;
114
+ align-items: center;
115
+ -webkit-user-select: none;
116
+ -moz-user-select: none;
117
+ -ms-user-select: none;
118
+ user-select: none;
119
+
120
+ &--disabled {
121
+ opacity: 0.5;
122
+ }
123
+
124
+ &__icon {
125
+ display: flex;
126
+ align-items: center;
127
+ justify-content: center;
128
+ border: 1px solid $--border-color;
129
+ background-color: $--bg-color-2;
130
+ transition: all 0.2s;
131
+ flex-shrink: 0;
132
+
133
+ &--square {
134
+ border-radius: $--radius-sm;
135
+ }
136
+
137
+ &--circle {
138
+ border-radius: 50%;
139
+ }
140
+
141
+ &--checked {
142
+ background-color: $--color-primary;
143
+ border-color: $--color-primary;
144
+ }
145
+
146
+ &--disabled {
147
+ background-color: $--bg-color;
148
+ border-color: $--border-color;
149
+ }
150
+ }
151
+
152
+ &__check {
153
+ color: $--text-color-white;
154
+ font-size: 12px;
155
+ font-weight: bold;
156
+ line-height: 1;
157
+ }
158
+
159
+ &__label {
160
+ margin-left: $--spacing-sm;
161
+ font-size: $--font-size-base;
162
+ color: $--text-color;
163
+ line-height: 1.5;
164
+ }
165
+
166
+ &--checked &__label {
167
+ color: $--text-color;
168
+ }
169
+
170
+ &--disabled &__label {
171
+ color: $--text-color-3;
172
+ }
173
+ }
174
+ </style>
@@ -0,0 +1,72 @@
1
+ <template>
2
+ <view class="u-checkbox-group">
3
+ <slot />
4
+ </view>
5
+ </template>
6
+
7
+ <script setup lang="ts">
8
+ import { computed, provide, ref, watch } from 'vue'
9
+
10
+ interface Props {
11
+ modelValue?: any[]
12
+ disabled?: boolean
13
+ max?: number
14
+ }
15
+
16
+ const props = withDefaults(defineProps<Props>(), {
17
+ modelValue: () => [],
18
+ disabled: false,
19
+ max: 0
20
+ })
21
+
22
+ const emit = defineEmits<{
23
+ 'update:modelValue': [value: any[]]
24
+ change: [value: any[]]
25
+ }>()
26
+
27
+ const innerValue = ref([...props.modelValue])
28
+
29
+ watch(() => props.modelValue, (val) => {
30
+ innerValue.value = [...val]
31
+ }, { deep: true })
32
+
33
+ const toggle = (value: any) => {
34
+ const index = innerValue.value.indexOf(value)
35
+
36
+ if (index > -1) {
37
+ innerValue.value.splice(index, 1)
38
+ } else {
39
+ if (props.max > 0 && innerValue.value.length >= props.max) {
40
+ return
41
+ }
42
+ innerValue.value.push(value)
43
+ }
44
+
45
+ emit('update:modelValue', [...innerValue.value])
46
+ emit('change', [...innerValue.value])
47
+ }
48
+
49
+ provide('u-checkbox-group', {
50
+ modelValue: innerValue,
51
+ disabled: computed(() => props.disabled),
52
+ max: computed(() => props.max),
53
+ toggle
54
+ })
55
+ </script>
56
+
57
+ <script lang="ts">
58
+ export default {
59
+ options: {
60
+ virtualHost: true,
61
+ styleIsolation: 'shared'
62
+ }
63
+ }
64
+ </script>
65
+
66
+ <style lang="scss" scoped>
67
+ .u-checkbox-group {
68
+ display: flex;
69
+ flex-wrap: wrap;
70
+ gap: $--spacing-base;
71
+ }
72
+ </style>