@star-ai/star-ui 0.0.3 → 0.0.5

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.
@@ -1,10 +1,153 @@
1
1
 
2
2
  // Button 组件入口文件
3
- import StarButton from './Button.vue'
3
+ const StarButton = {
4
+ name: 'StarButton',
5
+
6
+ // 组件属性定义
7
+ props: {
8
+ // 按钮类型
9
+ type: {
10
+ type: String,
11
+ default: 'default',
12
+ validator: (value) => {
13
+ return ['default', 'primary', 'success', 'warning', 'error', 'info'].includes(value)
14
+ }
15
+ },
16
+
17
+ // 按钮大小
18
+ size: {
19
+ type: String,
20
+ default: 'medium',
21
+ validator: (value) => {
22
+ return ['mini', 'small', 'medium', 'large'].includes(value)
23
+ }
24
+ },
25
+
26
+ // 是否禁用
27
+ disabled: {
28
+ type: Boolean,
29
+ default: false
30
+ },
31
+
32
+ // 是否加载中
33
+ loading: {
34
+ type: Boolean,
35
+ default: false
36
+ },
37
+
38
+ // 是否为朴素按钮
39
+ plain: {
40
+ type: Boolean,
41
+ default: false
42
+ },
43
+
44
+ // 是否为块级按钮
45
+ block: {
46
+ type: Boolean,
47
+ default: false
48
+ },
49
+
50
+ // 左侧图标
51
+ icon: {
52
+ type: String,
53
+ default: ''
54
+ },
55
+
56
+ // 右侧图标
57
+ rightIcon: {
58
+ type: String,
59
+ default: ''
60
+ },
61
+
62
+ // 自定义样式
63
+ customStyle: {
64
+ type: Object,
65
+ default: () => ({})
66
+ },
67
+
68
+ // 点击防抖时间(毫秒)
69
+ debounce: {
70
+ type: Number,
71
+ default: 0
72
+ }
73
+ },
74
+
75
+ data() {
76
+ return {
77
+ canClick: true
78
+ }
79
+ },
80
+
81
+ methods: {
82
+ handleClick(event) {
83
+ // 防抖处理
84
+ if (!this.canClick) return
85
+
86
+ if (this.debounce > 0) {
87
+ this.canClick = false
88
+ setTimeout(() => {
89
+ this.canClick = true
90
+ }, this.debounce)
91
+ }
92
+
93
+ // 触发点击事件
94
+ if (!this.disabled && !this.loading) {
95
+ this.$emit('click', event)
96
+ }
97
+ }
98
+ }
99
+ }
100
+
101
+ // 添加模板
102
+ StarButton.template = `<view
103
+ class="star-button"
104
+ :class="[
105
+ `star-button--${type}`,
106
+ `star-button--${size}`,
107
+ {
108
+ 'star-button--disabled': disabled,
109
+ 'star-button--loading': loading,
110
+ 'star-button--block': block,
111
+ 'star-button--plain': plain
112
+ }
113
+ ]"
114
+ :style="[customStyle]"
115
+ @click="handleClick"
116
+ >
117
+ <!-- 加载状态 -->
118
+ <view v-if="loading" class="star-button__loading">
119
+ <view class="star-button__loading-spinner"></view>
120
+ </view>
121
+
122
+ <!-- 图标 -->
123
+ <text
124
+ v-if="icon && !loading"
125
+ class="star-button__icon"
126
+ :class="icon"
127
+ ></text>
128
+
129
+ <!-- 文字内容 -->
130
+ <text class="star-button__text">
131
+ <slot></slot>
132
+ </text>
133
+
134
+ <!-- 右侧图标 -->
135
+ <text
136
+ v-if="rightIcon && !loading"
137
+ class="star-button__right-icon"
138
+ :class="rightIcon"
139
+ ></text>
140
+ </view>`
4
141
 
5
142
  StarButton.install = function(Vue) {
6
143
  Vue.component(StarButton.name, StarButton)
7
144
  }
8
145
 
9
- export default StarButton
10
- export { StarButton }
146
+ // CommonJS 导出
147
+ module.exports = StarButton
148
+ module.exports.default = StarButton
149
+
150
+ // 浏览器全局变量导出
151
+ if (typeof window !== 'undefined') {
152
+ window.StarButton = StarButton
153
+ }
@@ -1,10 +1,264 @@
1
1
 
