vue3-dynamic-island 1.0.1
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 +269 -0
- package/dist/index.js +535 -0
- package/dist/index.umd.cjs +1 -0
- package/dist/style.css +1 -0
- package/package.json +53 -0
package/README.md
ADDED
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
# Dynamic Island
|
|
2
|
+
|
|
3
|
+
A commercial-grade Dynamic Island notification component for Vue 3, inspired by Apple's Dynamic Island design.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🎨 Apple-inspired Dynamic Island UI design
|
|
8
|
+
- 🚀 Global notification system with queue management
|
|
9
|
+
- 🎯 Multiple notification types (default, success, error, warning, info)
|
|
10
|
+
- 📦 Dynamic component embedding support
|
|
11
|
+
- 🎭 Multiple animation effects (fade, slide, zoom, bounce)
|
|
12
|
+
- 🔄 Auto-close and persistent modes
|
|
13
|
+
- 🖱️ Drag-and-drop functionality with position persistence
|
|
14
|
+
- 🔊 Sound notifications
|
|
15
|
+
- 🎨 Custom styling support
|
|
16
|
+
- 💾 localStorage position memory
|
|
17
|
+
- 📱 Responsive design
|
|
18
|
+
- 🎯 TypeScript support
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install dynamic-island
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Usage
|
|
27
|
+
|
|
28
|
+
### Basic Setup
|
|
29
|
+
|
|
30
|
+
```vue
|
|
31
|
+
<script setup>
|
|
32
|
+
import { useDynamicIsland } from 'dynamic-island'
|
|
33
|
+
|
|
34
|
+
const island = useDynamicIsland()
|
|
35
|
+
|
|
36
|
+
const showNotification = () => {
|
|
37
|
+
island.success('Success', 'Operation completed successfully!')
|
|
38
|
+
}
|
|
39
|
+
</script>
|
|
40
|
+
|
|
41
|
+
<template>
|
|
42
|
+
<button @click="showNotification">Show Notification</button>
|
|
43
|
+
</template>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Global Installation
|
|
47
|
+
|
|
48
|
+
```vue
|
|
49
|
+
<script setup>
|
|
50
|
+
import { createApp } from 'vue'
|
|
51
|
+
import App from './App.vue'
|
|
52
|
+
import DynamicIsland from 'dynamic-island'
|
|
53
|
+
|
|
54
|
+
const app = createApp(App)
|
|
55
|
+
app.use(DynamicIsland)
|
|
56
|
+
app.mount('#app')
|
|
57
|
+
</script>
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## API
|
|
61
|
+
|
|
62
|
+
### useDynamicIsland()
|
|
63
|
+
|
|
64
|
+
Returns an object with the following methods:
|
|
65
|
+
|
|
66
|
+
#### show(options)
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
island.show({
|
|
70
|
+
type: 'success', // 'default' | 'success' | 'error' | 'warning' | 'info'
|
|
71
|
+
title: 'Notification Title',
|
|
72
|
+
subtitle: 'Optional subtitle',
|
|
73
|
+
icon: MyIconComponent, // Optional custom icon
|
|
74
|
+
showIcon: true, // Show/hide icon
|
|
75
|
+
showClose: true, // Show/hide close button
|
|
76
|
+
duration: 3000, // Auto-close duration (ms)
|
|
77
|
+
persistent: false, // Don't auto-close
|
|
78
|
+
animation: 'slide', // 'fade' | 'slide' | 'zoom' | 'bounce'
|
|
79
|
+
progress: 50, // Progress value (0-100)
|
|
80
|
+
showProgress: false, // Show progress bar
|
|
81
|
+
dynamicComponent: { // Embed custom component
|
|
82
|
+
component: MyComponent,
|
|
83
|
+
props: { /* props */ }
|
|
84
|
+
},
|
|
85
|
+
backgroundColor: '#ff0000', // Custom background color
|
|
86
|
+
textColor: '#ffffff', // Custom text color
|
|
87
|
+
soundEnabled: true, // Enable sound
|
|
88
|
+
soundUrl: '/sound.mp3', // Custom sound URL
|
|
89
|
+
memPosition: false, // Remember position
|
|
90
|
+
onClick: () => {}, // Click callback
|
|
91
|
+
onClose: () => {} // Close callback
|
|
92
|
+
})
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
#### success(title, subtitle, options)
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
island.success('Success', 'Operation completed!')
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
#### error(title, subtitle, options)
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
island.error('Error', 'Something went wrong!')
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
#### warning(title, subtitle, options)
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
island.warning('Warning', 'Please check your input')
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
#### info(title, subtitle, options)
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
island.info('Info', 'You have 3 new messages')
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
#### close(id)
|
|
120
|
+
|
|
121
|
+
Close a specific notification by ID.
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
const notificationId = island.show({ title: 'Test' })
|
|
125
|
+
island.close(notificationId)
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
#### clear()
|
|
129
|
+
|
|
130
|
+
Clear all notifications.
|
|
131
|
+
|
|
132
|
+
```typescript
|
|
133
|
+
island.clear()
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
#### clearQueue()
|
|
137
|
+
|
|
138
|
+
Clear the notification queue.
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
island.clearQueue()
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
#### updateProgress(id, progress)
|
|
145
|
+
|
|
146
|
+
Update progress of a notification.
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
const notificationId = island.show({
|
|
150
|
+
title: 'Uploading',
|
|
151
|
+
showProgress: true,
|
|
152
|
+
progress: 0,
|
|
153
|
+
persistent: true
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
// Update progress
|
|
157
|
+
island.updateProgress(notificationId, 50)
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
#### updateIsland(id, updates)
|
|
161
|
+
|
|
162
|
+
Update a notification's properties.
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
const notificationId = island.show({ title: 'Test' })
|
|
166
|
+
island.updateIsland(notificationId, { title: 'Updated' })
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
#### setSoundEnabled(enabled)
|
|
170
|
+
|
|
171
|
+
Enable/disable sound notifications globally.
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
island.setSoundEnabled(false)
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## Examples
|
|
178
|
+
|
|
179
|
+
### Dynamic Component Embedding
|
|
180
|
+
|
|
181
|
+
```vue
|
|
182
|
+
<script setup>
|
|
183
|
+
import { useDynamicIsland } from 'dynamic-island'
|
|
184
|
+
import MyForm from './MyForm.vue'
|
|
185
|
+
|
|
186
|
+
const island = useDynamicIsland()
|
|
187
|
+
|
|
188
|
+
const showForm = () => {
|
|
189
|
+
island.show({
|
|
190
|
+
type: 'info',
|
|
191
|
+
title: 'User Form',
|
|
192
|
+
subtitle: 'Please fill in your information',
|
|
193
|
+
persistent: true,
|
|
194
|
+
dynamicComponent: {
|
|
195
|
+
component: MyForm,
|
|
196
|
+
props: {
|
|
197
|
+
onSubmit: (data) => {
|
|
198
|
+
console.log('Form submitted:', data)
|
|
199
|
+
island.clear()
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
})
|
|
204
|
+
}
|
|
205
|
+
</script>
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Custom Styling
|
|
209
|
+
|
|
210
|
+
```typescript
|
|
211
|
+
island.show({
|
|
212
|
+
title: 'Custom Style',
|
|
213
|
+
subtitle: 'Gradient background',
|
|
214
|
+
backgroundColor: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
|
|
215
|
+
textColor: '#ffffff'
|
|
216
|
+
})
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### Progress Bar
|
|
220
|
+
|
|
221
|
+
```typescript
|
|
222
|
+
const notificationId = island.show({
|
|
223
|
+
type: 'info',
|
|
224
|
+
title: 'Processing',
|
|
225
|
+
subtitle: 'Please wait...',
|
|
226
|
+
showProgress: true,
|
|
227
|
+
progress: 0,
|
|
228
|
+
persistent: true
|
|
229
|
+
})
|
|
230
|
+
|
|
231
|
+
// Simulate progress
|
|
232
|
+
let progress = 0
|
|
233
|
+
const interval = setInterval(() => {
|
|
234
|
+
progress += 10
|
|
235
|
+
island.updateProgress(notificationId, progress)
|
|
236
|
+
|
|
237
|
+
if (progress >= 100) {
|
|
238
|
+
clearInterval(interval)
|
|
239
|
+
island.close(notificationId)
|
|
240
|
+
island.success('Complete', 'Operation finished!')
|
|
241
|
+
}
|
|
242
|
+
}, 500)
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
## Drag and Drop
|
|
246
|
+
|
|
247
|
+
- Click and drag the notification by the header area
|
|
248
|
+
- Position is automatically saved to localStorage
|
|
249
|
+
- Component stays within viewport boundaries
|
|
250
|
+
- 12px safety margin from screen edges
|
|
251
|
+
|
|
252
|
+
## Browser Support
|
|
253
|
+
|
|
254
|
+
- Chrome (latest)
|
|
255
|
+
- Firefox (latest)
|
|
256
|
+
- Safari (latest)
|
|
257
|
+
- Edge (latest)
|
|
258
|
+
|
|
259
|
+
## License
|
|
260
|
+
|
|
261
|
+
MIT
|
|
262
|
+
|
|
263
|
+
## Author
|
|
264
|
+
|
|
265
|
+
Your Name
|
|
266
|
+
|
|
267
|
+
## Contributing
|
|
268
|
+
|
|
269
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,535 @@
|
|
|
1
|
+
import { ref as w, computed as H, defineComponent as AV, onUnmounted as uV, watch as j, openBlock as c, createBlock as T, Teleport as dV, createElementVNode as r, normalizeStyle as U, createVNode as mV, TransitionGroup as gV, withCtx as fV, createElementBlock as l, Fragment as hV, renderList as wV, unref as pV, normalizeClass as X, resolveDynamicComponent as z, toDisplayString as F, createCommentVNode as I, withModifiers as _, mergeProps as yV, nextTick as $ } from "vue";
|
|
2
|
+
const L = "dynamic-island-position", O = "dynamic-island-mem-position", SV = () => `island-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`, xV = () => ({
|
|
3
|
+
x: Math.max(
|
|
4
|
+
12,
|
|
5
|
+
Math.min(
|
|
6
|
+
window.innerWidth / 2 - 150,
|
|
7
|
+
window.innerWidth - 320 - 12 - 20
|
|
8
|
+
)
|
|
9
|
+
),
|
|
10
|
+
y: Math.max(12, 20)
|
|
11
|
+
}), vV = () => {
|
|
12
|
+
try {
|
|
13
|
+
const V = localStorage.getItem(L);
|
|
14
|
+
if (V) {
|
|
15
|
+
const n = JSON.parse(V);
|
|
16
|
+
if (typeof n.x == "number" && typeof n.y == "number")
|
|
17
|
+
return {
|
|
18
|
+
x: Math.max(
|
|
19
|
+
12,
|
|
20
|
+
Math.min(
|
|
21
|
+
n.x,
|
|
22
|
+
window.innerWidth - 320 - 12 - 20
|
|
23
|
+
)
|
|
24
|
+
),
|
|
25
|
+
y: Math.max(
|
|
26
|
+
12,
|
|
27
|
+
Math.min(
|
|
28
|
+
n.y,
|
|
29
|
+
window.innerHeight - 80 - 12
|
|
30
|
+
)
|
|
31
|
+
)
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
} catch {
|
|
35
|
+
console.warn("Failed to load position from localStorage");
|
|
36
|
+
}
|
|
37
|
+
return xV();
|
|
38
|
+
}, Z = (V) => {
|
|
39
|
+
try {
|
|
40
|
+
localStorage.setItem(L, JSON.stringify(V));
|
|
41
|
+
} catch {
|
|
42
|
+
console.warn("Failed to save position to localStorage");
|
|
43
|
+
}
|
|
44
|
+
}, f = w([]), C = w([]), D = w(vV()), eV = w(!0), J = 3, tV = H(() => f.value.length < J), oV = H(() => C.value.length > 0), nV = () => {
|
|
45
|
+
for (; tV.value && oV.value; ) {
|
|
46
|
+
const V = C.value.shift();
|
|
47
|
+
V && f.value.push(V);
|
|
48
|
+
}
|
|
49
|
+
}, MV = (V) => {
|
|
50
|
+
const n = {
|
|
51
|
+
id: V.id || SV(),
|
|
52
|
+
type: V.type || "default",
|
|
53
|
+
title: V.title,
|
|
54
|
+
subtitle: V.subtitle,
|
|
55
|
+
icon: V.icon,
|
|
56
|
+
showIcon: V.showIcon ?? !0,
|
|
57
|
+
showClose: V.showClose ?? !0,
|
|
58
|
+
duration: V.duration ?? 3e3,
|
|
59
|
+
persistent: V.persistent ?? !1,
|
|
60
|
+
animation: V.animation || "slide",
|
|
61
|
+
progress: V.progress,
|
|
62
|
+
showProgress: V.showProgress ?? !1,
|
|
63
|
+
dynamicComponent: V.dynamicComponent,
|
|
64
|
+
backgroundColor: V.backgroundColor,
|
|
65
|
+
textColor: V.textColor,
|
|
66
|
+
soundEnabled: V.soundEnabled ?? !0,
|
|
67
|
+
soundUrl: V.soundUrl,
|
|
68
|
+
onClick: V.onClick,
|
|
69
|
+
onClose: V.onClose,
|
|
70
|
+
createdAt: Date.now(),
|
|
71
|
+
memPosition: V.memPosition ?? !1
|
|
72
|
+
};
|
|
73
|
+
return f.value.length < J ? (f.value.push(n), n.memPosition && sV()) : C.value.push(n), n.id;
|
|
74
|
+
}, CV = (V) => {
|
|
75
|
+
var a;
|
|
76
|
+
const n = f.value.findIndex((s) => s.id === V);
|
|
77
|
+
if (n > -1) {
|
|
78
|
+
const s = f.value[n];
|
|
79
|
+
(a = s.onClose) == null || a.call(s), f.value.splice(n, 1), s.memPosition && DV(), nV();
|
|
80
|
+
}
|
|
81
|
+
}, EV = () => {
|
|
82
|
+
f.value.forEach((V) => {
|
|
83
|
+
var n;
|
|
84
|
+
(n = V.onClose) == null || n.call(V);
|
|
85
|
+
}), f.value = [], C.value = [];
|
|
86
|
+
}, IV = () => {
|
|
87
|
+
C.value = [];
|
|
88
|
+
}, kV = (V, n, a) => {
|
|
89
|
+
const y = n || 320, b = a || 80;
|
|
90
|
+
D.value = {
|
|
91
|
+
// X轴:确保组件完全在可视区内,右侧增加滚动条安全区
|
|
92
|
+
x: Math.max(
|
|
93
|
+
12,
|
|
94
|
+
Math.min(
|
|
95
|
+
V.x,
|
|
96
|
+
window.innerWidth - y - 12 - 0
|
|
97
|
+
)
|
|
98
|
+
),
|
|
99
|
+
// Y轴:确保组件完全在可视区内,底部保留safeArea
|
|
100
|
+
y: Math.max(
|
|
101
|
+
12,
|
|
102
|
+
Math.min(V.y, window.innerHeight - b - 12)
|
|
103
|
+
)
|
|
104
|
+
}, Z(D.value);
|
|
105
|
+
}, sV = () => {
|
|
106
|
+
try {
|
|
107
|
+
const V = localStorage.getItem(L);
|
|
108
|
+
V && localStorage.setItem(O, V);
|
|
109
|
+
} catch {
|
|
110
|
+
console.warn("Failed to save mem_position to localStorage");
|
|
111
|
+
}
|
|
112
|
+
Z(D.value);
|
|
113
|
+
}, DV = () => {
|
|
114
|
+
try {
|
|
115
|
+
const V = localStorage.getItem(O);
|
|
116
|
+
if (V) {
|
|
117
|
+
const n = JSON.parse(V);
|
|
118
|
+
typeof n.x == "number" && typeof n.y == "number" && (Z(n), D.value = n);
|
|
119
|
+
}
|
|
120
|
+
localStorage.removeItem(O);
|
|
121
|
+
} catch {
|
|
122
|
+
console.warn("Failed to restore mem_position from localStorage");
|
|
123
|
+
}
|
|
124
|
+
}, bV = (V) => {
|
|
125
|
+
eV.value = V;
|
|
126
|
+
}, BV = (V, n) => {
|
|
127
|
+
const a = f.value.find((s) => s.id === V);
|
|
128
|
+
a && (a.progress = Math.max(0, Math.min(100, n)));
|
|
129
|
+
}, QV = (V, n) => {
|
|
130
|
+
const a = f.value.find((s) => s.id === V);
|
|
131
|
+
a && Object.assign(a, n);
|
|
132
|
+
}, aV = () => ({
|
|
133
|
+
visibleIslands: f,
|
|
134
|
+
queue: C,
|
|
135
|
+
position: D,
|
|
136
|
+
globalSoundEnabled: eV,
|
|
137
|
+
maxVisible: J,
|
|
138
|
+
hasVisibleSlots: tV,
|
|
139
|
+
hasQueuedItems: oV,
|
|
140
|
+
add: MV,
|
|
141
|
+
remove: CV,
|
|
142
|
+
clear: EV,
|
|
143
|
+
clearQueue: IV,
|
|
144
|
+
updatePosition: kV,
|
|
145
|
+
saveMemPosition: sV,
|
|
146
|
+
setGlobalSoundEnabled: bV,
|
|
147
|
+
updateProgress: BV,
|
|
148
|
+
updateIsland: QV,
|
|
149
|
+
processQueue: nV
|
|
150
|
+
}), k = new URL("data:audio/mpeg;base64,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knmSNGpnU/dT0H2qRZFHRWjpIqVTUk/UbPl0EAACA12sDZ4GHg2IgAVRmYZEBhYWmRVgY7ap03CGwg2WrWCcF/H5n3FO1kDVK9kZtyT2bldZDVm0ODaF48HWc6hUxnd95g7gvavsYtnFq+26brG+Mf/cHe7YrnWYOIW95pbE+Mbe/OrXti319W3rfrNbNLa+PSNcmNh8O7VMQU1FMy4xMDEgKGJldGEgMilVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVX/+5JkuQzzzkXQB3JAAgAADSDgAAEPlQswdceACAAANIKAAARVVVVVAAAADIgCAggAOfxoBIemFg8mQQ31cDAJOTXESjHwpTBAPa+JioCipTDQC1KueBgggGkFF0Y7AxAoDOgQASAhYV0NW8NXBcGDY2GqwyKQIgxFvBuwToNgUmThSGWFbENFy/NBW4hcg4pQighUmj6JSHO/JY8Tg7BQYuccYuYmSKkBSWXf47DBBRACYHeRckjIiw5xRJ0u0S7/yCJE0XCGFAg5FzcqLKRFiBGJdLqy6TJkRb/7kwRQnCDl83PGZuRQihOE+bkWMUVrLpFTIvE0iySJd//6aJfNyKEUNCfTrL5uRQnDQ3/+RUyLxeqSMS6RUyLxlSLxiXSZTEFNRTMuMTAxIChiZXRhIDIpVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//uSZL0AB8h9yN52gAAAAA0gwAAAAAABpBwAACAAADSDgAAEVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVQ==", import.meta.url).href, YV = {
|
|
151
|
+
default: k,
|
|
152
|
+
success: k,
|
|
153
|
+
error: k,
|
|
154
|
+
warning: k,
|
|
155
|
+
info: k
|
|
156
|
+
};
|
|
157
|
+
let G = null;
|
|
158
|
+
const RV = () => (G || (G = new (window.AudioContext || window.webkitAudioContext)()), G), M = (V, n, a = "sine") => {
|
|
159
|
+
try {
|
|
160
|
+
const s = RV(), A = s.createOscillator(), u = s.createGain();
|
|
161
|
+
A.connect(u), u.connect(s.destination), A.frequency.value = V, A.type = a, u.gain.setValueAtTime(0.3, s.currentTime), u.gain.exponentialRampToValueAtTime(
|
|
162
|
+
0.01,
|
|
163
|
+
s.currentTime + n
|
|
164
|
+
), A.start(s.currentTime), A.stop(s.currentTime + n);
|
|
165
|
+
} catch (s) {
|
|
166
|
+
console.warn("Failed to play sound:", s);
|
|
167
|
+
}
|
|
168
|
+
}, VV = (V) => {
|
|
169
|
+
switch (V) {
|
|
170
|
+
case "success":
|
|
171
|
+
M(880, 0.15), setTimeout(() => M(1100, 0.2), 100);
|
|
172
|
+
break;
|
|
173
|
+
case "error":
|
|
174
|
+
M(200, 0.3, "sawtooth");
|
|
175
|
+
break;
|
|
176
|
+
case "warning":
|
|
177
|
+
M(600, 0.2), setTimeout(() => M(500, 0.2), 150);
|
|
178
|
+
break;
|
|
179
|
+
case "info":
|
|
180
|
+
M(700, 0.15);
|
|
181
|
+
break;
|
|
182
|
+
}
|
|
183
|
+
}, NV = (V, n, a = !0) => {
|
|
184
|
+
if (!a) return;
|
|
185
|
+
const s = n || YV[V];
|
|
186
|
+
s ? new Audio(s).play().catch((u) => {
|
|
187
|
+
console.warn("Failed to play sound:", u), VV(V);
|
|
188
|
+
}) : VV(V);
|
|
189
|
+
}, TV = ["onClick"], UV = { class: "island-content" }, FV = {
|
|
190
|
+
key: 0,
|
|
191
|
+
class: "island-icon"
|
|
192
|
+
}, GV = { key: 1 }, OV = {
|
|
193
|
+
key: 1,
|
|
194
|
+
class: "island-icon default-icon"
|
|
195
|
+
}, HV = {
|
|
196
|
+
key: 0,
|
|
197
|
+
viewBox: "0 0 24 24",
|
|
198
|
+
fill: "none",
|
|
199
|
+
stroke: "currentColor",
|
|
200
|
+
"stroke-width": "2"
|
|
201
|
+
}, LV = {
|
|
202
|
+
key: 1,
|
|
203
|
+
viewBox: "0 0 24 24",
|
|
204
|
+
fill: "none",
|
|
205
|
+
stroke: "currentColor",
|
|
206
|
+
"stroke-width": "2"
|
|
207
|
+
}, ZV = {
|
|
208
|
+
key: 2,
|
|
209
|
+
viewBox: "0 0 24 24",
|
|
210
|
+
fill: "none",
|
|
211
|
+
stroke: "currentColor",
|
|
212
|
+
"stroke-width": "2"
|
|
213
|
+
}, JV = {
|
|
214
|
+
key: 3,
|
|
215
|
+
viewBox: "0 0 24 24",
|
|
216
|
+
fill: "none",
|
|
217
|
+
stroke: "currentColor",
|
|
218
|
+
"stroke-width": "2"
|
|
219
|
+
}, WV = {
|
|
220
|
+
key: 4,
|
|
221
|
+
viewBox: "0 0 24 24",
|
|
222
|
+
fill: "none",
|
|
223
|
+
stroke: "currentColor",
|
|
224
|
+
"stroke-width": "2"
|
|
225
|
+
}, PV = { class: "island-text" }, KV = { class: "island-title" }, qV = {
|
|
226
|
+
key: 0,
|
|
227
|
+
class: "island-subtitle"
|
|
228
|
+
}, jV = ["onClick"], XV = {
|
|
229
|
+
key: 0,
|
|
230
|
+
class: "island-progress"
|
|
231
|
+
}, zV = {
|
|
232
|
+
key: 1,
|
|
233
|
+
class: "island-dynamic-component"
|
|
234
|
+
}, _V = /* @__PURE__ */ AV({
|
|
235
|
+
__name: "DynamicIsland",
|
|
236
|
+
setup(V) {
|
|
237
|
+
const n = aV(), { visibleIslands: a, position: s, globalSoundEnabled: A } = n, u = w(null), p = w(!1), y = w({ x: 0, y: 0 }), b = H(() => ({
|
|
238
|
+
left: `${s.value.x}px`,
|
|
239
|
+
top: `${s.value.y}px`,
|
|
240
|
+
zIndex: 99999
|
|
241
|
+
})), W = (o) => {
|
|
242
|
+
const e = {};
|
|
243
|
+
return o.backgroundColor && (e.background = o.backgroundColor), o.textColor && (e.color = o.textColor), e;
|
|
244
|
+
}, P = (o) => {
|
|
245
|
+
const e = o.target;
|
|
246
|
+
e.closest(".island-close") || e.closest(".island-dynamic-component") || !e.closest(".island-header") || (p.value = !0, y.value = {
|
|
247
|
+
x: o.clientX - s.value.x,
|
|
248
|
+
y: o.clientY - s.value.y
|
|
249
|
+
}, document.addEventListener("mousemove", Q), document.addEventListener("mouseup", i));
|
|
250
|
+
}, Q = (o) => {
|
|
251
|
+
var x, v;
|
|
252
|
+
if (!p.value) return;
|
|
253
|
+
const e = 12, t = 20, m = ((x = u.value) == null ? void 0 : x.offsetWidth) || 320, B = ((v = u.value) == null ? void 0 : v.offsetHeight) || 80;
|
|
254
|
+
let h = o.clientX - y.value.x, E = o.clientY - y.value.y;
|
|
255
|
+
h = Math.max(
|
|
256
|
+
e,
|
|
257
|
+
Math.min(
|
|
258
|
+
h,
|
|
259
|
+
window.innerWidth - m - e - t
|
|
260
|
+
)
|
|
261
|
+
), E = Math.max(
|
|
262
|
+
e,
|
|
263
|
+
Math.min(E, window.innerHeight - B - e)
|
|
264
|
+
), n.updatePosition({ x: h, y: E }, m, B);
|
|
265
|
+
}, i = () => {
|
|
266
|
+
p.value = !1, document.removeEventListener("mousemove", Q), document.removeEventListener("mouseup", i);
|
|
267
|
+
}, d = (o) => {
|
|
268
|
+
var e;
|
|
269
|
+
p.value || (e = o.onClick) == null || e.call(o);
|
|
270
|
+
}, g = (o) => {
|
|
271
|
+
n.remove(o);
|
|
272
|
+
}, iV = (o, e) => {
|
|
273
|
+
lV("dynamic-island"), $(() => {
|
|
274
|
+
e();
|
|
275
|
+
});
|
|
276
|
+
}, rV = (o, e) => {
|
|
277
|
+
$(() => {
|
|
278
|
+
e();
|
|
279
|
+
});
|
|
280
|
+
}, S = /* @__PURE__ */ new Map(), cV = (o) => {
|
|
281
|
+
if (o.persistent || o.duration <= 0) return;
|
|
282
|
+
K(o.id);
|
|
283
|
+
const e = window.setTimeout(() => {
|
|
284
|
+
n.remove(o.id);
|
|
285
|
+
}, o.duration);
|
|
286
|
+
S.set(o.id, e);
|
|
287
|
+
}, K = (o) => {
|
|
288
|
+
const e = S.get(o);
|
|
289
|
+
e && (clearTimeout(e), S.delete(o));
|
|
290
|
+
};
|
|
291
|
+
uV(() => {
|
|
292
|
+
S.forEach((o) => clearTimeout(o)), S.clear();
|
|
293
|
+
}), j(
|
|
294
|
+
() => a.value.length,
|
|
295
|
+
() => {
|
|
296
|
+
a.value.forEach((o) => {
|
|
297
|
+
!o.persistent && o.duration > 0 && !S.has(o.id) && (cV(o), o.soundEnabled && A.value && NV(o.type, o.soundUrl, !0));
|
|
298
|
+
});
|
|
299
|
+
},
|
|
300
|
+
{ immediate: !0 }
|
|
301
|
+
), j(
|
|
302
|
+
a,
|
|
303
|
+
(o, e) => {
|
|
304
|
+
const t = new Set(o.map((m) => m.id));
|
|
305
|
+
new Set((e || []).map((m) => m.id)), e == null || e.forEach((m) => {
|
|
306
|
+
t.has(m.id) || K(m.id);
|
|
307
|
+
});
|
|
308
|
+
},
|
|
309
|
+
{ deep: !0 }
|
|
310
|
+
);
|
|
311
|
+
function lV(o) {
|
|
312
|
+
const e = document.getElementById(o);
|
|
313
|
+
if (!e)
|
|
314
|
+
return console.warn(`ID为 ${o} 的DOM元素不存在`), null;
|
|
315
|
+
const t = e.getBoundingClientRect(), m = window.innerWidth || document.documentElement.clientWidth, B = window.innerHeight || document.documentElement.clientHeight, h = 12, E = 12, x = h, v = B - h, Y = h, R = m - h - E, q = t.top >= x && t.left >= Y && t.bottom <= v && t.right <= R;
|
|
316
|
+
if (!q) {
|
|
317
|
+
const N = {
|
|
318
|
+
// 垂直方向:贴合顶部安全区 / 贴合底部安全区 / 保持原位
|
|
319
|
+
top: t.top < x ? x : t.bottom > v ? v - t.height : t.top,
|
|
320
|
+
// 水平方向:贴合左侧安全区 / 贴合右侧安全区 / 保持原位
|
|
321
|
+
left: t.left < Y ? Y : t.right > R ? R - t.width : t.left
|
|
322
|
+
};
|
|
323
|
+
console.log("safePosition", N), e.style.position = "fixed", e.style.left = `${N.left}px`, console.log(`✅ 已调整ID为 ${o} 的DOM到视口内`, N);
|
|
324
|
+
}
|
|
325
|
+
return {
|
|
326
|
+
width: e.offsetWidth,
|
|
327
|
+
clientWidth: e.clientWidth,
|
|
328
|
+
position: {
|
|
329
|
+
top: t.top,
|
|
330
|
+
left: t.left,
|
|
331
|
+
right: t.right,
|
|
332
|
+
bottom: t.bottom,
|
|
333
|
+
x: t.x,
|
|
334
|
+
y: t.y
|
|
335
|
+
},
|
|
336
|
+
isInViewport: q,
|
|
337
|
+
// safePosition, // 你需要的:带安全区的目标位置
|
|
338
|
+
domRect: t
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
return (o, e) => (c(), T(dV, { to: "body" }, [
|
|
342
|
+
r("div", {
|
|
343
|
+
id: "dynamic-island",
|
|
344
|
+
ref_key: "containerRef",
|
|
345
|
+
ref: u,
|
|
346
|
+
class: "dynamic-island-container",
|
|
347
|
+
style: U(b.value),
|
|
348
|
+
onMousedown: P
|
|
349
|
+
}, [
|
|
350
|
+
mV(gV, {
|
|
351
|
+
name: "island",
|
|
352
|
+
tag: "div",
|
|
353
|
+
class: "island-list",
|
|
354
|
+
onEnter: iV,
|
|
355
|
+
onLeave: rV
|
|
356
|
+
}, {
|
|
357
|
+
default: fV(() => [
|
|
358
|
+
(c(!0), l(hV, null, wV(pV(a), (t) => (c(), l("div", {
|
|
359
|
+
key: t.id,
|
|
360
|
+
class: X(["dynamic-island", [
|
|
361
|
+
`island-${t.type}`,
|
|
362
|
+
`animation-${t.animation}`
|
|
363
|
+
]]),
|
|
364
|
+
style: U(W(t)),
|
|
365
|
+
onClick: (m) => d(t)
|
|
366
|
+
}, [
|
|
367
|
+
r("div", UV, [
|
|
368
|
+
r("div", {
|
|
369
|
+
class: X(["island-header", { "draggable-area": !0 }])
|
|
370
|
+
}, [
|
|
371
|
+
t.showIcon && t.icon ? (c(), l("div", FV, [
|
|
372
|
+
typeof t.icon != "string" ? (c(), T(z(t.icon), { key: 0 })) : (c(), l("span", GV, F(t.icon), 1))
|
|
373
|
+
])) : t.showIcon ? (c(), l("div", OV, [
|
|
374
|
+
t.type === "success" ? (c(), l("svg", HV, [...e[1] || (e[1] = [
|
|
375
|
+
r("path", { d: "M20 6L9 17l-5-5" }, null, -1)
|
|
376
|
+
])])) : t.type === "error" ? (c(), l("svg", LV, [...e[2] || (e[2] = [
|
|
377
|
+
r("circle", {
|
|
378
|
+
cx: "12",
|
|
379
|
+
cy: "12",
|
|
380
|
+
r: "10"
|
|
381
|
+
}, null, -1),
|
|
382
|
+
r("path", { d: "M15 9l-6 6M9 9l6 6" }, null, -1)
|
|
383
|
+
])])) : t.type === "warning" ? (c(), l("svg", ZV, [...e[3] || (e[3] = [
|
|
384
|
+
r("path", { d: "M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z" }, null, -1),
|
|
385
|
+
r("line", {
|
|
386
|
+
x1: "12",
|
|
387
|
+
y1: "9",
|
|
388
|
+
x2: "12",
|
|
389
|
+
y2: "13"
|
|
390
|
+
}, null, -1),
|
|
391
|
+
r("line", {
|
|
392
|
+
x1: "12",
|
|
393
|
+
y1: "17",
|
|
394
|
+
x2: "12.01",
|
|
395
|
+
y2: "17"
|
|
396
|
+
}, null, -1)
|
|
397
|
+
])])) : t.type === "info" ? (c(), l("svg", JV, [...e[4] || (e[4] = [
|
|
398
|
+
r("circle", {
|
|
399
|
+
cx: "12",
|
|
400
|
+
cy: "12",
|
|
401
|
+
r: "10"
|
|
402
|
+
}, null, -1),
|
|
403
|
+
r("line", {
|
|
404
|
+
x1: "12",
|
|
405
|
+
y1: "16",
|
|
406
|
+
x2: "12",
|
|
407
|
+
y2: "12"
|
|
408
|
+
}, null, -1),
|
|
409
|
+
r("line", {
|
|
410
|
+
x1: "12",
|
|
411
|
+
y1: "8",
|
|
412
|
+
x2: "12.01",
|
|
413
|
+
y2: "8"
|
|
414
|
+
}, null, -1)
|
|
415
|
+
])])) : (c(), l("svg", WV, [...e[5] || (e[5] = [
|
|
416
|
+
r("circle", {
|
|
417
|
+
cx: "12",
|
|
418
|
+
cy: "12",
|
|
419
|
+
r: "10"
|
|
420
|
+
}, null, -1),
|
|
421
|
+
r("line", {
|
|
422
|
+
x1: "12",
|
|
423
|
+
y1: "8",
|
|
424
|
+
x2: "12",
|
|
425
|
+
y2: "12"
|
|
426
|
+
}, null, -1),
|
|
427
|
+
r("line", {
|
|
428
|
+
x1: "12",
|
|
429
|
+
y1: "16",
|
|
430
|
+
x2: "12.01",
|
|
431
|
+
y2: "16"
|
|
432
|
+
}, null, -1)
|
|
433
|
+
])]))
|
|
434
|
+
])) : I("", !0),
|
|
435
|
+
r("div", PV, [
|
|
436
|
+
r("div", KV, F(t.title), 1),
|
|
437
|
+
t.subtitle ? (c(), l("div", qV, F(t.subtitle), 1)) : I("", !0)
|
|
438
|
+
]),
|
|
439
|
+
t.showClose ? (c(), l("button", {
|
|
440
|
+
key: 2,
|
|
441
|
+
class: "island-close",
|
|
442
|
+
onClick: _((m) => g(t.id), ["stop"]),
|
|
443
|
+
onMousedown: e[0] || (e[0] = _(() => {
|
|
444
|
+
}, ["stop"]))
|
|
445
|
+
}, [...e[6] || (e[6] = [
|
|
446
|
+
r("svg", {
|
|
447
|
+
viewBox: "0 0 24 24",
|
|
448
|
+
fill: "none",
|
|
449
|
+
stroke: "currentColor",
|
|
450
|
+
"stroke-width": "2"
|
|
451
|
+
}, [
|
|
452
|
+
r("path", { d: "M18 6L6 18M6 6l12 12" })
|
|
453
|
+
], -1)
|
|
454
|
+
])], 40, jV)) : I("", !0)
|
|
455
|
+
]),
|
|
456
|
+
t.showProgress && t.progress !== void 0 ? (c(), l("div", XV, [
|
|
457
|
+
r("div", {
|
|
458
|
+
class: "progress-bar",
|
|
459
|
+
style: U({ width: `${t.progress}%` })
|
|
460
|
+
}, null, 4)
|
|
461
|
+
])) : I("", !0),
|
|
462
|
+
t.dynamicComponent ? (c(), l("div", zV, [
|
|
463
|
+
(c(), T(z(t.dynamicComponent.component), yV({ ref_for: !0 }, t.dynamicComponent.props), null, 16))
|
|
464
|
+
])) : I("", !0)
|
|
465
|
+
])
|
|
466
|
+
], 14, TV))), 128))
|
|
467
|
+
]),
|
|
468
|
+
_: 1
|
|
469
|
+
})
|
|
470
|
+
], 36)
|
|
471
|
+
]));
|
|
472
|
+
}
|
|
473
|
+
}), $V = (V, n) => {
|
|
474
|
+
const a = V.__vccOpts || V;
|
|
475
|
+
for (const [s, A] of n)
|
|
476
|
+
a[s] = A;
|
|
477
|
+
return a;
|
|
478
|
+
}, Ve = /* @__PURE__ */ $V(_V, [["__scopeId", "data-v-7c261bf3"]]), te = () => {
|
|
479
|
+
const V = aV();
|
|
480
|
+
return {
|
|
481
|
+
show: (i) => V.add(i),
|
|
482
|
+
success: (i, d, g) => V.add({
|
|
483
|
+
type: "success",
|
|
484
|
+
title: i,
|
|
485
|
+
subtitle: d,
|
|
486
|
+
...g
|
|
487
|
+
}),
|
|
488
|
+
error: (i, d, g) => V.add({
|
|
489
|
+
type: "error",
|
|
490
|
+
title: i,
|
|
491
|
+
subtitle: d,
|
|
492
|
+
duration: (g == null ? void 0 : g.duration) ?? 8e3,
|
|
493
|
+
...g
|
|
494
|
+
}),
|
|
495
|
+
warning: (i, d, g) => V.add({
|
|
496
|
+
type: "warning",
|
|
497
|
+
title: i,
|
|
498
|
+
subtitle: d,
|
|
499
|
+
...g
|
|
500
|
+
}),
|
|
501
|
+
info: (i, d, g) => V.add({
|
|
502
|
+
type: "info",
|
|
503
|
+
title: i,
|
|
504
|
+
subtitle: d,
|
|
505
|
+
...g
|
|
506
|
+
}),
|
|
507
|
+
close: (i) => {
|
|
508
|
+
console.log("close", i), V.remove(i);
|
|
509
|
+
},
|
|
510
|
+
clear: () => {
|
|
511
|
+
V.clear();
|
|
512
|
+
},
|
|
513
|
+
clearQueue: () => {
|
|
514
|
+
V.clearQueue();
|
|
515
|
+
},
|
|
516
|
+
updateProgress: (i, d) => {
|
|
517
|
+
V.updateProgress(i, d);
|
|
518
|
+
},
|
|
519
|
+
updateIsland: (i, d) => {
|
|
520
|
+
V.updateIsland(i, d);
|
|
521
|
+
},
|
|
522
|
+
setSoundEnabled: (i) => {
|
|
523
|
+
V.setGlobalSoundEnabled(i);
|
|
524
|
+
}
|
|
525
|
+
};
|
|
526
|
+
}, oe = {
|
|
527
|
+
install(V) {
|
|
528
|
+
V.component("DynamicIsland", Ve);
|
|
529
|
+
}
|
|
530
|
+
};
|
|
531
|
+
export {
|
|
532
|
+
Ve as DynamicIsland,
|
|
533
|
+
oe as default,
|
|
534
|
+
te as useDynamicIsland
|
|
535
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(function(f,e){typeof exports=="object"&&typeof module<"u"?e(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],e):(f=typeof globalThis<"u"?globalThis:f||self,e(f.Vue3DynamicIsland={},f.Vue))})(this,function(f,e){"use strict";var N=typeof document<"u"?document.currentScript:null;const D="dynamic-island-position",b="dynamic-island-mem-position",z=()=>`island-${Date.now()}-${Math.random().toString(36).substr(2,9)}`,v=()=>({x:Math.max(12,Math.min(window.innerWidth/2-150,window.innerWidth-320-12-20)),y:Math.max(12,20)}),$=()=>{try{const V=localStorage.getItem(D);if(V){const a=JSON.parse(V);if(typeof a.x=="number"&&typeof a.y=="number")return{x:Math.max(12,Math.min(a.x,window.innerWidth-320-12-20)),y:Math.max(12,Math.min(a.y,window.innerHeight-80-12))}}}catch{console.warn("Failed to load position from localStorage")}return v()},Q=V=>{try{localStorage.setItem(D,JSON.stringify(V))}catch{console.warn("Failed to save position to localStorage")}},m=e.ref([]),p=e.ref([]),x=e.ref($()),O=e.ref(!0),R=3,L=e.computed(()=>m.value.length<R),H=e.computed(()=>p.value.length>0),Z=()=>{for(;L.value&&H.value;){const V=p.value.shift();V&&m.value.push(V)}},ee=V=>{const a={id:V.id||z(),type:V.type||"default",title:V.title,subtitle:V.subtitle,icon:V.icon,showIcon:V.showIcon??!0,showClose:V.showClose??!0,duration:V.duration??3e3,persistent:V.persistent??!1,animation:V.animation||"slide",progress:V.progress,showProgress:V.showProgress??!1,dynamicComponent:V.dynamicComponent,backgroundColor:V.backgroundColor,textColor:V.textColor,soundEnabled:V.soundEnabled??!0,soundUrl:V.soundUrl,onClick:V.onClick,onClose:V.onClose,createdAt:Date.now(),memPosition:V.memPosition??!1};return m.value.length<R?(m.value.push(a),a.memPosition&&J()):p.value.push(a),a.id},Ve=V=>{var r;const a=m.value.findIndex(s=>s.id===V);if(a>-1){const s=m.value[a];(r=s.onClose)==null||r.call(s),m.value.splice(a,1),s.memPosition&&ae(),Z()}},te=()=>{m.value.forEach(V=>{var a;(a=V.onClose)==null||a.call(V)}),m.value=[],p.value=[]},oe=()=>{p.value=[]},ne=(V,a,r)=>{const y=a||320,B=r||80;x.value={x:Math.max(12,Math.min(V.x,window.innerWidth-y-12-0)),y:Math.max(12,Math.min(V.y,window.innerHeight-B-12))},Q(x.value)},J=()=>{try{const V=localStorage.getItem(D);V&&localStorage.setItem(b,V)}catch{console.warn("Failed to save mem_position to localStorage")}Q(x.value)},ae=()=>{try{const V=localStorage.getItem(b);if(V){const a=JSON.parse(V);typeof a.x=="number"&&typeof a.y=="number"&&(Q(a),x.value=a)}localStorage.removeItem(b)}catch{console.warn("Failed to restore mem_position from localStorage")}},se=V=>{O.value=V},re=(V,a)=>{const r=m.value.find(s=>s.id===V);r&&(r.progress=Math.max(0,Math.min(100,a)))},ce=(V,a)=>{const r=m.value.find(s=>s.id===V);r&&Object.assign(r,a)},P=()=>({visibleIslands:m,queue:p,position:x,globalSoundEnabled:O,maxVisible:R,hasVisibleSlots:L,hasQueuedItems:H,add:ee,remove:Ve,clear:te,clearQueue:oe,updatePosition:ne,saveMemPosition:J,setGlobalSoundEnabled:se,updateProgress:re,updateIsland:ce,processQueue:Z}),C=new URL("data:audio/mpeg;base64,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knmSNGpnU/dT0H2qRZFHRWjpIqVTUk/UbPl0EAACA12sDZ4GHg2IgAVRmYZEBhYWmRVgY7ap03CGwg2WrWCcF/H5n3FO1kDVK9kZtyT2bldZDVm0ODaF48HWc6hUxnd95g7gvavsYtnFq+26brG+Mf/cHe7YrnWYOIW95pbE+Mbe/OrXti319W3rfrNbNLa+PSNcmNh8O7VMQU1FMy4xMDEgKGJldGEgMilVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVX/+5JkuQzzzkXQB3JAAgAADSDgAAEPlQswdceACAAANIKAAARVVVVVAAAADIgCAggAOfxoBIemFg8mQQ31cDAJOTXESjHwpTBAPa+JioCipTDQC1KueBgggGkFF0Y7AxAoDOgQASAhYV0NW8NXBcGDY2GqwyKQIgxFvBuwToNgUmThSGWFbENFy/NBW4hcg4pQighUmj6JSHO/JY8Tg7BQYuccYuYmSKkBSWXf47DBBRACYHeRckjIiw5xRJ0u0S7/yCJE0XCGFAg5FzcqLKRFiBGJdLqy6TJkRb/7kwRQnCDl83PGZuRQihOE+bkWMUVrLpFTIvE0iySJd//6aJfNyKEUNCfTrL5uRQnDQ3/+RUyLxeqSMS6RUyLxlSLxiXSZTEFNRTMuMTAxIChiZXRhIDIpVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//uSZL0AB8h9yN52gAAAAA0gwAAAAAABpBwAACAAADSDgAAEVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVQ==",typeof document>"u"&&typeof location>"u"?require("url").pathToFileURL(__filename).href:typeof document>"u"?location.href:N&&N.tagName.toUpperCase()==="SCRIPT"&&N.src||new URL("index.umd.cjs",document.baseURI).href).href,le={default:C,success:C,error:C,warning:C,info:C};let Y=null;const ie=()=>(Y||(Y=new(window.AudioContext||window.webkitAudioContext)),Y),h=(V,a,r="sine")=>{try{const s=ie(),l=s.createOscillator(),i=s.createGain();l.connect(i),i.connect(s.destination),l.frequency.value=V,l.type=r,i.gain.setValueAtTime(.3,s.currentTime),i.gain.exponentialRampToValueAtTime(.01,s.currentTime+a),l.start(s.currentTime),l.stop(s.currentTime+a)}catch(s){console.warn("Failed to play sound:",s)}},W=V=>{switch(V){case"success":h(880,.15),setTimeout(()=>h(1100,.2),100);break;case"error":h(200,.3,"sawtooth");break;case"warning":h(600,.2),setTimeout(()=>h(500,.2),150);break;case"info":h(700,.15);break}},de=(V,a,r=!0)=>{if(!r)return;const s=a||le[V];s?new Audio(s).play().catch(i=>{console.warn("Failed to play sound:",i),W(V)}):W(V)},Ae=["onClick"],me={class:"island-content"},ue={key:0,class:"island-icon"},fe={key:1},ge={key:1,class:"island-icon default-icon"},pe={key:0,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2"},he={key:1,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2"},we={key:2,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2"},ye={key:3,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2"},Ee={key:4,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2"},Se={class:"island-text"},ke={class:"island-title"},xe={key:0,class:"island-subtitle"},Ce=["onClick"],Me={key:0,class:"island-progress"},Be={key:1,class:"island-dynamic-component"},K=((V,a)=>{const r=V.__vccOpts||V;for(const[s,l]of a)r[s]=l;return r})(e.defineComponent({__name:"DynamicIsland",setup(V){const a=P(),{visibleIslands:r,position:s,globalSoundEnabled:l}=a,i=e.ref(null),w=e.ref(!1),y=e.ref({x:0,y:0}),B=e.computed(()=>({left:`${s.value.x}px`,top:`${s.value.y}px`,zIndex:99999})),q=n=>{const t={};return n.backgroundColor&&(t.background=n.backgroundColor),n.textColor&&(t.color=n.textColor),t},j=n=>{const t=n.target;t.closest(".island-close")||t.closest(".island-dynamic-component")||!t.closest(".island-header")||(w.value=!0,y.value={x:n.clientX-s.value.x,y:n.clientY-s.value.y},document.addEventListener("mousemove",T),document.addEventListener("mouseup",c))},T=n=>{var S,k;if(!w.value)return;const t=12,o=20,A=((S=i.value)==null?void 0:S.offsetWidth)||320,I=((k=i.value)==null?void 0:k.offsetHeight)||80;let g=n.clientX-y.value.x,M=n.clientY-y.value.y;g=Math.max(t,Math.min(g,window.innerWidth-A-t-o)),M=Math.max(t,Math.min(M,window.innerHeight-I-t)),a.updatePosition({x:g,y:M},A,I)},c=()=>{w.value=!1,document.removeEventListener("mousemove",T),document.removeEventListener("mouseup",c)},d=n=>{var t;w.value||(t=n.onClick)==null||t.call(n)},u=n=>{a.remove(n)},De=(n,t)=>{Re("dynamic-island"),e.nextTick(()=>{t()})},be=(n,t)=>{e.nextTick(()=>{t()})},E=new Map,Qe=n=>{if(n.persistent||n.duration<=0)return;X(n.id);const t=window.setTimeout(()=>{a.remove(n.id)},n.duration);E.set(n.id,t)},X=n=>{const t=E.get(n);t&&(clearTimeout(t),E.delete(n))};e.onUnmounted(()=>{E.forEach(n=>clearTimeout(n)),E.clear()}),e.watch(()=>r.value.length,()=>{r.value.forEach(n=>{!n.persistent&&n.duration>0&&!E.has(n.id)&&(Qe(n),n.soundEnabled&&l.value&&de(n.type,n.soundUrl,!0))})},{immediate:!0}),e.watch(r,(n,t)=>{const o=new Set(n.map(A=>A.id));new Set((t||[]).map(A=>A.id)),t==null||t.forEach(A=>{o.has(A.id)||X(A.id)})},{deep:!0});function Re(n){const t=document.getElementById(n);if(!t)return console.warn(`ID为 ${n} 的DOM元素不存在`),null;const o=t.getBoundingClientRect(),A=window.innerWidth||document.documentElement.clientWidth,I=window.innerHeight||document.documentElement.clientHeight,g=12,M=12,S=g,k=I-g,U=g,F=A-g-M,_=o.top>=S&&o.left>=U&&o.bottom<=k&&o.right<=F;if(!_){const G={top:o.top<S?S:o.bottom>k?k-o.height:o.top,left:o.left<U?U:o.right>F?F-o.width:o.left};console.log("safePosition",G),t.style.position="fixed",t.style.left=`${G.left}px`,console.log(`✅ 已调整ID为 ${n} 的DOM到视口内`,G)}return{width:t.offsetWidth,clientWidth:t.clientWidth,position:{top:o.top,left:o.left,right:o.right,bottom:o.bottom,x:o.x,y:o.y},isInViewport:_,domRect:o}}return(n,t)=>(e.openBlock(),e.createBlock(e.Teleport,{to:"body"},[e.createElementVNode("div",{id:"dynamic-island",ref_key:"containerRef",ref:i,class:"dynamic-island-container",style:e.normalizeStyle(B.value),onMousedown:j},[e.createVNode(e.TransitionGroup,{name:"island",tag:"div",class:"island-list",onEnter:De,onLeave:be},{default:e.withCtx(()=>[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(e.unref(r),o=>(e.openBlock(),e.createElementBlock("div",{key:o.id,class:e.normalizeClass(["dynamic-island",[`island-${o.type}`,`animation-${o.animation}`]]),style:e.normalizeStyle(q(o)),onClick:A=>d(o)},[e.createElementVNode("div",me,[e.createElementVNode("div",{class:e.normalizeClass(["island-header",{"draggable-area":!0}])},[o.showIcon&&o.icon?(e.openBlock(),e.createElementBlock("div",ue,[typeof o.icon!="string"?(e.openBlock(),e.createBlock(e.resolveDynamicComponent(o.icon),{key:0})):(e.openBlock(),e.createElementBlock("span",fe,e.toDisplayString(o.icon),1))])):o.showIcon?(e.openBlock(),e.createElementBlock("div",ge,[o.type==="success"?(e.openBlock(),e.createElementBlock("svg",pe,[...t[1]||(t[1]=[e.createElementVNode("path",{d:"M20 6L9 17l-5-5"},null,-1)])])):o.type==="error"?(e.openBlock(),e.createElementBlock("svg",he,[...t[2]||(t[2]=[e.createElementVNode("circle",{cx:"12",cy:"12",r:"10"},null,-1),e.createElementVNode("path",{d:"M15 9l-6 6M9 9l6 6"},null,-1)])])):o.type==="warning"?(e.openBlock(),e.createElementBlock("svg",we,[...t[3]||(t[3]=[e.createElementVNode("path",{d:"M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z"},null,-1),e.createElementVNode("line",{x1:"12",y1:"9",x2:"12",y2:"13"},null,-1),e.createElementVNode("line",{x1:"12",y1:"17",x2:"12.01",y2:"17"},null,-1)])])):o.type==="info"?(e.openBlock(),e.createElementBlock("svg",ye,[...t[4]||(t[4]=[e.createElementVNode("circle",{cx:"12",cy:"12",r:"10"},null,-1),e.createElementVNode("line",{x1:"12",y1:"16",x2:"12",y2:"12"},null,-1),e.createElementVNode("line",{x1:"12",y1:"8",x2:"12.01",y2:"8"},null,-1)])])):(e.openBlock(),e.createElementBlock("svg",Ee,[...t[5]||(t[5]=[e.createElementVNode("circle",{cx:"12",cy:"12",r:"10"},null,-1),e.createElementVNode("line",{x1:"12",y1:"8",x2:"12",y2:"12"},null,-1),e.createElementVNode("line",{x1:"12",y1:"16",x2:"12.01",y2:"16"},null,-1)])]))])):e.createCommentVNode("",!0),e.createElementVNode("div",Se,[e.createElementVNode("div",ke,e.toDisplayString(o.title),1),o.subtitle?(e.openBlock(),e.createElementBlock("div",xe,e.toDisplayString(o.subtitle),1)):e.createCommentVNode("",!0)]),o.showClose?(e.openBlock(),e.createElementBlock("button",{key:2,class:"island-close",onClick:e.withModifiers(A=>u(o.id),["stop"]),onMousedown:t[0]||(t[0]=e.withModifiers(()=>{},["stop"]))},[...t[6]||(t[6]=[e.createElementVNode("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2"},[e.createElementVNode("path",{d:"M18 6L6 18M6 6l12 12"})],-1)])],40,Ce)):e.createCommentVNode("",!0)]),o.showProgress&&o.progress!==void 0?(e.openBlock(),e.createElementBlock("div",Me,[e.createElementVNode("div",{class:"progress-bar",style:e.normalizeStyle({width:`${o.progress}%`})},null,4)])):e.createCommentVNode("",!0),o.dynamicComponent?(e.openBlock(),e.createElementBlock("div",Be,[(e.openBlock(),e.createBlock(e.resolveDynamicComponent(o.dynamicComponent.component),e.mergeProps({ref_for:!0},o.dynamicComponent.props),null,16))])):e.createCommentVNode("",!0)])],14,Ae))),128))]),_:1})],36)]))}}),[["__scopeId","data-v-7c261bf3"]]),Ie=()=>{const V=P();return{show:c=>V.add(c),success:(c,d,u)=>V.add({type:"success",title:c,subtitle:d,...u}),error:(c,d,u)=>V.add({type:"error",title:c,subtitle:d,duration:(u==null?void 0:u.duration)??8e3,...u}),warning:(c,d,u)=>V.add({type:"warning",title:c,subtitle:d,...u}),info:(c,d,u)=>V.add({type:"info",title:c,subtitle:d,...u}),close:c=>{console.log("close",c),V.remove(c)},clear:()=>{V.clear()},clearQueue:()=>{V.clearQueue()},updateProgress:(c,d)=>{V.updateProgress(c,d)},updateIsland:(c,d)=>{V.updateIsland(c,d)},setSoundEnabled:c=>{V.setGlobalSoundEnabled(c)}}},Ne={install(V){V.component("DynamicIsland",K)}};f.DynamicIsland=K,f.default=Ne,f.useDynamicIsland=Ie,Object.defineProperties(f,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
|
package/dist/style.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.dynamic-island-container[data-v-7c261bf3]{position:fixed;pointer-events:auto}.island-list[data-v-7c261bf3]{display:flex;flex-direction:column;gap:8px}.dynamic-island[data-v-7c261bf3]{min-width:240px;max-width:320px;background:#000000d9;backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px);border-radius:10px;padding:10px 14px;box-shadow:0 6px 24px #00000059,0 0 0 1px #ffffff1a;color:#fff;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;transition:all .3s cubic-bezier(.4,0,.2,1);pointer-events:auto}.island-success[data-v-7c261bf3]{background:#22c55ee6}.island-error[data-v-7c261bf3]{background:#ef4444e6}.island-warning[data-v-7c261bf3]{background:#f59e0be6}.island-info[data-v-7c261bf3]{background:#3b82f6e6}.island-content[data-v-7c261bf3]{display:flex;flex-direction:column;gap:8px}.island-header[data-v-7c261bf3]{display:flex;align-items:center;gap:10px;cursor:grab}.island-header[data-v-7c261bf3]:active{cursor:grabbing}.island-icon[data-v-7c261bf3]{width:20px;height:20px;flex-shrink:0;display:flex;align-items:center;justify-content:center}.island-icon svg[data-v-7c261bf3]{width:100%;height:100%}.default-icon[data-v-7c261bf3]{background:#fff3;border-radius:50%;padding:3px}.island-text[data-v-7c261bf3]{flex:1;min-width:0}.island-title[data-v-7c261bf3]{font-size:13px;font-weight:600;line-height:1.4;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.island-subtitle[data-v-7c261bf3]{font-size:11px;opacity:.85;margin-top:1px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.island-close[data-v-7c261bf3]{width:22px;height:22px;border:none;background:#ffffff26;border-radius:50%;cursor:pointer;display:flex;align-items:center;justify-content:center;color:#fff;transition:all .2s ease;flex-shrink:0}.island-close[data-v-7c261bf3]:hover{background:#ffffff40;transform:scale(1.1)}.island-close svg[data-v-7c261bf3]{width:12px;height:12px}.island-progress[data-v-7c261bf3]{height:2px;background:#fff3;border-radius:2px;overflow:hidden}.progress-bar[data-v-7c261bf3]{height:100%;background:#fff;border-radius:2px;transition:width .3s ease}.island-dynamic-component[data-v-7c261bf3]{max-height:500px;overflow-y:auto}.island-dynamic-component[data-v-7c261bf3]::-webkit-scrollbar{width:6px;height:6px}.island-dynamic-component[data-v-7c261bf3]::-webkit-scrollbar-track{background:#ffffff1a;border-radius:5px}.island-dynamic-component[data-v-7c261bf3]::-webkit-scrollbar-thumb{background:#ffffff4d;border-radius:5px}.island-enter-active[data-v-7c261bf3],.island-leave-active[data-v-7c261bf3]{transition:all .4s cubic-bezier(.4,0,.2,1)}.island-enter-from[data-v-7c261bf3]{opacity:0;transform:translateY(-20px) scale(.9)}.island-leave-to[data-v-7c261bf3]{opacity:0;transform:translateY(-10px) scale(.95)}.animation-fade.island-enter-from[data-v-7c261bf3]{opacity:0}.animation-slide.island-enter-from[data-v-7c261bf3]{opacity:0;transform:translate(100px)}.animation-zoom.island-enter-from[data-v-7c261bf3]{opacity:0;transform:scale(.5)}.animation-bounce.island-enter-from[data-v-7c261bf3]{opacity:0;transform:translateY(-50px)}.animation-bounce.island-enter-active[data-v-7c261bf3]{animation:bounceIn-7c261bf3 .5s cubic-bezier(.68,-.55,.265,1.55)}@keyframes bounceIn-7c261bf3{0%{opacity:0;transform:translateY(-50px) scale(.3)}50%{transform:translateY(10px) scale(1.05)}70%{transform:translateY(-5px) scale(.95)}to{opacity:1;transform:translateY(0) scale(1)}}@media (max-width: 480px){.dynamic-island[data-v-7c261bf3]{min-width:calc(100vw - 24px);max-width:calc(100vw - 24px)}}
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "vue3-dynamic-island",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "A commercial-grade Dynamic Island notification component for Vue 3",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts"
|
|
13
|
+
},
|
|
14
|
+
"./style.css": "./dist/index.css"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist"
|
|
18
|
+
],
|
|
19
|
+
"keywords": [
|
|
20
|
+
"vue",
|
|
21
|
+
"vue3",
|
|
22
|
+
"notification",
|
|
23
|
+
"dynamic-island",
|
|
24
|
+
"toast",
|
|
25
|
+
"alert",
|
|
26
|
+
"component",
|
|
27
|
+
"typescript"
|
|
28
|
+
],
|
|
29
|
+
"author": "piapia_",
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "https://gitee.com/tender_only/dynamic-island"
|
|
34
|
+
},
|
|
35
|
+
"bugs": {
|
|
36
|
+
"url": "https://gitee.com/tender_only/dynamic-island/issues"
|
|
37
|
+
},
|
|
38
|
+
"homepage": "https://gitee.com/tender_only/dynamic-island",
|
|
39
|
+
"scripts": {
|
|
40
|
+
"dev": "vite",
|
|
41
|
+
"build": "vite build",
|
|
42
|
+
"preview": "vite preview",
|
|
43
|
+
"prepublishOnly": "npm run build"
|
|
44
|
+
},
|
|
45
|
+
"peerDependencies": {
|
|
46
|
+
"vue": "^3.0.0"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@vitejs/plugin-vue": "^5.0.3",
|
|
50
|
+
"typescript": "^5.3.3",
|
|
51
|
+
"vite": "^5.0.12"
|
|
52
|
+
}
|
|
53
|
+
}
|