little-dizzy 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.
- package/README.en.md +36 -0
- package/README.md +162 -0
- package/dist/little-dizzy.css +1 -0
- package/dist/little-dizzy.js +269 -0
- package/dist/little-dizzy.umd.cjs +45 -0
- package/dist/vite.svg +1 -0
- package/package.json +55 -0
- package/src/components/Button.vue +176 -0
- package/src/components/Card.vue +98 -0
- package/src/components/HelloWorld.vue +43 -0
- package/src/components/Modal.vue +182 -0
- package/src/index.js +55 -0
- package/src/snippets/index.js +166 -0
- package/src/snippets/presets/button.js +19 -0
- package/src/snippets/presets/card.js +25 -0
- package/src/snippets/presets/index.js +22 -0
- package/src/snippets/presets/modal.js +30 -0
- package/src/styles/_variables.scss +293 -0
- package/src/styles/main.scss +17 -0
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<button class="btn" :class="[
|
|
3
|
+
`btn-${type}`,
|
|
4
|
+
`btn-${size}`,
|
|
5
|
+
{ 'btn-block': block },
|
|
6
|
+
{ 'btn-disabled': disabled }
|
|
7
|
+
]" :disabled="disabled" @click="$emit('click', $event)">
|
|
8
|
+
<slot></slot>
|
|
9
|
+
</button>
|
|
10
|
+
</template>
|
|
11
|
+
|
|
12
|
+
<script setup>
|
|
13
|
+
import { computed } from 'vue'
|
|
14
|
+
|
|
15
|
+
// 定义组件属性
|
|
16
|
+
const props = defineProps({
|
|
17
|
+
// 按钮类型
|
|
18
|
+
type: {
|
|
19
|
+
type: String,
|
|
20
|
+
default: 'primary',
|
|
21
|
+
validator: (value) => {
|
|
22
|
+
return ['primary', 'success', 'warning', 'danger', 'info', 'secondary'].includes(value)
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
// 按钮尺寸
|
|
26
|
+
size: {
|
|
27
|
+
type: String,
|
|
28
|
+
default: 'medium',
|
|
29
|
+
validator: (value) => {
|
|
30
|
+
return ['small', 'medium', 'large'].includes(value)
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
// 是否为块级按钮
|
|
34
|
+
block: {
|
|
35
|
+
type: Boolean,
|
|
36
|
+
default: false
|
|
37
|
+
},
|
|
38
|
+
// 是否禁用
|
|
39
|
+
disabled: {
|
|
40
|
+
type: Boolean,
|
|
41
|
+
default: false
|
|
42
|
+
}
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
// 定义组件事件
|
|
46
|
+
const emit = defineEmits(['click'])
|
|
47
|
+
</script>
|
|
48
|
+
|
|
49
|
+
<style scoped lang="scss">
|
|
50
|
+
@use 'sass:color';
|
|
51
|
+
// 导入变量
|
|
52
|
+
@use '../styles/_variables.scss' as *;
|
|
53
|
+
|
|
54
|
+
// 按钮基础样式
|
|
55
|
+
.btn {
|
|
56
|
+
display: inline-block;
|
|
57
|
+
padding: 8px 16px;
|
|
58
|
+
border: 1px solid transparent;
|
|
59
|
+
border-radius: $border-radius-md;
|
|
60
|
+
font-size: $font-size-base;
|
|
61
|
+
font-weight: 400;
|
|
62
|
+
line-height: 1.5;
|
|
63
|
+
text-align: center;
|
|
64
|
+
white-space: nowrap;
|
|
65
|
+
vertical-align: middle;
|
|
66
|
+
cursor: pointer;
|
|
67
|
+
transition: all 0.3s;
|
|
68
|
+
|
|
69
|
+
&:hover:not(.btn-disabled) {
|
|
70
|
+
opacity: 0.9;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
&:active:not(.btn-disabled) {
|
|
74
|
+
opacity: 1;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
&.btn-disabled {
|
|
78
|
+
cursor: not-allowed;
|
|
79
|
+
opacity: 0.6;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// 主要按钮
|
|
83
|
+
&-primary {
|
|
84
|
+
color: #fff;
|
|
85
|
+
background-color: $primary-color;
|
|
86
|
+
border-color: $primary-color;
|
|
87
|
+
|
|
88
|
+
&:hover:not(.btn-disabled) {
|
|
89
|
+
background-color: color.adjust($primary-color, $lightness: -10%);
|
|
90
|
+
border-color: color.adjust($primary-color, $lightness: -10%);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// 成功按钮
|
|
95
|
+
&-success {
|
|
96
|
+
color: #fff;
|
|
97
|
+
background-color: $success-color;
|
|
98
|
+
border-color: $success-color;
|
|
99
|
+
|
|
100
|
+
&:hover:not(.btn-disabled) {
|
|
101
|
+
background-color: color.adjust($success-color, $lightness: -10%);
|
|
102
|
+
border-color: color.adjust($success-color, $lightness: -10%);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// 警告按钮
|
|
107
|
+
&-warning {
|
|
108
|
+
color: #fff;
|
|
109
|
+
background-color: $warning-color;
|
|
110
|
+
border-color: $warning-color;
|
|
111
|
+
|
|
112
|
+
&:hover:not(.btn-disabled) {
|
|
113
|
+
background-color: color.adjust($warning-color, $lightness: -10%);
|
|
114
|
+
border-color: color.adjust($warning-color, $lightness: -10%);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// 危险按钮
|
|
119
|
+
&-danger {
|
|
120
|
+
color: #fff;
|
|
121
|
+
background-color: $danger-color;
|
|
122
|
+
border-color: $danger-color;
|
|
123
|
+
|
|
124
|
+
&:hover:not(.btn-disabled) {
|
|
125
|
+
background-color: color.adjust($danger-color, $lightness: -10%);
|
|
126
|
+
border-color: color.adjust($danger-color, $lightness: -10%);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// 信息按钮
|
|
131
|
+
&-info {
|
|
132
|
+
color: #fff;
|
|
133
|
+
background-color: $info-color;
|
|
134
|
+
border-color: $info-color;
|
|
135
|
+
|
|
136
|
+
&:hover:not(.btn-disabled) {
|
|
137
|
+
background-color: color.adjust($info-color, $lightness: -10%);
|
|
138
|
+
border-color: color.adjust($info-color, $lightness: -10%);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// 次要按钮
|
|
143
|
+
&-secondary {
|
|
144
|
+
color: #606266;
|
|
145
|
+
background-color: #fff;
|
|
146
|
+
border-color: #dcdfe6;
|
|
147
|
+
|
|
148
|
+
&:hover:not(.btn-disabled) {
|
|
149
|
+
color: $primary-color;
|
|
150
|
+
border-color: $primary-color;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// 按钮尺寸
|
|
155
|
+
&-small {
|
|
156
|
+
padding: 4px 8px;
|
|
157
|
+
font-size: $font-size-small;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
&-medium {
|
|
161
|
+
padding: 8px 16px;
|
|
162
|
+
font-size: $font-size-base;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
&-large {
|
|
166
|
+
padding: 12px 24px;
|
|
167
|
+
font-size: $font-size-large;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// 块级按钮
|
|
171
|
+
&-block {
|
|
172
|
+
display: block;
|
|
173
|
+
width: 100%;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
</style>
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="card" :class="{ 'card-shadow': shadow }">
|
|
3
|
+
<!-- 卡片头部 -->
|
|
4
|
+
<div class="card-header" v-if="$slots.header || title">
|
|
5
|
+
<h3 class="card-header-title" v-if="title">{{ title }}</h3>
|
|
6
|
+
<slot name="header"></slot>
|
|
7
|
+
</div>
|
|
8
|
+
|
|
9
|
+
<!-- 卡片主体 -->
|
|
10
|
+
<div class="card-body">
|
|
11
|
+
<slot></slot>
|
|
12
|
+
</div>
|
|
13
|
+
|
|
14
|
+
<!-- 卡片底部 -->
|
|
15
|
+
<div class="card-footer" v-if="$slots.footer">
|
|
16
|
+
<slot name="footer"></slot>
|
|
17
|
+
</div>
|
|
18
|
+
</div>
|
|
19
|
+
</template>
|
|
20
|
+
|
|
21
|
+
<script setup>
|
|
22
|
+
import { computed } from 'vue'
|
|
23
|
+
|
|
24
|
+
// 定义组件属性
|
|
25
|
+
const props = defineProps({
|
|
26
|
+
// 卡片标题
|
|
27
|
+
title: {
|
|
28
|
+
type: String,
|
|
29
|
+
default: ''
|
|
30
|
+
},
|
|
31
|
+
// 是否显示阴影
|
|
32
|
+
shadow: {
|
|
33
|
+
type: Boolean,
|
|
34
|
+
default: true
|
|
35
|
+
}
|
|
36
|
+
})
|
|
37
|
+
</script>
|
|
38
|
+
|
|
39
|
+
<style scoped lang="scss">
|
|
40
|
+
// 导入变量
|
|
41
|
+
@use '../styles/_variables.scss' as *;
|
|
42
|
+
|
|
43
|
+
// 卡片样式
|
|
44
|
+
.card {
|
|
45
|
+
position: relative;
|
|
46
|
+
display: flex;
|
|
47
|
+
flex-direction: column;
|
|
48
|
+
min-width: 0;
|
|
49
|
+
word-wrap: break-word;
|
|
50
|
+
background-color: #fff;
|
|
51
|
+
background-clip: border-box;
|
|
52
|
+
border: 1px solid rgba(0, 0, 0, 0.125);
|
|
53
|
+
border-radius: $border-radius-lg;
|
|
54
|
+
transition: box-shadow 0.3s;
|
|
55
|
+
|
|
56
|
+
// 阴影样式
|
|
57
|
+
&-shadow {
|
|
58
|
+
box-shadow: $shadow-sm;
|
|
59
|
+
|
|
60
|
+
&:hover {
|
|
61
|
+
box-shadow: $shadow-md;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// 卡片头部
|
|
66
|
+
&-header {
|
|
67
|
+
padding: 16px;
|
|
68
|
+
border-bottom: 1px solid rgba(0, 0, 0, 0.125);
|
|
69
|
+
display: flex;
|
|
70
|
+
justify-content: space-between;
|
|
71
|
+
align-items: center;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// 卡片头部标题
|
|
75
|
+
&-header-title {
|
|
76
|
+
margin: 0;
|
|
77
|
+
font-size: $font-size-large;
|
|
78
|
+
font-weight: 600;
|
|
79
|
+
color: #303133;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// 卡片主体
|
|
83
|
+
&-body {
|
|
84
|
+
flex: 1 1 auto;
|
|
85
|
+
padding: 16px;
|
|
86
|
+
color: #606266;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// 卡片底部
|
|
90
|
+
&-footer {
|
|
91
|
+
padding: 16px;
|
|
92
|
+
border-top: 1px solid rgba(0, 0, 0, 0.125);
|
|
93
|
+
background-color: #fafafa;
|
|
94
|
+
border-bottom-left-radius: calc($border-radius-lg - 1px);
|
|
95
|
+
border-bottom-right-radius: calc($border-radius-lg - 1px);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
</style>
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { ref } from 'vue'
|
|
3
|
+
|
|
4
|
+
defineProps({
|
|
5
|
+
msg: String,
|
|
6
|
+
})
|
|
7
|
+
|
|
8
|
+
const count = ref(0)
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
<template>
|
|
12
|
+
<h1>{{ msg }}</h1>
|
|
13
|
+
|
|
14
|
+
<div class="card">
|
|
15
|
+
<button type="button" @click="count++">count is {{ count }}</button>
|
|
16
|
+
<p>
|
|
17
|
+
Edit
|
|
18
|
+
<code>components/HelloWorld.vue</code> to test HMR
|
|
19
|
+
</p>
|
|
20
|
+
</div>
|
|
21
|
+
|
|
22
|
+
<p>
|
|
23
|
+
Check out
|
|
24
|
+
<a href="https://vuejs.org/guide/quick-start.html#local" target="_blank"
|
|
25
|
+
>create-vue</a
|
|
26
|
+
>, the official Vue + Vite starter
|
|
27
|
+
</p>
|
|
28
|
+
<p>
|
|
29
|
+
Learn more about IDE Support for Vue in the
|
|
30
|
+
<a
|
|
31
|
+
href="https://vuejs.org/guide/scaling-up/tooling.html#ide-support"
|
|
32
|
+
target="_blank"
|
|
33
|
+
>Vue Docs Scaling up Guide</a
|
|
34
|
+
>.
|
|
35
|
+
</p>
|
|
36
|
+
<p class="read-the-docs">Click on the Vite and Vue logos to learn more</p>
|
|
37
|
+
</template>
|
|
38
|
+
|
|
39
|
+
<style scoped>
|
|
40
|
+
.read-the-docs {
|
|
41
|
+
color: #888;
|
|
42
|
+
}
|
|
43
|
+
</style>
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="modal" :class="{ 'modal-show': visible }" v-if="visible">
|
|
3
|
+
<div class="modal-dialog">
|
|
4
|
+
<div class="modal-content">
|
|
5
|
+
<!-- 模态框头部 -->
|
|
6
|
+
<div class="modal-header">
|
|
7
|
+
<h3 class="modal-header-title" v-if="title">{{ title }}</h3>
|
|
8
|
+
<button class="modal-header-close" @click="handleClose">×</button>
|
|
9
|
+
</div>
|
|
10
|
+
|
|
11
|
+
<!-- 模态框主体 -->
|
|
12
|
+
<div class="modal-body">
|
|
13
|
+
<slot></slot>
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
<!-- 模态框底部 -->
|
|
17
|
+
<div class="modal-footer" v-if="$slots.footer">
|
|
18
|
+
<slot name="footer"></slot>
|
|
19
|
+
</div>
|
|
20
|
+
<!-- 默认底部按钮 -->
|
|
21
|
+
<div class="modal-footer" v-else-if="showFooter">
|
|
22
|
+
<button class="btn btn-secondary" @click="handleCancel">取消</button>
|
|
23
|
+
<button class="btn btn-primary" @click="handleConfirm">确定</button>
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
26
|
+
</div>
|
|
27
|
+
</div>
|
|
28
|
+
</template>
|
|
29
|
+
|
|
30
|
+
<script setup>
|
|
31
|
+
import { ref, computed, watch } from 'vue'
|
|
32
|
+
import Button from './Button.vue'
|
|
33
|
+
|
|
34
|
+
// 定义组件属性
|
|
35
|
+
const props = defineProps({
|
|
36
|
+
// 是否显示模态框
|
|
37
|
+
visible: {
|
|
38
|
+
type: Boolean,
|
|
39
|
+
default: false
|
|
40
|
+
},
|
|
41
|
+
// 模态框标题
|
|
42
|
+
title: {
|
|
43
|
+
type: String,
|
|
44
|
+
default: ''
|
|
45
|
+
},
|
|
46
|
+
// 是否显示默认底部按钮
|
|
47
|
+
showFooter: {
|
|
48
|
+
type: Boolean,
|
|
49
|
+
default: true
|
|
50
|
+
}
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
// 定义组件事件
|
|
54
|
+
const emit = defineEmits(['close', 'cancel', 'confirm'])
|
|
55
|
+
|
|
56
|
+
// 关闭模态框
|
|
57
|
+
const handleClose = () => {
|
|
58
|
+
emit('close')
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// 取消按钮事件
|
|
62
|
+
const handleCancel = () => {
|
|
63
|
+
emit('cancel')
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// 确定按钮事件
|
|
67
|
+
const handleConfirm = () => {
|
|
68
|
+
emit('confirm')
|
|
69
|
+
}
|
|
70
|
+
</script>
|
|
71
|
+
|
|
72
|
+
<style scoped lang="scss">
|
|
73
|
+
// 导入变量
|
|
74
|
+
@use '../styles/_variables.scss' as *;
|
|
75
|
+
|
|
76
|
+
// 模态框样式
|
|
77
|
+
.modal {
|
|
78
|
+
position: fixed;
|
|
79
|
+
top: 0;
|
|
80
|
+
left: 0;
|
|
81
|
+
z-index: 1050;
|
|
82
|
+
display: none;
|
|
83
|
+
width: 100%;
|
|
84
|
+
height: 100%;
|
|
85
|
+
overflow: hidden;
|
|
86
|
+
outline: 0;
|
|
87
|
+
background-color: rgba(0, 0, 0, 0.5);
|
|
88
|
+
|
|
89
|
+
// 显示模态框
|
|
90
|
+
&-show {
|
|
91
|
+
display: flex;
|
|
92
|
+
justify-content: center;
|
|
93
|
+
align-items: center;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// 模态框对话框
|
|
97
|
+
&-dialog {
|
|
98
|
+
position: relative;
|
|
99
|
+
width: auto;
|
|
100
|
+
margin: 10px;
|
|
101
|
+
pointer-events: none;
|
|
102
|
+
|
|
103
|
+
@media (min-width: 576px) {
|
|
104
|
+
max-width: 500px;
|
|
105
|
+
margin: 1.75rem auto;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// 模态框内容
|
|
110
|
+
&-content {
|
|
111
|
+
position: relative;
|
|
112
|
+
display: flex;
|
|
113
|
+
flex-direction: column;
|
|
114
|
+
width: 100%;
|
|
115
|
+
pointer-events: auto;
|
|
116
|
+
background-color: #fff;
|
|
117
|
+
background-clip: padding-box;
|
|
118
|
+
border: 1px solid rgba(0, 0, 0, 0.2);
|
|
119
|
+
border-radius: $border-radius-lg;
|
|
120
|
+
outline: 0;
|
|
121
|
+
box-shadow: $shadow-lg;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// 模态框头部
|
|
125
|
+
&-header {
|
|
126
|
+
display: flex;
|
|
127
|
+
justify-content: space-between;
|
|
128
|
+
align-items: center;
|
|
129
|
+
padding: 16px;
|
|
130
|
+
border-bottom: 1px solid #dee2e6;
|
|
131
|
+
border-top-left-radius: calc($border-radius-lg - 1px);
|
|
132
|
+
border-top-right-radius: calc($border-radius-lg - 1px);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// 模态框头部标题
|
|
136
|
+
&-header-title {
|
|
137
|
+
margin: 0;
|
|
138
|
+
font-size: $font-size-large;
|
|
139
|
+
font-weight: 600;
|
|
140
|
+
color: #303133;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// 模态框头部关闭按钮
|
|
144
|
+
&-header-close {
|
|
145
|
+
padding: 0;
|
|
146
|
+
background-color: transparent;
|
|
147
|
+
border: 0;
|
|
148
|
+
cursor: pointer;
|
|
149
|
+
font-size: 1.5rem;
|
|
150
|
+
line-height: 1;
|
|
151
|
+
color: #6c757d;
|
|
152
|
+
opacity: 0.5;
|
|
153
|
+
|
|
154
|
+
&:hover {
|
|
155
|
+
opacity: 1;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// 模态框主体
|
|
160
|
+
&-body {
|
|
161
|
+
position: relative;
|
|
162
|
+
flex: 1 1 auto;
|
|
163
|
+
padding: 16px;
|
|
164
|
+
color: #606266;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// 模态框底部
|
|
168
|
+
&-footer {
|
|
169
|
+
display: flex;
|
|
170
|
+
justify-content: flex-end;
|
|
171
|
+
align-items: center;
|
|
172
|
+
padding: 16px;
|
|
173
|
+
border-top: 1px solid #dee2e6;
|
|
174
|
+
border-bottom-left-radius: calc($border-radius-lg - 1px);
|
|
175
|
+
border-bottom-right-radius: calc($border-radius-lg - 1px);
|
|
176
|
+
|
|
177
|
+
>*+* {
|
|
178
|
+
margin-left: 8px;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
</style>
|
package/src/index.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LittleDizzy 组件库
|
|
3
|
+
*
|
|
4
|
+
* 使用方式:
|
|
5
|
+
*
|
|
6
|
+
* 1. 完整引入
|
|
7
|
+
* import LittleDizzy from 'little-dizzy'
|
|
8
|
+
* import 'little-dizzy/dist/styles/index.css'
|
|
9
|
+
* app.use(LittleDizzy)
|
|
10
|
+
*
|
|
11
|
+
* 2. 按需引入组件
|
|
12
|
+
* import { Button, Card, Modal } from 'little-dizzy'
|
|
13
|
+
* app.component('Button', Button)
|
|
14
|
+
*
|
|
15
|
+
* 3. 引入代码片段
|
|
16
|
+
* import { snippets, registerSnippet } from 'little-dizzy'
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
// 导入组件
|
|
20
|
+
import Button from './components/Button.vue'
|
|
21
|
+
import Card from './components/Card.vue'
|
|
22
|
+
import Modal from './components/Modal.vue'
|
|
23
|
+
|
|
24
|
+
// 导入代码片段系统
|
|
25
|
+
import * as snippetsModule from './snippets/index.js'
|
|
26
|
+
|
|
27
|
+
// 组件列表
|
|
28
|
+
const components = {
|
|
29
|
+
Button,
|
|
30
|
+
Card,
|
|
31
|
+
Modal
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// 安装函数
|
|
35
|
+
const install = (app, options = {}) => {
|
|
36
|
+
// 注册所有组件
|
|
37
|
+
Object.entries(components).forEach(([name, component]) => {
|
|
38
|
+
app.component(options.prefix ? `${options.prefix}${name}` : name, component)
|
|
39
|
+
})
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// 导出代码片段相关
|
|
43
|
+
export const snippets = snippetsModule.getSnippets
|
|
44
|
+
export const registerSnippet = snippetsModule.registerSnippet
|
|
45
|
+
export const registerSnippets = snippetsModule.registerSnippets
|
|
46
|
+
export const getSnippet = snippetsModule.getSnippet
|
|
47
|
+
|
|
48
|
+
// 导出单个组件(按需引入)
|
|
49
|
+
export { Button, Card, Modal }
|
|
50
|
+
|
|
51
|
+
// 默认导出(完整引入)
|
|
52
|
+
export default {
|
|
53
|
+
install,
|
|
54
|
+
...components
|
|
55
|
+
}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LittleDizzy 代码片段系统
|
|
3
|
+
*
|
|
4
|
+
* 使用方式:
|
|
5
|
+
*
|
|
6
|
+
* import { registerSnippet, getSnippets } from 'little-dizzy'
|
|
7
|
+
*
|
|
8
|
+
* // 注册自定义代码片段
|
|
9
|
+
* registerSnippet({
|
|
10
|
+
* name: 'MyButton',
|
|
11
|
+
* type: 'html',
|
|
12
|
+
* label: '我的按钮',
|
|
13
|
+
* code: '<button class="my-btn">Click</button>'
|
|
14
|
+
* })
|
|
15
|
+
*
|
|
16
|
+
* // 获取所有代码片段
|
|
17
|
+
* const allSnippets = getSnippets()
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
// 代码片段注册表
|
|
21
|
+
const snippetRegistry = new Map()
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* 注册代码片段
|
|
25
|
+
* @param {Object} snippet - 代码片段对象
|
|
26
|
+
* @param {string} snippet.name - 唯一标识符
|
|
27
|
+
* @param {string} snippet.type - 类型: 'vue' | 'html' | 'css' | 'javascript'
|
|
28
|
+
* @param {string} snippet.label - 显示名称
|
|
29
|
+
* @param {string} snippet.code - 代码内容
|
|
30
|
+
* @returns {boolean} 是否注册成功
|
|
31
|
+
*/
|
|
32
|
+
export function registerSnippet (snippet) {
|
|
33
|
+
if (!snippet || !snippet.name) {
|
|
34
|
+
console.warn('[LittleDizzy] Snippet must have a name property')
|
|
35
|
+
return false
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
snippetRegistry.set(snippet.name, {
|
|
39
|
+
name: snippet.name,
|
|
40
|
+
type: snippet.type || 'html',
|
|
41
|
+
label: snippet.label || snippet.name,
|
|
42
|
+
code: snippet.code || '',
|
|
43
|
+
isCustom: snippet.isCustom || false,
|
|
44
|
+
...snippet
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
return true
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* 批量注册代码片段
|
|
52
|
+
* @param {Array} snippets - 代码片段数组
|
|
53
|
+
* @returns {number} 成功注册的数量
|
|
54
|
+
*/
|
|
55
|
+
export function registerSnippets (snippets) {
|
|
56
|
+
if (!Array.isArray(snippets)) {
|
|
57
|
+
console.warn('[LittleDizzy] registerSnippets expects an array')
|
|
58
|
+
return 0
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
let count = 0
|
|
62
|
+
snippets.forEach(snippet => {
|
|
63
|
+
if (registerSnippet(snippet)) count++
|
|
64
|
+
})
|
|
65
|
+
return count
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* 获取所有已注册的代码片段
|
|
70
|
+
* @returns {Object} 代码片段对象 { name: snippet }
|
|
71
|
+
*/
|
|
72
|
+
export function getSnippets () {
|
|
73
|
+
const result = {}
|
|
74
|
+
snippetRegistry.forEach((value, key) => {
|
|
75
|
+
result[key] = value
|
|
76
|
+
})
|
|
77
|
+
return result
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* 获取单个代码片段
|
|
82
|
+
* @param {string} name - 代码片段名称
|
|
83
|
+
* @returns {Object|undefined} 代码片段对象
|
|
84
|
+
*/
|
|
85
|
+
export function getSnippet (name) {
|
|
86
|
+
return snippetRegistry.get(name)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* 检查代码片段是否存在
|
|
91
|
+
* @param {string} name - 代码片段名称
|
|
92
|
+
* @returns {boolean}
|
|
93
|
+
*/
|
|
94
|
+
export function hasSnippet (name) {
|
|
95
|
+
return snippetRegistry.has(name)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* 移除代码片段
|
|
100
|
+
* @param {string} name - 代码片段名称
|
|
101
|
+
* @returns {boolean} 是否移除成功
|
|
102
|
+
*/
|
|
103
|
+
export function removeSnippet (name) {
|
|
104
|
+
return snippetRegistry.delete(name)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* 清空所有代码片段
|
|
109
|
+
*/
|
|
110
|
+
export function clearSnippets () {
|
|
111
|
+
snippetRegistry.clear()
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* 获取代码片段数量
|
|
116
|
+
* @returns {number}
|
|
117
|
+
*/
|
|
118
|
+
export function getSnippetCount () {
|
|
119
|
+
return snippetRegistry.size
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* 获取代码片段列表(数组形式)
|
|
124
|
+
* @returns {Array}
|
|
125
|
+
*/
|
|
126
|
+
export function getSnippetList () {
|
|
127
|
+
return Array.from(snippetRegistry.values())
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// 代码类型配置
|
|
131
|
+
export const codeTypes = {
|
|
132
|
+
vue: {
|
|
133
|
+
label: 'Vue',
|
|
134
|
+
extension: '.vue',
|
|
135
|
+
color: '#42b883'
|
|
136
|
+
},
|
|
137
|
+
html: {
|
|
138
|
+
label: 'HTML',
|
|
139
|
+
extension: '.html',
|
|
140
|
+
color: '#e34c26'
|
|
141
|
+
},
|
|
142
|
+
javascript: {
|
|
143
|
+
label: 'JavaScript',
|
|
144
|
+
extension: '.js',
|
|
145
|
+
color: '#f7df1e'
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// 导入并注册预设代码片段
|
|
150
|
+
import { presetSnippets } from './presets/index.js'
|
|
151
|
+
registerSnippets(presetSnippets)
|
|
152
|
+
|
|
153
|
+
// 默认导出
|
|
154
|
+
export default {
|
|
155
|
+
registerSnippet,
|
|
156
|
+
registerSnippets,
|
|
157
|
+
getSnippets,
|
|
158
|
+
getSnippet,
|
|
159
|
+
hasSnippet,
|
|
160
|
+
removeSnippet,
|
|
161
|
+
clearSnippets,
|
|
162
|
+
getSnippetCount,
|
|
163
|
+
getSnippetList,
|
|
164
|
+
codeTypes
|
|
165
|
+
}
|
|
166
|
+
|