little-dizzy 2.3.0 → 2.5.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 +704 -198
- package/dist/little-dizzy.umd.cjs +61 -6
- package/package.json +2 -2
- package/src/components/Backtop.vue +151 -0
- package/src/components/Card.vue +10 -9
- package/src/components/Carousel.vue +287 -0
- package/src/components/Loading.vue +224 -0
- package/src/components/Table.vue +361 -0
- package/src/components/custom/Lztext.vue +36 -55
- package/src/components/custom/lztheme.vue +97 -58
- package/src/index.js +12 -1
- package/src/snippets/presets/backtop.js +25 -0
- package/src/snippets/presets/carousel.js +22 -0
- package/src/snippets/presets/index.js +10 -2
- package/src/snippets/presets/loading.js +20 -0
- package/src/snippets/presets/table.js +28 -0
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="ld-table-wrapper" :class="{ 'ld-table--bordered': bordered, 'ld-table--striped': striped }">
|
|
3
|
+
<!-- Loading 遮罩层 -->
|
|
4
|
+
<div v-if="isLoading" class="ld-table-loading">
|
|
5
|
+
<div class="loading-spinner">
|
|
6
|
+
<svg class="circular" viewBox="0 0 50 50">
|
|
7
|
+
<circle class="path" cx="25" cy="25" r="20" fill="none" />
|
|
8
|
+
</svg>
|
|
9
|
+
</div>
|
|
10
|
+
<span v-if="loadingText" class="loading-text">{{ loadingText }}</span>
|
|
11
|
+
</div>
|
|
12
|
+
|
|
13
|
+
<table class="ld-table">
|
|
14
|
+
<thead>
|
|
15
|
+
<tr>
|
|
16
|
+
<th v-for="col in columns" :key="col.key" :style="{ width: col.width, textAlign: col.align || 'left' }"
|
|
17
|
+
@click="col.sortable && handleSort(col.key)">
|
|
18
|
+
<div class="th-content">
|
|
19
|
+
<span>{{ col.title }}</span>
|
|
20
|
+
<span v-if="col.sortable" class="sort-icon" :class="getSortClass(col.key)">
|
|
21
|
+
<svg viewBox="0 0 24 24" width="14" height="14">
|
|
22
|
+
<path fill="currentColor" d="M7 10l5-5 5 5H7zm0 4l5 5 5-5H7z" />
|
|
23
|
+
</svg>
|
|
24
|
+
</span>
|
|
25
|
+
</div>
|
|
26
|
+
</th>
|
|
27
|
+
</tr>
|
|
28
|
+
</thead>
|
|
29
|
+
<tbody>
|
|
30
|
+
<tr v-if="!sortedData.length && !isLoading">
|
|
31
|
+
<td :colspan="columns.length" class="empty-cell">
|
|
32
|
+
<slot name="empty">
|
|
33
|
+
<div class="empty-content">
|
|
34
|
+
<svg viewBox="0 0 64 41" width="64" height="41">
|
|
35
|
+
<g transform="translate(0 1)" fill="none" fill-rule="evenodd">
|
|
36
|
+
<ellipse fill="var(--ld-color-bg-secondary, #f5f5f5)" cx="32" cy="33" rx="32" ry="7" />
|
|
37
|
+
<g fill-rule="nonzero" stroke="var(--ld-color-border, #d9d9d9)">
|
|
38
|
+
<path
|
|
39
|
+
d="M55 12.76L44.854 1.258C44.367.474 43.656 0 42.907 0H21.093c-.749 0-1.46.474-1.947 1.257L9 12.761V22h46v-9.24z" />
|
|
40
|
+
<path
|
|
41
|
+
d="M41.613 15.931c0-1.605.994-2.93 2.227-2.931H55v18.137C55 33.26 53.68 35 52.05 35h-40.1C10.32 35 9 33.259 9 31.137V13h11.16c1.233 0 2.227 1.323 2.227 2.928v.022c0 1.605 1.005 2.901 2.237 2.901h14.752c1.232 0 2.237-1.308 2.237-2.913v-.007z"
|
|
42
|
+
fill="var(--ld-color-bg, #fafafa)" />
|
|
43
|
+
</g>
|
|
44
|
+
</g>
|
|
45
|
+
</svg>
|
|
46
|
+
<span>暂无数据</span>
|
|
47
|
+
</div>
|
|
48
|
+
</slot>
|
|
49
|
+
</td>
|
|
50
|
+
</tr>
|
|
51
|
+
<tr v-for="(row, rowIndex) in sortedData" :key="rowIndex" @click="$emit('row-click', row, rowIndex)">
|
|
52
|
+
<td v-for="col in columns" :key="col.key" :style="{ textAlign: col.align || 'left' }">
|
|
53
|
+
<slot :name="col.key" :row="row" :index="rowIndex" :value="row[col.key]">
|
|
54
|
+
{{ row[col.key] }}
|
|
55
|
+
</slot>
|
|
56
|
+
</td>
|
|
57
|
+
</tr>
|
|
58
|
+
</tbody>
|
|
59
|
+
</table>
|
|
60
|
+
</div>
|
|
61
|
+
</template>
|
|
62
|
+
|
|
63
|
+
<script setup>
|
|
64
|
+
import { ref, computed, watch, onMounted } from 'vue'
|
|
65
|
+
|
|
66
|
+
defineOptions({
|
|
67
|
+
name: 'ldTable'
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
const props = defineProps({
|
|
71
|
+
columns: {
|
|
72
|
+
type: Array,
|
|
73
|
+
required: true
|
|
74
|
+
},
|
|
75
|
+
data: {
|
|
76
|
+
type: Array,
|
|
77
|
+
default: () => []
|
|
78
|
+
},
|
|
79
|
+
bordered: {
|
|
80
|
+
type: Boolean,
|
|
81
|
+
default: false
|
|
82
|
+
},
|
|
83
|
+
striped: {
|
|
84
|
+
type: Boolean,
|
|
85
|
+
default: false
|
|
86
|
+
},
|
|
87
|
+
loading: {
|
|
88
|
+
type: Boolean,
|
|
89
|
+
default: false
|
|
90
|
+
},
|
|
91
|
+
loadingText: {
|
|
92
|
+
type: String,
|
|
93
|
+
default: ''
|
|
94
|
+
},
|
|
95
|
+
// API 相关
|
|
96
|
+
api: {
|
|
97
|
+
type: Function,
|
|
98
|
+
default: null
|
|
99
|
+
},
|
|
100
|
+
autoLoad: {
|
|
101
|
+
type: Boolean,
|
|
102
|
+
default: true
|
|
103
|
+
},
|
|
104
|
+
loadParams: {
|
|
105
|
+
type: Object,
|
|
106
|
+
default: () => ({})
|
|
107
|
+
}
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
const emit = defineEmits(['row-click', 'load-success', 'load-error'])
|
|
111
|
+
|
|
112
|
+
// 内部状态
|
|
113
|
+
const internalLoading = ref(false)
|
|
114
|
+
const apiData = ref([])
|
|
115
|
+
|
|
116
|
+
// 是否使用 API 模式
|
|
117
|
+
const isApiMode = computed(() => typeof props.api === 'function')
|
|
118
|
+
|
|
119
|
+
// 实际的 loading 状态
|
|
120
|
+
const isLoading = computed(() => props.loading || internalLoading.value)
|
|
121
|
+
|
|
122
|
+
// 实际使用的数据
|
|
123
|
+
const tableData = computed(() => isApiMode.value ? apiData.value : props.data)
|
|
124
|
+
|
|
125
|
+
// 加载数据
|
|
126
|
+
const load = async (params = {}) => {
|
|
127
|
+
if (!isApiMode.value) return
|
|
128
|
+
|
|
129
|
+
internalLoading.value = true
|
|
130
|
+
try {
|
|
131
|
+
const mergedParams = { ...props.loadParams, ...params }
|
|
132
|
+
const result = await props.api(mergedParams)
|
|
133
|
+
apiData.value = Array.isArray(result) ? result : (result?.data || result?.list || [])
|
|
134
|
+
emit('load-success', apiData.value)
|
|
135
|
+
return apiData.value
|
|
136
|
+
} catch (error) {
|
|
137
|
+
console.error('[ld-table] Load error:', error)
|
|
138
|
+
emit('load-error', error)
|
|
139
|
+
throw error
|
|
140
|
+
} finally {
|
|
141
|
+
internalLoading.value = false
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// 重新加载
|
|
146
|
+
const reload = (params = {}) => {
|
|
147
|
+
return load(params)
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// 清空数据
|
|
151
|
+
const clear = () => {
|
|
152
|
+
apiData.value = []
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// 监听 loadParams 变化
|
|
156
|
+
watch(() => props.loadParams, (newParams) => {
|
|
157
|
+
if (isApiMode.value && props.autoLoad) {
|
|
158
|
+
load()
|
|
159
|
+
}
|
|
160
|
+
}, { deep: true })
|
|
161
|
+
|
|
162
|
+
// 自动加载
|
|
163
|
+
onMounted(() => {
|
|
164
|
+
if (isApiMode.value && props.autoLoad) {
|
|
165
|
+
load()
|
|
166
|
+
}
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
const sortKey = ref('')
|
|
170
|
+
const sortOrder = ref('') // 'asc' | 'desc' | ''
|
|
171
|
+
|
|
172
|
+
const handleSort = (key) => {
|
|
173
|
+
if (sortKey.value === key) {
|
|
174
|
+
sortOrder.value = sortOrder.value === 'asc' ? 'desc' : sortOrder.value === 'desc' ? '' : 'asc'
|
|
175
|
+
if (!sortOrder.value) sortKey.value = ''
|
|
176
|
+
} else {
|
|
177
|
+
sortKey.value = key
|
|
178
|
+
sortOrder.value = 'asc'
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const getSortClass = (key) => {
|
|
183
|
+
if (sortKey.value !== key) return ''
|
|
184
|
+
return sortOrder.value === 'asc' ? 'sort-asc' : sortOrder.value === 'desc' ? 'sort-desc' : ''
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const sortedData = computed(() => {
|
|
188
|
+
const data = tableData.value
|
|
189
|
+
if (!sortKey.value || !sortOrder.value) return data
|
|
190
|
+
|
|
191
|
+
return [...data].sort((a, b) => {
|
|
192
|
+
const aVal = a[sortKey.value]
|
|
193
|
+
const bVal = b[sortKey.value]
|
|
194
|
+
|
|
195
|
+
if (typeof aVal === 'number' && typeof bVal === 'number') {
|
|
196
|
+
return sortOrder.value === 'asc' ? aVal - bVal : bVal - aVal
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const aStr = String(aVal || '')
|
|
200
|
+
const bStr = String(bVal || '')
|
|
201
|
+
return sortOrder.value === 'asc' ? aStr.localeCompare(bStr) : bStr.localeCompare(aStr)
|
|
202
|
+
})
|
|
203
|
+
})
|
|
204
|
+
|
|
205
|
+
// 暴露方法
|
|
206
|
+
defineExpose({
|
|
207
|
+
load,
|
|
208
|
+
reload,
|
|
209
|
+
clear,
|
|
210
|
+
getData: () => apiData.value
|
|
211
|
+
})
|
|
212
|
+
</script>
|
|
213
|
+
|
|
214
|
+
<style scoped>
|
|
215
|
+
.ld-table-wrapper {
|
|
216
|
+
position: relative;
|
|
217
|
+
width: 100%;
|
|
218
|
+
overflow-x: auto;
|
|
219
|
+
border-radius: 8px;
|
|
220
|
+
background: var(--ld-color-bg, #fff);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/* Loading 遮罩层 - Element Plus 风格 */
|
|
224
|
+
.ld-table-loading {
|
|
225
|
+
position: absolute;
|
|
226
|
+
top: 0;
|
|
227
|
+
left: 0;
|
|
228
|
+
right: 0;
|
|
229
|
+
bottom: 0;
|
|
230
|
+
z-index: 10;
|
|
231
|
+
display: flex;
|
|
232
|
+
flex-direction: column;
|
|
233
|
+
align-items: center;
|
|
234
|
+
justify-content: center;
|
|
235
|
+
gap: 8px;
|
|
236
|
+
background: var(--ld-table-loading-bg, rgba(255, 255, 255, 0.9));
|
|
237
|
+
transition: opacity 0.3s;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
.loading-spinner {
|
|
241
|
+
width: 42px;
|
|
242
|
+
height: 42px;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
.loading-spinner .circular {
|
|
246
|
+
width: 100%;
|
|
247
|
+
height: 100%;
|
|
248
|
+
animation: loading-rotate 2s linear infinite;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
.loading-spinner .path {
|
|
252
|
+
stroke: var(--ld-color-primary, #409eff);
|
|
253
|
+
stroke-width: 4;
|
|
254
|
+
stroke-linecap: round;
|
|
255
|
+
animation: loading-dash 1.5s ease-in-out infinite;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
@keyframes loading-rotate {
|
|
259
|
+
100% {
|
|
260
|
+
transform: rotate(360deg);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
@keyframes loading-dash {
|
|
265
|
+
0% {
|
|
266
|
+
stroke-dasharray: 1, 200;
|
|
267
|
+
stroke-dashoffset: 0;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
50% {
|
|
271
|
+
stroke-dasharray: 90, 150;
|
|
272
|
+
stroke-dashoffset: -40px;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
100% {
|
|
276
|
+
stroke-dasharray: 90, 150;
|
|
277
|
+
stroke-dashoffset: -120px;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
.loading-text {
|
|
282
|
+
font-size: 14px;
|
|
283
|
+
color: var(--ld-color-primary, #409eff);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
.ld-table {
|
|
287
|
+
width: 100%;
|
|
288
|
+
border-collapse: collapse;
|
|
289
|
+
font-size: 14px;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
.ld-table th,
|
|
293
|
+
.ld-table td {
|
|
294
|
+
padding: 12px 16px;
|
|
295
|
+
text-align: left;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
.ld-table th {
|
|
299
|
+
background: var(--ld-color-bg-secondary, #f8f9fa);
|
|
300
|
+
color: var(--ld-color-text, #333);
|
|
301
|
+
font-weight: 600;
|
|
302
|
+
white-space: nowrap;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
.ld-table td {
|
|
306
|
+
color: var(--ld-color-text-secondary, #666);
|
|
307
|
+
border-bottom: 1px solid var(--ld-color-border, #eee);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
.ld-table tbody tr:hover {
|
|
311
|
+
background: var(--ld-color-bg-hover, #f5f5f5);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
.ld-table--bordered .ld-table th,
|
|
315
|
+
.ld-table--bordered .ld-table td {
|
|
316
|
+
border: 1px solid var(--ld-color-border, #eee);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
.ld-table--striped tbody tr:nth-child(even) {
|
|
320
|
+
background: var(--ld-color-bg-secondary, #f8f9fa);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
.th-content {
|
|
324
|
+
display: flex;
|
|
325
|
+
align-items: center;
|
|
326
|
+
gap: 4px;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
.sort-icon {
|
|
330
|
+
opacity: 0.3;
|
|
331
|
+
cursor: pointer;
|
|
332
|
+
transition: opacity 0.3s;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
.sort-icon:hover {
|
|
336
|
+
opacity: 0.6;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
.sort-icon.sort-asc,
|
|
340
|
+
.sort-icon.sort-desc {
|
|
341
|
+
opacity: 1;
|
|
342
|
+
color: var(--ld-color-primary, #6366f1);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
.sort-icon.sort-desc svg {
|
|
346
|
+
transform: rotate(180deg);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
.empty-cell {
|
|
350
|
+
text-align: center;
|
|
351
|
+
padding: 40px 16px;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
.empty-content {
|
|
355
|
+
display: flex;
|
|
356
|
+
flex-direction: column;
|
|
357
|
+
align-items: center;
|
|
358
|
+
gap: 8px;
|
|
359
|
+
color: var(--ld-color-text-muted, #999);
|
|
360
|
+
}
|
|
361
|
+
</style>
|
|
@@ -1,32 +1,41 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="Lztext-wrapper">
|
|
3
3
|
<div class="loader-wrapper">
|
|
4
|
-
<span class="loader-letter"
|
|
5
|
-
|
|
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>
|
|
4
|
+
<span v-for="(char, index) in characters" :key="index" class="loader-letter"
|
|
5
|
+
:style="{ animationDelay: `${0.1 + index * 0.105}s` }">{{ char === ' ' ? '\u00A0' : char }}</span>
|
|
14
6
|
<div class="loader"></div>
|
|
15
7
|
</div>
|
|
16
8
|
</div>
|
|
17
9
|
</template>
|
|
18
10
|
|
|
19
11
|
<script setup>
|
|
12
|
+
import { computed } from 'vue'
|
|
13
|
+
|
|
20
14
|
/**
|
|
21
15
|
* 渐变文字动画
|
|
22
16
|
*
|
|
23
|
-
*
|
|
17
|
+
* 通过 text 属性传入文字内容
|
|
24
18
|
* @component Lztext
|
|
19
|
+
* @example <LdLztext text="Hello World" />
|
|
25
20
|
*/
|
|
26
21
|
defineOptions({
|
|
27
22
|
name: 'Lztext'
|
|
28
23
|
})
|
|
29
24
|
|
|
25
|
+
const props = defineProps({
|
|
26
|
+
/**
|
|
27
|
+
* 显示的文字内容
|
|
28
|
+
*/
|
|
29
|
+
text: {
|
|
30
|
+
type: String,
|
|
31
|
+
default: 'Generating'
|
|
32
|
+
}
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
// 将文字拆分为字符数组
|
|
36
|
+
const characters = computed(() => {
|
|
37
|
+
return props.text.split('')
|
|
38
|
+
})
|
|
30
39
|
</script>
|
|
31
40
|
|
|
32
41
|
<style scoped>
|
|
@@ -57,13 +66,11 @@ defineOptions({
|
|
|
57
66
|
z-index: 1;
|
|
58
67
|
|
|
59
68
|
background-color: transparent;
|
|
60
|
-
mask: repeating-linear-gradient(
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
black 8px
|
|
66
|
-
);
|
|
69
|
+
mask: repeating-linear-gradient(90deg,
|
|
70
|
+
transparent 0,
|
|
71
|
+
transparent 6px,
|
|
72
|
+
black 7px,
|
|
73
|
+
black 8px);
|
|
67
74
|
}
|
|
68
75
|
|
|
69
76
|
.loader::after {
|
|
@@ -79,12 +86,10 @@ defineOptions({
|
|
|
79
86
|
radial-gradient(circle at 55% 55%, #0ff 0%, transparent 45%),
|
|
80
87
|
radial-gradient(circle at 45% 55%, #0f0 0%, transparent 45%),
|
|
81
88
|
radial-gradient(circle at 55% 45%, #00f 0%, transparent 45%);
|
|
82
|
-
mask: radial-gradient(
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
black 25%
|
|
87
|
-
);
|
|
89
|
+
mask: radial-gradient(circle at 50% 50%,
|
|
90
|
+
transparent 0%,
|
|
91
|
+
transparent 10%,
|
|
92
|
+
black 25%);
|
|
88
93
|
animation:
|
|
89
94
|
transform-animation 2s infinite alternate,
|
|
90
95
|
opacity-animation 4s infinite;
|
|
@@ -95,19 +100,23 @@ defineOptions({
|
|
|
95
100
|
0% {
|
|
96
101
|
transform: translate(-55%);
|
|
97
102
|
}
|
|
103
|
+
|
|
98
104
|
100% {
|
|
99
105
|
transform: translate(55%);
|
|
100
106
|
}
|
|
101
107
|
}
|
|
102
108
|
|
|
103
109
|
@keyframes opacity-animation {
|
|
110
|
+
|
|
104
111
|
0%,
|
|
105
112
|
100% {
|
|
106
113
|
opacity: 0;
|
|
107
114
|
}
|
|
115
|
+
|
|
108
116
|
15% {
|
|
109
117
|
opacity: 1;
|
|
110
118
|
}
|
|
119
|
+
|
|
111
120
|
65% {
|
|
112
121
|
opacity: 0;
|
|
113
122
|
}
|
|
@@ -120,49 +129,21 @@ defineOptions({
|
|
|
120
129
|
z-index: 2;
|
|
121
130
|
}
|
|
122
131
|
|
|
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
132
|
@keyframes loader-letter-anim {
|
|
155
133
|
0% {
|
|
156
134
|
opacity: 0;
|
|
157
135
|
}
|
|
136
|
+
|
|
158
137
|
5% {
|
|
159
138
|
opacity: 1;
|
|
160
139
|
text-shadow: 0 0 4px #fff;
|
|
161
140
|
transform: scale(1.1) translateY(-2px);
|
|
162
141
|
}
|
|
142
|
+
|
|
163
143
|
20% {
|
|
164
144
|
opacity: 0.2;
|
|
165
145
|
}
|
|
146
|
+
|
|
166
147
|
100% {
|
|
167
148
|
opacity: 0;
|
|
168
149
|
}
|