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,161 @@
1
+ <script setup lang="uts" >
2
+ import { computed } from 'vue'
3
+ import type { TListItemProps } from './type.uts'
4
+
5
+ /**
6
+ * TListItem 列表项组件
7
+ * @description 列表中的单个项目
8
+ */
9
+
10
+ // 定义 props
11
+ const props = withDefaults(defineProps<TListItemProps>(), {
12
+ title: '',
13
+ description: '',
14
+ icon: '',
15
+ extra: '',
16
+ arrow: false,
17
+ clickable: false,
18
+ disabled: false
19
+ })
20
+
21
+ // 定义 emits
22
+ const emit = defineEmits<{
23
+ click: []
24
+ }>()
25
+
26
+ /**
27
+ * 计算列表项样式类
28
+ */
29
+ const itemClass = computed<string>(() => {
30
+ const classes: string[] = ['t-list-item']
31
+
32
+ if (props.clickable && !props.disabled) {
33
+ classes.push('t-list-item--clickable')
34
+ }
35
+
36
+ if (props.disabled) {
37
+ classes.push('t-list-item--disabled')
38
+ }
39
+
40
+ return classes.join(' ')
41
+ })
42
+
43
+ /**
44
+ * 处理点击事件
45
+ */
46
+ const handleClick = (): void => {
47
+ if (!props.disabled && props.clickable) {
48
+ emit('click')
49
+ }
50
+ }
51
+ </script>
52
+
53
+ <template>
54
+ <view :class="itemClass" @click="handleClick">
55
+ <!-- 左侧图标 -->
56
+ <view v-if="icon" class="t-list-item__icon">
57
+ <text class="t-list-item__icon-text">{{ icon }}</text>
58
+ </view>
59
+
60
+ <!-- 中间内容 -->
61
+ <view class="t-list-item__content">
62
+ <slot>
63
+ <text v-if="title" class="t-list-item__title">{{ title }}</text>
64
+ <text v-if="description" class="t-list-item__description">{{ description }}</text>
65
+ </slot>
66
+ </view>
67
+
68
+ <!-- 右侧内容 -->
69
+ <view class="t-list-item__extra">
70
+ <text v-if="extra" class="t-list-item__extra-text">{{ extra }}</text>
71
+ <text v-if="arrow" class="t-list-item__arrow">›</text>
72
+ </view>
73
+ </view>
74
+ </template>
75
+
76
+ <style lang="scss" scoped>
77
+ .t-list-item {
78
+ display: flex;
79
+ flex-direction: row;
80
+ gap: 24rpx;
81
+ align-items: center;
82
+ padding: 12px 16px;
83
+ background-color: #ffffff;
84
+ position: relative;
85
+
86
+ &::after {
87
+ content: '';
88
+ position: absolute;
89
+ left: 16px;
90
+ right: 0;
91
+ bottom: 0;
92
+ height: 1px;
93
+ background-color: #ebeef5;
94
+ }
95
+
96
+ &:last-child::after {
97
+ display: none;
98
+ }
99
+
100
+ &--clickable {
101
+ cursor: pointer;
102
+ transition: background-color 0.3s;
103
+
104
+ &:active {
105
+ background-color: #f5f7fa;
106
+ }
107
+ }
108
+
109
+ &--disabled {
110
+ opacity: 0.5;
111
+ cursor: not-allowed;
112
+ }
113
+
114
+ &__icon {
115
+ display: flex;
116
+ align-items: center;
117
+ justify-content: center;
118
+
119
+ &-text {
120
+ font-size: 20px;
121
+ color: #909399;
122
+ }
123
+ }
124
+
125
+ &__content {
126
+ flex: 1;
127
+ display: flex;
128
+ flex-direction: column;
129
+ }
130
+
131
+ &__title {
132
+ font-size: 16px;
133
+ color: #303133;
134
+ line-height: 24px;
135
+ }
136
+
137
+ &__description {
138
+ font-size: 14px;
139
+ color: #909399;
140
+ line-height: 20px;
141
+ margin-top: 4px;
142
+ }
143
+
144
+ &__extra {
145
+ display: flex;
146
+ align-items: center;
147
+ margin-left: 12px;
148
+
149
+ &-text {
150
+ font-size: 14px;
151
+ color: #909399;
152
+ }
153
+ }
154
+
155
+ &__arrow {
156
+ font-size: 20px;
157
+ color: #c0c4cc;
158
+ margin-left: 8px;
159
+ }
160
+ }
161
+ </style>
@@ -0,0 +1,49 @@
1
+ /**
2
+ * TListItem 列表项组件属性类型定义
3
+ */
4
+ export type TListItemProps = {
5
+ /**
6
+ * 列表项标题
7
+ */
8
+ title?: string
9
+
10
+ /**
11
+ * 列表项描述
12
+ */
13
+ description?: string
14
+
15
+ /**
16
+ * 左侧图标
17
+ */
18
+ icon?: string
19
+
20
+ /**
21
+ * 右侧文字
22
+ */
23
+ extra?: string
24
+
25
+ /**
26
+ * 是否显示右侧箭头
27
+ * @default false
28
+ */
29
+ arrow?: boolean
30
+
31
+ /**
32
+ * 是否可点击
33
+ * @default false
34
+ */
35
+ clickable?: boolean
36
+
37
+ /**
38
+ * 是否禁用
39
+ * @default false
40
+ */
41
+ disabled?: boolean
42
+ }
43
+
44
+ export type TListItemEmits = {
45
+ /**
46
+ * 点击列表项时触发
47
+ */
48
+ click: () => void
49
+ }
@@ -0,0 +1,153 @@
1
+ <script setup lang="uts" >
2
+ import { computed } from 'vue'
3
+ import type { TLoadingProps } from './type.uts'
4
+
5
+ /**
6
+ * TLoading 加载组件
7
+ * @description 用于显示加载状态
8
+ */
9
+
10
+ // 定义 props
11
+ const props = withDefaults(defineProps<TLoadingProps>(), {
12
+ loading: false,
13
+ text: '',
14
+ size: 'medium',
15
+ color: '#409eff',
16
+ fullscreen: false,
17
+ mask: true,
18
+ maskBgColor: 'rgba(255, 255, 255, 0.9)'
19
+ })
20
+
21
+ /**
22
+ * 计算加载容器样式类
23
+ */
24
+ const loadingClass = computed<string>(() => {
25
+ const classes: string[] = ['t-loading']
26
+
27
+ if (props.fullscreen) {
28
+ classes.push('t-loading--fullscreen')
29
+ }
30
+
31
+ return classes.join(' ')
32
+ })
33
+
34
+ /**
35
+ * 计算遮罩层样式
36
+ */
37
+ const maskStyle = computed<string>(() => {
38
+ const styles: string[] = []
39
+
40
+ if (props.maskBgColor != '') {
41
+ styles.push(`background-color: ${props.maskBgColor}`)
42
+ }
43
+
44
+ return styles.join('; ')
45
+ })
46
+
47
+ /**
48
+ * 计算加载图标样式类
49
+ */
50
+ const spinnerClass = computed<string>(() => {
51
+ const classes: string[] = ['t-loading__spinner']
52
+
53
+ classes.push(`t-loading__spinner--${props.size}`)
54
+
55
+ return classes.join(' ')
56
+ })
57
+
58
+ /**
59
+ * 计算加载图标样式
60
+ */
61
+ const spinnerStyle = computed<string>(() => {
62
+ const styles: string[] = []
63
+
64
+ if (props.color != '') {
65
+ styles.push(`border-color: ${props.color}`)
66
+ styles.push(`border-top-color: transparent`)
67
+ }
68
+
69
+ return styles.join('; ')
70
+ })
71
+ </script>
72
+
73
+ <template>
74
+ <view v-if="loading" :class="loadingClass">
75
+ <view v-if="mask" class="t-loading__mask" :style="maskStyle"></view>
76
+ <view class="t-loading__content">
77
+ <view :class="spinnerClass" :style="spinnerStyle"></view>
78
+ <text v-if="text" class="t-loading__text">{{ text }}</text>
79
+ </view>
80
+ </view>
81
+ </template>
82
+
83
+ <style lang="scss" scoped>
84
+ .t-loading {
85
+ position: relative;
86
+
87
+ &--fullscreen {
88
+ position: fixed;
89
+ top: 0;
90
+ left: 0;
91
+ right: 0;
92
+ bottom: 0;
93
+ z-index: 9999;
94
+ }
95
+
96
+ &__mask {
97
+ position: absolute;
98
+ top: 0;
99
+ left: 0;
100
+ right: 0;
101
+ bottom: 0;
102
+ background-color: rgba(255, 255, 255, 0.9);
103
+ }
104
+
105
+ &__content {
106
+ position: absolute;
107
+ top: 50%;
108
+ left: 50%;
109
+ transform: translate(-50%, -50%);
110
+ display: flex;
111
+ flex-direction: column;
112
+ align-items: center;
113
+ z-index: 1;
114
+ }
115
+
116
+ &__spinner {
117
+ border: 2px solid #409eff;
118
+ border-top-color: transparent;
119
+ border-radius: 50%;
120
+ animation: spin 1s linear infinite;
121
+
122
+ &--small {
123
+ width: 20px;
124
+ height: 20px;
125
+ }
126
+
127
+ &--medium {
128
+ width: 30px;
129
+ height: 30px;
130
+ }
131
+
132
+ &--large {
133
+ width: 40px;
134
+ height: 40px;
135
+ }
136
+ }
137
+
138
+ &__text {
139
+ margin-top: 12px;
140
+ font-size: 14px;
141
+ color: #606266;
142
+ }
143
+
144
+ @keyframes spin {
145
+ from {
146
+ transform: rotate(0deg);
147
+ }
148
+ to {
149
+ transform: rotate(360deg);
150
+ }
151
+ }
152
+ }
153
+ </style>
@@ -0,0 +1,43 @@
1
+ /**
2
+ * TLoading 加载组件属性类型定义
3
+ */
4
+ export type TLoadingProps = {
5
+ /**
6
+ * 是否显示加载
7
+ * @default false
8
+ */
9
+ loading?: boolean
10
+
11
+ /**
12
+ * 加载文字提示
13
+ */
14
+ text?: string
15
+
16
+ /**
17
+ * 加载图标大小
18
+ * @default "medium"
19
+ */
20
+ size?: 'small' | 'medium' | 'large'
21
+
22
+ /**
23
+ * 加载图标颜色
24
+ */
25
+ color?: string
26
+
27
+ /**
28
+ * 是否全屏加载
29
+ * @default false
30
+ */
31
+ fullscreen?: boolean
32
+
33
+ /**
34
+ * 是否显示遮罩层
35
+ * @default true
36
+ */
37
+ mask?: boolean
38
+
39
+ /**
40
+ * 遮罩层背景色
41
+ */
42
+ maskBgColor?: string
43
+ }
@@ -0,0 +1,120 @@
1
+ <script setup lang="uts">
2
+ interface Props {
3
+ title?: string
4
+ leftText?: string
5
+ rightText?: string
6
+ leftIcon?: string
7
+ rightIcon?: string
8
+ fixed?: boolean
9
+ placeholder?: boolean
10
+ zIndex?: number
11
+ safeAreaInsetTop?: boolean
12
+ customClass?: string
13
+ customStyle?: string
14
+ }
15
+
16
+ const props = withDefaults(defineProps<Props>(), {
17
+ title: '',
18
+ leftText: '',
19
+ rightText: '',
20
+ leftIcon: '',
21
+ rightIcon: '',
22
+ fixed: false,
23
+ placeholder: false,
24
+ zIndex: 1,
25
+ safeAreaInsetTop: false,
26
+ customClass: '',
27
+ customStyle: ''
28
+ })
29
+
30
+ const emit = defineEmits<{
31
+ 'click-left': []
32
+ 'click-right': []
33
+ }>()
34
+ </script>
35
+
36
+ <template>
37
+ <view class="t-navbar-wrapper">
38
+ <view
39
+ class="t-navbar"
40
+ :class="[customClass, { 't-navbar--fixed': fixed }]"
41
+ :style="`z-index: ${zIndex}; ${customStyle}`"
42
+ >
43
+ <view class="t-navbar__left" @click="emit('click-left')">
44
+ <text v-if="leftIcon" class="t-navbar__icon">{{ leftIcon }}</text>
45
+ <text v-if="leftText" class="t-navbar__text">{{ leftText }}</text>
46
+ <slot name="left"></slot>
47
+ </view>
48
+ <view class="t-navbar__title">
49
+ <text class="t-navbar__title-text">{{ title }}</text>
50
+ <slot name="title"></slot>
51
+ </view>
52
+ <view class="t-navbar__right" @click="emit('click-right')">
53
+ <text v-if="rightText" class="t-navbar__text">{{ rightText }}</text>
54
+ <text v-if="rightIcon" class="t-navbar__icon">{{ rightIcon }}</text>
55
+ <slot name="right"></slot>
56
+ </view>
57
+ </view>
58
+ <view v-if="fixed && placeholder" class="t-navbar__placeholder"></view>
59
+ </view>
60
+ </template>
61
+
62
+ <style lang="scss" scoped>
63
+ .t-navbar {
64
+ display: flex;
65
+ flex-direction: row;
66
+ align-items: center;
67
+ justify-content: space-between;
68
+ height: 44px;
69
+ padding: 0 16px;
70
+ background-color: #fff;
71
+ border-bottom: 1px solid #ebedf0;
72
+
73
+ &--fixed {
74
+ position: fixed;
75
+ top: 0;
76
+ left: 0;
77
+ right: 0;
78
+ }
79
+ }
80
+
81
+ .t-navbar__left,
82
+ .t-navbar__right {
83
+ display: flex;
84
+ flex-direction: row;;
85
+ align-items: center;
86
+ min-width: 60px;
87
+ cursor: pointer;
88
+ }
89
+
90
+ .t-navbar__right {
91
+ justify-content: flex-end;
92
+ }
93
+
94
+ .t-navbar__title {
95
+ flex: 1;
96
+ display: flex;
97
+ align-items: center;
98
+ text-align: center;
99
+ }
100
+
101
+ .t-navbar__title-text {
102
+ font-size: 16px;
103
+ font-weight: 500;
104
+ color: #323233;
105
+ }
106
+
107
+ .t-navbar__text {
108
+ font-size: 14px;
109
+ color: #1890ff;
110
+ }
111
+
112
+ .t-navbar__icon {
113
+ font-size: 18px;
114
+ color: #323233;
115
+ }
116
+
117
+ .t-navbar__placeholder {
118
+ height: 44px;
119
+ }
120
+ </style>
@@ -0,0 +1,22 @@
1
+ /**
2
+ * TNavBar 组件类型定义
3
+ */
4
+
5
+ export interface TNavBarProps {
6
+ title?: string
7
+ leftText?: string
8
+ rightText?: string
9
+ leftIcon?: string
10
+ rightIcon?: string
11
+ fixed?: boolean
12
+ placeholder?: boolean
13
+ zIndex?: number
14
+ safeAreaInsetTop?: boolean
15
+ customClass?: string
16
+ customStyle?: string
17
+ }
18
+
19
+ export interface TNavBarEmits {
20
+ 'click-left': () => void
21
+ 'click-right': () => void
22
+ }
@@ -0,0 +1,106 @@
1
+ <script setup lang="uts">
2
+ import { ref } from 'vue'
3
+ import type { NoticeBarMode } from './type.uts'
4
+
5
+ interface Props {
6
+ text?: string
7
+ mode?: NoticeBarMode
8
+ color?: string
9
+ background?: string
10
+ leftIcon?: string
11
+ scrollable?: boolean
12
+ customClass?: string
13
+ customStyle?: string
14
+ }
15
+
16
+ const props = withDefaults(defineProps<Props>(), {
17
+ text: '',
18
+ mode: undefined,
19
+ color: '#ed6a0c',
20
+ background: '#fffbe8',
21
+ leftIcon: '📢',
22
+ scrollable: false,
23
+ customClass: '',
24
+ customStyle: ''
25
+ })
26
+
27
+ const emit = defineEmits<{
28
+ click: []
29
+ close: []
30
+ }>()
31
+
32
+ const visible = ref<boolean>(true)
33
+
34
+ const handleClick = (): void => {
35
+ emit('click')
36
+ }
37
+
38
+ const handleClose = (): void => {
39
+ visible.value = false
40
+ emit('close')
41
+ }
42
+ </script>
43
+
44
+ <template>
45
+ <view
46
+ v-if="visible"
47
+ class="t-notice-bar"
48
+ :class="customClass"
49
+ :style="`background: ${background}; color: ${color}; ${customStyle}`"
50
+ @click="handleClick"
51
+ >
52
+ <text v-if="leftIcon" class="t-notice-bar__icon">{{ leftIcon }}</text>
53
+ <view class="t-notice-bar__content" :class="{ 't-notice-bar__content--scrollable': scrollable }">
54
+ <text class="t-notice-bar__text">{{ text }}</text>
55
+ </view>
56
+ <text v-if="mode === 'closeable'" class="t-notice-bar__close" @click.stop="handleClose">✕</text>
57
+ <text v-if="mode === 'link'" class="t-notice-bar__link">›</text>
58
+ </view>
59
+ </template>
60
+
61
+ <style lang="scss" scoped>
62
+ .t-notice-bar {
63
+ display: flex;
64
+ flex-direction: row;
65
+ align-items: center;
66
+ padding: 10px 12px;
67
+ font-size: 14px;
68
+ overflow: hidden;;
69
+ }
70
+
71
+ .t-notice-bar__icon {
72
+ margin-right: 8px;
73
+ }
74
+
75
+ .t-notice-bar__content {
76
+ flex: 1;
77
+ overflow: hidden;
78
+
79
+ &--scrollable {
80
+ .t-notice-bar__text {
81
+ animation: t-notice-scroll 10s linear infinite;
82
+ }
83
+ }
84
+ }
85
+
86
+ .t-notice-bar__text {
87
+ display: inline-block;
88
+ white-space: nowrap;
89
+ }
90
+
91
+ .t-notice-bar__close,
92
+ .t-notice-bar__link {
93
+ margin-left: 8px;
94
+ font-size: 16px;
95
+ cursor: pointer;
96
+ }
97
+
98
+ @keyframes t-notice-scroll {
99
+ 0% {
100
+ transform: translateX(0);
101
+ }
102
+ 100% {
103
+ transform: translateX(-100%);
104
+ }
105
+ }
106
+ </style>
@@ -0,0 +1,21 @@
1
+ /**
2
+ * TNoticeBar 组件类型定义
3
+ */
4
+
5
+ export type NoticeBarMode = 'closeable' | 'link'
6
+
7
+ export interface TNoticeBarProps {
8
+ text?: string
9
+ mode?: NoticeBarMode
10
+ color?: string
11
+ background?: string
12
+ leftIcon?: string
13
+ scrollable?: boolean
14
+ customClass?: string
15
+ customStyle?: string
16
+ }
17
+
18
+ export interface TNoticeBarEmits {
19
+ click: () => void
20
+ close: () => void
21
+ }