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.
@@ -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">&times;</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
+