tang-ui-x 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 (98) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +141 -0
  3. package/components/TActionSheet/index.uvue +170 -0
  4. package/components/TActionSheet/type.uts +29 -0
  5. package/components/TAvatar/index.uvue +156 -0
  6. package/components/TAvatar/type.uts +54 -0
  7. package/components/TBadge/index.uvue +152 -0
  8. package/components/TBadge/type.uts +48 -0
  9. package/components/TButton/README.md +111 -0
  10. package/components/TButton/index.uvue +380 -0
  11. package/components/TButton/type.uts +95 -0
  12. package/components/TCard/index.uvue +174 -0
  13. package/components/TCard/type.uts +50 -0
  14. package/components/TCell/index.uvue +49 -0
  15. package/components/TCheckbox/index.uvue +187 -0
  16. package/components/TCheckboxGroup/index.uvue +139 -0
  17. package/components/TCheckboxGroup/type.uts +26 -0
  18. package/components/TCol/index.uvue +82 -0
  19. package/components/TCol/type.uts +30 -0
  20. package/components/TCollapse/index.uvue +93 -0
  21. package/components/TCollapse/type.uts +36 -0
  22. package/components/TCollapseItem/index.uvue +194 -0
  23. package/components/TCollapseItem/type.uts +25 -0
  24. package/components/TDialog/index.uvue +386 -0
  25. package/components/TDialog/type.uts +84 -0
  26. package/components/TDivider/index.uvue +235 -0
  27. package/components/TDivider/type.uts +91 -0
  28. package/components/TEmpty/index.uvue +128 -0
  29. package/components/TErrorState/index.uvue +57 -0
  30. package/components/TGrid/index.uvue +115 -0
  31. package/components/TGrid/type.uts +77 -0
  32. package/components/TGridItem/index.uvue +243 -0
  33. package/components/TGridItem/type.uts +64 -0
  34. package/components/TIcon/index.uvue +96 -0
  35. package/components/TImage/index.uvue +255 -0
  36. package/components/TImage/type.uts +146 -0
  37. package/components/TInput/README.md +119 -0
  38. package/components/TInput/index.uvue +376 -0
  39. package/components/TInput/type.uts +138 -0
  40. package/components/TList/index.uvue +82 -0
  41. package/components/TList/type.uts +68 -0
  42. package/components/TListItem/index.uvue +161 -0
  43. package/components/TListItem/type.uts +49 -0
  44. package/components/TLoading/index.uvue +153 -0
  45. package/components/TLoading/type.uts +43 -0
  46. package/components/TNavBar/index.uvue +120 -0
  47. package/components/TNavBar/type.uts +22 -0
  48. package/components/TNoticeBar/index.uvue +106 -0
  49. package/components/TNoticeBar/type.uts +21 -0
  50. package/components/TNumberInput/index.uvue +226 -0
  51. package/components/TPicker/index.uvue +276 -0
  52. package/components/TPicker/type.uts +105 -0
  53. package/components/TPopup/index.uvue +442 -0
  54. package/components/TProgress/index.uvue +103 -0
  55. package/components/TProgress/type.uts +64 -0
  56. package/components/TRadioButton/index.uvue +232 -0
  57. package/components/TRadioGroup/index.uvue +117 -0
  58. package/components/TRadioGroup/type.uts +25 -0
  59. package/components/TRate/index.uvue +182 -0
  60. package/components/TRow/index.uvue +105 -0
  61. package/components/TRow/type.uts +52 -0
  62. package/components/TSearchBar/index.uvue +255 -0
  63. package/components/TSearchBar/type.uts +140 -0
  64. package/components/TSelect/index.uvue +655 -0
  65. package/components/TSelect/type.uts +57 -0
  66. package/components/TSlider/index.uvue +72 -0
  67. package/components/TSlider/type.uts +21 -0
  68. package/components/TSwiper/index.uvue +222 -0
  69. package/components/TSwiper/type.uts +77 -0
  70. package/components/TSwitch/index.uvue +177 -0
  71. package/components/TSwitch/type.uts +52 -0
  72. package/components/TText/README.md +124 -0
  73. package/components/TText/index.uvue +257 -0
  74. package/components/TText/type.uts +114 -0
  75. package/components/TTextarea/index.uvue +239 -0
  76. package/components/TTextarea/type.uts +106 -0
  77. package/components/TToast/type.uts +14 -0
  78. package/components/Tabs/README.md +297 -0
  79. package/components/Tabs/index.uvue +383 -0
  80. package/components/Tabs/type.uts +10 -0
  81. package/components/Tags/README.md +297 -0
  82. package/components/Tags/index.uvue +383 -0
  83. package/components/Tags/type.uts +10 -0
  84. package/components/VbenFrom/index.uvue +392 -0
  85. package/composables/useModal.uts +294 -0
  86. package/composables/useTheme.uts +235 -0
  87. package/composables/useToast.uts +322 -0
  88. package/index.js +62 -0
  89. package/package.json +48 -0
  90. package/style/colors/index.scss +157 -0
  91. package/style/index.scss +399 -0
  92. package/types/index.uts +52 -0
  93. package/uni.scss +79 -0
  94. package/utils/color.uts +92 -0
  95. package/utils/common.uts +245 -0
  96. package/utils/dom.uts +275 -0
  97. package/utils/index.uts +10 -0
  98. package/utils/validator.uts +155 -0
