@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
package/package.json ADDED
@@ -0,0 +1,93 @@
1
+ {
2
+ "name": "@atooyu/uxto-ui",
3
+ "version": "1.0.0",
4
+ "description": "跨平台 UI 组件库 - 支持 Android、iOS、鸿蒙",
5
+ "keywords": [
6
+ "uxto-ui",
7
+ "uni-app",
8
+ "cross-platform",
9
+ "android",
10
+ "ios",
11
+ "harmony",
12
+ "vue3",
13
+ "components"
14
+ ],
15
+ "author": "",
16
+ "license": "MIT",
17
+ "main": "dist/index.js",
18
+ "module": "dist/index.mjs",
19
+ "types": "dist/index.d.ts",
20
+ "exports": {
21
+ ".": {
22
+ "import": "./dist/index.mjs",
23
+ "require": "./dist/index.js",
24
+ "types": "./dist/index.d.ts"
25
+ },
26
+ "./style": "./dist/style.css",
27
+ "./scss": "./src/styles/index.scss"
28
+ },
29
+ "files": [
30
+ "dist",
31
+ "src/components",
32
+ "src/styles"
33
+ ],
34
+ "sideEffects": [
35
+ "**/*.css",
36
+ "**/*.scss"
37
+ ],
38
+ "repository": {
39
+ "type": "git",
40
+ "url": "https://github.com/atooyu/uxto-ui.git"
41
+ },
42
+ "bugs": {
43
+ "url": "https://github.com/atooyu/uxto-ui/issues"
44
+ },
45
+ "homepage": "https://uxto-ui.atooyu.com",
46
+ "scripts": {
47
+ "dev": "uni -p app",
48
+ "dev:h5": "uni",
49
+ "dev:mp-weixin": "uni -p mp-weixin",
50
+ "build:app": "uni build -p app",
51
+ "build:h5": "uni build",
52
+ "build:mp-weixin": "uni build -p mp-weixin",
53
+ "build:harmony": "uni build -p app-harmony",
54
+ "build:lib": "vite build --config vite.build.config.ts",
55
+ "build:types": "tsc --emitDeclarationOnly --declaration --outDir dist",
56
+ "build:all": "npm run build:lib && npm run build:types",
57
+ "docs:dev": "cd docs && npm run docs:dev",
58
+ "docs:build": "cd docs && npm run docs:build",
59
+ "lint": "eslint . --ext .vue,.js,.ts,.jsx,.tsx",
60
+ "test": "vitest",
61
+ "prepublishOnly": "npm run build:all"
62
+ },
63
+ "dependencies": {
64
+ "@dcloudio/uni-app": "3.0.0-4060620250520001",
65
+ "@dcloudio/uni-app-harmony": "3.0.0-4060620250520001",
66
+ "@dcloudio/uni-components": "3.0.0-4060620250520001",
67
+ "@dcloudio/uni-h5": "3.0.0-4060620250520001",
68
+ "vue": "^3.5.13"
69
+ },
70
+ "devDependencies": {
71
+ "@dcloudio/types": "^3.4.14",
72
+ "@dcloudio/uni-automator": "3.0.0-4060620250520001",
73
+ "@dcloudio/uni-cli-shared": "3.0.0-4060620250520001",
74
+ "@dcloudio/uni-stacktracey": "3.0.0-4060620250520001",
75
+ "@dcloudio/vite-plugin-uni": "3.0.0-4060620250520001",
76
+ "@types/node": "^22.13.10",
77
+ "@vue/runtime-core": "^3.5.13",
78
+ "sass": "^1.85.1",
79
+ "typescript": "^5.8.2",
80
+ "vite": "^5.2.8",
81
+ "vitest": "^3.0.8"
82
+ },
83
+ "engines": {
84
+ "node": ">=18.0.0"
85
+ },
86
+ "publishConfig": {
87
+ "access": "public",
88
+ "registry": "https://registry.npmjs.org/"
89
+ },
90
+ "peerDependencies": {
91
+ "vue": "^3.4.0"
92
+ }
93
+ }
@@ -0,0 +1,51 @@
1
+ // 组件导出
2
+ export { default as UButton } from './u-button/u-button.vue'
3
+ export { default as UInput } from './u-input/u-input.vue'
4
+ export { default as UCell } from './u-cell/u-cell.vue'
5
+ export { default as UCellGroup } from './u-cell-group/u-cell-group.vue'
6
+ export { default as UModal } from './u-modal/u-modal.vue'
7
+ export { default as UIcon } from './u-icon/u-icon.vue'
8
+ // SVG 图标库
9
+ export * from './u-icon/index'
10
+ export { default as ULoading } from './u-loading/u-loading.vue'
11
+ export { default as UTag } from './u-tag/u-tag.vue'
12
+ export { default as USwitch } from './u-switch/u-switch.vue'
13
+ export { default as UImage } from './u-image/u-image.vue'
14
+ export { default as UDivider } from './u-divider/u-divider.vue'
15
+ export { default as UNoticeBar } from './u-notice-bar/u-notice-bar.vue'
16
+ export { default as ULayout } from './u-layout/u-layout.vue'
17
+ export { default as UBadge } from './u-badge/u-badge.vue'
18
+ export { default as ULoadingPage } from './u-loading-page/u-loading-page.vue'
19
+ export { default as UParse } from './u-parse/u-parse.vue'
20
+ export { default as UKeyboard } from './u-keyboard/u-keyboard.vue'
21
+ export { default as UPicker } from './u-picker/u-picker.vue'
22
+ export { default as UDatetimePicker } from './u-datetime-picker/u-datetime-picker.vue'
23
+ export { default as URate } from './u-rate/u-rate.vue'
24
+ export { default as UGrid } from './u-grid/u-grid.vue'
25
+ export { default as UGridItem } from './u-grid-item/u-grid-item.vue'
26
+ export { default as USwiper } from './u-swiper/u-swiper.vue'
27
+ export { default as USwiperItem } from './u-swiper-item/u-swiper-item.vue'
28
+ export { default as USearch } from './u-search/u-search.vue'
29
+ export { default as UNumberBox } from './u-number-box/u-number-box.vue'
30
+ export { default as UUpload } from './u-upload/u-upload.vue'
31
+ export { default as UTextarea } from './u-textarea/u-textarea.vue'
32
+ export { default as USlider } from './u-slider/u-slider.vue'
33
+ export { default as UList } from './u-list/u-list.vue'
34
+ export { default as UListItem } from './u-list-item/u-list-item.vue'
35
+ export { default as ULineProgress } from './u-line-progress/u-line-progress.vue'
36
+ export { default as UCountDown } from './u-count-down/u-count-down.vue'
37
+ export { default as UTooltip } from './u-tooltip/u-tooltip.vue'
38
+ export { default as UAvatar } from './u-avatar/u-avatar.vue'
39
+ export { default as UEmpty } from './u-empty/u-empty.vue'
40
+ export { default as UCheckbox } from './u-checkbox/u-checkbox.vue'
41
+ export { default as UCheckboxGroup } from './u-checkbox-group/u-checkbox-group.vue'
42
+ export { default as URadio } from './u-radio/u-radio.vue'
43
+ export { default as URadioGroup } from './u-radio-group/u-radio-group.vue'
44
+ export { default as UToast } from './u-toast/u-toast.vue'
45
+ export { default as UPopup } from './u-popup/u-popup.vue'
46
+ export { default as UCodeInput } from './u-code-input/u-code-input.vue'
47
+ export { default as USkeleton } from './u-skeleton/u-skeleton.vue'
48
+ export { default as UTransition } from './u-transition/u-transition.vue'
49
+ export { default as ULink } from './u-link/u-link.vue'
50
+ export { default as UReadMore } from './u-read-more/u-read-more.vue'
51
+ export { default as UTabbar } from './u-tabbar/u-tabbar.vue'
@@ -0,0 +1,205 @@
1
+ <template>
2
+ <view class="u-avatar" :class="avatarClass" :style="avatarStyle">
3
+ <slot>
4
+ <image v-if="src" class="u-avatar__image" :src="src" mode="aspectFill" @error="handleError" />
5
+ <text v-else-if="text" class="u-avatar__text">{{ displayText }}</text>
6
+ <text v-else class="u-avatar__icon">{{ icon || '👤' }}</text>
7
+ </slot>
8
+ <view v-if="badge && !badgeSlot" class="u-avatar__badge" :class="badgeClass">
9
+ <text v-if="!dot" class="u-avatar__badge-text">{{ badge }}</text>
10
+ </view>
11
+ <slot name="badge" />
12
+ </view>
13
+ </template>
14
+
15
+ <script setup lang="ts">
16
+ import { computed, ref, useSlots } from 'vue'
17
+
18
+ type AvatarSize = 'small' | 'medium' | 'large' | 'xlarge'
19
+ type AvatarShape = 'circle' | 'square'
20
+ type BadgePosition = 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left'
21
+
22
+ interface Props {
23
+ src?: string
24
+ text?: string
25
+ icon?: string
26
+ size?: AvatarSize | number
27
+ shape?: AvatarShape
28
+ color?: string
29
+ bgColor?: string
30
+ badge?: string | number
31
+ dot?: boolean
32
+ badgeColor?: string
33
+ badgePosition?: BadgePosition
34
+ maxTextLength?: number
35
+ }
36
+
37
+ const props = withDefaults(defineProps<Props>(), {
38
+ src: '',
39
+ text: '',
40
+ icon: '',
41
+ size: 'medium',
42
+ shape: 'circle',
43
+ bgColor: '#e8e8e8',
44
+ dot: false,
45
+ badgePosition: 'top-right',
46
+ maxTextLength: 2
47
+ })
48
+
49
+ const slots = useSlots()
50
+ const loadError = ref(false)
51
+
52
+ const badgeSlot = computed(() => Boolean(slots.badge))
53
+
54
+ const handleError = () => {
55
+ loadError.value = true
56
+ }
57
+
58
+ const displayText = computed(() => {
59
+ if (!props.text) return ''
60
+ if (props.text.length <= props.maxTextLength) return props.text
61
+ return props.text.slice(0, props.maxTextLength)
62
+ })
63
+
64
+ const sizeMap: Record<string, number> = {
65
+ small: 32,
66
+ medium: 48,
67
+ large: 64,
68
+ xlarge: 80
69
+ }
70
+
71
+ const avatarSize = computed(() => {
72
+ if (typeof props.size === 'number') return props.size
73
+ return sizeMap[props.size] || 48
74
+ })
75
+
76
+ const avatarClass = computed(() => [
77
+ `u-avatar--${props.shape}`,
78
+ {
79
+ 'u-avatar--error': loadError.value
80
+ }
81
+ ])
82
+
83
+ const avatarStyle = computed(() => {
84
+ const style: Record<string, string> = {}
85
+ const size = avatarSize.value
86
+
87
+ style.width = `${size}px`
88
+ style.height = `${size}px`
89
+
90
+ if (props.bgColor) {
91
+ style.backgroundColor = props.bgColor
92
+ }
93
+
94
+ if (props.color) {
95
+ style.color = props.color
96
+ }
97
+
98
+ if (props.shape === 'square') {
99
+ style.borderRadius = '4px'
100
+ }
101
+
102
+ return style
103
+ })
104
+
105
+ const badgeClass = computed(() => [
106
+ `u-avatar__badge--${props.badgePosition}`,
107
+ {
108
+ 'u-avatar__badge--dot': props.dot
109
+ }
110
+ ])
111
+ </script>
112
+
113
+ <script lang="ts">
114
+ export default {
115
+ options: {
116
+ virtualHost: true,
117
+ styleIsolation: 'shared'
118
+ }
119
+ }
120
+ </script>
121
+
122
+ <style lang="scss" scoped>
123
+ .u-avatar {
124
+ position: relative;
125
+ display: inline-flex;
126
+ align-items: center;
127
+ justify-content: center;
128
+ overflow: hidden;
129
+ box-sizing: border-box;
130
+ background-color: $--bg-color;
131
+ font-weight: 500;
132
+
133
+ &--circle {
134
+ border-radius: 50%;
135
+ }
136
+
137
+ &--square {
138
+ border-radius: $--radius-sm;
139
+ }
140
+
141
+ &__image {
142
+ width: 100%;
143
+ height: 100%;
144
+ }
145
+
146
+ &__text {
147
+ font-size: 16px;
148
+ color: $--text-color-2;
149
+ line-height: 1;
150
+ }
151
+
152
+ &__icon {
153
+ font-size: 24px;
154
+ color: $--text-color-3;
155
+ }
156
+
157
+ &__badge {
158
+ position: absolute;
159
+ z-index: 1;
160
+ display: flex;
161
+ align-items: center;
162
+ justify-content: center;
163
+ min-width: 16px;
164
+ height: 16px;
165
+ padding: 0 4px;
166
+ font-size: 10px;
167
+ color: $--text-color-white;
168
+ background-color: $--color-danger;
169
+ border-radius: 999px;
170
+ box-sizing: border-box;
171
+
172
+ &--dot {
173
+ min-width: 8px;
174
+ width: 8px;
175
+ height: 8px;
176
+ padding: 0;
177
+ border-radius: 50%;
178
+ }
179
+
180
+ &--top-right {
181
+ top: 0;
182
+ right: 0;
183
+ transform: translate(25%, -25%);
184
+ }
185
+
186
+ &--top-left {
187
+ top: 0;
188
+ left: 0;
189
+ transform: translate(-25%, -25%);
190
+ }
191
+
192
+ &--bottom-right {
193
+ bottom: 0;
194
+ right: 0;
195
+ transform: translate(25%, 25%);
196
+ }
197
+
198
+ &--bottom-left {
199
+ bottom: 0;
200
+ left: 0;
201
+ transform: translate(-25%, 25%);
202
+ }
203
+ }
204
+ }
205
+ </style>
@@ -0,0 +1,145 @@
1
+ <template>
2
+ <view class="u-badge" :class="{ 'u-badge--fixed': fixed }">
3
+ <slot />
4
+ <view
5
+ v-if="showBadge"
6
+ class="u-badge__content"
7
+ :class="[`u-badge__content--${type}`, { 'u-badge__content--dot': dot, 'u-badge__content--alone': !$slots.default }]"
8
+ :style="badgeStyle"
9
+ >
10
+ <text v-if="!dot && displayValue" class="u-badge__text">{{ displayValue }}</text>
11
+ </view>
12
+ </view>
13
+ </template>
14
+
15
+ <script setup lang="ts">
16
+ import { computed } from 'vue'
17
+
18
+ type BadgeType = 'primary' | 'success' | 'warning' | 'danger' | 'info'
19
+
20
+ interface Props {
21
+ value?: number | string
22
+ max?: number
23
+ dot?: boolean
24
+ hidden?: boolean
25
+ type?: BadgeType
26
+ color?: string
27
+ offset?: [number, number]
28
+ fixed?: boolean
29
+ }
30
+
31
+ const props = withDefaults(defineProps<Props>(), {
32
+ max: 99,
33
+ dot: false,
34
+ hidden: false,
35
+ type: 'danger',
36
+ fixed: false
37
+ })
38
+
39
+ const showBadge = computed(() => {
40
+ return !props.hidden && (props.dot || props.value !== undefined)
41
+ })
42
+
43
+ const displayValue = computed(() => {
44
+ if (props.dot) return ''
45
+ if (typeof props.value === 'number') {
46
+ return props.value > props.max ? `${props.max}+` : props.value
47
+ }
48
+ return props.value
49
+ })
50
+
51
+ const badgeStyle = computed(() => {
52
+ const style: Record<string, string> = {}
53
+
54
+ if (props.color) {
55
+ style.backgroundColor = props.color
56
+ }
57
+
58
+ if (props.offset && props.offset.length === 2) {
59
+ const [x, y] = props.offset
60
+ style.transform = `translate(${x}px, ${y}px)`
61
+ }
62
+
63
+ return style
64
+ })
65
+ </script>
66
+
67
+ <script lang="ts">
68
+ export default {
69
+ options: {
70
+ virtualHost: true,
71
+ styleIsolation: 'shared'
72
+ }
73
+ }
74
+ </script>
75
+
76
+ <style lang="scss" scoped>
77
+ .u-badge {
78
+ position: relative;
79
+ display: inline-block;
80
+
81
+ &--fixed {
82
+ position: absolute;
83
+ top: 0;
84
+ right: 0;
85
+ transform: translate(50%, -50%);
86
+ }
87
+
88
+ &__content {
89
+ position: absolute;
90
+ top: 0;
91
+ right: 0;
92
+ transform: translate(50%, -50%);
93
+ display: inline-flex;
94
+ align-items: center;
95
+ justify-content: center;
96
+ min-width: 16px;
97
+ height: 16px;
98
+ padding: 0 5px;
99
+ border-radius: 999px;
100
+ font-size: $--font-size-xs;
101
+ line-height: 1;
102
+ color: $--text-color-white;
103
+ white-space: nowrap;
104
+ box-sizing: border-box;
105
+
106
+ &--dot {
107
+ min-width: 8px;
108
+ width: 8px;
109
+ height: 8px;
110
+ padding: 0;
111
+ border-radius: 50%;
112
+ }
113
+
114
+ &--alone {
115
+ position: relative;
116
+ transform: none;
117
+ }
118
+
119
+ &--primary {
120
+ background-color: $--color-primary;
121
+ }
122
+
123
+ &--success {
124
+ background-color: $--color-success;
125
+ }
126
+
127
+ &--warning {
128
+ background-color: $--color-warning;
129
+ }
130
+
131
+ &--danger {
132
+ background-color: $--color-danger;
133
+ }
134
+
135
+ &--info {
136
+ background-color: $--color-info;
137
+ }
138
+ }
139
+
140
+ &__text {
141
+ display: inline-block;
142
+ vertical-align: middle;
143
+ }
144
+ }
145
+ </style>