lumina-slides 8.9.4 → 9.0.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.
Files changed (119) hide show
  1. package/LUMINA_LLM_EXAMPLES.json +234 -0
  2. package/README.md +18 -18
  3. package/dist/lumina-slides.js +13207 -12659
  4. package/dist/lumina-slides.umd.cjs +215 -215
  5. package/dist/style.css +1 -1
  6. package/package.json +5 -4
  7. package/src/App.vue +16 -0
  8. package/src/animation/index.ts +11 -0
  9. package/src/animation/registry.ts +126 -0
  10. package/src/animation/stagger.ts +95 -0
  11. package/src/animation/types.ts +53 -0
  12. package/src/components/LandingPage.vue +229 -0
  13. package/src/components/LuminaDeck.vue +224 -0
  14. package/src/components/LuminaSpeakerNotes.vue +701 -0
  15. package/src/components/base/BaseSlide.vue +122 -0
  16. package/src/components/base/LuminaElement.vue +67 -0
  17. package/src/components/base/VideoPlayer.vue +204 -0
  18. package/src/components/layouts/LayoutAuto.vue +71 -0
  19. package/src/components/layouts/LayoutChart.vue +287 -0
  20. package/src/components/layouts/LayoutCustom.vue +92 -0
  21. package/src/components/layouts/LayoutDiagram.vue +253 -0
  22. package/src/components/layouts/LayoutFeatures.vue +121 -0
  23. package/src/components/layouts/LayoutFlex.vue +172 -0
  24. package/src/components/layouts/LayoutFree.vue +62 -0
  25. package/src/components/layouts/LayoutHalf.vue +127 -0
  26. package/src/components/layouts/LayoutStatement.vue +74 -0
  27. package/src/components/layouts/LayoutSteps.vue +106 -0
  28. package/src/components/layouts/LayoutTimeline.vue +104 -0
  29. package/src/components/layouts/LayoutVideo.vue +41 -0
  30. package/src/components/parts/FlexBullets.vue +45 -0
  31. package/src/components/parts/FlexButton.vue +132 -0
  32. package/src/components/parts/FlexImage.vue +54 -0
  33. package/src/components/parts/FlexOrdered.vue +44 -0
  34. package/src/components/parts/FlexSpacer.vue +13 -0
  35. package/src/components/parts/FlexStepper.vue +59 -0
  36. package/src/components/parts/FlexText.vue +29 -0
  37. package/src/components/parts/FlexTimeline.vue +67 -0
  38. package/src/components/parts/FlexTitle.vue +39 -0
  39. package/src/components/parts/LuminaBackground.vue +100 -0
  40. package/src/components/site/LivePreview.vue +101 -0
  41. package/src/components/site/SiteApi.vue +301 -0
  42. package/src/components/site/SiteDashboard.vue +604 -0
  43. package/src/components/site/SiteDocs.vue +3267 -0
  44. package/src/components/site/SiteExamples.vue +65 -0
  45. package/src/components/site/SiteFooter.vue +6 -0
  46. package/src/components/site/SiteHome.vue +362 -0
  47. package/src/components/site/SiteNavBar.vue +122 -0
  48. package/src/components/site/SitePlayground.vue +389 -0
  49. package/src/components/site/SitePromptBuilder.vue +266 -0
  50. package/src/components/site/SiteUserMenu.vue +90 -0
  51. package/src/components/studio/ActionEditor.vue +108 -0
  52. package/src/components/studio/ArrayEditor.vue +124 -0
  53. package/src/components/studio/CollapsibleSection.vue +33 -0
  54. package/src/components/studio/ColorField.vue +22 -0
  55. package/src/components/studio/EditorCanvas.vue +326 -0
  56. package/src/components/studio/EditorLayoutFeatures.vue +18 -0
  57. package/src/components/studio/EditorLayoutFixed.vue +46 -0
  58. package/src/components/studio/EditorLayoutFlex.vue +133 -0
  59. package/src/components/studio/EditorLayoutHalf.vue +18 -0
  60. package/src/components/studio/EditorLayoutStatement.vue +18 -0
  61. package/src/components/studio/EditorLayoutSteps.vue +18 -0
  62. package/src/components/studio/EditorLayoutTimeline.vue +18 -0
  63. package/src/components/studio/EditorNode.vue +89 -0
  64. package/src/components/studio/FieldEditor.vue +133 -0
  65. package/src/components/studio/IconPicker.vue +109 -0
  66. package/src/components/studio/LayerItem.vue +117 -0
  67. package/src/components/studio/LuminaStudio.vue +30 -0
  68. package/src/components/studio/SaveSuccessModal.vue +138 -0
  69. package/src/components/studio/SlideNavigator.vue +373 -0
  70. package/src/components/studio/SliderField.vue +44 -0
  71. package/src/components/studio/StudioInspector.vue +595 -0
  72. package/src/components/studio/StudioJsonEditor.vue +191 -0
  73. package/src/components/studio/StudioLayers.vue +145 -0
  74. package/src/components/studio/StudioSettings.vue +514 -0
  75. package/src/components/studio/StudioSidebar.vue +29 -0
  76. package/src/components/studio/StudioToolbar.vue +222 -0
  77. package/src/components/studio/fieldLabels.ts +224 -0
  78. package/src/components/studio/inspectors/DiagramEdgeEditor.vue +77 -0
  79. package/src/components/studio/inspectors/DiagramNodeEditor.vue +117 -0
  80. package/src/components/studio/nodes/StudioDiagramNode.vue +138 -0
  81. package/src/composables/useAuth.ts +87 -0
  82. package/src/composables/useEditor.ts +224 -0
  83. package/src/composables/useElementState.ts +81 -0
  84. package/src/composables/useFlexLayout.ts +122 -0
  85. package/src/composables/useKeyboard.ts +45 -0
  86. package/src/composables/useLumina.ts +32 -0
  87. package/src/composables/useStudio.ts +87 -0
  88. package/src/composables/useSwipeNav.ts +53 -0
  89. package/src/composables/useTransition.ts +373 -0
  90. package/src/core/Lumina.ts +819 -0
  91. package/src/core/animationConfig.ts +251 -0
  92. package/src/core/compression.ts +34 -0
  93. package/src/core/elementController.ts +170 -0
  94. package/src/core/elementId.ts +27 -0
  95. package/src/core/elementResolver.ts +207 -0
  96. package/src/core/events.ts +53 -0
  97. package/src/core/fonts.ts +100 -0
  98. package/src/core/presets.ts +231 -0
  99. package/src/core/prompts.ts +272 -0
  100. package/src/core/schema.ts +478 -0
  101. package/src/core/speaker-channel.ts +250 -0
  102. package/src/core/store.ts +461 -0
  103. package/src/core/theme.ts +666 -0
  104. package/src/core/types.ts +1611 -0
  105. package/src/directives/vStudio.ts +45 -0
  106. package/src/index.ts +175 -0
  107. package/src/main.ts +17 -0
  108. package/src/router/index.ts +92 -0
  109. package/src/style/main.css +462 -0
  110. package/src/utils/deep.ts +127 -0
  111. package/src/utils/firebase.ts +184 -0
  112. package/src/utils/streaming.ts +134 -0
  113. package/src/views/DashboardView.vue +32 -0
  114. package/src/views/DeckView.vue +289 -0
  115. package/src/views/HomeView.vue +17 -0
  116. package/src/views/SiteLayout.vue +21 -0
  117. package/src/views/StudioView.vue +61 -0
  118. package/src/vite-env.d.ts +6 -0
  119. package/IMPLEMENTATION.md +0 -418
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Animation preset registry. Built-in presets (fadeUp, scaleIn, etc.) and registerPreset/getPreset.
3
+ *
4
+ * @module animation/registry
5
+ * @see ANIMATION_IDEAS.md §1 Presets
6
+ */
7
+
8
+ import type { PresetDef } from './types';
9
+
10
+ /**
11
+ * Built-in animation presets. When `preset` is used in animate() or revealInSequence, these provide from/to/ease.
12
+ * Duration is taken from the call-site or config.
13
+ */
14
+ export const BUILTIN_PRESETS: Record<string, PresetDef> = {
15
+ fadeUp: {
16
+ from: { opacity: 0, y: 20 },
17
+ to: { opacity: 1, y: 0 },
18
+ ease: 'power2.out',
19
+ },
20
+ fadeIn: {
21
+ from: { opacity: 0 },
22
+ to: { opacity: 1 },
23
+ ease: 'power2.out',
24
+ },
25
+ scaleIn: {
26
+ from: { opacity: 0, scale: 0.9 },
27
+ to: { opacity: 1, scale: 1 },
28
+ ease: 'back.out(1.2)',
29
+ },
30
+ slideLeft: {
31
+ from: { opacity: 0, x: 40 },
32
+ to: { opacity: 1, x: 0 },
33
+ ease: 'power2.out',
34
+ },
35
+ slideRight: {
36
+ from: { opacity: 0, x: -40 },
37
+ to: { opacity: 1, x: 0 },
38
+ ease: 'power2.out',
39
+ },
40
+ zoomIn: {
41
+ from: { opacity: 0, scale: 0.7 },
42
+ to: { opacity: 1, scale: 1 },
43
+ ease: 'power2.out',
44
+ },
45
+ blurIn: {
46
+ from: { opacity: 0, filter: 'blur(12px)' },
47
+ to: { opacity: 1, filter: 'blur(0)' },
48
+ ease: 'power2.out',
49
+ },
50
+ spring: {
51
+ from: { opacity: 0, y: 30 },
52
+ to: { opacity: 1, y: 0 },
53
+ ease: 'elastic.out(1, 0.4)',
54
+ },
55
+ drop: {
56
+ from: { y: -80, opacity: 0 },
57
+ to: { y: 0, opacity: 1 },
58
+ ease: 'back.out(1.5)',
59
+ },
60
+ fadeOut: {
61
+ from: { opacity: 1 },
62
+ to: { opacity: 0 },
63
+ ease: 'power2.in',
64
+ },
65
+ };
66
+
67
+ const custom: Record<string, PresetDef> = {};
68
+
69
+ /**
70
+ * Returns a preset by name. Built-ins first, then custom. Null if not found.
71
+ */
72
+ export function getPreset(name: string): PresetDef | null {
73
+ return BUILTIN_PRESETS[name] ?? custom[name] ?? null;
74
+ }
75
+
76
+ /**
77
+ * Registers a custom preset. Overrides a built-in if the same name is used.
78
+ */
79
+ export function registerPreset(name: string, def: PresetDef): void {
80
+ custom[name] = { ...def };
81
+ }
82
+
83
+ /**
84
+ * Resolves from/to/ease/duration from preset + explicit overrides. Used by animate() and revealInSequence.
85
+ * - If `preset` is set: expand via getPreset, then merge from/to/ease/duration from input.
86
+ * - If not: use defaults and merge from/to/ease/duration from input.
87
+ * `motion` is ignored in this stage (future: meta.motions).
88
+ *
89
+ * @param input - preset?, motion?, from?, to?, ease?, duration?
90
+ * @param defaults - fallbacks when a value is missing (e.g. from config or revealInSequence defaults).
91
+ * @returns { from, to, ease, duration } with `to` always set; `from` can be {} for gsap.to.
92
+ */
93
+ export function resolveAnimationFromInput(
94
+ input: {
95
+ preset?: string;
96
+ motion?: string;
97
+ from?: Record<string, string | number>;
98
+ to?: Record<string, string | number>;
99
+ ease?: string;
100
+ duration?: number;
101
+ },
102
+ defaults?: { from?: Record<string, string | number>; to?: Record<string, string | number>; ease?: string; duration?: number }
103
+ ): { from: Record<string, string | number>; to: Record<string, string | number>; ease: string; duration: number } {
104
+ let from: Record<string, string | number> = { ...(defaults?.from ?? {}) };
105
+ let to: Record<string, string | number> = { ...(defaults?.to ?? { opacity: 1 }) };
106
+ let ease = defaults?.ease ?? 'power2.out';
107
+ let duration = defaults?.duration ?? 0.5;
108
+
109
+ if (input.preset) {
110
+ const p = getPreset(input.preset);
111
+ if (p) {
112
+ from = { ...p.from };
113
+ to = { ...p.to };
114
+ ease = p.ease;
115
+ }
116
+ }
117
+
118
+ if (input.from && Object.keys(input.from).length) from = { ...from, ...input.from };
119
+ if (input.to && Object.keys(input.to).length) to = { ...to, ...input.to };
120
+ if (input.ease != null) ease = input.ease;
121
+ if (input.duration != null) duration = input.duration;
122
+
123
+ if (Object.keys(to).length === 0) to = { opacity: 1 };
124
+
125
+ return { from, to, ease, duration };
126
+ }
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Stagger: compute order and delays for sequential element animations.
3
+ * Modes: sequential, center-out, ends-in, wave, random.
4
+ *
5
+ * @module animation/stagger
6
+ * @see ANIMATION_IDEAS.md §2 Stagger modes
7
+ * @see ANIMATION_STRATEGY.md §7 Stagger
8
+ */
9
+
10
+ import type { StaggerMode, StaggerOptions, StaggerStep } from './types';
11
+
12
+ /**
13
+ * Seeded PRNG (mulberry32) for deterministic shuffle when mode is 'random'.
14
+ */
15
+ function mulberry32(seed: number): () => number {
16
+ return () => {
17
+ let t = (seed += 0x6d2b79f5);
18
+ t = Math.imul(t ^ (t >>> 15), t | 1);
19
+ t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
20
+ return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
21
+ };
22
+ }
23
+
24
+ function shuffleWithSeed<T>(arr: T[], seed: number): T[] {
25
+ const out = [...arr];
26
+ const rng = mulberry32(seed);
27
+ for (let i = out.length - 1; i > 0; i--) {
28
+ const j = Math.floor(rng() * (i + 1));
29
+ [out[i], out[j]] = [out[j], out[i]];
30
+ }
31
+ return out;
32
+ }
33
+
34
+ /**
35
+ * Computes ordered steps with delays for stagger modes.
36
+ *
37
+ * - **sequential**: delay = (i+1) * delayMs
38
+ * - **center-out**: order by distance from center (nearest first), then (i+1)*delayMs
39
+ * - **ends-in**: order by distance from center (farthest first), then (i+1)*delayMs
40
+ * - **wave**: delay = i * (delayMs * 0.6) for overlap
41
+ * - **random**: shuffle ids with randomSeed, then (i+1)*delayMs
42
+ *
43
+ * @param opts - ids, delayMs, mode (default 'sequential'), randomSeed (for random).
44
+ * @returns Array of { id, delayMs, index }.
45
+ */
46
+ export function computeStagger(opts: StaggerOptions): StaggerStep[] {
47
+ const { ids, delayMs, mode = 'sequential', randomSeed = 0 } = opts;
48
+ if (!ids.length) return [];
49
+
50
+ let ordered: string[];
51
+
52
+ switch (mode) {
53
+ case 'sequential':
54
+ ordered = ids;
55
+ break;
56
+ case 'center-out': {
57
+ const n = ids.length;
58
+ const center = (n - 1) / 2;
59
+ const withDist = ids.map((id, i) => ({ id, d: Math.abs(i - center) }));
60
+ withDist.sort((a, b) => a.d - b.d);
61
+ ordered = withDist.map((x) => x.id);
62
+ break;
63
+ }
64
+ case 'ends-in': {
65
+ const n = ids.length;
66
+ const center = (n - 1) / 2;
67
+ const withDist = ids.map((id, i) => ({ id, d: Math.abs(i - center) }));
68
+ withDist.sort((a, b) => b.d - a.d);
69
+ ordered = withDist.map((x) => x.id);
70
+ break;
71
+ }
72
+ case 'wave':
73
+ ordered = ids;
74
+ break;
75
+ case 'random':
76
+ ordered = shuffleWithSeed(ids, randomSeed);
77
+ break;
78
+ default:
79
+ ordered = ids;
80
+ }
81
+
82
+ const steps: StaggerStep[] = [];
83
+
84
+ if (mode === 'wave') {
85
+ for (let i = 0; i < ordered.length; i++) {
86
+ steps.push({ id: ordered[i], delayMs: i * (delayMs * 0.6), index: i });
87
+ }
88
+ } else {
89
+ for (let i = 0; i < ordered.length; i++) {
90
+ steps.push({ id: ordered[i], delayMs: (i + 1) * delayMs, index: i });
91
+ }
92
+ }
93
+
94
+ return steps;
95
+ }
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Animation system types. Used by presets, stagger, and the resolver.
3
+ *
4
+ * @module animation/types
5
+ * @see ANIMATION_STRATEGY.md
6
+ * @see ANIMATION_IDEAS.md
7
+ */
8
+
9
+ /**
10
+ * Stagger mode for revealInSequence and enter/exit. Controls the order and delays.
11
+ *
12
+ * - `sequential`: one after another; delay = (i+1) * delayMs
13
+ * - `center-out`: center first, then toward the ends
14
+ * - `ends-in`: ends first, then toward the center
15
+ * - `wave`: overlapping; delay = i * (delayMs * 0.6)
16
+ * - `random`: shuffled order (stable per slide when randomSeed is fixed), then sequential
17
+ */
18
+ export type StaggerMode = 'sequential' | 'center-out' | 'ends-in' | 'wave' | 'random';
19
+
20
+ /**
21
+ * Input for computing staggered steps. Used by revealInSequence and enter.
22
+ */
23
+ export interface StaggerOptions {
24
+ /** Element ids to stagger. Order can be changed by mode. */
25
+ ids: string[];
26
+ /** Base delay in ms between steps (exact meaning depends on mode). */
27
+ delayMs: number;
28
+ /** Stagger mode. Default: 'sequential'. */
29
+ mode?: StaggerMode;
30
+ /** For mode 'random', seed for deterministic shuffle. Omit for arbitrary order. */
31
+ randomSeed?: number;
32
+ }
33
+
34
+ /**
35
+ * One step in a stagger sequence: which element and when to start (delay in ms).
36
+ */
37
+ export interface StaggerStep {
38
+ /** Element id. */
39
+ id: string;
40
+ /** Delay in ms before starting this element. */
41
+ delayMs: number;
42
+ /** Index in the final ordered sequence (0-based). */
43
+ index: number;
44
+ }
45
+
46
+ /**
47
+ * Definition of a built-in or registered animation preset. from/to/ease only; duration typically from call-site or config.
48
+ */
49
+ export interface PresetDef {
50
+ from: Record<string, string | number>;
51
+ to: Record<string, string | number>;
52
+ ease: string;
53
+ }
@@ -0,0 +1,229 @@
1
+ <template>
2
+ <div class="min-h-screen bg-[#0f172a] text-slate-300 font-sans selection:bg-cyan-500/30 selection:text-cyan-200">
3
+ <!-- Navigation -->
4
+ <nav class="fixed top-0 left-0 right-0 z-50 backdrop-blur-md border-b border-white/5 bg-[#0f172a]/80">
5
+ <div class="max-w-7xl mx-auto px-6 h-20 flex items-center justify-between">
6
+ <div class="flex items-center gap-3">
7
+ <div
8
+ class="w-8 h-8 rounded-lg bg-gradient-to-br from-cyan-400 to-blue-600 flex items-center justify-center shadow-lg shadow-cyan-500/20">
9
+ <span class="text-white font-bold text-lg">L</span>
10
+ </div>
11
+ <span class="text-xl font-bold text-white tracking-tight">Lumina<span
12
+ class="text-cyan-400">Engine</span></span>
13
+ </div>
14
+ <div class="flex items-center gap-8">
15
+ <a href="#features" class="text-sm font-medium hover:text-white transition-colors">Features</a>
16
+ <a href="#showcase" class="text-sm font-medium hover:text-white transition-colors">Showcase</a>
17
+ <a href="https://github.com/lumina-engine" target="_blank"
18
+ class="text-sm font-medium hover:text-white transition-colors">GitHub</a>
19
+ <a href="/deck/deck"
20
+ class="px-5 py-2.5 rounded-full bg-white text-slate-900 font-semibold text-sm hover:bg-cyan-50 transition-all transform hover:scale-105 shadow-lg shadow-white/10">
21
+ Live Demo
22
+ </a>
23
+ </div>
24
+ </div>
25
+ </nav>
26
+
27
+ <!-- Hero Section -->
28
+ <header class="relative pt-40 pb-20 lg:pt-52 lg:pb-32 px-6 overflow-hidden">
29
+ <!-- Background Glows -->
30
+ <div
31
+ class="absolute top-0 left-1/2 -translate-x-1/2 w-full h-[600px] bg-gradient-to-b from-blue-500/10 to-transparent pointer-events-none rounded-full blur-3xl opacity-50">
32
+ </div>
33
+ <div
34
+ class="absolute top-20 right-0 w-[500px] h-[500px] bg-cyan-500/10 rounded-full blur-[100px] pointer-events-none">
35
+ </div>
36
+
37
+ <div class="max-w-7xl mx-auto relative z-10 text-center">
38
+ <div
39
+ class="inline-flex items-center gap-2 px-4 py-2 rounded-full bg-white/5 border border-white/10 text-cyan-400 text-sm font-medium mb-8 animate-fade-in-up">
40
+ <span class="w-2 h-2 rounded-full bg-cyan-400 animate-pulse"></span>
41
+ v8.0.0 Now Available
42
+ </div>
43
+ <h1
44
+ class="text-5xl md:text-7xl lg:text-8xl font-black text-white tracking-tight leading-tight mb-8 drop-shadow-2xl">
45
+ Cinematic Presentations<br>
46
+ <span
47
+ class="text-transparent bg-clip-text bg-gradient-to-r from-cyan-400 via-blue-500 to-purple-600">
48
+ for the Modern Web
49
+ </span>
50
+ </h1>
51
+ <p class="text-lg md:text-xl text-slate-400 max-w-2xl mx-auto mb-12 leading-relaxed">
52
+ Build stunning, high-performance slide decks using Vue 3 and GSAP.
53
+ Zero config, fully declarative, and infinitely customizable.
54
+ </p>
55
+ <div class="flex flex-col sm:flex-row items-center justify-center gap-6">
56
+ <a href="/deck/deck"
57
+ class="px-8 py-4 rounded-xl bg-gradient-to-r from-cyan-500 to-blue-600 text-white font-bold text-lg hover:shadow-2xl hover:shadow-cyan-500/25 transition-all transform hover:-translate-y-1">
58
+ Start Presentation
59
+ </a>
60
+ <a href="#code"
61
+ class="px-8 py-4 rounded-xl bg-white/5 border border-white/10 text-white font-semibold text-lg hover:bg-white/10 transition-all backdrop-blur-sm">
62
+ View Documentation
63
+ </a>
64
+ </div>
65
+ </div>
66
+ </header>
67
+
68
+ <!-- Feature Grid -->
69
+ <section id="features" class="py-24 bg-slate-900/50">
70
+ <div class="max-w-7xl mx-auto px-6">
71
+ <div class="grid md:grid-cols-3 gap-8">
72
+ <!-- Feature 1 -->
73
+ <div
74
+ class="p-8 rounded-3xl bg-white/5 border border-white/5 hover:border-cyan-500/30 transition-colors group">
75
+ <div
76
+ class="w-14 h-14 rounded-2xl bg-blue-500/10 flex items-center justify-center mb-6 group-hover:scale-110 transition-transform duration-300">
77
+ <svg class="w-7 h-7 text-blue-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
78
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
79
+ d="M13 10V3L4 14h7v7l9-11h-7z" />
80
+ </svg>
81
+ </div>
82
+ <h3 class="text-2xl font-bold text-white mb-3">Instant Performance</h3>
83
+ <p class="text-slate-400 leading-relaxed">
84
+ Powered by GSAP for butter-smooth 60fps animations, even with complex SVG and WebGL content.
85
+ </p>
86
+ </div>
87
+
88
+ <!-- Feature 2 -->
89
+ <div
90
+ class="p-8 rounded-3xl bg-white/5 border border-white/5 hover:border-purple-500/30 transition-colors group">
91
+ <div
92
+ class="w-14 h-14 rounded-2xl bg-purple-500/10 flex items-center justify-center mb-6 group-hover:scale-110 transition-transform duration-300">
93
+ <svg class="w-7 h-7 text-purple-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
94
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
95
+ d="M4 6h16M4 12h16m-7 6h7" />
96
+ </svg>
97
+ </div>
98
+ <h3 class="text-2xl font-bold text-white mb-3">Declarative Syntax</h3>
99
+ <p class="text-slate-400 leading-relaxed">
100
+ Define your slides using simple JSON or Vue components. No messy imperative code required.
101
+ </p>
102
+ </div>
103
+
104
+ <!-- Feature 3 -->
105
+ <div
106
+ class="p-8 rounded-3xl bg-white/5 border border-white/5 hover:border-emerald-500/30 transition-colors group">
107
+ <div
108
+ class="w-14 h-14 rounded-2xl bg-emerald-500/10 flex items-center justify-center mb-6 group-hover:scale-110 transition-transform duration-300">
109
+ <svg class="w-7 h-7 text-emerald-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
110
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
111
+ d="M7 21a4 4 0 01-4-4V5a2 2 0 012-2h4a2 2 0 012 2v12a4 4 0 01-2 2h-2zM15 7h6a2 2 0 012 2v2a2 2 0 01-2 2h-6V7zM15 14h6a2 2 0 012 2v2a2 2 0 01-2 2h-6v-4z" />
112
+ </svg>
113
+ </div>
114
+ <h3 class="text-2xl font-bold text-white mb-3">Theme System</h3>
115
+ <p class="text-slate-400 leading-relaxed">
116
+ Built-in support for dark mode, layouts, and custom transitions. Fully Tailwind compatible.
117
+ </p>
118
+ </div>
119
+ </div>
120
+ </div>
121
+ </section>
122
+
123
+ <!-- Code Preview -->
124
+ <section id="code" class="py-24 px-6">
125
+ <div class="max-w-6xl mx-auto grid lg:grid-cols-2 gap-12 items-center">
126
+ <div>
127
+ <h2 class="text-3xl md:text-5xl font-bold text-white mb-6">Simple yet Powerful</h2>
128
+ <p class="text-lg text-slate-400 mb-8 leading-relaxed">
129
+ Create complex animations without the headache. Lumina Engine handles the timeline, you handle
130
+ the content.
131
+ </p>
132
+ <ul class="space-y-4 mb-8">
133
+ <li class="flex items-center gap-3 text-slate-300">
134
+ <div
135
+ class="w-6 h-6 rounded-full bg-cyan-500/20 flex items-center justify-center text-cyan-400 text-xs">
136
+ ✓</div>
137
+ Automatic slide transitions
138
+ </li>
139
+ <li class="flex items-center gap-3 text-slate-300">
140
+ <div
141
+ class="w-6 h-6 rounded-full bg-cyan-500/20 flex items-center justify-center text-cyan-400 text-xs">
142
+ ✓</div>
143
+ Built-in keyboard events
144
+ </li>
145
+ <li class="flex items-center gap-3 text-slate-300">
146
+ <div
147
+ class="w-6 h-6 rounded-full bg-cyan-500/20 flex items-center justify-center text-cyan-400 text-xs">
148
+ ✓</div>
149
+ Reactive state management
150
+ </li>
151
+ </ul>
152
+ </div>
153
+ <div class="relative group">
154
+ <div
155
+ class="absolute -inset-1 bg-gradient-to-r from-cyan-600 to-blue-600 rounded-2xl blur opacity-25 group-hover:opacity-50 transition duration-1000">
156
+ </div>
157
+ <div class="relative rounded-xl bg-[#0B1120] border border-white/5 overflow-hidden shadow-2xl">
158
+ <div class="flex items-center px-4 py-3 bg-white/5 border-b border-white/5">
159
+ <div class="flex gap-2">
160
+ <div class="w-3 h-3 rounded-full bg-red-500/50"></div>
161
+ <div class="w-3 h-3 rounded-full bg-yellow-500/50"></div>
162
+ <div class="w-3 h-3 rounded-full bg-green-500/50"></div>
163
+ </div>
164
+ <div class="ml-4 text-xs text-slate-500 font-mono">MyDeck.json</div>
165
+ </div>
166
+ <div class="p-6 font-mono text-sm overflow-x-auto">
167
+ <div class="text-blue-400"> const deck = [</div>
168
+ <div class="pl-4">
169
+ <span class="text-purple-400">{</span>
170
+ <div class="pl-4">
171
+ <span class="text-sky-300">id:</span> <span
172
+ class="text-emerald-400">"slide-1"</span>,<br>
173
+ <span class="text-sky-300">layout:</span> <span
174
+ class="text-emerald-400">"hero"</span>,<br>
175
+ <span class="text-sky-300">content:</span> <span class="text-emerald-400">"Hello
176
+ World"</span>,<br>
177
+ <span class="text-sky-300">animation:</span> <span
178
+ class="text-emerald-400">"fade-in-up"</span>
179
+ </div>
180
+ <span class="text-purple-400">},</span>
181
+ </div>
182
+ <div class="pl-4">
183
+ <span class="text-purple-400">{</span>
184
+ <div class="pl-4">
185
+ <span class="text-sky-300">id:</span> <span
186
+ class="text-emerald-400">"slide-2"</span>,<br>
187
+ <span class="text-sky-300">layout:</span> <span
188
+ class="text-emerald-400">"split"</span>,<br>
189
+ <span class="text-sky-300">image:</span> <span
190
+ class="text-emerald-400">"/demo.png"</span>
191
+ </div>
192
+ <span class="text-purple-400">}</span>
193
+ </div>
194
+ <div class="text-blue-400">]</div>
195
+ </div>
196
+ </div>
197
+ </div>
198
+ </div>
199
+ </section>
200
+
201
+ <!-- Footer -->
202
+ <footer class="py-12 border-t border-white/5 bg-[#0f172a] text-center">
203
+ <p class="text-slate-500 text-sm">
204
+ © {{ new Date().getFullYear() }} Lumina Engine. Released under MIT License. <br>
205
+ Created by <a href="https://pailletjp.com" target="_blank"
206
+ class="text-slate-400 hover:text-cyan-400 transition-colors">Juan Pablo Paillet</a> for the Vue
207
+ community.
208
+ </p>
209
+ </footer>
210
+ </div>
211
+ </template>
212
+
213
+ <style scoped>
214
+ .animate-fade-in-up {
215
+ animation: fadeInUp 0.8s ease-out forwards;
216
+ }
217
+
218
+ @keyframes fadeInUp {
219
+ from {
220
+ opacity: 0;
221
+ transform: translateY(20px);
222
+ }
223
+
224
+ to {
225
+ opacity: 1;
226
+ transform: translateY(0);
227
+ }
228
+ }
229
+ </style>