2
2
  // Input 组件入口文件
3
- import StarInput from './Input.vue'
3
+ const StarInput = {
4
+ name: 'StarInput',
5
+
6
+ props: {
7
+ // 输入框类型
8
+ type: {
9
+ type: String,
10
+ default: 'text'
11
+ },
12
+
13
+ // 绑定值
14
+ value: {
15
+ type: [String, Number],
16
+ default: ''
17
+ },
18
+
19
+ // 原生属性
20
+ placeholder: {
21
+ type: String,
22
+ default: ''
23
+ },
24
+
25
+ disabled: {
26
+ type: Boolean,
27
+ default: false
28
+ },
29
+
30
+ maxlength: {
31
+ type: [String, Number],
32
+ default: 140
33
+ },
34
+
35
+ focus: {
36
+ type: Boolean,
37
+ default: false
38
+ },
39
+
40
+ confirmType: {
41
+ type: String,
42
+ default: 'done'
43
+ },
44
+
45
+ placeholderStyle: {
46
+ type: String,
47
+ default: ''
48
+ },
49
+
50
+ placeholderClass: {
51
+ type: String,
52
+ default: ''
53
+ },
54
+
55
+ cursorSpacing: {
56
+ type: [String, Number],
57
+ default: 0
58
+ },
59
+
60
+ // 自定义属性
61
+ size: {
62
+ type: String,
63
+ default: 'medium',
64
+ validator: (value) => ['mini', 'small', 'medium', 'large'].includes(value)
65
+ },
66
+
67
+ clearable: {
68
+ type: Boolean,
69
+ default: false
70
+ },
71
+
72
+ showPassword: {
73
+ type: Boolean,
74
+ default: false
75
+ },
76
+
77
+ prefixIcon: {
78
+ type: String,
79
+ default: ''
80
+ },
81
+
82
+ suffixIcon: {
83
+ type: String,
84
+ default: ''
85
+ },
86
+
87
+ prepend: {
88
+ type: String,
89
+ default: ''
90
+ },
91
+
92
+ append: {
93
+ type: String,
94
+ default: ''
95
+ },
96
+
97
+ readonly: {
98
+ type: Boolean,
99
+ default: false
100
+ }
101
+ },
102
+
103
+ data() {
104
+ return {
105
+ currentValue: this.value,
106
+ isFocused: false,
107
+ passwordVisible: false
108
+ }
109
+ },
110
+
111
+ computed: {
112
+ inputClasses() {
113
+ return [
114
+ `star-input--${this.size}`,
115
+ {
116
+ 'star-input--disabled': this.disabled,
117
+ 'star-input--focused': this.isFocused,
118
+ 'star-input--with-prepend': this.prepend || this.$slots.prepend,
119
+ 'star-input--with-append': this.append || this.$slots.append,
120
+ 'star-input--readonly': this.readonly
121
+ }
122
+ ]
123
+ }
124
+ },
125
+
126
+ watch: {
127
+ value(newVal) {
128
+ this.currentValue = newVal
129
+ }
130
+ },
131
+
132
+ methods: {
133
+ handleInput(event) {
134
+ const value = event.detail.value
135
+ this.currentValue = value
136
+ this.$emit('input', value)
137
+ this.$emit('change', value)
138
+ },
139
+
140
+ handleFocus(event) {
141
+ this.isFocused = true
142
+ this.$emit('focus', event)
143
+ },
144
+
145
+ handleBlur(event) {
146
+ this.isFocused = false
147
+ this.$emit('blur', event)
148
+ },
149
+
150
+ handleConfirm(event) {
151
+ this.$emit('confirm', event)
152
+ },
153
+
154
+ handleKeyboardHeightChange(event) {
155
+ this.$emit('keyboardheightchange', event)
156
+ },
157
+
158
+ handleClear() {
159
+ this.currentValue = ''
160
+ this.$emit('input', '')
161
+ this.$emit('change', '')
162
+ this.$emit('clear')
163
+ },
164
+
165
+ togglePasswordVisible() {
166
+ this.passwordVisible = !this.passwordVisible
167
+ },
168
+
169
+ handlePrefixIconClick() {
170
+ this.$emit('click-prefix')
171
+ },
172
+
173
+ handleSuffixIconClick() {
174
+ this.$emit('click-suffix')
175
+ }
176
+ }
177
+ }
178
+
179
+ // 添加模板
180
+ StarInput.template = `<view class="star-input" :class="inputClasses">
181
+ <!-- 前置内容 -->
182
+ <view v-if="$slots.prepend || prepend" class="star-input__prepend">
183
+ <slot name="prepend">
184
+ <text v-if="prepend" class="star-input__prepend-text">{{ prepend }}</text>
185
+ </slot>
186
+ </view>
187
+
188
+ <!-- 输入框主体 -->
189
+ <view class="star-input__wrapper">
190
+ <!-- 前置图标 -->
191
+ <text
192
+ v-if="prefixIcon"
193
+ class="star-input__prefix-icon"
194
+ :class="prefixIcon"
195
+ @click="handlePrefixIconClick"
196
+ ></text>
197
+
198
+ <!-- 输入框 -->
199
+ <input
200
+ class="star-input__inner"
201
+ :type="showPassword ? (passwordVisible ? 'text' : 'password') : type"
202
+ :value="currentValue"
203
+ :placeholder="placeholder"
204
+ :disabled="disabled"
205
+ :maxlength="maxlength"
206
+ :focus="focus"
207
+ :confirm-type="confirmType"
208
+ :placeholder-style="placeholderStyle"
209
+ :placeholder-class="placeholderClass"
210
+ :cursor-spacing="cursorSpacing"
211
+ @input="handleInput"
212
+ @focus="handleFocus"
213
+ @blur="handleBlur"
214
+ @confirm="handleConfirm"
215
+ @keyboardheightchange="handleKeyboardHeightChange"
216
+ />
217
+
218
+ <!-- 清除按钮 -->
219
+ <view
220
+ v-if="clearable && currentValue && !disabled"
221
+ class="star-input__clear"
222
+ @click="handleClear"
223
+ >
224
+ <text class="star-icon-close"></text>
225
+ </view>
226
+
227
+ <!-- 密码可见切换按钮 -->
228
+ <view
229
+ v-if="showPassword && currentValue"
230
+ class="star-input__password-toggle"
231
+ @click="togglePasswordVisible"
232
+ >
233
+ <text :class="passwordVisible ? 'star-icon-eye-open' : 'star-icon-eye-close'"></text>
234
+ </view>
235
+
236
+ <!-- 后置图标 -->
237
+ <text
238
+ v-if="suffixIcon"
239
+ class="star-input__suffix-icon"
240
+ :class="suffixIcon"
241
+ @click="handleSuffixIconClick"
242
+ ></text>
243
+ </view>
244
+
245
+ <!-- 后置内容 -->
246
+ <view v-if="$slots.append || append" class="star-input__append">
247
+ <slot name="append">
248
+ <text v-if="append" class="star-input__append-text">{{ append }}</text>
249
+ </slot>
250
+ </view>
251
+ </view>`
4
252
 
