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,376 @@
1
+ <script setup lang="uts" >
2
+ import { computed, ref } from 'vue'
3
+ import type {TInputProps, InputType, InputSize } from './type.uts'
4
+
5
+ /**
6
+ * TInput 输入框组件
7
+ * @description 支持多种类型、尺寸的输入框组件
8
+ */
9
+
10
+ const props = withDefaults(defineProps<TInputProps>(), {
11
+ type: 'text',
12
+ size: 'medium',
13
+ placeholder: '',
14
+ disabled: false,
15
+ readonly: false,
16
+ clearable: false,
17
+ showCount: false,
18
+ maxlength: -1,
19
+ prefixIcon: '',
20
+ suffixIcon: '',
21
+ rows: 3,
22
+ autoHeight: false,
23
+ autoFocus: false,
24
+ customClass: '',
25
+ customStyle: ''
26
+ })
27
+
28
+ // 使用 defineModel
29
+ const model = defineModel<string | number>({ default: '' })
30
+
31
+ // Emits 定义
32
+ const emit = defineEmits<{
33
+ input: [value: string | number]
34
+ change: [value: string | number]
35
+ focus: []
36
+ blur: []
37
+ clear: []
38
+ confirm: []
39
+ }>()
40
+
41
+ // 是否聚焦
42
+ const isFocused = ref(false)
43
+
44
+ /**
45
+ * 计算输入框包装类名
46
+ */
47
+ const inputWrapperClasses = computed((): string => {
48
+ const classes: string[] = []
49
+
50
+ // 尺寸样式
51
+ classes.push(`t-input--${props.size}`)
52
+
53
+ // 类型样式
54
+ if (props.type === 'textarea') {
55
+ classes.push('t-input--textarea')
56
+ }
57
+
58
+ // 禁用状态
59
+ if (props.disabled) {
60
+ classes.push('t-input--disabled')
61
+ }
62
+
63
+ // 只读状态
64
+ if (props.readonly) {
65
+ classes.push('t-input--readonly')
66
+ }
67
+
68
+ // 聚焦状态
69
+ if (isFocused.value) {
70
+ classes.push('t-input--focused')
71
+ }
72
+
73
+ // 前缀图标
74
+ if (props.prefixIcon) {
75
+ classes.push('t-input--prefix')
76
+ }
77
+
78
+ // 后缀图标或清除按钮
79
+ if (props.suffixIcon || props.clearable) {
80
+ classes.push('t-input--suffix')
81
+ }
82
+
83
+ // 自定义类名
84
+ if (props.customClass) {
85
+ classes.push(props.customClass)
86
+ }
87
+
88
+ return classes.join(' ')
89
+ })
90
+
91
+ /**
92
+ * 计算当前输入长度
93
+ */
94
+ const currentLength = computed((): number => {
95
+ const value = model.value?.toString() || ''
96
+ return value.length
97
+ })
98
+
99
+ /**
100
+ * 处理输入事件
101
+ */
102
+ const handleInput = (e: any) => {
103
+ const value = e.detail.value
104
+ model.value = value
105
+ emit('input', value)
106
+ }
107
+
108
+ /**
109
+ * 处理聚焦事件
110
+ */
111
+ const handleFocus = () => {
112
+ isFocused.value = true
113
+ emit('focus')
114
+ }
115
+
116
+ /**
117
+ * 处理失焦事件
118
+ */
119
+ const handleBlur = () => {
120
+ isFocused.value = false
121
+ emit('blur')
122
+ emit('change', model.value)
123
+ }
124
+
125
+ /**
126
+ * 处理清除事件
127
+ */
128
+ const handleClear = () => {
129
+ model.value = ''
130
+ emit('input', '')
131
+ emit('change', '')
132
+ emit('clear')
133
+ }
134
+
135
+ /**
136
+ * 处理确认事件
137
+ */
138
+ const handleConfirm = () => {
139
+ emit('confirm')
140
+ }
141
+ </script>
142
+
143
+ <template>
144
+ <view class="t-input" :class="inputWrapperClasses" :style="customStyle">
145
+ <!-- 前缀图标 -->
146
+ <view v-if="prefixIcon" class="t-input__prefix">
147
+ <text class="t-input__icon">{{ prefixIcon }}</text>
148
+ </view>
149
+
150
+ <!-- 输入框 -->
151
+ <input
152
+ v-if="type !== 'textarea'"
153
+ class="t-input__inner"
154
+ :type="type"
155
+ :value="model"
156
+ :placeholder="placeholder"
157
+ :disabled="disabled"
158
+ :readonly="readonly"
159
+ :maxlength="maxlength"
160
+ :focus="autoFocus"
161
+ @input="handleInput"
162
+ @focus="handleFocus"
163
+ @blur="handleBlur"
164
+ @confirm="handleConfirm"
165
+ />
166
+
167
+ <!-- 文本域 -->
168
+ <textarea
169
+ v-else
170
+ class="t-input__textarea"
171
+ :value="model"
172
+ :placeholder="placeholder"
173
+ :disabled="disabled"
174
+ :readonly="readonly"
175
+ :maxlength="maxlength"
176
+ :auto-height="autoHeight"
177
+ :focus="autoFocus"
178
+ @input="handleInput"
179
+ @focus="handleFocus"
180
+ @blur="handleBlur"
181
+ />
182
+
183
+ <!-- 清除按钮 -->
184
+ <view
185
+ v-if="clearable && model && !disabled && !readonly"
186
+ class="t-input__suffix t-input__clear"
187
+ @click="handleClear"
188
+ >
189
+ <text class="t-input__icon">✕</text>
190
+ </view>
191
+
192
+ <!-- 后缀图标 -->
193
+ <view v-else-if="suffixIcon" class="t-input__suffix">
194
+ <text class="t-input__icon">{{ suffixIcon }}</text>
195
+ </view>
196
+
197
+ <!-- 字数统计 -->
198
+ <view v-if="showCount && maxlength > 0" class="t-input__count">
199
+ <text class="t-input__count-text">{{ currentLength }}/{{ maxlength }}</text>
200
+ </view>
201
+ </view>
202
+ </template>
203
+
204
+ <style lang="scss" scoped>
205
+ .t-input {
206
+ // 重置 uni-view 的默认样式
207
+ flex-shrink: 0;
208
+ flex-grow: 0;
209
+ flex-basis: auto;
210
+ min-height: 0;
211
+ min-width: 0;
212
+ position: relative;
213
+ display: flex;
214
+ flex-direction: row;
215
+ align-items: center;
216
+ width: 100%;
217
+ box-sizing: border-box;
218
+ background-color: #ffffff;
219
+ border: 1px solid #dcdfe6;
220
+ border-radius: 4px;
221
+ transition: border-color 0.3s;
222
+
223
+ &__prefix,
224
+ &__suffix {
225
+ display: flex;
226
+ align-items: center;
227
+ justify-content: center;
228
+ padding: 0 8px;
229
+ color: #909399;
230
+ }
231
+
232
+ &__clear {
233
+ cursor: pointer;
234
+ transition: color 0.3s;
235
+
236
+ &:hover {
237
+ color: #606266;
238
+ }
239
+ }
240
+
241
+ &__icon {
242
+ font-size: 16px;
243
+ }
244
+
245
+ &__inner,
246
+ &__textarea {
247
+ flex: 1;
248
+ width: 100%;
249
+ padding: 0 12px;
250
+ font-size: 14px;
251
+ color: #606266;
252
+ background-color: transparent;
253
+ border: none;
254
+ outline: none;
255
+ box-sizing: border-box;
256
+
257
+ &::placeholder {
258
+ color: #c0c4cc;
259
+ }
260
+ }
261
+
262
+ &__inner {
263
+ height: 100%;
264
+ }
265
+
266
+ &__textarea {
267
+ padding: 8px 12px;
268
+ line-height: 1.5;
269
+ resize: none;
270
+ }
271
+
272
+ &__count {
273
+ position: absolute;
274
+ right: 8px;
275
+ bottom: 4px;
276
+ font-size: 12px;
277
+ color: #909399;
278
+ }
279
+
280
+ // 尺寸样式
281
+ &--large {
282
+ height: 44px;
283
+
284
+ .t-input__inner {
285
+ font-size: 16px;
286
+ }
287
+ }
288
+
289
+ &--medium {
290
+ height: 36px;
291
+
292
+ .t-input__inner {
293
+ font-size: 14px;
294
+ }
295
+ }
296
+
297
+ &--small {
298
+ height: 28px;
299
+
300
+ .t-input__inner {
301
+ font-size: 12px;
302
+ padding: 0 8px;
303
+ }
304
+
305
+ .t-input__prefix,
306
+ .t-input__suffix {
307
+ padding: 0 6px;
308
+ }
309
+ }
310
+
311
+ &--mini {
312
+ height: 24px;
313
+
314
+ .t-input__inner {
315
+ font-size: 12px;
316
+ padding: 0 8px;
317
+ }
318
+
319
+ .t-input__prefix,
320
+ .t-input__suffix {
321
+ padding: 0 6px;
322
+ }
323
+ }
324
+
325
+ // 文本域样式
326
+ &--textarea {
327
+ height: auto;
328
+ padding: 0;
329
+
330
+ .t-input__textarea {
331
+ min-height: 60px;
332
+ }
333
+ }
334
+
335
+ // 聚焦状态
336
+ &--focused {
337
+ border-color: #409eff;
338
+ }
339
+
340
+ // 禁用状态
341
+ &--disabled {
342
+ background-color: #f5f7fa;
343
+ border-color: #e4e7ed;
344
+ color: #c0c4cc;
345
+ cursor: not-allowed;
346
+
347
+ .t-input__inner,
348
+ .t-input__textarea {
349
+ color: #c0c4cc;
350
+ cursor: not-allowed;
351
+ }
352
+ }
353
+
354
+ // 只读状态
355
+ &--readonly {
356
+ .t-input__inner,
357
+ .t-input__textarea {
358
+ cursor: default;
359
+ }
360
+ }
361
+
362
+ // 前缀图标
363
+ &--prefix {
364
+ .t-input__inner {
365
+ padding-left: 0;
366
+ }
367
+ }
368
+
369
+ // 后缀图标
370
+ &--suffix {
371
+ .t-input__inner {
372
+ padding-right: 0;
373
+ }
374
+ }
375
+ }
376
+ </style>
@@ -0,0 +1,138 @@
1
+ /**
2
+ * TInput 组件类型定义
3
+ */
4
+
5
+ /**
6
+ * 输入框类型
7
+ */
8
+ export type InputType = 'text' | 'number' | 'password' | 'tel' | 'textarea'
9
+
10
+ /**
11
+ * 输入框尺寸
12
+ */
13
+ export type InputSize = 'large' | 'medium' | 'small' | 'mini'
14
+
15
+ /**
16
+ * 输入框 Props 接口
17
+ */
18
+ export interface TInputProps {
19
+ /**
20
+ * 输入框类型
21
+ * @default 'text'
22
+ */
23
+ type?: InputType
24
+
25
+ /**
26
+ * 输入框尺寸
27
+ * @default 'medium'
28
+ */
29
+ size?: InputSize
30
+
31
+ /**
32
+ * 占位文本
33
+ */
34
+ placeholder?: string
35
+
36
+ /**
37
+ * 是否禁用
38
+ * @default false
39
+ */
40
+ disabled?: boolean
41
+
42
+ /**
43
+ * 是否只读
44
+ * @default false
45
+ */
46
+ readonly?: boolean
47
+
48
+ /**
49
+ * 是否显示清除按钮
50
+ * @default false
51
+ */
52
+ clearable?: boolean
53
+
54
+ /**
55
+ * 是否显示字数统计
56
+ * @default false
57
+ */
58
+ showCount?: boolean
59
+
60
+ /**
61
+ * 最大输入长度
62
+ * @default -1
63
+ */
64
+ maxlength?: number
65
+
66
+ /**
67
+ * 前缀图标
68
+ */
69
+ prefixIcon?: string
70
+
71
+ /**
72
+ * 后缀图标
73
+ */
74
+ suffixIcon?: string
75
+
76
+ /**
77
+ * 文本域行数
78
+ * @default 3
79
+ */
80
+ rows?: number
81
+
82
+ /**
83
+ * 文本域自动高度
84
+ * @default false
85
+ */
86
+ autoHeight?: boolean
87
+
88
+ /**
89
+ * 自动获取焦点
90
+ * @default false
91
+ */
92
+ autoFocus?: boolean
93
+
94
+ /**
95
+ * 自定义类名
96
+ */
97
+ customClass?: string
98
+
99
+ /**
100
+ * 自定义样式
101
+ */
102
+ customStyle?: string
103
+ }
104
+
105
+ /**
106
+ * 输入框事件接口
107
+ */
108
+ export interface TInputEmits {
109
+ /**
110
+ * 输入事件
111
+ */
112
+ input: (value: string | number) => void
113
+
114
+ /**
115
+ * 值改变事件
116
+ */
117
+ change: (value: string | number) => void
118
+
119
+ /**
120
+ * 获得焦点事件
121
+ */
122
+ focus: () => void
123
+
124
+ /**
125
+ * 失去焦点事件
126
+ */
127
+ blur: () => void
128
+
129
+ /**
130
+ * 清除事件
131
+ */
132
+ clear: () => void
133
+
134
+ /**
135
+ * 确认事件
136
+ */
137
+ confirm: () => void
138
+ }
@@ -0,0 +1,82 @@
1
+ <script setup lang="uts" >
2
+ import { computed } from 'vue'
3
+ import type { TListProps } from './type.uts'
4
+
5
+ /**
6
+ * TList 列表组件
7
+ * @description 用于展示列表数据
8
+ */
9
+
10
+ // 定义 props
11
+ const props = withDefaults(defineProps<TListProps>(), {
12
+ title: '',
13
+ border: true,
14
+ spacing: 'medium'
15
+ })
16
+
17
+ /**
18
+ * 计算列表样式类
19
+ */
20
+ const listClass = computed<string>(() => {
21
+ const classes: string[] = ['t-list']
22
+
23
+ if (props.border) {
24
+ classes.push('t-list--border')
25
+ }
26
+
27
+ classes.push(`t-list--spacing-${props.spacing}`)
28
+
29
+ return classes.join(' ')
30
+ })
31
+ </script>
32
+
33
+ <template>
34
+ <view class="t-list-wrapper">
35
+ <view v-if="title" class="t-list__title">
36
+ <text class="t-list__title-text">{{ title }}</text>
37
+ </view>
38
+ <view :class="listClass">
39
+ <slot></slot>
40
+ </view>
41
+ </view>
42
+ </template>
43
+
44
+ <style lang="scss" scoped>
45
+ .t-list-wrapper {
46
+ width: 100%;
47
+ }
48
+
49
+ .t-list {
50
+ background-color: #ffffff;
51
+
52
+ &--border {
53
+ border-top: 1px solid #ebeef5;
54
+ border-bottom: 1px solid #ebeef5;
55
+ }
56
+
57
+ &--spacing-none {
58
+ padding: 0;
59
+ }
60
+
61
+ &--spacing-small {
62
+ padding: 8px 0;
63
+ }
64
+
65
+ &--spacing-medium {
66
+ padding: 12px 0;
67
+ }
68
+
69
+ &--spacing-large {
70
+ padding: 16px 0;
71
+ }
72
+
73
+ &__title {
74
+ padding: 12px 16px 8px;
75
+
76
+ &-text {
77
+ font-size: 14px;
78
+ color: #909399;
79
+ }
80
+ }
81
+ }
82
+ </style>
@@ -0,0 +1,68 @@
1
+ /**
2
+ * TList 列表组件属性类型定义
3
+ */
4
+ export type TListProps = {
5
+ /**
6
+ * 列表标题
7
+ */
8
+ title?: string
9
+
10
+ /**
11
+ * 是否显示边框
12
+ * @default true
13
+ */
14
+ border?: boolean
15
+
16
+ /**
17
+ * 列表项间距
18
+ * @default "medium"
19
+ */
20
+ spacing?: 'none' | 'small' | 'medium' | 'large'
21
+ }
22
+
23
+ export type TListItemProps = {
24
+ /**
25
+ * 列表项标题
26
+ */
27
+ title?: string
28
+
29
+ /**
30
+ * 列表项描述
31
+ */
32
+ description?: string
33
+
34
+ /**
35
+ * 左侧图标
36
+ */
37
+ icon?: string
38
+
39
+ /**
40
+ * 右侧文字
41
+ */
42
+ extra?: string
43
+
44
+ /**
45
+ * 是否显示右侧箭头
46
+ * @default false
47
+ */
48
+ arrow?: boolean
49
+
50
+ /**
51
+ * 是否可点击
52
+ * @default false
53
+ */
54
+ clickable?: boolean
55
+
56
+ /**
57
+ * 是否禁用
58
+ * @default false
59
+ */
60
+ disabled?: boolean
61
+ }
62
+
63
+ export type TListItemEmits = {
64
+ /**
65
+ * 点击列表项时触发
66
+ */
67
+ click: () => void
68
+ }