lumina-slides 8.9.3 → 8.9.4

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/IMPLEMENTATION.md CHANGED
@@ -247,7 +247,7 @@ Use `engine.element(id)` or `engine.element(slideIndex, path)` to get an **Eleme
247
247
 
248
248
  4. **Order:** `new Lumina(...)` → `engine.on('ready', ...)` → `engine.on('slideChange', ...)` → `engine.load(deck)`.
249
249
 
250
- **Example (vanilla JS):**
250
+ **Example (vanilla JS) — simple reveal with delay:**
251
251
 
252
252
  ```js
253
253
  const engine = new Lumina("#app", { theme: "midnight" });
@@ -278,6 +278,131 @@ engine.load({
278
278
 
279
279
  ---
280
280
 
281
+ ## Delay-controlled animations (vanilla JS, no Vue)
282
+
283
+ Staggered reveals and per-element animations are driven from vanilla JS using `setTimeout`, `engine.element(id).show()`, and `engine.element(id).animate()`. Register `ready` and `slideChange` **before** `engine.load(deck)`.
284
+
285
+ **Helper to reveal a slide’s elements with delay and optional animation:**
286
+
287
+ ```js
288
+ /**
289
+ * Reveal all elements of a slide with staggered delay. Pure JavaScript, no Vue.
290
+ * @param {import('lumina-slides').Lumina} engine
291
+ * @param {number} slideIndex
292
+ * @param {Object} [opts]
293
+ * @param {number} [opts.delayMs=500] - Delay between each element (ms).
294
+ * @param {boolean} [opts.animate=true] - If true, animate from { opacity: 0, y: 20 } to { opacity: 1, y: 0 }.
295
+ * @param {number} [opts.animDuration=0.5] - Animation duration in seconds.
296
+ */
297
+ function revealSlideWithDelay(engine, slideIndex, opts = {}) {
298
+ const { delayMs = 500, animate = true, animDuration = 0.5 } = opts;
299
+ const ids = engine.elements(slideIndex);
300
+ if (!ids || !ids.length) return;
301
+
302
+ ids.forEach((id, i) => {
303
+ const t = (i + 1) * delayMs;
304
+ setTimeout(() => {
305
+ const el = engine.element(id);
306
+ el.show();
307
+ if (animate) {
308
+ el.animate({
309
+ from: { opacity: 0, y: 20 },
310
+ to: { opacity: 1, y: 0 },
311
+ duration: animDuration,
312
+ ease: "power2.out",
313
+ });
314
+ }
315
+ }, t);
316
+ });
317
+ }
318
+ ```
319
+
320
+ **Full HTML + vanilla JS example (delay-controlled animations):**
321
+
322
+ ```html
323
+ <!DOCTYPE html>
324
+ <html lang="en">
325
+ <head>
326
+ <meta charset="UTF-8" />
327
+ <title>Lumina – delay-controlled animations (vanilla JS)</title>
328
+ <link rel="stylesheet" href="node_modules/lumina-slides/dist/style.css" />
329
+ </head>
330
+ <body>
331
+ <div id="app" style="width:100vw;height:100vh;"></div>
332
+ <script type="module">
333
+ import { Lumina } from "lumina-slides";
334
+
335
+ const engine = new Lumina("#app", { theme: "midnight" });
336
+
337
+ function revealSlideWithDelay(engine, slideIndex, opts = {}) {
338
+ const { delayMs = 500, animate = true, animDuration = 0.5 } = opts;
339
+ const ids = engine.elements(slideIndex);
340
+ if (!ids || !ids.length) return;
341
+ ids.forEach((id, i) => {
342
+ setTimeout(() => {
343
+ engine.element(id).show();
344
+ if (animate) {
345
+ engine.element(id).animate({
346
+ from: { opacity: 0, y: 20 },
347
+ to: { opacity: 1, y: 0 },
348
+ duration: animDuration,
349
+ ease: "power2.out",
350
+ });
351
+ }
352
+ }, (i + 1) * delayMs);
353
+ });
354
+ }
355
+
356
+ // Must register before load so callbacks run when DOM is ready
357
+ engine.on("ready", () => revealSlideWithDelay(engine, 0, { delayMs: 600, animDuration: 0.5 }));
358
+ engine.on("slideChange", ({ index }) => revealSlideWithDelay(engine, index, { delayMs: 600, animDuration: 0.5 }));
359
+
360
+ engine.load({
361
+ meta: {
362
+ title: "Staggered reveal",
363
+ elementControl: { defaultVisible: false },
364
+ initialElementState: {
365
+ "s0-tag": { visible: false },
366
+ "s0-title": { visible: false },
367
+ "s0-subtitle": { visible: false },
368
+ "s1-header": { visible: false },
369
+ "s1-features-0": { visible: false },
370
+ "s1-features-1": { visible: false },
371
+ },
372
+ },
373
+ slides: [
374
+ { type: "statement", title: "Welcome", subtitle: "Each line appears with a delay", tag: "Intro" },
375
+ { type: "features", title: "Highlights", features: [
376
+ { title: "First", desc: "Revealed after 600ms", icon: "star" },
377
+ { title: "Second", desc: "Revealed after 1200ms", icon: "zap" },
378
+ ]},
379
+ ],
380
+ });
381
+ </script>
382
+ </body>
383
+ </html>
384
+ ```
385
+
386
+ **Animation-only (no show/hide), with custom stagger:**
387
+
388
+ ```js
389
+ engine.on("ready", () => {
390
+ const ids = engine.elements(0);
391
+ ids.forEach((id, i) => {
392
+ setTimeout(() => {
393
+ engine.element(id).animate({
394
+ from: { opacity: 0, scale: 0.95 },
395
+ to: { opacity: 1, scale: 1 },
396
+ duration: 0.6,
397
+ ease: "back.out(1.2)",
398
+ });
399
+ }, i * 400);
400
+ });
401
+ });
402
+ ```
403
+
404
+ ---
405
+
281
406
  ## Animation options (engine and deck)
282
407
 
283
408
  - **Engine options:** `options.animation: { enabled?: boolean, type?: 'fade'|'cascade'|'zoom', durationIn?, durationOut? }` when creating `new Lumina(selector, options)`.