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.
@@ -0,0 +1,170 @@
1
+ <template>
2
+ <div class="Lztext-wrapper">
3
+ <div class="loader-wrapper">
4
+ <span class="loader-letter">G</span>
5
+ <span class="loader-letter">e</span>
6
+ <span class="loader-letter">n</span>
7
+ <span class="loader-letter">e</span>
8
+ <span class="loader-letter">r</span>
9
+ <span class="loader-letter">a</span>
10
+ <span class="loader-letter">t</span>
11
+ <span class="loader-letter">i</span>
12
+ <span class="loader-letter">n</span>
13
+ <span class="loader-letter">g</span>
14
+ <div class="loader"></div>
15
+ </div>
16
+ </div>
17
+ </template>
18
+
19
+ <script setup>
20
+ /**
21
+ * 渐变文字动画
22
+ *
23
+ * 由 LittleDizzy Demo 自动生成
24
+ * @component Lztext
25
+ */
26
+ defineOptions({
27
+ name: 'Lztext'
28
+ })
29
+
30
+ </script>
31
+
32
+ <style scoped>
33
+ .loader-wrapper {
34
+ position: relative;
35
+ display: flex;
36
+ align-items: center;
37
+ justify-content: center;
38
+ height: 120px;
39
+ width: auto;
40
+ margin: 2rem;
41
+
42
+ font-family: "Poppins", sans-serif;
43
+ font-size: 1.6em;
44
+ font-weight: 600;
45
+ user-select: none;
46
+ color: #fff;
47
+
48
+ scale: 2;
49
+ }
50
+
51
+ .loader {
52
+ position: absolute;
53
+ top: 0;
54
+ left: 0;
55
+ height: 100%;
56
+ width: 100%;
57
+ z-index: 1;
58
+
59
+ background-color: transparent;
60
+ mask: repeating-linear-gradient(
61
+ 90deg,
62
+ transparent 0,
63
+ transparent 6px,
64
+ black 7px,
65
+ black 8px
66
+ );
67
+ }
68
+
69
+ .loader::after {
70
+ content: "";
71
+ position: absolute;
72
+ top: 0;
73
+ left: 0;
74
+ width: 100%;
75
+ height: 100%;
76
+
77
+ background-image: radial-gradient(circle at 50% 50%, #ff0 0%, transparent 50%),
78
+ radial-gradient(circle at 45% 45%, #f00 0%, transparent 45%),
79
+ radial-gradient(circle at 55% 55%, #0ff 0%, transparent 45%),
80
+ radial-gradient(circle at 45% 55%, #0f0 0%, transparent 45%),
81
+ radial-gradient(circle at 55% 45%, #00f 0%, transparent 45%);
82
+ mask: radial-gradient(
83
+ circle at 50% 50%,
84
+ transparent 0%,
85
+ transparent 10%,
86
+ black 25%
87
+ );
88
+ animation:
89
+ transform-animation 2s infinite alternate,
90
+ opacity-animation 4s infinite;
91
+ animation-timing-function: cubic-bezier(0.6, 0.8, 0.5, 1);
92
+ }
93
+
94
+ @keyframes transform-animation {
95
+ 0% {
96
+ transform: translate(-55%);
97
+ }
98
+ 100% {
99
+ transform: translate(55%);
100
+ }
101
+ }
102
+
103
+ @keyframes opacity-animation {
104
+ 0%,
105
+ 100% {
106
+ opacity: 0;
107
+ }
108
+ 15% {
109
+ opacity: 1;
110
+ }
111
+ 65% {
112
+ opacity: 0;
113
+ }
114
+ }
115
+
116
+ .loader-letter {
117
+ display: inline-block;
118
+ opacity: 0;
119
+ animation: loader-letter-anim 4s infinite linear;
120
+ z-index: 2;
121
+ }
122
+
123
+ .loader-letter:nth-child(1) {
124
+ animation-delay: 0.1s;
125
+ }
126
+ .loader-letter:nth-child(2) {
127
+ animation-delay: 0.205s;
128
+ }
129
+ .loader-letter:nth-child(3) {
130
+ animation-delay: 0.31s;
131
+ }
132
+ .loader-letter:nth-child(4) {
133
+ animation-delay: 0.415s;
134
+ }
135
+ .loader-letter:nth-child(5) {
136
+ animation-delay: 0.521s;
137
+ }
138
+ .loader-letter:nth-child(6) {
139
+ animation-delay: 0.626s;
140
+ }
141
+ .loader-letter:nth-child(7) {
142
+ animation-delay: 0.731s;
143
+ }
144
+ .loader-letter:nth-child(8) {
145
+ animation-delay: 0.837s;
146
+ }
147
+ .loader-letter:nth-child(9) {
148
+ animation-delay: 0.942s;
149
+ }
150
+ .loader-letter:nth-child(10) {
151
+ animation-delay: 1.047s;
152
+ }
153
+
154
+ @keyframes loader-letter-anim {
155
+ 0% {
156
+ opacity: 0;
157
+ }
158
+ 5% {
159
+ opacity: 1;
160
+ text-shadow: 0 0 4px #fff;
161
+ transform: scale(1.1) translateY(-2px);
162
+ }
163
+ 20% {
164
+ opacity: 0.2;
165
+ }
166
+ 100% {
167
+ opacity: 0;
168
+ }
169
+ }
170
+ </style>
@@ -6,15 +6,17 @@
6
6
  */
7
7
 
8
8
  import Lzbutton from './lzbutton.vue'
9
+ import Lztext from './Lztext.vue'
9
10
  import Lztheme from './lztheme.vue'
10
11
 
11
12
  // 自定义组件导出
12
13
  export const customComponents = {
13
14
  Lzbutton,
15
+ Lztext,
14
16
  Lztheme
15
17
  }
16
18
 
17
19
  // 单独导出每个组件
18
- export { Lzbutton, Lztheme }
20
+ export { Lzbutton, Lztext, Lztheme }
19
21
 
20
22
  export default customComponents
@@ -1,10 +1,10 @@
1
1
  <template>
2
2
  <div class="lzbutton-wrapper">
3
3
  <button class="button">
4
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 24">
5
- <path d="m18 0 8 12 10-8-4 20H4L0 4l10 8 8-12z"></path>
6
- </svg>
7
- Unlock Pro
4
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 24">
5
+ <path d="m18 0 8 12 10-8-4 20H4L0 4l10 8 8-12z"></path>
6
+ </svg>
7
+ <slot>Unlock Pro</slot>
8
8
  </button>
9
9
  </div>
10
10
  </template>
@@ -36,7 +36,7 @@ defineOptions({
36
36
  color: #fff;
37
37
  border: none;
38
38
  background-position: left center;
39
- box-shadow: 0 30px 10px -20px rgba(0,0,0,.2);
39
+ box-shadow: 0 30px 10px -20px rgba(0, 0, 0, .2);
40
40
  transition: background .3s ease;
41
41
  }
42
42
 
@@ -1,26 +1,28 @@
1
1
  <template>
2
2
  <div class="lztheme-wrapper">
3
- <label for="theme" class="theme">
4
- <span class="theme__toggle-wrap">
5
- <input id="theme" class="theme__toggle" type="checkbox" role="switch" name="theme" value="dark">
6
- <span class="theme__fill"></span>
7
- <span class="theme__icon">
8
- <span class="theme__icon-part"></span>
9
- <span class="theme__icon-part"></span>
10
- <span class="theme__icon-part"></span>
11
- <span class="theme__icon-part"></span>
12
- <span class="theme__icon-part"></span>
13
- <span class="theme__icon-part"></span>
14
- <span class="theme__icon-part"></span>
15
- <span class="theme__icon-part"></span>
16
- <span class="theme__icon-part"></span>
17
- </span>
18
- </span>
3
+ <label :for="inputId" class="theme">
4
+ <span class="theme__toggle-wrap">
5
+ <input :id="inputId" ref="toggleRef" class="theme__toggle" type="checkbox" role="switch" name="theme"
6
+ value="dark" :checked="isDark" @change="handleChange">
7
+ <span class="theme__icon">
8
+ <span class="theme__icon-part"></span>
9
+ <span class="theme__icon-part"></span>
10
+ <span class="theme__icon-part"></span>
11
+ <span class="theme__icon-part"></span>
12
+ <span class="theme__icon-part"></span>
13
+ <span class="theme__icon-part"></span>
14
+ <span class="theme__icon-part"></span>
15
+ <span class="theme__icon-part"></span>
16
+ <span class="theme__icon-part"></span>
17
+ </span>
18
+ </span>
19
19
  </label>
20
20
  </div>
21
21
  </template>
22
22
 
23
23
  <script setup>
24
+ import { ref, watch } from 'vue'
25
+
24
26
  /**
25
27
  * 主题切换
26
28
  *
@@ -30,6 +32,53 @@
30
32
  defineOptions({
31
33
  name: 'Lztheme'
32
34
  })
35
+
36
+ // 生成唯一 ID,避免多个实例冲突
37
+ let idCounter = 0
38
+ const inputId = `lztheme-toggle-${++idCounter}-${Date.now()}`
39
+
40
+ // Props
41
+ const props = defineProps({
42
+ // 是否为暗色主题
43
+ modelValue: {
44
+ type: Boolean,
45
+ default: false
46
+ }
47
+ })
48
+
49
+ // Emits
50
+ const emit = defineEmits(['update:modelValue', 'change'])
51
+
52
+ // 内部状态
53
+ const toggleRef = ref(null)
54
+ const isDark = ref(props.modelValue)
55
+
56
+ // 监听 prop 变化,同步到内部状态
57
+ watch(() => props.modelValue, (newVal) => {
58
+ isDark.value = newVal
59
+ })
60
+
61
+ // 处理切换
62
+ const handleChange = (event) => {
63
+ const checked = event.target.checked
64
+ isDark.value = checked
65
+ emit('update:modelValue', checked)
66
+ emit('change', checked)
67
+ }
68
+
69
+ // 暴露方法给父组件
70
+ defineExpose({
71
+ toggle: () => {
72
+ if (toggleRef.value) {
73
+ toggleRef.value.click()
74
+ }
75
+ },
76
+ setDark: (value) => {
77
+ isDark.value = value
78
+ emit('update:modelValue', value)
79
+ emit('change', value)
80
+ }
81
+ })
33
82
  </script>
34
83
 
35
84
  <style scoped>
@@ -40,23 +89,13 @@ defineOptions({
40
89
  -webkit-tap-highlight-color: transparent;
41
90
  }
42
91
 
43
- .theme__fill,
44
92
  .theme__icon {
45
93
  transition: 0.3s;
46
94
  }
47
95
 
48
- .theme__fill {
49
- background-color: var(--bg);
50
- display: block;
51
- mix-blend-mode: difference;
52
- position: fixed;
53
- inset: 0;
54
- height: 100%;
55
- transform: translateX(-100%);
56
- }
57
-
58
96
  .theme__icon,
59
97
  .theme__toggle {
98
+ cursor: pointer;
60
99
  z-index: 1;
61
100
  }
62
101
 
@@ -67,27 +106,28 @@ defineOptions({
67
106
 
68
107
  .theme__icon {
69
108
  display: block;
70
- top: 0.5em;
71
- left: 0.5em;
109
+ top: 50%;
110
+ left: 0.7em;
111
+ transform: translateY(-50%);
72
112
  width: 1.5em;
73
113
  height: 1.5em;
74
114
  }
75
115
 
76
116
  .theme__icon-part {
77
117
  border-radius: 50%;
78
- box-shadow: 0.4em -0.4em 0 0.5em hsl(0,0%,100%) inset;
118
+ box-shadow: 0.4em -0.4em 0 0.5em hsl(0, 0%, 100%) inset;
79
119
  top: calc(50% - 0.5em);
80
120
  left: calc(50% - 0.5em);
81
121
  width: 1em;
82
122
  height: 1em;
83
123
  transition: box-shadow var(--transDur) ease-in-out,
84
- opacity var(--transDur) ease-in-out,
85
- transform var(--transDur) ease-in-out;
124
+ opacity var(--transDur) ease-in-out,
125
+ transform var(--transDur) ease-in-out;
86
126
  transform: scale(0.5);
87
127
  }
88
128
 
89
- .theme__icon-part ~ .theme__icon-part {
90
- background-color: hsl(0,0%,100%);
129
+ .theme__icon-part~.theme__icon-part {
130
+ background-color: hsl(0, 0%, 100%);
91
131
  border-radius: 0.05em;
92
132
  top: 50%;
93
133
  left: calc(50% - 0.05em);
@@ -137,7 +177,7 @@ defineOptions({
137
177
  }
138
178
 
139
179
  .theme__toggle {
140
- background-color: hsl(48,90%,85%);
180
+ background-color: hsl(48, 90%, 85%);
141
181
  border-radius: 25% / 50%;
142
182
  box-shadow: 0 0 0 0.125em var(--primaryT);
143
183
  padding: 0.25em;
@@ -146,12 +186,12 @@ defineOptions({
146
186
  -webkit-appearance: none;
147
187
  appearance: none;
148
188
  transition: background-color var(--transDur) ease-in-out,
149
- box-shadow 0.15s ease-in-out,
150
- transform var(--transDur) ease-in-out;
189
+ box-shadow 0.15s ease-in-out,
190
+ transform var(--transDur) ease-in-out;
151
191
  }
152
192
 
153
193
  .theme__toggle:before {
154
- background-color: hsl(48,90%,55%);
194
+ background-color: hsl(48, 90%, 55%);
155
195
  border-radius: 50%;
156
196
  content: "";
157
197
  width: 2.5em;
@@ -166,62 +206,61 @@ defineOptions({
166
206
 
167
207
  /* Checked */
168
208
  .theme__toggle:checked {
169
- background-color: hsl(198,90%,15%);
209
+ background-color: hsl(198, 90%, 15%);
170
210
  }
171
211
 
172
- .theme__toggle:checked:before,
173
- .theme__toggle:checked ~ .theme__icon {
212
+ .theme__toggle:checked:before {
174
213
  transform: translateX(3em);
175
214
  }
176
215
 
177
- .theme__toggle:checked:before {
178
- background-color: hsl(198,90%,55%);
216
+ .theme__toggle:checked~.theme__icon {
217
+ transform: translateX(3em) translateY(-50%);
179
218
  }
180
219
 
181
- .theme__toggle:checked ~ .theme__fill {
182
- transform: translateX(0);
220
+ .theme__toggle:checked:before {
221
+ background-color: hsl(198, 90%, 55%);
183
222
  }
184
223
 
185
- .theme__toggle:checked ~ .theme__icon .theme__icon-part:nth-child(1) {
186
- box-shadow: 0.2em -0.2em 0 0.2em hsl(0,0%,100%) inset;
224
+ .theme__toggle:checked~.theme__icon .theme__icon-part:nth-child(1) {
225
+ box-shadow: 0.2em -0.2em 0 0.2em hsl(0, 0%, 100%) inset;
187
226
  transform: scale(1);
188
- top: 0.2em;
189
- left: -0.2em;
227
+ top: calc(50% - 0.5em);
228
+ left: calc(50% - 0.5em);
190
229
  }
191
230
 
192
- .theme__toggle:checked ~ .theme__icon .theme__icon-part ~ .theme__icon-part {
231
+ .theme__toggle:checked~.theme__icon .theme__icon-part~.theme__icon-part {
193
232
  opacity: 0;
194
233
  }
195
234
 
196
- .theme__toggle:checked ~ .theme__icon .theme__icon-part:nth-child(2) {
235
+ .theme__toggle:checked~.theme__icon .theme__icon-part:nth-child(2) {
197
236
  transform: rotate(45deg) translateY(0.8em);
198
237
  }
199
238
 
200
- .theme__toggle:checked ~ .theme__icon .theme__icon-part:nth-child(3) {
239
+ .theme__toggle:checked~.theme__icon .theme__icon-part:nth-child(3) {
201
240
  transform: rotate(90deg) translateY(0.8em);
202
241
  }
203
242
 
204
- .theme__toggle:checked ~ .theme__icon .theme__icon-part:nth-child(4) {
243
+ .theme__toggle:checked~.theme__icon .theme__icon-part:nth-child(4) {
205
244
  transform: rotate(135deg) translateY(0.8em);
206
245
  }
207
246
 
208
- .theme__toggle:checked ~ .theme__icon .theme__icon-part:nth-child(5) {
247
+ .theme__toggle:checked~.theme__icon .theme__icon-part:nth-child(5) {
209
248
  transform: rotate(180deg) translateY(0.8em);
210
249
  }
211
250
 
212
- .theme__toggle:checked ~ .theme__icon .theme__icon-part:nth-child(6) {
251
+ .theme__toggle:checked~.theme__icon .theme__icon-part:nth-child(6) {
213
252
  transform: rotate(225deg) translateY(0.8em);
214
253
  }
215
254
 
216
- .theme__toggle:checked ~ .theme__icon .theme__icon-part:nth-child(7) {
255
+ .theme__toggle:checked~.theme__icon .theme__icon-part:nth-child(7) {
217
256
  transform: rotate(270deg) translateY(0.8em);
218
257
  }
219
258
 
220
- .theme__toggle:checked ~ .theme__icon .theme__icon-part:nth-child(8) {
259
+ .theme__toggle:checked~.theme__icon .theme__icon-part:nth-child(8) {
221
260
  transform: rotate(315deg) translateY(0.8em);
222
261
  }
223
262
 
224
- .theme__toggle:checked ~ .theme__icon .theme__icon-part:nth-child(9) {
263
+ .theme__toggle:checked~.theme__icon .theme__icon-part:nth-child(9) {
225
264
  transform: rotate(360deg) translateY(0.8em);
226
265
  }
227
266