starai-ui 0.1.19

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.
package/README.md ADDED
@@ -0,0 +1,251 @@
1
+ # star-ui-library
2
+
3
+ 基于Uniapp的Vue2组件库
4
+
5
+ ## 项目介绍
6
+
7
+ star-ui-library是一个基于Uniapp和Vue2开发的移动端组件库,提供了丰富的UI组件,帮助开发者快速构建美观、易用的移动应用。
8
+
9
+ ## 特性
10
+
11
+ - 🎨 基于Uniapp和Vue2,支持多端编译
12
+ - 📱 丰富的移动端UI组件
13
+ - 🔧 支持按需引入
14
+ - 📦 轻量、高效
15
+
16
+ ## 快速开始
17
+
18
+ ### 安装
19
+
20
+ ```bash
21
+ npm install @star-ai/star-ui
22
+ pnpm add @star-ai/star-ui
23
+ ```
24
+
25
+ ### 使用
26
+
27
+ ```javascript
28
+ // 全局引入
29
+ import StarUI from '@star-ai/star-ui'
30
+ import '@star-ai/star-ui/lib/styles/index.scss'
31
+
32
+ Vue.use(StarUI)
33
+
34
+ // 按需引入
35
+ import { StarButton, StarInput } from '@star-ai/star-ui'
36
+ import '@star-ai/star-ui/lib/styles/index.scss'
37
+
38
+ Vue.use(StarButton)
39
+ Vue.use(StarInput)
40
+ ```
41
+
42
+ ## 组件文档
43
+
44
+ ### Button 按钮
45
+
46
+ ```vue
47
+ <star-button type="primary">主要按钮</star-button>
48
+ ```
49
+
50
+ ### Input 输入框
51
+
52
+ ```vue
53
+ <star-input v-model="value" placeholder="请输入内容"></star-input>
54
+ ```
55
+
56
+ ## Uni-app 特别说明
57
+
58
+ ### 在 Uni-app 中使用
59
+
60
+ 1. **全局引入(推荐)**:
61
+
62
+ 在 `main.js` 中:
63
+ ```javascript
64
+ import Vue from 'vue'
65
+ import App from './App'
66
+ import StarUI from '@star-ai/star-ui'
67
+ import '@star-ai/star-ui/lib/styles/index.scss'
68
+
69
+ Vue.use(StarUI)
70
+
71
+ App.mpType = 'app'
72
+
73
+ const app = new Vue({
74
+ ...App
75
+ })
76
+ app.$mount()
77
+ ```
78
+
79
+ 2. **按需引入**:
80
+
81
+ ```vue
82
+ <template>
83
+ <view>
84
+ <star-button type="primary">按钮</star-button>
85
+ <star-input v-model="value"></star-input>
86
+ </view>
87
+ </template>
88
+
89
+ <script>
90
+ import { StarButton, StarInput } from '@star-ai/star-ui'
91
+
92
+ export default {
93
+ components: {
94
+ StarButton,
95
+ StarInput
96
+ },
97
+ data() {
98
+ return {
99
+ value: ''
100
+ }
101
+ }
102
+ }
103
+ </script>
104
+
105
+ <style>
106
+ /* 引入全局样式 */
107
+ @import '@star-ai/star-ui/lib/styles/index.scss';
108
+ </style>
109
+ ```
110
+
111
+ 3. **直接引入组件**:
112
+
113
+ ```vue
114
+ <template>
115
+ <view>
116
+ <star-button type="primary">按钮</star-button>
117
+ </view>
118
+ </template>
119
+
120
+ <script>
121
+ import StarButton from '@star-ai/star-ui/lib/components/Button/Button.vue'
122
+
123
+ export default {
124
+ components: {
125
+ StarButton
126
+ }
127
+ }
128
+ </script>
129
+ ```
130
+
131
+ ### 注意事项
132
+
133
+ 1. **组件名称**:所有组件以 `star-` 为前缀,如 `star-button`、`star-input`
134
+ 2. **样式引入**:确保引入了组件库的样式文件
135
+ 3. **Vue 版本**:组件库基于 Vue 2.x 开发,与 Uni-app 保持兼容
136
+ 4. **编译平台**:支持 H5、小程序、App 等多端编译
137
+
138
+ ## 开发指南
139
+
140
+ ### 项目结构
141
+
142
+ ```
143
+ ├── packages/ # 组件源码
144
+ │ ├── components/ # 组件目录
145
+ │ ├── styles/ # 样式文件
146
+ │ └── index.js # 入口文件
147
+ ├── lib/ # 构建后的npm包
148
+ ├── examples/ # 示例代码
149
+ ├── build/ # 构建脚本
150
+ └── docs/ # 文档
151
+ ```
152
+
153
+ ### 开发命令
154
+
155
+ ```bash
156
+ # 安装依赖
157
+ yarn install
158
+
159
+ # 启动H5开发服务器
160
+ npm run dev:h5
161
+
162
+ # 构建H5版本
163
+ npm run build:h5
164
+
165
+ # 构建小程序版本
166
+ npm run build:mp-weixin
167
+
168
+ # 构建App版本
169
+ npm run build:app-plus
170
+
171
+ # 构建npm包
172
+ npm run build:lib
173
+ ```
174
+
175
+ ## npm包发布流程
176
+
177
+ ### 1. 准备工作
178
+
179
+ 确保你已经:
180
+ - 拥有npm账号并已登录
181
+ - 确保package.json中的配置正确
182
+ - 已完成代码开发和测试
183
+
184
+ ### 2. 构建npm包
185
+
186
+ ```bash
187
+ # 执行构建脚本
188
+ npm run build:lib
189
+ ```
190
+
191
+ 此命令会执行以下操作:
192
+ - 清空lib目录
193
+ - 复制所有组件到lib/components
194
+ - 为每个组件创建单独的index.js入口文件
195
+ - 复制样式文件到lib/styles
196
+ - 创建主入口文件lib/index.js
197
+
198
+ ### 3. 检查构建结果
199
+
200
+ 构建完成后,检查lib目录是否包含以下内容:
201
+ - lib/index.js # 主入口文件
202
+ - lib/components/ # 组件目录
203
+ - lib/styles/ # 样式文件
204
+
205
+ ### 4. 更新版本号
206
+
207
+ 根据语义化版本规则更新package.json中的version字段:
208
+
209
+ ```bash
210
+ # 补丁版本(修复bug)
211
+ npm version patch
212
+
213
+ # 小版本(新增功能)
214
+ npm version minor
215
+
216
+ # 大版本(不兼容更改)
217
+ npm version major
218
+ ```
219
+
220
+ ### 5. 登录npm账号
221
+
222
+ 如果尚未登录npm账号,执行以下命令登录:
223
+
224
+ ```bash
225
+ npm login
226
+ ```
227
+
228
+ ### 6. 发布npm包
229
+
230
+ ```bash
231
+ npm publish --access=public
232
+ ```
233
+
234
+ ### 7. 验证发布结果
235
+
236
+ 发布成功后,可以在npm官网查看你的包:
237
+
238
+ ```
239
+ https://www.npmjs.com/package/@star-ai/star-ui
240
+ ```
241
+
242
+ ## 注意事项
243
+
244
+ - 发布前请确保所有测试通过
245
+ - 发布前请检查package.json中的配置是否正确
246
+ - 每次发布请更新版本号
247
+ - 如果是私有包,请移除--access public参数
248
+
249
+ ## License
250
+
251
+ MIT
@@ -0,0 +1,328 @@
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
+ install(Vue) {
48
+ Vue.component(this.name, this)
49
+ },
50
+ // 组件属性定义
51
+ props: {
52
+ // 按钮类型
53
+ type: {
54
+ type: String,
55
+ default: 'default',
56
+ validator: (value) => {
57
+ return ['default', 'primary', 'success', 'warning', 'error', 'info'].includes(value)
58
+ }
59
+ },
60
+
61
+ // 按钮大小
62
+ size: {
63
+ type: String,
64
+ default: 'medium',
65
+ validator: (value) => {
66
+ return ['mini', 'small', 'medium', 'large'].includes(value)
67
+ }
68
+ },
69
+
70
+ // 是否禁用
71
+ disabled: {
72
+ type: Boolean,
73
+ default: false
74
+ },
75
+
76
+ // 是否加载中
77
+ loading: {
78
+ type: Boolean,
79
+ default: false
80
+ },
81
+
82
+ // 是否为朴素按钮
83
+ plain: {
84
+ type: Boolean,
85
+ default: false
86
+ },
87
+
88
+ // 是否为块级按钮
89
+ block: {
90
+ type: Boolean,
91
+ default: false
92
+ },
93
+
94
+ // 左侧图标
95
+ icon: {
96
+ type: String,
97
+ default: ''
98
+ },
99
+
100
+ // 右侧图标
101
+ rightIcon: {
102
+ type: String,
103
+ default: ''
104
+ },
105
+
106
+ // 自定义样式
107
+ customStyle: {
108
+ type: Object,
109
+ default: () => ({})
110
+ },
111
+
112
+ // 点击防抖时间(毫秒)
113
+ debounce: {
114
+ type: Number,
115
+ default: 0
116
+ }
117
+ },
118
+
119
+ data() {
120
+ return {
121
+ canClick: true
122
+ }
123
+ },
124
+
125
+ methods: {
126
+ handleClick(event) {
127
+ // 防抖处理
128
+ if (!this.canClick) return
129
+
130
+ if (this.debounce > 0) {
131
+ this.canClick = false
132
+ setTimeout(() => {
133
+ this.canClick = true
134
+ }, this.debounce)
135
+ }
136
+
137
+ // 触发点击事件
138
+ if (!this.disabled && !this.loading) {
139
+ this.$emit('click', event)
140
+ }
141
+ }
142
+ }
143
+ }
144
+ </script>
145
+
146
+ <style lang="scss" scoped>
147
+ // 引入样式变量
148
+ @import "../../styles/variables.scss";
149
+
150
+ .star-button {
151
+ display: inline-flex;
152
+ align-items: center;
153
+ justify-content: center;
154
+ position: relative;
155
+ box-sizing: border-box;
156
+ padding: 0 16px;
157
+ height: 44px;
158
+ line-height: 44px;
159
+ border-radius: $border-radius-base;
160
+ font-size: $font-size-base;
161
+ font-weight: 500;
162
+ text-align: center;
163
+ vertical-align: middle;
164
+ transition: all 0.3s;
165
+ cursor: pointer;
166
+ user-select: none;
167
+
168
+ // 块级按钮
169
+ &--block {
170
+ display: flex;
171
+ width: 100%;
172
+ }
173
+
174
+ // 禁用状态
175
+ &--disabled {
176
+ opacity: 0.6;
177
+ cursor: not-allowed;
178
+ }
179
+
180
+ // 大小
181
+ &--mini {
182
+ padding: 0 8px;
183
+ height: 24px;
184
+ line-height: 24px;
185
+ font-size: $font-size-sm;
186
+ border-radius: $border-radius-sm;
187
+ }
188
+
189
+ &--small {
190
+ padding: 0 12px;
191
+ height: 32px;
192
+ line-height: 32px;
193
+ font-size: $font-size-sm;
194
+ border-radius: $border-radius-sm;
195
+ }
196
+
197
+ &--large {
198
+ padding: 0 20px;
199
+ height: 48px;
200
+ line-height: 48px;
201
+ font-size: $font-size-lg;
202
+ border-radius: $border-radius-lg;
203
+ }
204
+
205
+ // 类型 - 默认
206
+ &--default {
207
+ color: $text-color;
208
+ background-color: $bg-color;
209
+ border: 1px solid $border-color;
210
+
211
+ &:not(.star-button--disabled):not(.star-button--loading):active {
212
+ background-color: darken($bg-color, 5%);
213
+ }
214
+ }
215
+
216
+ // 类型 - 主要
217
+ &--primary {
218
+ color: $white;
219
+ background-color: $primary-color;
220
+ border: 1px solid $primary-color;
221
+
222
+ &.star-button--plain {
223
+ color: $primary-color;
224
+ background-color: transparent;
225
+ }
226
+
227
+ &:not(.star-button--disabled):not(.star-button--loading):active {
228
+ background-color: darken($primary-color, 10%);
229
+ border-color: darken($primary-color, 10%);
230
+ }
231
+ }
232
+
233
+ // 类型 - 成功
234
+ &--success {
235
+ color: $white;
236
+ background-color: $success-color;
237
+ border: 1px solid $success-color;
238
+
239
+ &.star-button--plain {
240
+ color: $success-color;
241
+ background-color: transparent;
242
+ }
243
+ }
244
+
245
+ // 类型 - 警告
246
+ &--warning {
247
+ color: $white;
248
+ background-color: $warning-color;
249
+ border: 1px solid $warning-color;
250
+
251
+ &.star-button--plain {
252
+ color: $warning-color;
253
+ background-color: transparent;
254
+ }
255
+ }
256
+
257
+ // 类型 - 错误
258
+ &--error {
259
+ color: $white;
260
+ background-color: $error-color;
261
+ border: 1px solid $error-color;
262
+
263
+ &.star-button--plain {
264
+ color: $error-color;
265
+ background-color: transparent;
266
+ }
267
+ }
268
+
269
+ // 类型 - 信息
270
+ &--info {
271
+ color: $white;
272
+ background-color: $info-color;
273
+ border: 1px solid $info-color;
274
+
275
+ &.star-button--plain {
276
+ color: $info-color;
277
+ background-color: transparent;
278
+ }
279
+ }
280
+
281
+ // 加载中
282
+ &--loading {
283
+ cursor: not-allowed;
284
+ }
285
+
286
+ // 图标
287
+ &__icon,
288
+ &__right-icon {
289
+ font-family: "star-icon-font" !important; // 使用你自己的图标字体
290
+ margin-right: 4px;
291
+ font-size: inherit;
292
+ }
293
+
294
+ &__right-icon {
295
+ margin-right: 0;
296
+ margin-left: 4px;
297
+ }
298
+
299
+ &__text {
300
+ display: inline-block;
301
+ vertical-align: middle;
302
+ }
303
+
304
+ // 加载动画
305
+ &__loading {
306
+ margin-right: 4px;
307
+ }
308
+
309
+ &__loading-spinner {
310
+ display: inline-block;
311
+ width: 14px;
312
+ height: 14px;
313
+ border: 2px solid;
314
+ border-color: currentColor transparent transparent transparent;
315
+ border-radius: 50%;
316
+ animation: star-button-spin 1s linear infinite;
317
+ }
318
+ }
319
+
320
+ @keyframes star-button-spin {
321
+ 0% {
322
+ transform: rotate(0deg);
323
+ }
324
+ 100% {
325
+ transform: rotate(360deg);
326
+ }
327
+ }
328
+ </style>
@@ -0,0 +1,408 @@
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
+ install(Vue) {
81
+ Vue.component(this.name, this)
82
+ },
83
+
84
+ props: {
85
+ // 输入框类型
86
+ type: {
87
+ type: String,
88
+ default: 'text'
89
+ },
90
+
91
+ // 绑定值
92
+ value: {
93
+ type: [String, Number],
94
+ default: ''
95
+ },
96
+
97
+ // 原生属性
98
+ placeholder: {
99
+ type: String,
100
+ default: ''
101
+ },
102
+
103
+ disabled: {
104
+ type: Boolean,
105
+ default: false
106
+ },
107
+
108
+ maxlength: {
109
+ type: [String, Number],
110
+ default: 140
111
+ },
112
+
113
+ focus: {
114
+ type: Boolean,
115
+ default: false
116
+ },
117
+
118
+ confirmType: {
119
+ type: String,
120
+ default: 'done'
121
+ },
122
+
123
+ placeholderStyle: {
124
+ type: String,
125
+ default: ''
126
+ },
127
+
128
+ placeholderClass: {
129
+ type: String,
130
+ default: ''
131
+ },
132
+
133
+ cursorSpacing: {
134
+ type: [String, Number],
135
+ default: 0
136
+ },
137
+
138
+ // 自定义属性
139
+ size: {
140
+ type: String,
141
+ default: 'medium',
142
+ validator: (value) => ['mini', 'small', 'medium', 'large'].includes(value)
143
+ },
144
+
145
+ clearable: {
146
+ type: Boolean,
147
+ default: false
148
+ },
149
+
150
+ showPassword: {
151
+ type: Boolean,
152
+ default: false
153
+ },
154
+
155
+ prefixIcon: {
156
+ type: String,
157
+ default: ''
158
+ },
159
+
160
+ suffixIcon: {
161
+ type: String,
162
+ default: ''
163
+ },
164
+
165
+ prepend: {
166
+ type: String,
167
+ default: ''
168
+ },
169
+
170
+ append: {
171
+ type: String,
172
+ default: ''
173
+ },
174
+
175
+ readonly: {
176
+ type: Boolean,
177
+ default: false
178
+ }
179
+ },
180
+
181
+ data() {
182
+ return {
183
+ currentValue: this.value,
184
+ isFocused: false,
185
+ passwordVisible: false
186
+ }
187
+ },
188
+
189
+ computed: {
190
+ inputClasses() {
191
+ return [
192
+ `star-input--${this.size}`,
193
+ {
194
+ 'star-input--disabled': this.disabled,
195
+ 'star-input--focused': this.isFocused,
196
+ 'star-input--with-prepend': this.prepend || this.$slots.prepend,
197
+ 'star-input--with-append': this.append || this.$slots.append,
198
+ 'star-input--readonly': this.readonly
199
+ }
200
+ ]
201
+ }
202
+ },
203
+
204
+ watch: {
205
+ value(newVal) {
206
+ this.currentValue = newVal
207
+ }
208
+ },
209
+
210
+ methods: {
211
+ handleInput(event) {
212
+ const value = event.detail.value
213
+ this.currentValue = value
214
+ this.$emit('input', value)
215
+ this.$emit('change', value)
216
+ },
217
+
218
+ handleFocus(event) {
219
+ this.isFocused = true
220
+ this.$emit('focus', event)
221
+ },
222
+
223
+ handleBlur(event) {
224
+ this.isFocused = false
225
+ this.$emit('blur', event)
226
+ },
227
+
228
+ handleConfirm(event) {
229
+ this.$emit('confirm', event)
230
+ },
231
+
232
+ handleKeyboardHeightChange(event) {
233
+ this.$emit('keyboardheightchange', event)
234
+ },
235
+
236
+ handleClear() {
237
+ this.currentValue = ''
238
+ this.$emit('input', '')
239
+ this.$emit('change', '')
240
+ this.$emit('clear')
241
+ },
242
+
243
+ togglePasswordVisible() {
244
+ this.passwordVisible = !this.passwordVisible
245
+ },
246
+
247
+ handlePrefixIconClick() {
248
+ this.$emit('click-prefix')
249
+ },
250
+
251
+ handleSuffixIconClick() {
252
+ this.$emit('click-suffix')
253
+ }
254
+ }
255
+ }
256
+ </script>
257
+
258
+ <style lang="scss" scoped>
259
+ @import "../../styles/variables.scss";
260
+
261
+ .star-input {
262
+ display: inline-flex;
263
+ width: 100%;
264
+ font-size: $font-size-base;
265
+ line-height: normal;
266
+
267
+ &__prepend,
268
+ &__append {
269
+ display: flex;
270
+ align-items: center;
271
+ justify-content: center;
272
+ padding: 0 12px;
273
+ background-color: $bg-color-grey;
274
+ border: 1px solid $border-color;
275
+ white-space: nowrap;
276
+
277
+ &-text {
278
+ color: $text-color-secondary;
279
+ }
280
+ }
281
+
282
+ &__prepend {
283
+ border-right: 0;
284
+ border-radius: $border-radius-base 0 0 $border-radius-base;
285
+ }
286
+
287
+ &__append {
288
+ border-left: 0;
289
+ border-radius: 0 $border-radius-base $border-radius-base 0;
290
+ }
291
+
292
+ &__wrapper {
293
+ display: flex;
294
+ align-items: center;
295
+ flex: 1;
296
+ position: relative;
297
+ padding: 0 12px;
298
+ border: 1px solid $border-color;
299
+ border-radius: $border-radius-base;
300
+ background-color: $bg-color;
301
+ transition: border-color 0.3s;
302
+
303
+ .star-input--with-prepend & {
304
+ border-top-left-radius: 0;
305
+ border-bottom-left-radius: 0;
306
+ border-left: 0;
307
+ }
308
+
309
+ .star-input--with-append & {
310
+ border-top-right-radius: 0;
311
+ border-bottom-right-radius: 0;
312
+ border-right: 0;
313
+ }
314
+ }
315
+
316
+ &--focused &__wrapper {
317
+ border-color: $primary-color;
318
+ }
319
+
320
+ &--disabled &__wrapper {
321
+ background-color: $bg-color-grey;
322
+ cursor: not-allowed;
323
+ }
324
+
325
+ &__inner {
326
+ flex: 1;
327
+ width: 100%;
328
+ height: 100%;
329
+ padding: 0;
330
+ border: none;
331
+ outline: none;
332
+ background: transparent;
333
+ font-size: inherit;
334
+ color: $text-color;
335
+
336
+ .star-input--disabled & {
337
+ color: $text-color-disabled;
338
+ cursor: not-allowed;
339
+ }
340
+
341
+ &::placeholder {
342
+ color: $text-color-light;
343
+ }
344
+ }
345
+
346
+ &__prefix-icon,
347
+ &__suffix-icon {
348
+ font-family: "star-icon-font" !important;
349
+ color: $text-color-light;
350
+ font-size: 18px;
351
+ cursor: pointer;
352
+ transition: color 0.3s;
353
+
354
+ &:hover {
355
+ color: $text-color;
356
+ }
357
+ }
358
+
359
+ &__prefix-icon {
360
+ margin-right: 8px;
361
+ }
362
+
363
+ &__suffix-icon {
364
+ margin-left: 8px;
365
+ }
366
+
367
+ &__clear,
368
+ &__password-toggle {
369
+ display: flex;
370
+ align-items: center;
371
+ justify-content: center;
372
+ width: 20px;
373
+ height: 20px;
374
+ margin-left: 8px;
375
+ color: $text-color-light;
376
+ cursor: pointer;
377
+ transition: color 0.3s;
378
+
379
+ &:hover {
380
+ color: $text-color;
381
+ }
382
+
383
+ .star-icon-close,
384
+ .star-icon-eye-open,
385
+ .star-icon-eye-close {
386
+ font-family: "star-icon-font" !important;
387
+ font-size: 16px;
388
+ }
389
+ }
390
+
391
+ // 尺寸
392
+ &--mini &__wrapper {
393
+ height: 24px;
394
+ }
395
+
396
+ &--small &__wrapper {
397
+ height: 32px;
398
+ }
399
+
400
+ &--medium &__wrapper {
401
+ height: 40px;
402
+ }
403
+
404
+ &--large &__wrapper {
405
+ height: 48px;
406
+ }
407
+ }
408
+ </style>
package/index.js ADDED
@@ -0,0 +1,41 @@
1
+
2
+ // 导入所有组件
3
+ import starButton from './components/star-button'
4
+ import starInput from './components/star-input'
5
+
6
+ // 组件列表
7
+ const components = [starButton, starInput]
8
+
9
+ // 安装函数
10
+ const install = function(Vue, opts = {}) {
11
+ components.forEach(component => {
12
+ if(component.install) {
13
+ Vue.use(component)
14
+ } else if (component.name) {
15
+ Vue.component(component.name, component)
16
+ }
17
+ })
18
+
19
+ // 挂载全局方法
20
+ Vue.prototype.$STAR_UI = {
21
+ size: opts.size || '',
22
+ zIndex: opts.zIndex || 2000
23
+ }
24
+ }
25
+
26
+ // 如果是浏览器环境且已引入Vue,则自动安装
27
+ if (typeof window !== 'undefined' && window.Vue) {
28
+ install(window.Vue)
29
+ }
30
+
31
+ // 导出默认对象
32
+ export default {
33
+ version: '0.1.19',
34
+ install,
35
+ // 导出所有组件
36
+ 'star-button': starButton, 'star-input': starInput
37
+ }
38
+
39
+ // 按需导出组件
40
+ export { starButton as 'star-button' }
41
+ export { starInput as 'star-input' }
package/package.json ADDED
@@ -0,0 +1,113 @@
1
+ {
2
+ "name": "starai-ui",
3
+ "version": "0.1.19",
4
+ "description": "基于Uniapp的Vue2组件库",
5
+ "main": "index.js",
6
+ "module": "index.js",
7
+ "umd:main": "index.js",
8
+ "files": ["components", "styles", "index.js"],
9
+ "scripts": {
10
+ "serve": "npm run dev:h5",
11
+ "build:lib": "node build/build.js",
12
+ "build:lib:prod": "cross-env BUILD_NPM_PACKAGE=true node build/build.js",
13
+ "build": "npm run build:h5",
14
+ "build:app-plus": "cross-env NODE_ENV=production UNI_PLATFORM=app-plus vue-cli-service uni-build",
15
+ "build:custom": "cross-env NODE_ENV=production uniapp-cli custom",
16
+ "build:h5": "cross-env NODE_ENV=production UNI_PLATFORM=h5 vue-cli-service uni-build",
17
+ "build:mp-360": "cross-env NODE_ENV=production UNI_PLATFORM=mp-360 vue-cli-service uni-build",
18
+ "build:mp-alipay": "cross-env NODE_ENV=production UNI_PLATFORM=mp-alipay vue-cli-service uni-build",
19
+ "build:mp-baidu": "cross-env NODE_ENV=production UNI_PLATFORM=mp-baidu vue-cli-service uni-build",
20
+ "build:mp-harmony": "cross-env NODE_ENV=production UNI_PLATFORM=mp-harmony vue-cli-service uni-build",
21
+ "build:mp-jd": "cross-env NODE_ENV=production UNI_PLATFORM=mp-jd vue-cli-service uni-build",
22
+ "build:mp-kuaishou": "cross-env NODE_ENV=production UNI_PLATFORM=mp-kuaishou vue-cli-service uni-build",
23
+ "build:mp-lark": "cross-env NODE_ENV=production UNI_PLATFORM=mp-lark vue-cli-service uni-build",
24
+ "build:mp-qq": "cross-env NODE_ENV=production UNI_PLATFORM=mp-qq vue-cli-service uni-build",
25
+ "build:mp-toutiao": "cross-env NODE_ENV=production UNI_PLATFORM=mp-toutiao vue-cli-service uni-build",
26
+ "build:mp-weixin": "cross-env NODE_ENV=production UNI_PLATFORM=mp-weixin vue-cli-service uni-build",
27
+ "build:mp-xhs": "cross-env NODE_ENV=production UNI_PLATFORM=mp-xhs vue-cli-service uni-build",
28
+ "build:quickapp-native": "cross-env NODE_ENV=production UNI_PLATFORM=quickapp-native vue-cli-service uni-build",
29
+ "build:quickapp-webview": "cross-env NODE_ENV=production UNI_PLATFORM=quickapp-webview vue-cli-service uni-build",
30
+ "build:quickapp-webview-huawei": "cross-env NODE_ENV=production UNI_PLATFORM=quickapp-webview-huawei vue-cli-service uni-build",
31
+ "build:quickapp-webview-union": "cross-env NODE_ENV=production UNI_PLATFORM=quickapp-webview-union vue-cli-service uni-build",
32
+ "dev:app-plus": "cross-env NODE_ENV=development UNI_PLATFORM=app-plus vue-cli-service uni-build --watch",
33
+ "dev:custom": "cross-env NODE_ENV=development uniapp-cli custom",
34
+ "dev:h5": "cross-env NODE_ENV=development UNI_PLATFORM=h5 vue-cli-service uni-serve",
35
+ "dev:mp-360": "cross-env NODE_ENV=development UNI_PLATFORM=mp-360 vue-cli-service uni-build --watch",
36
+ "dev:mp-alipay": "cross-env NODE_ENV=development UNI_PLATFORM=mp-alipay vue-cli-service uni-build --watch",
37
+ "dev:mp-baidu": "cross-env NODE_ENV=development UNI_PLATFORM=mp-baidu vue-cli-service uni-build --watch",
38
+ "dev:mp-harmony": "cross-env NODE_ENV=development UNI_PLATFORM=mp-harmony vue-cli-service uni-build --watch",
39
+ "dev:mp-jd": "cross-env NODE_ENV=development UNI_PLATFORM=mp-jd vue-cli-service uni-build --watch",
40
+ "dev:mp-kuaishou": "cross-env NODE_ENV=development UNI_PLATFORM=mp-kuaishou vue-cli-service uni-build --watch",
41
+ "dev:mp-lark": "cross-env NODE_ENV=development UNI_PLATFORM=mp-lark vue-cli-service uni-build --watch",
42
+ "dev:mp-qq": "cross-env NODE_ENV=development UNI_PLATFORM=mp-qq vue-cli-service uni-build --watch",
43
+ "dev:mp-toutiao": "cross-env NODE_ENV=development UNI_PLATFORM=mp-toutiao vue-cli-service uni-build --watch",
44
+ "dev:mp-weixin": "cross-env NODE_ENV=development UNI_PLATFORM=mp-weixin vue-cli-service uni-build --watch",
45
+ "dev:mp-xhs": "cross-env NODE_ENV=development UNI_PLATFORM=mp-xhs vue-cli-service uni-build --watch",
46
+ "dev:quickapp-native": "cross-env NODE_ENV=development UNI_PLATFORM=quickapp-native vue-cli-service uni-build --watch",
47
+ "dev:quickapp-webview": "cross-env NODE_ENV=development UNI_PLATFORM=quickapp-webview vue-cli-service uni-build --watch",
48
+ "dev:quickapp-webview-huawei": "cross-env NODE_ENV=development UNI_PLATFORM=quickapp-webview-huawei vue-cli-service uni-build --watch",
49
+ "dev:quickapp-webview-union": "cross-env NODE_ENV=development UNI_PLATFORM=quickapp-webview-union vue-cli-service uni-build --watch",
50
+ "info": "node node_modules/@dcloudio/vue-cli-plugin-uni/commands/info.js",
51
+ "serve:quickapp-native": "node node_modules/@dcloudio/uni-quickapp-native/bin/serve.js",
52
+ "test:android": "cross-env UNI_PLATFORM=app-plus UNI_OS_NAME=android jest -i",
53
+ "test:h5": "cross-env UNI_PLATFORM=h5 jest -i",
54
+ "test:ios": "cross-env UNI_PLATFORM=app-plus UNI_OS_NAME=ios jest -i",
55
+ "test:mp-baidu": "cross-env UNI_PLATFORM=mp-baidu jest -i",
56
+ "test:mp-weixin": "cross-env UNI_PLATFORM=mp-weixin jest -i"
57
+ },
58
+ "peerDependencies": {
59
+ "vue": ">= 2.6.14 < 4"
60
+ },
61
+ "dependencies": {
62
+ "@vue/shared": "^3.0.0",
63
+ "core-js": "^3.8.3"
64
+ },
65
+ "devDependencies": {
66
+ "@dcloudio/types": "^3.3.2",
67
+ "@dcloudio/uni-automator": "^2.0.2-4080720251210002",
68
+ "@dcloudio/uni-cli-i18n": "^2.0.2-4080720251210002",
69
+ "@dcloudio/uni-cli-shared": "^2.0.2-4080720251210002",
70
+ "@dcloudio/uni-helper-json": "*",
71
+ "@dcloudio/uni-migration": "^2.0.2-4080720251210002",
72
+ "@dcloudio/uni-template-compiler": "^2.0.2-4080720251210002",
73
+ "@dcloudio/vue-cli-plugin-hbuilderx": "^2.0.2-4080720251210002",
74
+ "@dcloudio/vue-cli-plugin-uni": "^2.0.2-4080720251210002",
75
+ "@dcloudio/vue-cli-plugin-uni-optimize": "^2.0.2-4080720251210002",
76
+ "@dcloudio/webpack-uni-mp-loader": "^2.0.2-4080720251210002",
77
+ "@dcloudio/webpack-uni-pages-loader": "^2.0.2-4080720251210002",
78
+ "@vue/cli-plugin-babel": "~5.0.0",
79
+ "@vue/cli-service": "~5.0.0",
80
+ "babel-plugin-import": "^1.11.0",
81
+ "cross-env": "^7.0.2",
82
+ "fs-extra": "^10.0.0",
83
+ "jest": "^25.4.0",
84
+ "postcss-comment": "^2.0.0",
85
+ "sass": "^1.97.1",
86
+ "sass-loader": "10",
87
+ "vue-template-compiler": ">= 2.6.14 < 2.7"
88
+ },
89
+ "browserslist": [
90
+ "Android >= 4.4",
91
+ "ios >= 9"
92
+ ],
93
+ "keywords": [
94
+ "uniapp",
95
+ "vue2",
96
+ "component",
97
+ "ui",
98
+ "mobile"
99
+ ],
100
+ "author": "DengChengBo",
101
+ "license": "MIT",
102
+ "repository": {
103
+ "type": "git",
104
+ "url": "git+https://gitee.com/chengboDeng/star-ui-library.git"
105
+ },
106
+ "bugs": {
107
+ "url": "https://gitee.com/chengboDeng/star-ui-library/issues"
108
+ },
109
+ "homepage": "https://gitee.com/chengboDeng/star-ui-library#readme",
110
+ "uni-app": {
111
+ "scripts": {}
112
+ }
113
+ }
@@ -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;