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,232 @@
1
+ <script setup lang="uts" >
2
+ /**
3
+ * 单选按钮组件
4
+ * @description 支持单个按钮和选项组两种使用方式
5
+ */
6
+
7
+ type FormOption = {
8
+ label: string
9
+ value: string | number
10
+ }
11
+
12
+ type Props = {
13
+ /** 选项组模式:选项列表 */
14
+ options?: FormOption[]
15
+ /** 单个按钮模式:选项值 */
16
+ value?: string | number
17
+ /** 按钮尺寸 */
18
+ size?: 'small' | 'medium' | 'large'
19
+ /** 活动状态颜色 */
20
+ activeColor?: string
21
+ /** 非活动状态颜色 */
22
+ inactiveColor?: string
23
+ /** 是否禁用 */
24
+ disabled?: boolean
25
+ /** 是否选中(仅单个按钮模式) */
26
+ checked?: boolean
27
+ /** 名称属性(用于表单提交) */
28
+ name?: string
29
+ }
30
+
31
+ const props = withDefaults(defineProps<Props>(), {
32
+ options: () => [],
33
+ size: 'medium',
34
+ activeColor: '#00bba7',
35
+ inactiveColor: '#666666',
36
+ disabled: false,
37
+ checked: false
38
+ })
39
+
40
+ const model = defineModel<string | number>()
41
+
42
+ const emit = defineEmits<{
43
+ change: [value: string | number]
44
+ }>()
45
+
46
+ /**
47
+ * 计算样式变量
48
+ */
49
+ const cssVars = computed(() => ({
50
+ '--radio-active-color': props.activeColor,
51
+ '--radio-inactive-color': props.inactiveColor
52
+ }))
53
+
54
+ /**
55
+ * 是否为选项组模式
56
+ */
57
+ const isOptionsMode = computed(() => props.options && props.options.length > 0)
58
+
59
+ /**
60
+ * 单个按钮模式:判断是否被选中
61
+ */
62
+ const isChecked = computed(() => {
63
+ if (isOptionsMode.value) {
64
+ return model.value === props.value
65
+ }
66
+ return props.checked || model.value === props.value
67
+ })
68
+
69
+ /**
70
+ 选择 * 处理变化
71
+ */
72
+ const handleChange = (value: string | number) => {
73
+ model.value = value
74
+ emit('change', value)
75
+ }
76
+
77
+ /**
78
+ * 处理单个按钮点击
79
+ */
80
+ const handleClick = () => {
81
+ if (props.disabled || isOptionsMode.value) return
82
+ handleChange(props.value!)
83
+ }
84
+
85
+ /**
86
+ * 尺寸样式类
87
+ */
88
+ const sizeClass = computed(() => {
89
+ const sizeMap = {
90
+ 'small': 'radio-size-small',
91
+ 'medium': 'radio-size-medium',
92
+ 'large': 'radio-size-large'
93
+ }
94
+ return sizeMap[props.size] ?? 'radio-size-medium'
95
+ })
96
+ </script>
97
+
98
+ <template>
99
+ <!-- 选项组模式:使用 options 属性 -->
100
+ <view v-if="isOptionsMode" class="radio-group" :style="cssVars">
101
+ <view
102
+ v-for="option in props.options"
103
+ :key="option.value"
104
+ class="radio-item"
105
+ :class="{ 'radio-disabled': props.disabled }"
106
+ @click="!props.disabled && handleChange(option.value)"
107
+ >
108
+ <view class="radio-icon" :class="{ active: model === option.value, 'radio-disabled': props.disabled }">
109
+ <view v-if="model === option.value" class="radio-dot"></view>
110
+ </view>
111
+ <text class="radio-label">{{ option.label }}</text>
112
+ </view>
113
+ </view>
114
+
115
+ <!-- 单个按钮模式:使用插槽或默认内容 -->
116
+ <view v-else class="radio-item" :class="[sizeClass, { 'radio-disabled': props.disabled }]" @click="handleClick">
117
+ <view class="radio-icon" :class="{ active: isChecked, 'radio-disabled': props.disabled }">
118
+ <view v-if="isChecked" class="radio-dot"></view>
119
+ </view>
120
+ <slot>
121
+ <text v-if="props.value !== undefined" class="radio-label">{{ props.value }}</text>
122
+ </slot>
123
+ </view>
124
+ </template>
125
+
126
+ <style lang="scss" scoped>
127
+ /* 选项组容器 */
128
+ .radio-group {
129
+ flex-direction: column;
130
+ gap: 16rpx;
131
+ }
132
+
133
+ /* 单个按钮容器 */
134
+ .radio-item {
135
+ flex-direction: row;
136
+ align-items: center;
137
+ gap: 16rpx;
138
+
139
+ &.radio-disabled {
140
+ opacity: 0.5;
141
+ cursor: not-allowed;
142
+ }
143
+ }
144
+
145
+ /* 单选按钮图标 */
146
+ .radio-icon {
147
+ justify-content: center;
148
+ align-items: center;
149
+ border-radius: 50%;
150
+ border-width: 2rpx;
151
+ border-style: solid;
152
+ border-color: var(--radio-inactive-color);
153
+ transition: all 0.2s ease;
154
+
155
+ &.active {
156
+ border-color: var(--radio-active-color);
157
+ }
158
+
159
+ &.radio-disabled {
160
+ border-color: #dcdfe6;
161
+ }
162
+ }
163
+
164
+ /* 单选点 */
165
+ .radio-dot {
166
+ border-radius: 50%;
167
+ background-color: var(--radio-active-color);
168
+ }
169
+
170
+ /* 尺寸样式 */
171
+ .radio-size-small {
172
+ .radio-icon {
173
+ width: 28rpx;
174
+ height: 28rpx;
175
+ }
176
+
177
+ .radio-dot {
178
+ width: 14rpx;
179
+ height: 14rpx;
180
+ }
181
+
182
+ .radio-label {
183
+ font-size: 24rpx;
184
+ }
185
+ }
186
+
187
+ .radio-size-medium {
188
+ .radio-icon {
189
+ width: 36rpx;
190
+ height: 36rpx;
191
+ }
192
+
193
+ .radio-dot {
194
+ width: 20rpx;
195
+ height: 20rpx;
196
+ }
197
+
198
+ .radio-label {
199
+ font-size: 28rpx;
200
+ }
201
+ }
202
+
203
+ .radio-size-large {
204
+ .radio-icon {
205
+ width: 44rpx;
206
+ height: 44rpx;
207
+ }
208
+
209
+ .radio-dot {
210
+ width: 26rpx;
211
+ height: 26rpx;
212
+ }
213
+
214
+ .radio-label {
215
+ font-size: 32rpx;
216
+ }
217
+ }
218
+
219
+ /* 文本标签 */
220
+ .radio-label {
221
+ color: var(--radio-inactive-color);
222
+ transition: color 0.2s ease;
223
+
224
+ .radio-item.active & {
225
+ color: var(--radio-active-color);
226
+ }
227
+
228
+ .radio-disabled & {
229
+ color: #c0c4cc;
230
+ }
231
+ }
232
+ </style>
@@ -0,0 +1,117 @@
1
+ <script setup lang="uts">
2
+ import type { TRadioGroupProps, RadioOption } from './type.uts'
3
+
4
+ /**
5
+ * TRadioGroup 单选框组组件
6
+ * @description 用于在多个选项中选择一个的组件
7
+ */
8
+
9
+ // Props 定义 (从 type.uts 导入,排除 modelValue)
10
+ type Props = Omit<TRadioGroupProps, 'modelValue'>
11
+
12
+ const props = withDefaults(defineProps<Props>(), {
13
+ options: () => [] as RadioOption[],
14
+ direction: 'vertical',
15
+ disabled: false,
16
+ customClass: '',
17
+ customStyle: ''
18
+ })
19
+
20
+ // 使用 defineModel 管理双向绑定
21
+ const modelValue = defineModel<string | number>({ default: '' })
22
+
23
+ const emit = defineEmits<{
24
+ change: [value: string | number]
25
+ }>()
26
+
27
+ const handleChange = (option: RadioOption): void => {
28
+ if (props.disabled || option.disabled) return
29
+
30
+ modelValue.value = option.value
31
+ emit('change', option.value)
32
+ }
33
+
34
+ const isChecked = (option: RadioOption): boolean => {
35
+ return modelValue.value === option.value
36
+ }
37
+ </script>
38
+
39
+ <template>
40
+ <view
41
+ class="t-radio-group"
42
+ :class="[`t-radio-group--${direction}`, customClass]"
43
+ :style="customStyle"
44
+ >
45
+ <view
46
+ v-for="(option, index) in options"
47
+ :key="index"
48
+ class="t-radio-group__item"
49
+ :class="{ 't-radio-group__item--disabled': disabled || option.disabled }"
50
+ @click="() => handleChange(option)"
51
+ >
52
+ <view class="t-radio-group__icon" :class="{ 't-radio-group__icon--checked': isChecked(option) }">
53
+ <view v-if="isChecked(option)" class="t-radio-group__dot"></view>
54
+ </view>
55
+ <text class="t-radio-group__label">{{ option.label }}</text>
56
+ </view>
57
+ </view>
58
+ </template>
59
+
60
+ <style lang="scss" scoped>
61
+ .t-radio-group {
62
+ &--vertical {
63
+ display: flex;
64
+ flex-direction: column;
65
+ }
66
+
67
+ &--horizontal {
68
+ display: flex;
69
+ flex-direction: row;
70
+ flex-wrap: wrap;
71
+ }
72
+ }
73
+
74
+ .t-radio-group__item {
75
+ display: flex;
76
+ align-items: center;
77
+ padding: 12px 0;
78
+ cursor: pointer;
79
+
80
+ &--disabled {
81
+ opacity: 0.5;
82
+ cursor: not-allowed;
83
+ }
84
+
85
+ .t-radio-group--horizontal & {
86
+ margin-right: 24px;
87
+ }
88
+ }
89
+
90
+ .t-radio-group__icon {
91
+ width: 20px;
92
+ height: 20px;
93
+ border: 2px solid #c8c9cc;
94
+ border-radius: 50%;
95
+ margin-right: 8px;
96
+ display: flex;
97
+ align-items: center;
98
+ justify-content: center;
99
+ transition: all 0.3s;
100
+
101
+ &--checked {
102
+ border-color: #1890ff;
103
+ }
104
+ }
105
+
106
+ .t-radio-group__dot {
107
+ width: 10px;
108
+ height: 10px;
109
+ background-color: #1890ff;
110
+ border-radius: 50%;
111
+ }
112
+
113
+ .t-radio-group__label {
114
+ font-size: 14px;
115
+ color: #323233;
116
+ }
117
+ </style>
@@ -0,0 +1,25 @@
1
+ /**
2
+ * TRadioGroup 组件类型定义
3
+ */
4
+
5
+ export type RadioDirection = 'horizontal' | 'vertical'
6
+
7
+ export interface RadioOption {
8
+ label: string
9
+ value: string | number
10
+ disabled?: boolean
11
+ }
12
+
13
+ export interface TRadioGroupProps {
14
+ modelValue?: string | number
15
+ options?: RadioOption[]
16
+ direction?: RadioDirection
17
+ disabled?: boolean
18
+ customClass?: string
19
+ customStyle?: string
20
+ }
21
+
22
+ export interface TRadioGroupEmits {
23
+ 'update:modelValue': (value: string | number) => void
24
+ change: (value: string | number) => void
25
+ }
@@ -0,0 +1,182 @@
1
+ <script setup lang="uts" >
2
+ /**
3
+ * 评分组件属性类型
4
+ */
5
+ type RateProps = {
6
+ /** 最大评分 */
7
+ max?: number
8
+ /** 是否只读 */
9
+ readonly?: boolean
10
+ /** 是否禁用 */
11
+ disabled?: boolean
12
+ /** 星星大小 */
13
+ size?: number
14
+ /** 星星间距 */
15
+ gap?: number
16
+ /** 激活颜色 */
17
+ activeColor?: string
18
+ /** 未激活颜色 */
19
+ inactiveColor?: string
20
+ /** 是否显示评分 */
21
+ showScore?: boolean
22
+ /** 是否允许清除 */
23
+ allowClear?: boolean
24
+ /** 精度 */
25
+ precision?: number
26
+ /** 星星字符 */
27
+ starChar?: string
28
+ /** 是否震动 */
29
+ vibrate?: boolean
30
+ }
31
+
32
+ const props = withDefaults(defineProps<RateProps>(), {
33
+ max: 5,
34
+ readonly: false,
35
+ disabled: false,
36
+ size: 40,
37
+ gap: 2,
38
+ activeColor: '#ffc107',
39
+ inactiveColor: '#e4e7eb',
40
+ showScore: false,
41
+ allowClear: false,
42
+ precision: 0, // ⭐ 无半星 → 只允许整数
43
+ starChar: '★',
44
+ vibrate: false
45
+ })
46
+
47
+ const emit = defineEmits<{
48
+ change: [value: number]
49
+ click: [value: number]
50
+ hoverChange: [value: number]
51
+ }>()
52
+
53
+ const model = defineModel({ default: 0 })
54
+
55
+ /** 格式化评分显示 */
56
+ const formatScore = computed(() => {
57
+ const value = model.value.toFixed(props.precision)
58
+ return `${value}/${props.max}`
59
+ })
60
+
61
+ /** 每颗星的填充比例(仅 0% 或 100%) */
62
+ const stars = computed(() => {
63
+ return Array.from({ length: props.max }, (_, i) => {
64
+ const index = i + 1
65
+ return { index, percentage: index <= model.value ? 100 : 0 }
66
+ })
67
+ })
68
+
69
+ /** 基础星样式 */
70
+ const baseStarStyle = computed(() => ({
71
+ fontSize: `${props.size}rpx`,
72
+ marginRight: `${props.gap}rpx`,
73
+ color: props.inactiveColor,
74
+ cursor: props.readonly || props.disabled ? 'default' : 'pointer'
75
+ }))
76
+
77
+ /** 更新评分 */
78
+ const updateRating = (newRating: number) => {
79
+ model.value = newRating
80
+ emit('change', newRating)
81
+
82
+ if (props.vibrate) {
83
+ try {
84
+ uni.vibrateShort()
85
+ } catch {}
86
+ }
87
+ }
88
+
89
+ /** 点击事件(整星) */
90
+ const handleStarClick = (index: number) => {
91
+ if (props.readonly || props.disabled) return
92
+
93
+ let newRating = index
94
+
95
+ // 再次点击相同评分 → 清空
96
+ if (props.allowClear && newRating === model.value) {
97
+ newRating = 0
98
+ }
99
+
100
+ updateRating(newRating)
101
+ emit('click', newRating)
102
+ }
103
+
104
+ </script>
105
+
106
+ <template>
107
+ <view class="rate-wrapper">
108
+ <view class="rate-stars">
109
+ <view
110
+ v-for="star in stars"
111
+ :key="star.index"
112
+ class="star-item"
113
+ :style="baseStarStyle"
114
+ @tap="handleStarClick(star.index)"
115
+ @click="handleStarClick(star.index)"
116
+ >
117
+ <text
118
+ class="star-fill"
119
+ :style="{
120
+ color: star.percentage === 100 ? props.activeColor : props.inactiveColor
121
+ }"
122
+ >
123
+ {{ props.starChar }}
124
+ </text>
125
+ </view>
126
+ </view>
127
+
128
+ <view v-if="props.showScore" class="rate-score">
129
+ <text class="score-text">
130
+ {{ formatScore }}
131
+ </text>
132
+ </view>
133
+ </view>
134
+ </template>
135
+
136
+ <style scoped lang="scss">
137
+ .rate-wrapper {
138
+ display: flex;
139
+ flex-direction: row;
140
+ gap: 4rpx;
141
+ align-items: center;
142
+ user-select: none;
143
+ }
144
+
145
+ .rate-stars {
146
+ display: flex;
147
+ flex-direction: row;
148
+ align-items: center;
149
+ }
150
+
151
+ .star-item {
152
+ display: inline-block;
153
+ transition: transform 0.15s ease;
154
+ cursor: pointer;
155
+
156
+ &:active {
157
+ transform: scale(0.9);
158
+ }
159
+
160
+ &:last-child {
161
+ margin-right: 0 !important;
162
+ }
163
+ }
164
+
165
+ .star-fill {
166
+ display: inline-block;
167
+ font-weight: 600;
168
+ line-height: 1;
169
+ transition: color 0.25s ease;
170
+ }
171
+
172
+ .rate-score {
173
+ margin-left: 16rpx;
174
+ }
175
+
176
+ .score-text {
177
+ font-size: 28rpx;
178
+ font-weight: 500;
179
+ line-height: 1.2;
180
+ color: #374151;
181
+ }
182
+ </style>
@@ -0,0 +1,105 @@
1
+ <script setup lang="uts">
2
+ import { provide, computed } from 'vue'
3
+ import type { RowJustify, RowAlign } from './type.uts'
4
+
5
+ /**
6
+ * TRow 栅格行组件
7
+ * @description 基于 24 栅格系统的行容器,配合 TCol 使用
8
+ */
9
+
10
+ // Props 定义
11
+ interface Props {
12
+ gutter?: number
13
+ justify?: RowJustify
14
+ align?: RowAlign
15
+ wrap?: boolean
16
+ customClass?: string
17
+ customStyle?: string
18
+ }
19
+
20
+ const props = withDefaults(defineProps<Props>(), {
21
+ gutter: 0,
22
+ justify: 'start',
23
+ align: 'top',
24
+ wrap: true,
25
+ customClass: '',
26
+ customStyle: ''
27
+ })
28
+
29
+ // 提供 gutter 给子组件
30
+ provide('rowGutter', props.gutter)
31
+
32
+ /**
33
+ * 计算容器样式
34
+ */
35
+ const containerStyle = computed((): string => {
36
+ const styles: string[] = []
37
+
38
+ // 列间距(负边距抵消子元素的内边距)
39
+ if (props.gutter > 0) {
40
+ const margin = props.gutter / 2
41
+ styles.push(`margin-left: -${margin}px`)
42
+ styles.push(`margin-right: -${margin}px`)
43
+ }
44
+
45
+ // 水平对齐
46
+ const justifyMap = {
47
+ start: 'flex-start',
48
+ end: 'flex-end',
49
+ center: 'center',
50
+ 'space-around': 'space-around',
51
+ 'space-between': 'space-between',
52
+ 'space-evenly': 'space-evenly'
53
+ }
54
+ styles.push(`justify-content: ${justifyMap[props.justify]}`)
55
+
56
+ // 垂直对齐
57
+ const alignMap = {
58
+ top: 'flex-start',
59
+ middle: 'center',
60
+ bottom: 'flex-end'
61
+ }
62
+ styles.push(`align-items: ${alignMap[props.align]}`)
63
+
64
+ // 换行
65
+ if (props.wrap) {
66
+ styles.push('flex-wrap: wrap')
67
+ } else {
68
+ styles.push('flex-wrap: nowrap')
69
+ }
70
+
71
+ // 自定义样式
72
+ if (props.customStyle) {
73
+ styles.push(props.customStyle)
74
+ }
75
+
76
+ return styles.join('; ')
77
+ })
78
+
79
+ /**
80
+ * 计算容器类名
81
+ */
82
+ const containerClasses = computed((): string => {
83
+ const classes: string[] = ['t-row']
84
+
85
+ if (props.customClass) {
86
+ classes.push(props.customClass)
87
+ }
88
+
89
+ return classes.join(' ')
90
+ })
91
+ </script>
92
+
93
+ <template>
94
+ <view :class="containerClasses" :style="containerStyle">
95
+ <slot></slot>
96
+ </view>
97
+ </template>
98
+
99
+ <style lang="scss" scoped>
100
+ .t-row {
101
+ display: flex;
102
+ flex-direction: row;
103
+ width: 100%;
104
+ }
105
+ </style>
@@ -0,0 +1,52 @@
1
+ /**
2
+ * TRow 组件类型定义
3
+ */
4
+
5
+ /**
6
+ * 水平对齐方式
7
+ */
8
+ export type RowJustify = 'start' | 'end' | 'center' | 'space-around' | 'space-between' | 'space-evenly'
9
+
10
+ /**
11
+ * 垂直对齐方式
12
+ */
13
+ export type RowAlign = 'top' | 'middle' | 'bottom'
14
+
15
+ /**
16
+ * TRow Props 接口
17
+ */
18
+ export interface TRowProps {
19
+ /**
20
+ * 列间距(单位 px)
21
+ * @default 0
22
+ */
23
+ gutter?: number
24
+
25
+ /**
26
+ * 水平对齐方式
27
+ * @default 'start'
28
+ */
29
+ justify?: RowJustify
30
+
31
+ /**
32
+ * 垂直对齐方式
33
+ * @default 'top'
34
+ */
35
+ align?: RowAlign
36
+
37
+ /**
38
+ * 是否自动换行
39
+ * @default true
40
+ */
41
+ wrap?: boolean
42
+
43
+ /**
44
+ * 自定义类名
45
+ */
46
+ customClass?: string
47
+
48
+ /**
49
+ * 自定义样式
50
+ */
51
+ customStyle?: string
52
+ }