@star-ai/star-ui 0.0.2

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.
@@ -0,0 +1,404 @@
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>
@@ -0,0 +1,8 @@
1
+
2
+ import Input from './Input.vue'
3
+
4
+ Input.install = function(Vue) {
5
+ Vue.component(Input.name, Input)
6
+ }
7
+
8
+ export default Input
package/lib/index.js ADDED
@@ -0,0 +1,28 @@
1
+
2
+ // 自动导入所有组件
3
+ const components = []
4
+
5
+ const install = function(Vue, opts = {}) {
6
+ components.forEach(component => {
7
+ Vue.component(component.name, component)
8
+ })
9
+
10
+ // 挂载全局方法
11
+ Vue.prototype.$MY_UI = {
12
+ size: opts.size || '',
13
+ zIndex: opts.zIndex || 2000
14
+ }
15
+ }
16
+
17
+ // 如果是浏览器环境且已引入Vue,则自动安装
18
+ if (typeof window !== 'undefined' && window.Vue) {
19
+ install(window.Vue)
20
+ }
21
+
22
+ export default {
23
+ version: '0.1.0',
24
+ install,
25
+ // 按需导出所有组件
26
+ Button: require('./components/Button').default,
27
+ Input: require('./components/Input').default
28
+ }
@@ -0,0 +1,102 @@
1
+ // 导入变量和混合器
2
+ @import './variables.scss';
3
+ @import './mixins.scss';
4
+
5
+ // 全局样式重置
6
+ .star-reset {
7
+ box-sizing: border-box;
8
+
9
+ *,
10
+ *::before,
11
+ *::after {
12
+ box-sizing: border-box;
13
+ }
14
+
15
+ // 解决 H5 平台的一些问题
16
+ uni-page-body {
17
+ height: 100%;
18
+ }
19
+
20
+ uni-page-body,
21
+ uni-page-head {
22
+ background-color: $bg-color;
23
+ }
24
+ }
25
+
26
+ // 工具类
27
+ .star-text-center {
28
+ text-align: center;
29
+ }
30
+
31
+ .star-text-left {
32
+ text-align: left;
33
+ }
34
+
35
+ .star-text-right {
36
+ text-align: right;
37
+ }
38
+
39
+ .star-pull-left {
40
+ float: left;
41
+ }
42
+
43
+ .star-pull-right {
44
+ float: right;
45
+ }
46
+
47
+ .star-clearfix {
48
+ @include clearfix;
49
+ }
50
+
51
+ .star-ellipsis {
52
+ @include ellipsis;
53
+ }
54
+
55
+ // 间距工具类
56
+ @each $size, $value in (
57
+ xs: $spacing-xs,
58
+ sm: $spacing-sm,
59
+ base: $spacing-base,
60
+ lg: $spacing-lg,
61
+ xl: $spacing-xl
62
+ ) {
63
+ .star-m-#{$size} {
64
+ margin: $value;
65
+ }
66
+
67
+ .star-mt-#{$size} {
68
+ margin-top: $value;
69
+ }
70
+
71
+ .star-mr-#{$size} {
72
+ margin-right: $value;
73
+ }
74
+
75
+ .star-mb-#{$size} {
76
+ margin-bottom: $value;
77
+ }
78
+
79
+ .star-ml-#{$size} {
80
+ margin-left: $value;
81
+ }
82
+
83
+ .star-p-#{$size} {
84
+ padding: $value;
85
+ }
86
+
87
+ .star-pt-#{$size} {
88
+ padding-top: $value;
89
+ }
90
+
91
+ .star-pr-#{$size} {
92
+ padding-right: $value;
93
+ }
94
+
95
+ .star-pb-#{$size} {
96
+ padding-bottom: $value;
97
+ }
98
+
99
+ .star-pl-#{$size} {
100
+ padding-left: $value;
101
+ }
102
+ }
@@ -0,0 +1,84 @@
1
+ // 清除浮动
2
+ @mixin clearfix {
3
+ &::after {
4
+ content: "";
5
+ display: table;
6
+ clear: both;
7
+ }
8
+ }
9
+
10
+ // 单行省略
11
+ @mixin ellipsis {
12
+ overflow: hidden;
13
+ text-overflow: ellipsis;
14
+ white-space: nowrap;
15
+ }
16
+
17
+ // 多行省略
18
+ @mixin multi-ellipsis($lines: 2) {
19
+ display: -webkit-box;
20
+ overflow: hidden;
21
+ text-overflow: ellipsis;
22
+ -webkit-line-clamp: $lines;
23
+ -webkit-box-orient: vertical;
24
+ }
25
+
26
+ // 1px 边框(解决移动端 Retina 屏边框问题)
27
+ @mixin hairline($color: $border-color, $direction: bottom) {
28
+ position: relative;
29
+
30
+ &::after {
31
+ content: "";
32
+ position: absolute;
33
+ #{$direction}: 0;
34
+ left: 0;
35
+ right: 0;
36
+ height: 1px;
37
+ background-color: $color;
38
+ transform: scaleY(0.5);
39
+ transform-origin: 0 0;
40
+ }
41
+ }
42
+
43
+ // 禁用状态
44
+ @mixin disabled {
45
+ opacity: 0.6;
46
+ cursor: not-allowed;
47
+ pointer-events: none;
48
+ }
49
+
50
+ // 弹性布局快捷方式
51
+ @mixin flex-center {
52
+ display: flex;
53
+ align-items: center;
54
+ justify-content: center;
55
+ }
56
+
57
+ @mixin flex-between {
58
+ display: flex;
59
+ align-items: center;
60
+ justify-content: space-between;
61
+ }
62
+
63
+ @mixin flex-around {
64
+ display: flex;
65
+ align-items: center;
66
+ justify-content: space-around;
67
+ }
68
+
69
+ // 响应式
70
+ @mixin respond-to($breakpoint) {
71
+ @if $breakpoint == 'xs' {
72
+ @media (max-width: 575px) { @content; }
73
+ } @else if $breakpoint == 'sm' {
74
+ @media (min-width: 576px) { @content; }
75
+ } @else if $breakpoint == 'md' {
76
+ @media (min-width: 768px) { @content; }
77
+ } @else if $breakpoint == 'lg' {
78
+ @media (min-width: 992px) { @content; }
79
+ } @else if $breakpoint == 'xl' {
80
+ @media (min-width: 1200px) { @content; }
81
+ } @else if $breakpoint == 'xxl' {
82
+ @media (min-width: 1600px) { @content; }
83
+ }
84
+ }
@@ -0,0 +1,64 @@
1
+ // 颜色系统
2
+ $white: #ffffff;
3
+ $black: #000000;
4
+
5
+ // 主色调
6
+ $primary-color: #2979ff;
7
+ $primary-color-light: #5cadff;
8
+ $primary-color-dark: #2b85e4;
9
+
10
+ // 功能色
11
+ $success-color: #19be6b;
12
+ $warning-color: #ff9900;
13
+ $error-color: #fa3534;
14
+ $info-color: #909399;
15
+
16
+ // 中性色
17
+ $text-color: #333333;
18
+ $text-color-secondary: #666666;
19
+ $text-color-light: #999999;
20
+ $text-color-disabled: #c0c4cc;
21
+
22
+ $bg-color: #ffffff;
23
+ $bg-color-grey: #f5f5f5;
24
+ $bg-color-hover: #f6f6f6;
25
+
26
+ $border-color: #e4e7ed;
27
+ $border-color-light: #ebeef5;
28
+
29
+ // 阴影
30
+ $box-shadow-base: 0 2px 12px rgba(0, 0, 0, 0.1);
31
+ $box-shadow-light: 0 2px 8px rgba(0, 0, 0, 0.09);
32
+ $box-shadow-dark: 0 2px 16px rgba(0, 0, 0, 0.2);
33
+
34
+ // 边框半径
35
+ $border-radius-base: 4px;
36
+ $border-radius-sm: 2px;
37
+ $border-radius-lg: 8px;
38
+ $border-radius-circle: 50%;
39
+
40
+ // 字体
41
+ $font-size-xs: 10px;
42
+ $font-size-sm: 12px;
43
+ $font-size-base: 14px;
44
+ $font-size-lg: 16px;
45
+ $font-size-xl: 18px;
46
+ $font-size-xxl: 20px;
47
+
48
+ // 间距
49
+ $spacing-xs: 4px;
50
+ $spacing-sm: 8px;
51
+ $spacing-base: 16px;
52
+ $spacing-lg: 24px;
53
+ $spacing-xl: 32px;
54
+
55
+ // 层级
56
+ $z-index-normal: 1;
57
+ $z-index-dropdown: 1000;
58
+ $z-index-sticky: 1020;
59
+ $z-index-fixed: 1030;
60
+ $z-index-modal-backdrop: 1040;
61
+ $z-index-modal: 1050;
62
+ $z-index-popover: 1060;
63
+ $z-index-tooltip: 1070;
64
+ $z-index-toast: 1080;