lumina-slides 9.0.1 → 9.0.3
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/lumina-slides.js +7604 -7548
- package/dist/lumina-slides.umd.cjs +192 -192
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/animation/registry.ts +13 -10
- package/src/animation/stagger.ts +1 -1
- package/src/animation/types.ts +3 -1
- package/src/components/LuminaDeck.vue +15 -7
- package/src/components/site/SiteDocs.vue +352 -467
- package/src/components/site/SiteExamples.vue +1 -0
- package/src/core/Lumina.ts +73 -26
- package/src/core/animationConfig.ts +1 -1
- package/src/core/elementController.ts +14 -8
- package/src/core/elementResolver.ts +11 -5
- package/src/core/store.ts +1 -1
- package/src/core/types.ts +28 -6
- package/src/index.ts +5 -2
- package/src/utils/templateInterpolation.ts +52 -0
- package/src/views/DeckView.vue +55 -31
package/src/views/DeckView.vue
CHANGED
|
@@ -54,6 +54,29 @@
|
|
|
54
54
|
class="px-3 py-1.5 rounded bg-blue-600 text-white text-sm font-medium hover:bg-blue-500 disabled:opacity-50 disabled:cursor-not-allowed"
|
|
55
55
|
@click="onTimelinePlay">Play</button>
|
|
56
56
|
</div>
|
|
57
|
+
|
|
58
|
+
<!-- Template Tags: edit engine.data and see slides update (layout-template-tags example) -->
|
|
59
|
+
<div v-if="showTemplateTagsUI" class="fixed bottom-0 left-0 right-0 z-[90] flex items-center gap-4 px-4 py-3 bg-black/90 border-t border-white/10 backdrop-blur flex-wrap">
|
|
60
|
+
<span class="text-white/50 text-xs uppercase tracking-wider">engine.data</span>
|
|
61
|
+
<label class="flex items-center gap-2 text-sm text-white/80">
|
|
62
|
+
Product
|
|
63
|
+
<input v-model="templateProduct" type="text" placeholder="product"
|
|
64
|
+
class="w-28 px-2 py-1 rounded bg-white/10 border border-white/20 text-white text-sm focus:border-blue-500 focus:outline-none"
|
|
65
|
+
@input="onTemplateDataInput('product', ($event.target as HTMLInputElement).value)" />
|
|
66
|
+
</label>
|
|
67
|
+
<label class="flex items-center gap-2 text-sm text-white/80">
|
|
68
|
+
Version
|
|
69
|
+
<input v-model="templateVersion" type="text" placeholder="version"
|
|
70
|
+
class="w-24 px-2 py-1 rounded bg-white/10 border border-white/20 text-white text-sm focus:border-blue-500 focus:outline-none"
|
|
71
|
+
@input="onTemplateDataInput('version', ($event.target as HTMLInputElement).value)" />
|
|
72
|
+
</label>
|
|
73
|
+
<label class="flex items-center gap-2 text-sm text-white/80">
|
|
74
|
+
User
|
|
75
|
+
<input v-model="templateUser" type="text" placeholder="user"
|
|
76
|
+
class="w-28 px-2 py-1 rounded bg-white/10 border border-white/20 text-white text-sm focus:border-blue-500 focus:outline-none"
|
|
77
|
+
@input="onTemplateDataInput('user', ($event.target as HTMLInputElement).value)" />
|
|
78
|
+
</label>
|
|
79
|
+
</div>
|
|
57
80
|
</div>
|
|
58
81
|
</template>
|
|
59
82
|
|
|
@@ -85,16 +108,33 @@ const timelineCancelRef = ref<(() => void) | null>(null);
|
|
|
85
108
|
const timelineIntervalRef = ref<ReturnType<typeof setInterval> | null>(null);
|
|
86
109
|
|
|
87
110
|
const showTimelineUI = computed(() => {
|
|
88
|
-
const
|
|
111
|
+
const p = route.params.id;
|
|
112
|
+
const id = typeof p === 'string' ? p : (Array.isArray(p) && p[0] ? p[0] : '');
|
|
89
113
|
if (id !== 'animation-timeline') return false;
|
|
90
|
-
const slide = loadedDeck.value?.slides[currentSlideIndex.value]
|
|
114
|
+
const slide = loadedDeck.value?.slides[currentSlideIndex.value];
|
|
91
115
|
return !!slide?.timelineTracks;
|
|
92
116
|
});
|
|
93
117
|
|
|
118
|
+
// Template Tags example: edit engine.data and see slides update
|
|
119
|
+
const templateProduct = ref('Lumina');
|
|
120
|
+
const templateVersion = ref('2.0');
|
|
121
|
+
const templateUser = ref('World');
|
|
122
|
+
const showTemplateTagsUI = computed(() => {
|
|
123
|
+
const p = route.params.id;
|
|
124
|
+
const id = typeof p === 'string' ? p : (Array.isArray(p) && p[0] ? p[0] : '');
|
|
125
|
+
return id === 'layout-template-tags';
|
|
126
|
+
});
|
|
127
|
+
function onTemplateDataInput(key: string, value: string) {
|
|
128
|
+
engineRef.value?.data.set(key, value);
|
|
129
|
+
}
|
|
130
|
+
|
|
94
131
|
function onTimelineInput(e: Event) {
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
|
|
132
|
+
const t = e.target;
|
|
133
|
+
if (t instanceof HTMLInputElement) {
|
|
134
|
+
const v = parseFloat(t.value);
|
|
135
|
+
timelineProgress.value = v;
|
|
136
|
+
engineRef.value?.seekTo(v / 100);
|
|
137
|
+
}
|
|
98
138
|
}
|
|
99
139
|
|
|
100
140
|
function onTimelinePlay() {
|
|
@@ -163,7 +203,7 @@ async function onLoginAndDuplicate() {
|
|
|
163
203
|
await loginWithGoogle();
|
|
164
204
|
showLoginModal.value = false;
|
|
165
205
|
await duplicateAndEdit();
|
|
166
|
-
} catch (e
|
|
206
|
+
} catch (e) {
|
|
167
207
|
const msg = e instanceof Error ? e.message : 'Sign-in failed. Please try again.';
|
|
168
208
|
loginError.value = msg;
|
|
169
209
|
} finally {
|
|
@@ -176,7 +216,8 @@ onMounted(async () => {
|
|
|
176
216
|
initFirebase();
|
|
177
217
|
} catch (e) { }
|
|
178
218
|
|
|
179
|
-
const
|
|
219
|
+
const p = route.params.id;
|
|
220
|
+
const deckId = typeof p === 'string' ? p : (Array.isArray(p) && p[0] ? p[0] : '');
|
|
180
221
|
if (!deckId) return;
|
|
181
222
|
|
|
182
223
|
try {
|
|
@@ -208,7 +249,7 @@ onMounted(async () => {
|
|
|
208
249
|
showControls: true,
|
|
209
250
|
showProgressBar: true
|
|
210
251
|
},
|
|
211
|
-
theme:
|
|
252
|
+
theme: deckData.theme || 'default'
|
|
212
253
|
});
|
|
213
254
|
engineRef.value = engine;
|
|
214
255
|
|
|
@@ -227,29 +268,6 @@ onMounted(async () => {
|
|
|
227
268
|
});
|
|
228
269
|
}
|
|
229
270
|
|
|
230
|
-
if (deckId === 'animation-presets') {
|
|
231
|
-
const presets = ['fadeUp', 'scaleIn', 'spring'] as const;
|
|
232
|
-
engine.on('ready', () => engine?.revealInSequence(0, { preset: presets[0], delayMs: 450 }));
|
|
233
|
-
engine.on('slideChange', ({ index }) => {
|
|
234
|
-
engine?.revealInSequence(index, { preset: presets[index] ?? 'fadeUp', delayMs: 450 });
|
|
235
|
-
});
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
if (deckId === 'animation-stagger') {
|
|
239
|
-
const modes = ['center-out', 'wave', 'random'] as const;
|
|
240
|
-
engine.on('ready', () =>
|
|
241
|
-
engine?.revealInSequence(0, { preset: 'scaleIn', staggerMode: modes[0], delayMs: 380 })
|
|
242
|
-
);
|
|
243
|
-
engine.on('slideChange', ({ index }) => {
|
|
244
|
-
engine?.revealInSequence(index, {
|
|
245
|
-
preset: 'scaleIn',
|
|
246
|
-
staggerMode: modes[index] ?? 'sequential',
|
|
247
|
-
randomSeed: index,
|
|
248
|
-
delayMs: 380
|
|
249
|
-
});
|
|
250
|
-
});
|
|
251
|
-
}
|
|
252
|
-
|
|
253
271
|
if (deckId === 'animation-timeline') {
|
|
254
272
|
engine.on('ready', () => {
|
|
255
273
|
engine?.seekTo(0);
|
|
@@ -270,6 +288,12 @@ onMounted(async () => {
|
|
|
270
288
|
});
|
|
271
289
|
}
|
|
272
290
|
|
|
291
|
+
if (deckId === 'layout-template-tags') {
|
|
292
|
+
engine.data.set('product', templateProduct.value);
|
|
293
|
+
engine.data.set('version', templateVersion.value);
|
|
294
|
+
engine.data.set('user', templateUser.value);
|
|
295
|
+
}
|
|
296
|
+
|
|
273
297
|
engine.load(deckData);
|
|
274
298
|
} catch (error) {
|
|
275
299
|
console.error("Failed to load deck:", error);
|