little-dizzy 2.2.0 → 2.4.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/dist/little-dizzy.css +1 -1
- package/dist/little-dizzy.js +441 -152
- package/dist/little-dizzy.umd.cjs +120 -2
- package/dist/vite.svg +25 -1
- package/package.json +63 -61
- package/src/components/Card.vue +10 -9
- package/src/components/Message.vue +156 -0
- package/src/components/Modal.vue +27 -17
- package/src/components/custom/Lztext.vue +170 -0
- package/src/components/custom/index.js +3 -1
- package/src/components/custom/lzbutton.vue +5 -5
- package/src/components/custom/lztheme.vue +97 -58
- package/src/components/message.js +238 -0
- package/src/index.js +9 -1
- package/src/snippets/presets/index.js +4 -2
- package/src/snippets/presets/message.js +45 -0
- package/src/styles/_variables.scss +8 -0
- package/src/styles/tailwind.css +1 -0
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Message 全局消息提示服务
|
|
3
|
+
*
|
|
4
|
+
* 使用方法:
|
|
5
|
+
* import { message } from '@/components/message.js'
|
|
6
|
+
*
|
|
7
|
+
* message.success('操作成功')
|
|
8
|
+
* message.error('操作失败')
|
|
9
|
+
* message.warning('警告信息')
|
|
10
|
+
* message.info('提示信息')
|
|
11
|
+
*
|
|
12
|
+
* // 带配置
|
|
13
|
+
* message.success('操作成功', { duration: 5000, closable: true })
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { createApp, h, ref } from 'vue'
|
|
17
|
+
import Message from './Message.vue'
|
|
18
|
+
|
|
19
|
+
let messageInstance = null
|
|
20
|
+
let messageContainer = null
|
|
21
|
+
|
|
22
|
+
// Initialize message instance
|
|
23
|
+
const initMessage = () => {
|
|
24
|
+
if (messageInstance) return messageInstance
|
|
25
|
+
|
|
26
|
+
messageContainer = document.createElement('div')
|
|
27
|
+
messageContainer.id = 'ld-message-container'
|
|
28
|
+
document.body.appendChild(messageContainer)
|
|
29
|
+
|
|
30
|
+
const app = createApp({
|
|
31
|
+
setup () {
|
|
32
|
+
const messageRef = ref(null)
|
|
33
|
+
return () => h(Message, { ref: messageRef })
|
|
34
|
+
}
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
const vm = app.mount(messageContainer)
|
|
38
|
+
messageInstance = vm.$el.__vueParentComponent?.exposed || vm.$el.parentNode?.__vueParentComponent?.subTree?.component?.exposed
|
|
39
|
+
|
|
40
|
+
// Wait for next tick to get the exposed methods
|
|
41
|
+
return new Promise((resolve) => {
|
|
42
|
+
setTimeout(() => {
|
|
43
|
+
const container = document.querySelector('#ld-message-container')
|
|
44
|
+
if (container) {
|
|
45
|
+
const vueInstance = container._vnode?.component?.subTree?.component?.exposed
|
|
46
|
+
if (vueInstance) {
|
|
47
|
+
messageInstance = vueInstance
|
|
48
|
+
resolve(messageInstance)
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}, 0)
|
|
52
|
+
})
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Create a simpler implementation using reactive state
|
|
56
|
+
const messages = ref([])
|
|
57
|
+
let messageId = 0
|
|
58
|
+
|
|
59
|
+
const typeClasses = {
|
|
60
|
+
success: 'ld-message--success',
|
|
61
|
+
warning: 'ld-message--warning',
|
|
62
|
+
error: 'ld-message--error',
|
|
63
|
+
info: 'ld-message--info'
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const createMessageElement = (options) => {
|
|
67
|
+
const id = ++messageId
|
|
68
|
+
const type = options.type || 'info'
|
|
69
|
+
const content = options.content || ''
|
|
70
|
+
const duration = options.duration ?? 3000
|
|
71
|
+
const closable = options.closable ?? false
|
|
72
|
+
|
|
73
|
+
// Create message element
|
|
74
|
+
const msgEl = document.createElement('div')
|
|
75
|
+
msgEl.className = `ld-message ld-message--${type}`
|
|
76
|
+
msgEl.setAttribute('data-id', id)
|
|
77
|
+
|
|
78
|
+
// Icon SVGs
|
|
79
|
+
const icons = {
|
|
80
|
+
success: `<svg class="ld-message-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
|
|
81
|
+
<path d="M20 6L9 17l-5-5" stroke-linecap="round" stroke-linejoin="round"/>
|
|
82
|
+
</svg>`,
|
|
83
|
+
warning: `<svg class="ld-message-icon" viewBox="0 0 24 24" fill="currentColor">
|
|
84
|
+
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"/>
|
|
85
|
+
</svg>`,
|
|
86
|
+
error: `<svg class="ld-message-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
|
|
87
|
+
<circle cx="12" cy="12" r="10"/>
|
|
88
|
+
<path d="M15 9l-6 6M9 9l6 6" stroke-linecap="round"/>
|
|
89
|
+
</svg>`,
|
|
90
|
+
info: `<svg class="ld-message-icon" viewBox="0 0 24 24" fill="currentColor">
|
|
91
|
+
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"/>
|
|
92
|
+
</svg>`
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
let html = `${icons[type]}<span class="ld-message-content">${content}</span>`
|
|
96
|
+
|
|
97
|
+
if (closable) {
|
|
98
|
+
html += `<button class="ld-message-close" onclick="window.__ldMessageClose(${id})">
|
|
99
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
100
|
+
<path d="M18 6L6 18M6 6l12 12"/>
|
|
101
|
+
</svg>
|
|
102
|
+
</button>`
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
msgEl.innerHTML = html
|
|
106
|
+
|
|
107
|
+
return { id, element: msgEl, duration }
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Ensure container exists
|
|
111
|
+
const ensureContainer = () => {
|
|
112
|
+
let container = document.getElementById('ld-message-root')
|
|
113
|
+
if (!container) {
|
|
114
|
+
container = document.createElement('div')
|
|
115
|
+
container.id = 'ld-message-root'
|
|
116
|
+
document.body.appendChild(container)
|
|
117
|
+
|
|
118
|
+
// Add styles
|
|
119
|
+
const style = document.createElement('style')
|
|
120
|
+
style.textContent = `
|
|
121
|
+
#ld-message-root {
|
|
122
|
+
position: fixed;
|
|
123
|
+
top: 16px;
|
|
124
|
+
left: 50%;
|
|
125
|
+
transform: translateX(-50%);
|
|
126
|
+
z-index: 9999;
|
|
127
|
+
display: flex;
|
|
128
|
+
flex-direction: column;
|
|
129
|
+
align-items: center;
|
|
130
|
+
gap: 12px;
|
|
131
|
+
pointer-events: none;
|
|
132
|
+
}
|
|
133
|
+
.ld-message {
|
|
134
|
+
pointer-events: auto;
|
|
135
|
+
display: flex;
|
|
136
|
+
align-items: center;
|
|
137
|
+
gap: 12px;
|
|
138
|
+
padding: 12px 20px;
|
|
139
|
+
border-radius: 8px;
|
|
140
|
+
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
|
|
141
|
+
backdrop-filter: blur(8px);
|
|
142
|
+
animation: ldMessageIn 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
143
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
144
|
+
font-size: 14px;
|
|
145
|
+
font-weight: 500;
|
|
146
|
+
}
|
|
147
|
+
.ld-message.ld-message--closing {
|
|
148
|
+
animation: ldMessageOut 0.2s ease-in forwards;
|
|
149
|
+
}
|
|
150
|
+
.ld-message--success { background: rgba(16, 185, 129, 0.95); color: white; }
|
|
151
|
+
.ld-message--warning { background: rgba(245, 158, 11, 0.95); color: white; }
|
|
152
|
+
.ld-message--error { background: rgba(239, 68, 68, 0.95); color: white; }
|
|
153
|
+
.ld-message--info { background: rgba(14, 165, 233, 0.95); color: white; }
|
|
154
|
+
.ld-message-icon { width: 20px; height: 20px; flex-shrink: 0; }
|
|
155
|
+
.ld-message-content { white-space: nowrap; }
|
|
156
|
+
.ld-message-close {
|
|
157
|
+
display: flex;
|
|
158
|
+
align-items: center;
|
|
159
|
+
justify-content: center;
|
|
160
|
+
width: 20px;
|
|
161
|
+
height: 20px;
|
|
162
|
+
margin-left: 4px;
|
|
163
|
+
padding: 0;
|
|
164
|
+
border: none;
|
|
165
|
+
background: transparent;
|
|
166
|
+
color: currentColor;
|
|
167
|
+
cursor: pointer;
|
|
168
|
+
border-radius: 50%;
|
|
169
|
+
transition: background 0.2s;
|
|
170
|
+
}
|
|
171
|
+
.ld-message-close:hover { background: rgba(255,255,255,0.2); }
|
|
172
|
+
.ld-message-close svg { width: 14px; height: 14px; }
|
|
173
|
+
@keyframes ldMessageIn {
|
|
174
|
+
from { opacity: 0; transform: translateY(-20px) scale(0.9); }
|
|
175
|
+
to { opacity: 1; transform: translateY(0) scale(1); }
|
|
176
|
+
}
|
|
177
|
+
@keyframes ldMessageOut {
|
|
178
|
+
from { opacity: 1; transform: translateY(0) scale(1); }
|
|
179
|
+
to { opacity: 0; transform: translateY(-10px) scale(0.95); }
|
|
180
|
+
}
|
|
181
|
+
`
|
|
182
|
+
document.head.appendChild(style)
|
|
183
|
+
}
|
|
184
|
+
return container
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Close message
|
|
188
|
+
const closeMessage = (id) => {
|
|
189
|
+
const container = document.getElementById('ld-message-root')
|
|
190
|
+
if (!container) return
|
|
191
|
+
|
|
192
|
+
const msgEl = container.querySelector(`[data-id="${id}"]`)
|
|
193
|
+
if (msgEl) {
|
|
194
|
+
msgEl.classList.add('ld-message--closing')
|
|
195
|
+
setTimeout(() => {
|
|
196
|
+
msgEl.remove()
|
|
197
|
+
}, 200)
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Expose close function globally
|
|
202
|
+
if (typeof window !== 'undefined') {
|
|
203
|
+
window.__ldMessageClose = closeMessage
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Show message
|
|
207
|
+
const showMessage = (options) => {
|
|
208
|
+
const container = ensureContainer()
|
|
209
|
+
const { id, element, duration } = createMessageElement(options)
|
|
210
|
+
|
|
211
|
+
container.appendChild(element)
|
|
212
|
+
|
|
213
|
+
if (duration > 0) {
|
|
214
|
+
setTimeout(() => {
|
|
215
|
+
closeMessage(id)
|
|
216
|
+
}, duration)
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return id
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Export message API
|
|
223
|
+
export const message = {
|
|
224
|
+
success: (content, options = {}) => showMessage({ ...options, type: 'success', content }),
|
|
225
|
+
warning: (content, options = {}) => showMessage({ ...options, type: 'warning', content }),
|
|
226
|
+
error: (content, options = {}) => showMessage({ ...options, type: 'error', content }),
|
|
227
|
+
info: (content, options = {}) => showMessage({ ...options, type: 'info', content }),
|
|
228
|
+
close: closeMessage,
|
|
229
|
+
closeAll: () => {
|
|
230
|
+
const container = document.getElementById('ld-message-root')
|
|
231
|
+
if (container) {
|
|
232
|
+
container.innerHTML = ''
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
export default message
|
|
238
|
+
|
package/src/index.js
CHANGED
|
@@ -23,6 +23,8 @@
|
|
|
23
23
|
import Button from './components/Button.vue'
|
|
24
24
|
import Card from './components/Card.vue'
|
|
25
25
|
import Modal from './components/Modal.vue'
|
|
26
|
+
import Message from './components/Message.vue'
|
|
27
|
+
import { message } from './components/message.js'
|
|
26
28
|
|
|
27
29
|
// 导入自定义组件(由 Demo 上传生成)
|
|
28
30
|
import { customComponents } from './components/custom/index.js'
|
|
@@ -35,6 +37,7 @@ const components = {
|
|
|
35
37
|
Button,
|
|
36
38
|
Card,
|
|
37
39
|
Modal,
|
|
40
|
+
Message,
|
|
38
41
|
...customComponents
|
|
39
42
|
}
|
|
40
43
|
|
|
@@ -44,6 +47,11 @@ const install = (app, options = {}) => {
|
|
|
44
47
|
Object.entries(components).forEach(([name, component]) => {
|
|
45
48
|
app.component(options.prefix ? `${options.prefix}${name}` : name, component)
|
|
46
49
|
})
|
|
50
|
+
|
|
51
|
+
// 挂载 message 到全局属性
|
|
52
|
+
app.config.globalProperties.$message = message
|
|
53
|
+
// 同时提供 provide 方式
|
|
54
|
+
app.provide('message', message)
|
|
47
55
|
}
|
|
48
56
|
|
|
49
57
|
// 导出代码片段相关
|
|
@@ -53,7 +61,7 @@ export const registerSnippets = snippetsModule.registerSnippets
|
|
|
53
61
|
export const getSnippet = snippetsModule.getSnippet
|
|
54
62
|
|
|
55
63
|
// 导出内置组件(按需引入)
|
|
56
|
-
export { Button, Card, Modal }
|
|
64
|
+
export { Button, Card, Modal, Message, message }
|
|
57
65
|
|
|
58
66
|
// 重新导出自定义组件
|
|
59
67
|
export * from './components/custom/index.js'
|
|
@@ -7,16 +7,18 @@
|
|
|
7
7
|
import buttonSnippet from './button.js'
|
|
8
8
|
import cardSnippet from './card.js'
|
|
9
9
|
import modalSnippet from './modal.js'
|
|
10
|
+
import messageSnippet from './message.js'
|
|
10
11
|
|
|
11
12
|
// 所有预设代码片段
|
|
12
13
|
export const presetSnippets = [
|
|
13
14
|
buttonSnippet,
|
|
14
15
|
cardSnippet,
|
|
15
|
-
modalSnippet
|
|
16
|
+
modalSnippet,
|
|
17
|
+
messageSnippet
|
|
16
18
|
]
|
|
17
19
|
|
|
18
20
|
// 单独导出
|
|
19
|
-
export { buttonSnippet, cardSnippet, modalSnippet }
|
|
21
|
+
export { buttonSnippet, cardSnippet, modalSnippet, messageSnippet }
|
|
20
22
|
|
|
21
23
|
export default presetSnippets
|
|
22
24
|
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Message 消息提示组件示例代码
|
|
3
|
+
*/
|
|
4
|
+
export default {
|
|
5
|
+
name: 'Message',
|
|
6
|
+
type: 'vue',
|
|
7
|
+
label: 'Message 消息提示',
|
|
8
|
+
code: `<template>
|
|
9
|
+
<div class="message-demo">
|
|
10
|
+
<Button type="success" @click="showSuccess">成功提示</Button>
|
|
11
|
+
<Button type="warning" @click="showWarning">警告提示</Button>
|
|
12
|
+
<Button type="danger" @click="showError">错误提示</Button>
|
|
13
|
+
<Button type="info" @click="showInfo">信息提示</Button>
|
|
14
|
+
</div>
|
|
15
|
+
</template>
|
|
16
|
+
|
|
17
|
+
<script setup>
|
|
18
|
+
import { Button, message } from 'little-dizzy'
|
|
19
|
+
|
|
20
|
+
const showSuccess = () => {
|
|
21
|
+
message.success('操作成功!')
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const showWarning = () => {
|
|
25
|
+
message.warning('请注意!')
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const showError = () => {
|
|
29
|
+
message.error('操作失败!')
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const showInfo = () => {
|
|
33
|
+
message.info('这是一条提示信息', { duration: 5000, closable: true })
|
|
34
|
+
}
|
|
35
|
+
</script>
|
|
36
|
+
|
|
37
|
+
<style scoped>
|
|
38
|
+
.message-demo {
|
|
39
|
+
display: flex;
|
|
40
|
+
gap: 12px;
|
|
41
|
+
flex-wrap: wrap;
|
|
42
|
+
}
|
|
43
|
+
</style>`
|
|
44
|
+
}
|
|
45
|
+
|
|
@@ -34,6 +34,14 @@ $shadow-lg: 0 6px 20px rgba(0, 0, 0, 0.2);
|
|
|
34
34
|
margin: 0;
|
|
35
35
|
padding: 0;
|
|
36
36
|
box-sizing: border-box;
|
|
37
|
+
|
|
38
|
+
// 隐藏滚动条(保持滚动功能)
|
|
39
|
+
scrollbar-width: none; // Firefox
|
|
40
|
+
-ms-overflow-style: none; // IE/Edge
|
|
41
|
+
|
|
42
|
+
&::-webkit-scrollbar {
|
|
43
|
+
display: none; // Chrome/Safari/Opera
|
|
44
|
+
}
|
|
37
45
|
}
|
|
38
46
|
|
|
39
47
|
body {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@import "tailwindcss";
|