@@ -0,0 +1,72 @@
1
+ <script setup lang="uts">
2
+ import type { TSliderProps } from './type.uts'
3
+
4
+ /**
5
+ * TSlider 滑块组件
6
+ * @description 用于在给定范围内选择数值的滑块组件
7
+ */
8
+
9
+ // Props 定义 (从 type.uts 导入,排除 modelValue)
10
+ type Props = Omit<TSliderProps, 'modelValue'>
11
+
12
+ const props = withDefaults(defineProps<Props>(), {
13
+ min: 0,
14
+ max: 100,
15
+ step: 1,
16
+ disabled: false,
17
+ showValue: false,
18
+ activeColor: '#1890ff',
19
+ inactiveColor: '#e9e9e9',
20
+ customClass: '',
21
+ customStyle: ''
22
+ })
23
+
24
+ // 使用 defineModel 管理双向绑定
25
+ const modelValue = defineModel<number>({ default: 0 })
26
+
27
+ const emit = defineEmits<{
28
+ change: [value: number]
29
+ }>()
30
+
31
+ const handleChange = (event: any): void => {
32
+ const value = event.detail.value as number
33
+ modelValue.value = value
34
+ emit('change', value)
35
+ }
36
+ </script>
37
+
38
+ <template>
39
+ <view class="t-slider" :class="customClass" :style="customStyle">
40
+ <slider
41
+ :value="modelValue"
42
+ :min="min"
43
+ :max="max"
44
+ :step="step"
45
+ :disabled="disabled"
46
+ :activeColor="activeColor"
47
+ :backgroundColor="inactiveColor"
48
+ :block-size="24"
49
+ @change="handleChange"
50
+ />
51
+ <text v-if="showValue" class="t-slider__value">{{ modelValue }}</text>
52
+ </view>
53
+ </template>
54
+
55
+ <style lang="scss" scoped>
56
+ .t-slider {
57
+ display: flex;
58
+ align-items: center;
59
+ padding: 12px 0;
60
+ }
61
+
62
+ .t-slider__value {
63
+ margin-left: 12px;
64
+ font-size: 14px;
65
+ color: #323233;
66
+ min-width: 40px;
67
+ text-align: right;
68
+ }
69
+ uni-slider,slider{
70
+ width: 100%;
71
+ }
72
+ </style>
@@ -0,0 +1,21 @@
1
+ /**
2
+ * TSlider 组件类型定义
3
+ */
4
+
5
+ export interface TSliderProps {
6
+ modelValue?: number
7
+ min?: number
8
+ max?: number
9
+ step?: number
10
+ disabled?: boolean
11
+ showValue?: boolean
12
+ activeColor?: string
13
+ inactiveColor?: string
14
+ customClass?: string
15
+ customStyle?: string
16
+ }
17
+
18
+ export interface TSliderEmits {
19
+ 'update:modelValue': (value: number) => void
20
+ change: (value: number) => void
21
+ }
@@ -0,0 +1,222 @@
1
+ <script setup lang="uts">
2
+ import { computed, ref, watch } from 'vue'
3
+ import type { TSwiperProps } from './type.uts'
4
+
5
+ /**
6
+ * TSwiper 轮播图组件
7
+ * @description 基于 UniApp 原生 swiper 封装的轮播图组件
8
+ */
9
+
10
+ // 定义 props
11
+ const props = withDefaults(defineProps<TSwiperProps>(), {
12
+ height: '200px',
13
+ autoplay: true,
14
+ interval: 3000,
15
+ duration: 300,
16
+ circular: true,
17
+ indicatorType: 'dots',
18
+ indicatorPosition: 'bottom',
19
+ indicatorColor: 'rgba(0, 0, 0, 0.3)',
20
+ indicatorActiveColor: '#ffffff',
21
+ direction: 'horizontal'
22
+ })
23
+
24
+ // 使用 defineModel 管理当前索引
25
+ const currentIndex = defineModel<number>({ default: 0 })
26
+
27
+ // 定义 emits
28
+ const emit = defineEmits<{
29
+ change: [index: number]
30
+ click: [index: number]
31
+ }>()
32
+
33
+ // 轮播项总数(通过插槽统计)
34
+ const swiperItemCount = ref<number>(0)
35
+
36
+ /**
37
+ * 计算容器样式
38
+ */
39
+ const swiperStyle = computed<string>(() => {
40
+ const styles: string[] = []
41
+
42
+ if (props.height != '') {
43
+ styles.push(`height: ${props.height}`)
44
+ }
45
+
46
+ return styles.join('; ')
47
+ })
48
+
49
+ /**
50
+ * 计算指示器容器样式类
51
+ */
52
+ const indicatorClass = computed<string>(() => {
53
+ const classes: string[] = ['t-swiper__indicator']
54
+
55
+ classes.push(`t-swiper__indicator--${props.indicatorPosition}`)
56
+ classes.push(`t-swiper__indicator--${props.direction}`)
57
+
58
+ return classes.join(' ')
59
+ })
60
+
61
+ /**
62
+ * 获取指示器点样式
63
+ */
64
+ const getDotStyle = (index: number): string => {
65
+ const isActive = index === currentIndex.value
66
+ const bgColor = isActive ? props.indicatorActiveColor : props.indicatorColor
67
+
68
+ return `background-color: ${bgColor}`
69
+ }
70
+
71
+ /**
72
+ * 处理轮播改变事件
73
+ */
74
+ const handleChange = (e: any): void => {
75
+ const detail = e.detail
76
+ if (detail != null && detail.current != null) {
77
+ currentIndex.value = detail.current as number
78
+ emit('change', detail.current as number)
79
+ }
80
+ }
81
+
82
+ /**
83
+ * 处理点击事件
84
+ */
85
+ const handleClick = (): void => {
86
+ emit('click', currentIndex.value)
87
+ }
88
+
89
+ /**
90
+ * 计算是否显示指示器
91
+ */
92
+ const showIndicator = computed<boolean>(() => {
93
+ return props.indicatorType !== 'none'
94
+ })
95
+
96
+ /**
97
+ * 监听插槽变化以更新轮播项数量
98
+ * 注意:这是一个简化处理,实际项目中可能需要更复杂的逻辑
99
+ */
100
+ const updateItemCount = (count: number): void => {
101
+ swiperItemCount.value = count
102
+ }
103
+
104
+ // 导出方法供父组件使用
105
+ defineExpose({
106
+ updateItemCount
107
+ })
108
+ </script>
109
+
110
+ <template>
111
+ <view class="t-swiper" :style="swiperStyle">
112
+ <!-- 轮播容器 -->
113
+ <swiper
114
+ class="t-swiper__container"
115
+ :autoplay="autoplay"
116
+ :interval="interval"
117
+ :duration="duration"
118
+ :circular="circular"
119
+ :vertical="direction === 'vertical'"
120
+ :current="currentIndex"
121
+ @change="handleChange"
122
+ @click="handleClick"
123
+ >
124
+ <slot></slot>
125
+ </swiper>
126
+
127
+ <!-- 指示器 -->
128
+ <view v-if="showIndicator" :class="indicatorClass">
129
+ <!-- 点状指示器 -->
130
+ <template v-if="indicatorType === 'dots'">
131
+ <view
132
+ v-for="(item, index) in swiperItemCount"
133
+ :key="index"
134
+ class="t-swiper__dot"
135
+ :class="{ 't-swiper__dot--active': index === currentIndex }"
136
+ :style="getDotStyle(index)"
137
+ ></view>
138
+ </template>
139
+
140
+ <!-- 数字指示器 -->
141
+ <template v-if="indicatorType === 'number'">
142
+ <view class="t-swiper__number">
143
+ <text class="t-swiper__number-text">{{ currentIndex + 1 }}/{{ swiperItemCount }}</text>
144
+ </view>
145
+ </template>
146
+ </view>
147
+ </view>
148
+ </template>
149
+
150
+ <style lang="scss" scoped>
151
+ .t-swiper {
152
+ position: relative;
153
+ width: 100%;
154
+ overflow: hidden;
155
+
156
+ &__container {
157
+ width: 100%;
158
+ height: 100%;
159
+ }
160
+
161
+ &__indicator {
162
+ position: absolute;
163
+ display: flex;
164
+ align-items: center;
165
+ z-index: 10;
166
+
167
+ // 水平方向指示器位置
168
+ &--horizontal {
169
+ left: 50%;
170
+ transform: translateX(-50%);
171
+ flex-direction: row;
172
+
173
+ &.t-swiper__indicator--top {
174
+ top: 12px;
175
+ }
176
+
177
+ &.t-swiper__indicator--bottom {
178
+ bottom: 12px;
179
+ }
180
+ }
181
+
182
+ // 垂直方向指示器位置
183
+ &--vertical {
184
+ top: 50%;
185
+ transform: translateY(-50%);
186
+ flex-direction: column;
187
+
188
+ &.t-swiper__indicator--left {
189
+ left: 12px;
190
+ }
191
+
192
+ &.t-swiper__indicator--right {
193
+ right: 12px;
194
+ }
195
+ }
196
+ }
197
+
198
+ &__dot {
199
+ width: 8px;
200
+ height: 8px;
201
+ border-radius: 4px;
202
+ margin: 0 4px;
203
+ transition: all 0.3s;
204
+
205
+ &--active {
206
+ width: 16px;
207
+ }
208
+ }
209
+
210
+ &__number {
211
+ padding: 4px 12px;
212
+ background-color: rgba(0, 0, 0, 0.5);
213
+ border-radius: 12px;
214
+
215
+ &-text {
216
+ font-size: 12px;
217
+ color: #ffffff;
218
+ line-height: 1;
219
+ }
220
+ }
221
+ }
222
+ </style>
@@ -0,0 +1,77 @@
1
+ /**
2
+ * TSwiper 轮播图组件属性类型定义
3
+ */
4
+ export type TSwiperProps = {
5
+ /**
6
+ * 轮播图高度
7
+ * @default '200px'
8
+ */
9
+ height?: string
10
+
11
+ /**
12
+ * 是否自动切换
13
+ * @default true
14
+ */
15
+ autoplay?: boolean
16
+
17
+ /**
18
+ * 自动切换时间间隔(毫秒)
19
+ * @default 3000
20
+ */
21
+ interval?: number
22
+
23
+ /**
24
+ * 滑动动画时长(毫秒)
25
+ * @default 300
26
+ */
27
+ duration?: number
28
+
29
+ /**
30
+ * 是否循环播放
31
+ * @default true
32
+ */
33
+ circular?: boolean
34
+
35
+ /**
36
+ * 指示器类型
37
+ * @default 'dots'
38
+ */
39
+ indicatorType?: 'dots' | 'number' | 'none'
40
+
41
+ /**
42
+ * 指示器位置
43
+ * @default 'bottom'
44
+ */
45
+ indicatorPosition?: 'top' | 'bottom' | 'left' | 'right'
46
+
47
+ /**
48
+ * 指示器颜色
49
+ */
50
+ indicatorColor?: string
51
+
52
+ /**
53
+ * 指示器激活颜色
54
+ */
55
+ indicatorActiveColor?: string
56
+
57
+ /**
58
+ * 轮播方向
59
+ * @default 'horizontal'
60
+ */
61
+ direction?: 'horizontal' | 'vertical'
62
+ }
63
+
64
+ /**
65
+ * TSwiper 轮播图组件事件定义
66
+ */
67
+ export type TSwiperEmits = {
68
+ /**
69
+ * 当前轮播索引改变时触发
70
+ */
71
+ change: (index: number) => void
72
+
73
+ /**
74
+ * 点击轮播项时触发
75
+ */
76
+ click: (index: number) => void
77
+ }
@@ -0,0 +1,177 @@
1
+ <script setup lang="uts" >
2
+ import { computed, ref, watch } from 'vue'
3
+ import type { TSwitchProps } from './type.uts'
4
+
5
+ /**
6
+ * TSwitch 开关组件
7
+ * @description 用于两种状态之间的切换
8
+ */
9
+
10
+ // 定义 props
11
+ const props = withDefaults(defineProps<TSwitchProps>(), {
12
+ disabled: false,
13
+ size: 'medium',
14
+ activeColor: '#409eff',
15
+ inactiveColor: '#dcdfe6',
16
+ activeText: '',
17
+ inactiveText: '',
18
+ showText: false
19
+ })
20
+
21
+ // 使用 defineModel
22
+ const model = defineModel<boolean>({ default: false })
23
+
24
+ // 定义 emits
25
+ const emit = defineEmits<{
26
+ change: [value: boolean]
27
+ }>()
28
+
29
+ // 内部状态
30
+ const checked = ref<boolean>(model.value)
31
+
32
+ // 监听外部值变化
33
+ watch(() => model.value, (newVal: boolean) => {
34
+ checked.value = newVal
35
+ })
36
+
37
+ /**
38
+ * 计算开关样式类
39
+ */
40
+ const switchClass = computed<string>(() => {
41
+ const classes: string[] = ['t-switch']
42
+
43
+ classes.push(`t-switch--${props.size}`)
44
+
45
+ if (checked.value) {
46
+ classes.push('t-switch--checked')
47
+ }
48
+
49
+ if (props.disabled) {
50
+ classes.push('t-switch--disabled')
51
+ }
52
+
53
+ return classes.join(' ')
54
+ })
55
+
56
+ /**
57
+ * 计算开关背景样式
58
+ */
59
+ const switchStyle = computed<string>(() => {
60
+ const styles: string[] = []
61
+
62
+ const bgColor = checked.value ? props.activeColor : props.inactiveColor
63
+ if (bgColor != '') {
64
+ styles.push(`background-color: ${bgColor}`)
65
+ }
66
+
67
+ return styles.join('; ')
68
+ })
69
+
70
+ /**
71
+ * 处理开关点击
72
+ */
73
+ const handleClick = (): void => {
74
+ if (props.disabled) {
75
+ return
76
+ }
77
+
78
+ const newValue = !checked.value
79
+ checked.value = newValue
80
+ model.value = newValue
81
+ emit('change', newValue)
82
+ }
83
+ </script>
84
+
85
+ <template>
86
+ <view class="t-switch-wrapper" @click="handleClick">
87
+ <text v-if="showText && inactiveText" class="t-switch__text t-switch__text--inactive">
88
+ {{ inactiveText }}
89
+ </text>
90
+ <view :class="switchClass" :style="switchStyle">
91
+ <view class="t-switch__button"></view>
92
+ </view>
93
+ <text v-if="showText && activeText" class="t-switch__text t-switch__text--active">
94
+ {{ activeText }}
95
+ </text>
96
+ </view>
97
+ </template>
98
+
99
+ <style lang="scss" scoped>
100
+ .t-switch-wrapper {
101
+ display: inline-flex;
102
+ flex-direction: row;
103
+ align-items: center;
104
+ cursor: pointer;
105
+ }
106
+
107
+ .t-switch {
108
+ position: relative;
109
+ background-color: #dcdfe6;
110
+ border-radius: 100px;
111
+ transition: background-color 0.3s;
112
+
113
+ &--small {
114
+ width: 32px;
115
+ height: 18px;
116
+
117
+ .t-switch__button {
118
+ width: 14px;
119
+ height: 14px;
120
+ }
121
+ }
122
+
123
+ &--medium {
124
+ width: 40px;
125
+ height: 20px;
126
+
127
+ .t-switch__button {
128
+ width: 16px;
129
+ height: 16px;
130
+ }
131
+ }
132
+
133
+ &--large {
134
+ width: 50px;
135
+ height: 24px;
136
+
137
+ .t-switch__button {
138
+ width: 20px;
139
+ height: 20px;
140
+ }
141
+ }
142
+
143
+ &--checked {
144
+ .t-switch__button {
145
+ transform: translateX(100%);
146
+ }
147
+ }
148
+
149
+ &--disabled {
150
+ opacity: 0.6;
151
+ cursor: not-allowed;
152
+ }
153
+
154
+ &__button {
155
+ position: absolute;
156
+ top: 2px;
157
+ left: 2px;
158
+ background-color: #ffffff;
159
+ border-radius: 50%;
160
+ transition: transform 0.3s;
161
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
162
+ }
163
+
164
+ &__text {
165
+ font-size: 14px;
166
+ color: #606266;
167
+
168
+ &--inactive {
169
+ margin-right: 8px;
170
+ }
171
+
172
+ &--active {
173
+ margin-left: 8px;
174
+ }
175
+ }
176
+ }
177
+ </style>
@@ -0,0 +1,52 @@
1
+ /**
2
+ * TSwitch 开关组件属性类型定义
3
+ * 注意:使用 defineModel 进行双向绑定,无需显式定义
4
+ */
5
+ export type TSwitchProps = {
6
+ /**
7
+ * 是否禁用
8
+ * @default false
9
+ */
10
+ disabled?: boolean
11
+
12
+ /**
13
+ * 开关大小
14
+ * @default "medium"
15
+ */
16
+ size?: 'small' | 'medium' | 'large'
17
+
18
+ /**
19
+ * 打开时的颜色
20
+ * @default "#409eff"
21
+ */
22
+ activeColor?: string
23
+
24
+ /**
25
+ * 关闭时的颜色
26
+ * @default "#dcdfe6"
27
+ */
28
+ inactiveColor?: string
29
+
30
+ /**
31
+ * 打开时的文字
32
+ */
33
+ activeText?: string
34
+
35
+ /**
36
+ * 关闭时的文字
37
+ */
38
+ inactiveText?: string
39
+
40
+ /**
41
+ * 是否显示文字
42
+ * @default false
43
+ */
44
+ showText?: boolean
45
+ }
46
+
47
+ export type TSwitchEmits = {
48
+ /**
49
+ * 状态改变时触发
50
+ */
51
+ change: (value: boolean) => void
52
+ }