5
253
  StarInput.install = function(Vue) {
6
254
  Vue.component(StarInput.name, StarInput)
7
255
  }
8
256
 
9
- export default StarInput
10
- export { StarInput }
257
+ // CommonJS 导出
258
+ module.exports = StarInput
259
+ module.exports.default = StarInput
260
+
261
+ // 浏览器全局变量导出
262
+ if (typeof window !== 'undefined') {
263
+ window.StarInput = StarInput
264
+ }
package/lib/index.js CHANGED
@@ -1,10 +1,9 @@
1
-
2
1
  // star-ui 组件库主入口文件
3
- import packageJson from '../package.json'
2
+ const packageJson = require('../package.json')
4
3
 
5
4
  // 导入所有组件
6
- import StarButton from './components/Button/index.js'
7
- import StarInput from './components/Input/index.js'
5
+ const StarButton = require('./components/Button/index.js').default
6
+ const StarInput = require('./components/Input/index.js').default
8
7
 
9
8
  // 组件列表
10
9
  const components = [
@@ -46,25 +45,18 @@ const StarUI = {
46
45
  StarInput
47
46
  }
48
47
 
49
- // 导出模块
50
- if (typeof module !== 'undefined' && module.exports) {
51
- // CommonJS 导出
52
- module.exports = StarUI
53
- module.exports.default = StarUI
54
- // 为每个组件添加单独的导出(支持按需导入)
55
- components.forEach(component => {
56
- if (component.name) {
57
- module.exports[component.name] = component
58
- }
59
- })
60
- } else if (typeof define === 'function' && define.amd) {
61
- // AMD 导出
62
- define(() => StarUI)
63
- } else if (typeof window !== 'undefined') {
64
- // 浏览器全局变量导出
65
- window.StarUI = StarUI
66
- }
48
+ // CommonJS 导出
49
+ module.exports = StarUI
50
+ module.exports.default = StarUI
51
+
52
+ // 为每个组件添加单独的导出(支持按需导入)
53
+ components.forEach(component => {
54
+ if (component.name) {
55
+ module.exports[component.name] = component
56
+ }
57
+ })
67
58
 
68
- // ES模块导出
69
- export default StarUI
70
- export { StarButton, StarInput }
59
+ // 浏览器全局变量导出
60
+ if (typeof window !== 'undefined') {
61
+ window.StarUI = StarUI
62
+ }
package/lib/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@star-ai/star-ui",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "description": "基于Uniapp的Vue2组件库",
5
5
  "main": "index.js",
6
6
  "files": [
@@ -12,6 +12,9 @@
12
12
  "@vue/shared": "^3.0.0",
13
13
  "core-js": "^3.8.3"
14
14
  },
15
+ "peerDependencies": {
16
+ "vue": ">= 2.6.14 < 4"
17
+ },
15
18
  "keywords": [
16
19
  "uniapp",
17
20
  "vue2",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@star-ai/star-ui",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
4
4
  "description": "基于Uniapp的Vue2组件库",
5
5
  "main": "lib/index.js",
6
6
  "module": "lib/index.js",
@@ -59,7 +59,7 @@
59
59
  "test:mp-weixin": "cross-env UNI_PLATFORM=mp-weixin jest -i"
60
60
  },
61
61
  "peerDependencies": {
62
- "vue": ">= 2.6.14 < 2.7"
62
+ "vue": ">= 2.6.14 < 4"
63
63
  },
64
64
  "dependencies": {
65
65
  "@vue/shared": "^3.0.0",
@@ -1,325 +0,0 @@
1
- <template>
2
- <view
3
- class="star-button"
4
- :class="[
5
- `star-button--${type}`,
6
- `star-button--${size}`,
7
- {
8
- 'star-button--disabled': disabled,
9
- 'star-button--loading': loading,
10
- 'star-button--block': block,
11
- 'star-button--plain': plain
12
- }
13
- ]"
14
- :style="[customStyle]"
15
- @click="handleClick"
16
- >
17
- <!-- 加载状态 -->
18
- <view v-if="loading" class="star-button__loading">
19
- <view class="star-button__loading-spinner"></view>
20
- </view>
21
-
22
- <!-- 图标 -->
23
- <text
24
- v-if="icon && !loading"
25
- class="star-button__icon"
26
- :class="icon"
27
- ></text>
28
-
29
- <!-- 文字内容 -->
30
- <text class="star-button__text">
31
- <slot></slot>
32
- </text>
33
-
34
- <!-- 右侧图标 -->
35
- <text
36
- v-if="rightIcon && !loading"
37
- class="star-button__right-icon"
38
- :class="rightIcon"
39
- ></text>
40
- </view>
41
- </template>
42
-
43
- <script>
44
- export default {
45
- name: 'StarButton',
46
-
47
- // 组件属性定义
48
- props: {
49
- // 按钮类型
50
- type: {
51
- type: String,
52
- default: 'default',
53
- validator: (value) => {
54
- return ['default', 'primary', 'success', 'warning', 'error', 'info'].includes(value)
55
- }
56
- },
57
-
58
- // 按钮大小
59
- size: {
60
- type: String,
61
- default: 'medium',
62
- validator: (value) => {
63
- return ['mini', 'small', 'medium', 'large'].includes(value)
64
- }
65
- },
66
-
67
- // 是否禁用
68
- disabled: {
69
- type: Boolean,
70
- default: false
71
- },
72
-
73
- // 是否加载中
74
- loading: {
75
- type: Boolean,
76
- default: false
77
- },
78
-
79
- // 是否为朴素按钮
80
- plain: {
81
- type: Boolean,
82
- default: false
83
- },
84
-
85
- // 是否为块级按钮
86
- block: {
87
- type: Boolean,
88
- default: false
89
- },
90
-
91
- // 左侧图标
92
- icon: {
93
- type: String,
94
- default: ''
95
- },
96
-
97
- // 右侧图标
98
- rightIcon: {
99
- type: String,
100
- default: ''
101
- },
102
-
103
- // 自定义样式
104
- customStyle: {
105
- type: Object,
106
- default: () => ({})
107
- },
108
-
109
- // 点击防抖时间(毫秒)
110
- debounce: {
111
- type: Number,
112
- default: 0
113
- }
114
- },
115
-
116
- data() {
117
- return {
118
- canClick: true
119
- }
120
- },
121
-
122
- methods: {
123
- handleClick(event) {
124
- // 防抖处理
125
- if (!this.canClick) return
126
-
127
- if (this.debounce > 0) {
128
- this.canClick = false
129
- setTimeout(() => {
130
- this.canClick = true
131
- }, this.debounce)
132
- }
133
-
134
- // 触发点击事件
135
- if (!this.disabled && !this.loading) {
136
- this.$emit('click', event)
137
- }
138
- }
139
- }
140
- }
141
- </script>
142
-
143
- <style lang="scss" scoped>
144
- // 引入样式变量
145
- @import "../../styles/variables.scss";
146
-
147
- .star-button {
148
- display: inline-flex;
149
- align-items: center;
150
- justify-content: center;
151
- position: relative;
152
- box-sizing: border-box;
153
- padding: 0 16px;
154
- height: 44px;
155
- line-height: 44px;
156
- border-radius: $border-radius-base;
157
- font-size: $font-size-base;
158
- font-weight: 500;
159
- text-align: center;
160
- vertical-align: middle;
161
- transition: all 0.3s;
162
- cursor: pointer;
163
- user-select: none;
164
-
165
- // 块级按钮
166
- &--block {
167
- display: flex;
168
- width: 100%;
169
- }
170
-
171
- // 禁用状态
172
- &--disabled {
173
- opacity: 0.6;
174
- cursor: not-allowed;
175
- }
176
-
177
- // 大小
178
- &--mini {
179
- padding: 0 8px;
180
- height: 24px;
181
- line-height: 24px;
182
- font-size: $font-size-sm;
183
- border-radius: $border-radius-sm;
184
- }
185
-
186
- &--small {
187
- padding: 0 12px;
188
- height: 32px;
189
- line-height: 32px;
190
- font-size: $font-size-sm;
191
- border-radius: $border-radius-sm;
192
- }
193
-
194
- &--large {
195
- padding: 0 20px;
196
- height: 48px;
197
- line-height: 48px;
198
- font-size: $font-size-lg;
199
- border-radius: $border-radius-lg;
200
- }
201
-
202
- // 类型 - 默认
203
- &--default {
204
- color: $text-color;
205
- background-color: $bg-color;
206
- border: 1px solid $border-color;
207
-
208
- &:not(.star-button--disabled):not(.star-button--loading):active {
209
- background-color: darken($bg-color, 5%);
210
- }
211
- }
212
-
213
- // 类型 - 主要
214
- &--primary {
215
- color: $white;
216
- background-color: $primary-color;
217
- border: 1px solid $primary-color;
218
-
219
- &.star-button--plain {
220
- color: $primary-color;
221
- background-color: transparent;
222
- }
223
-
224
- &:not(.star-button--disabled):not(.star-button--loading):active {
225
- background-color: darken($primary-color, 10%);
226
- border-color: darken($primary-color, 10%);
227
- }
228
- }
229
-
230
- // 类型 - 成功
231
- &--success {
232
- color: $white;
233
- background-color: $success-color;
234
- border: 1px solid $success-color;
235
-
236
- &.star-button--plain {
237
- color: $success-color;
238
- background-color: transparent;
239
- }
240
- }
241
-
242
- // 类型 - 警告
243
- &--warning {
244
- color: $white;
245
- background-color: $warning-color;
246
- border: 1px solid $warning-color;
247
-
248
- &.star-button--plain {
249
- color: $warning-color;
250
- background-color: transparent;
251
- }
252
- }
253
-
254
- // 类型 - 错误
255
- &--error {
256
- color: $white;
257
- background-color: $error-color;
258
- border: 1px solid $error-color;
259
-
260
- &.star-button--plain {
261
- color: $error-color;
262
- background-color: transparent;
263
- }
264
- }
265
-
266
- // 类型 - 信息
267
- &--info {
268
- color: $white;
269
- background-color: $info-color;
270
- border: 1px solid $info-color;
271
-
272
- &.star-button--plain {
273
- color: $info-color;
274
- background-color: transparent;
275
- }
276
- }
277
-
278
- // 加载中
279
- &--loading {
280
- cursor: not-allowed;
281
- }
282
-
283
- // 图标
284
- &__icon,
285
- &__right-icon {
286
- font-family: "star-icon-font" !important; // 使用你自己的图标字体
287
- margin-right: 4px;
288
- font-size: inherit;
289
- }
290
-
291
- &__right-icon {
292
- margin-right: 0;
293
- margin-left: 4px;
294
- }
295
-
296
- &__text {
297
- display: inline-block;
298
- vertical-align: middle;
299
- }
300
-
301
- // 加载动画
302
- &__loading {
303
- margin-right: 4px;
304
- }
305
-
306
- &__loading-spinner {
307
- display: inline-block;
308
- width: 14px;
309
- height: 14px;
310
- border: 2px solid;
311
- border-color: currentColor transparent transparent transparent;
312
- border-radius: 50%;
313
- animation: star-button-spin 1s linear infinite;
314
- }
315
- }
316
-
317
- @keyframes star-button-spin {
318
- 0% {
319
- transform: rotate(0deg);
320
- }
321
- 100% {
322
- transform: rotate(360deg);
323
- }
324
- }
325
- </style>
@@ -1,404 +0,0 @@
1
- <template>
2
- <view class="star-input" :class="inputClasses">
3
- <!-- 前置内容 -->
4
- <view v-if="$slots.prepend || prepend" class="star-input__prepend">
5
- <slot name="prepend">
6
- <text v-if="prepend" class="star-input__prepend-text">{{ prepend }}</text>
7
- </slot>
8
- </view>
9
-
10
- <!-- 输入框主体 -->
11
- <view class="star-input__wrapper">
12
- <!-- 前置图标 -->
13
- <text
14
- v-if="prefixIcon"
15
- class="star-input__prefix-icon"
16
- :class="prefixIcon"
17
- @click="handlePrefixIconClick"
18
- ></text>
19
-
20
- <!-- 输入框 -->
21
- <input
22
- class="star-input__inner"
23
- :type="showPassword ? (passwordVisible ? 'text' : 'password') : type"
24
- :value="currentValue"
25
- :placeholder="placeholder"
26
- :disabled="disabled"
27
- :maxlength="maxlength"
28
- :focus="focus"
29
- :confirm-type="confirmType"
30
- :placeholder-style="placeholderStyle"
31
- :placeholder-class="placeholderClass"
32
- :cursor-spacing="cursorSpacing"
33
- @input="handleInput"
34
- @focus="handleFocus"
35
- @blur="handleBlur"
36
- @confirm="handleConfirm"
37
- @keyboardheightchange="handleKeyboardHeightChange"
38
- />
39
-
40
- <!-- 清除按钮 -->
41
- <view
42
- v-if="clearable && currentValue && !disabled"
43
- class="star-input__clear"
44
- @click="handleClear"
45
- >
46
- <text class="star-icon-close"></text>
47
- </view>
48
-
49
- <!-- 密码可见切换按钮 -->
50
- <view
51
- v-if="showPassword && currentValue"
52
- class="star-input__password-toggle"
53
- @click="togglePasswordVisible"
54
- >
55
- <text :class="passwordVisible ? 'star-icon-eye-open' : 'star-icon-eye-close'"></text>
56
- </view>
57
-
58
- <!-- 后置图标 -->
59
- <text
60
- v-if="suffixIcon"
61
- class="star-input__suffix-icon"
62
- :class="suffixIcon"
63
- @click="handleSuffixIconClick"
64
- ></text>
65
- </view>
66
-
67
- <!-- 后置内容 -->
68
- <view v-if="$slots.append || append" class="star-input__append">
69
- <slot name="append">
70
- <text v-if="append" class="star-input__append-text">{{ append }}</text>
71
- </slot>
72
- </view>
73
- </view>
74
- </template>
75
-
76
- <script>
77
- export default {
78
- name: 'StarInput',
79
-
80
- props: {
81
- // 输入框类型
82
- type: {
83
- type: String,
84
- default: 'text'
85
- },
86
-
87
- // 绑定值
88
- value: {
89
- type: [String, Number],
90
- default: ''
91
- },
92
-
93
- // 原生属性
94
- placeholder: {
95
- type: String,
96
- default: ''
97
- },
98
-
99
- disabled: {
100
- type: Boolean,
101
- default: false
102
- },
103
-
104
- maxlength: {
105
- type: [String, Number],
106
- default: 140
107
- },
108
-
109
- focus: {
110
- type: Boolean,
111
- default: false
112
- },
113
-
114
- confirmType: {
115
- type: String,
116
- default: 'done'
117
- },
118
-
119
- placeholderStyle: {
120
- type: String,
121
- default: ''
122
- },
123
-
124
- placeholderClass: {
125
- type: String,
126
- default: ''
127
- },
128
-
129
- cursorSpacing: {
130
- type: [String, Number],
131
- default: 0
132
- },
133
-
134
- // 自定义属性
135
- size: {
136
- type: String,
137
- default: 'medium',
138
- validator: (value) => ['mini', 'small', 'medium', 'large'].includes(value)
139
- },
140
-
141
- clearable: {
142
- type: Boolean,
143
- default: false
144
- },
145
-
146
- showPassword: {
147
- type: Boolean,
148
- default: false
149
- },
150
-
151
- prefixIcon: {
152
- type: String,
153
- default: ''
154
- },
155
-
156
- suffixIcon: {
157
- type: String,
158
- default: ''
159
- },
160
-
161
- prepend: {
162
- type: String,
163
- default: ''
164
- },
165
-
166
- append: {
167
- type: String,
168
- default: ''
169
- },
170
-
171
- readonly: {
172
- type: Boolean,
173
- default: false
174
- }
175
- },
176
-
177
- data() {
178
- return {
179
- currentValue: this.value,
180
- isFocused: false,
181
- passwordVisible: false
182
- }
183
- },
184
-
185
- computed: {
186
- inputClasses() {
187
- return [
188
- `star-input--${this.size}`,
189
- {
190
- 'star-input--disabled': this.disabled,
191
- 'star-input--focused': this.isFocused,
192
- 'star-input--with-prepend': this.prepend || this.$slots.prepend,
193
- 'star-input--with-append': this.append || this.$slots.append,
194
- 'star-input--readonly': this.readonly
195
- }
196
- ]
197
- }
198
- },
199
-
200
- watch: {
201
- value(newVal) {
202
- this.currentValue = newVal
203
- }
204
- },
205
-
206
- methods: {
207
- handleInput(event) {
208
- const value = event.detail.value
209
- this.currentValue = value
210
- this.$emit('input', value)
211
- this.$emit('change', value)
212
- },
213
-
214
- handleFocus(event) {
215
- this.isFocused = true
216
- this.$emit('focus', event)
217
- },
218
-
219
- handleBlur(event) {
220
- this.isFocused = false
221
- this.$emit('blur', event)
222
- },
223
-
224
- handleConfirm(event) {
225
- this.$emit('confirm', event)
226
- },
227
-
228
- handleKeyboardHeightChange(event) {
229
- this.$emit('keyboardheightchange', event)
230
- },
231
-
232
- handleClear() {
233
- this.currentValue = ''
234
- this.$emit('input', '')
235
- this.$emit('change', '')
236
- this.$emit('clear')
237
- },
238
-
239
- togglePasswordVisible() {
240
- this.passwordVisible = !this.passwordVisible
241
- },
242
-
243
- handlePrefixIconClick() {
244
- this.$emit('click-prefix')
245
- },
246
-
247
- handleSuffixIconClick() {
248
- this.$emit('click-suffix')
249
- }
250
- }
251
- }
252
- </script>
253
-
254
- <style lang="scss" scoped>
255
- @import "../../styles/variables.scss";
256
-
257
- .star-input {
258
- display: inline-flex;
259
- width: 100%;
260
- font-size: $font-size-base;
261
- line-height: normal;
262
-
263
- &__prepend,
264
- &__append {
265
- display: flex;
266
- align-items: center;
267
- justify-content: center;
268
- padding: 0 12px;
269
- background-color: $bg-color-grey;
270
- border: 1px solid $border-color;
271
- white-space: nowrap;
272
-
273
- &-text {
274
- color: $text-color-secondary;
275
- }
276
- }
277
-
278
- &__prepend {
279
- border-right: 0;
280
- border-radius: $border-radius-base 0 0 $border-radius-base;
281
- }
282
-
283
- &__append {
284
- border-left: 0;
285
- border-radius: 0 $border-radius-base $border-radius-base 0;
286
- }
287
-
288
- &__wrapper {
289
- display: flex;
290
- align-items: center;
291
- flex: 1;
292
- position: relative;
293
- padding: 0 12px;
294
- border: 1px solid $border-color;
295
- border-radius: $border-radius-base;
296
- background-color: $bg-color;
297
- transition: border-color 0.3s;
298
-
299
- .star-input--with-prepend & {
300
- border-top-left-radius: 0;
301
- border-bottom-left-radius: 0;
302
- border-left: 0;
303
- }
304
-
305
- .star-input--with-append & {
306
- border-top-right-radius: 0;
307
- border-bottom-right-radius: 0;
308
- border-right: 0;
309
- }
310
- }
311
-
312
- &--focused &__wrapper {
313
- border-color: $primary-color;
314
- }
315
-
316
- &--disabled &__wrapper {
317
- background-color: $bg-color-grey;
318
- cursor: not-allowed;
319
- }
320
-
321
- &__inner {
322
- flex: 1;
323
- width: 100%;
324
- height: 100%;
325
- padding: 0;
326
- border: none;
327
- outline: none;
328
- background: transparent;
329
- font-size: inherit;
330
- color: $text-color;
331
-
332
- .star-input--disabled & {
333
- color: $text-color-disabled;
334
- cursor: not-allowed;
335
- }
336
-
337
- &::placeholder {
338
- color: $text-color-light;
339
- }
340
- }
341
-
342
- &__prefix-icon,
343
- &__suffix-icon {
344
- font-family: "star-icon-font" !important;
345
- color: $text-color-light;
346
- font-size: 18px;
347
- cursor: pointer;
348
- transition: color 0.3s;
349
-
350
- &:hover {
351
- color: $text-color;
352
- }
353
- }
354
-
355
- &__prefix-icon {
356
- margin-right: 8px;
357
- }
358
-
359
- &__suffix-icon {
360
- margin-left: 8px;
361
- }
362
-
363
- &__clear,
364
- &__password-toggle {
365
- display: flex;
366
- align-items: center;
367
- justify-content: center;
368
- width: 20px;
369
- height: 20px;
370
- margin-left: 8px;
371
- color: $text-color-light;
372
- cursor: pointer;
373
- transition: color 0.3s;
374
-
375
- &:hover {
376
- color: $text-color;
377
- }
378
-
379
- .star-icon-close,
380
- .star-icon-eye-open,
381
- .star-icon-eye-close {
382
- font-family: "star-icon-font" !important;
383
- font-size: 16px;
384
- }
385
- }
386
-
387
- // 尺寸
388
- &--mini &__wrapper {
389
- height: 24px;
390
- }
391
-
392
- &--small &__wrapper {
393
- height: 32px;
394
- }
395
-
396
- &--medium &__wrapper {
397
- height: 40px;
398
- }
399
-
400
- &--large &__wrapper {
401
- height: 48px;
402
- }
403
- }
404
- </style>