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.
- package/LUMINA_LLM_EXAMPLES.json +234 -0
- package/README.md +18 -18
- package/dist/lumina-slides.js +13207 -12659
- package/dist/lumina-slides.umd.cjs +215 -215
- package/dist/style.css +1 -1
- package/package.json +5 -4
- package/src/App.vue +16 -0
- package/src/animation/index.ts +11 -0
- package/src/animation/registry.ts +126 -0
- package/src/animation/stagger.ts +95 -0
- package/src/animation/types.ts +53 -0
- package/src/components/LandingPage.vue +229 -0
- package/src/components/LuminaDeck.vue +224 -0
- package/src/components/LuminaSpeakerNotes.vue +701 -0
- package/src/components/base/BaseSlide.vue +122 -0
- package/src/components/base/LuminaElement.vue +67 -0
- package/src/components/base/VideoPlayer.vue +204 -0
- package/src/components/layouts/LayoutAuto.vue +71 -0
- package/src/components/layouts/LayoutChart.vue +287 -0
- package/src/components/layouts/LayoutCustom.vue +92 -0
- package/src/components/layouts/LayoutDiagram.vue +253 -0
- package/src/components/layouts/LayoutFeatures.vue +121 -0
- package/src/components/layouts/LayoutFlex.vue +172 -0
- package/src/components/layouts/LayoutFree.vue +62 -0
- package/src/components/layouts/LayoutHalf.vue +127 -0
- package/src/components/layouts/LayoutStatement.vue +74 -0
- package/src/components/layouts/LayoutSteps.vue +106 -0
- package/src/components/layouts/LayoutTimeline.vue +104 -0
- package/src/components/layouts/LayoutVideo.vue +41 -0
- package/src/components/parts/FlexBullets.vue +45 -0
- package/src/components/parts/FlexButton.vue +132 -0
- package/src/components/parts/FlexImage.vue +54 -0
- package/src/components/parts/FlexOrdered.vue +44 -0
- package/src/components/parts/FlexSpacer.vue +13 -0
- package/src/components/parts/FlexStepper.vue +59 -0
- package/src/components/parts/FlexText.vue +29 -0
- package/src/components/parts/FlexTimeline.vue +67 -0
- package/src/components/parts/FlexTitle.vue +39 -0
- package/src/components/parts/LuminaBackground.vue +100 -0
- package/src/components/site/LivePreview.vue +101 -0
- package/src/components/site/SiteApi.vue +301 -0
- package/src/components/site/SiteDashboard.vue +604 -0
- package/src/components/site/SiteDocs.vue +3267 -0
- package/src/components/site/SiteExamples.vue +65 -0
- package/src/components/site/SiteFooter.vue +6 -0
- package/src/components/site/SiteHome.vue +362 -0
- package/src/components/site/SiteNavBar.vue +122 -0
- package/src/components/site/SitePlayground.vue +389 -0
- package/src/components/site/SitePromptBuilder.vue +266 -0
- package/src/components/site/SiteUserMenu.vue +90 -0
- package/src/components/studio/ActionEditor.vue +108 -0
- package/src/components/studio/ArrayEditor.vue +124 -0
- package/src/components/studio/CollapsibleSection.vue +33 -0
- package/src/components/studio/ColorField.vue +22 -0
- package/src/components/studio/EditorCanvas.vue +326 -0
- package/src/components/studio/EditorLayoutFeatures.vue +18 -0
- package/src/components/studio/EditorLayoutFixed.vue +46 -0
- package/src/components/studio/EditorLayoutFlex.vue +133 -0
- package/src/components/studio/EditorLayoutHalf.vue +18 -0
- package/src/components/studio/EditorLayoutStatement.vue +18 -0
- package/src/components/studio/EditorLayoutSteps.vue +18 -0
- package/src/components/studio/EditorLayoutTimeline.vue +18 -0
- package/src/components/studio/EditorNode.vue +89 -0
- package/src/components/studio/FieldEditor.vue +133 -0
- package/src/components/studio/IconPicker.vue +109 -0
- package/src/components/studio/LayerItem.vue +117 -0
- package/src/components/studio/LuminaStudio.vue +30 -0
- package/src/components/studio/SaveSuccessModal.vue +138 -0
- package/src/components/studio/SlideNavigator.vue +373 -0
- package/src/components/studio/SliderField.vue +44 -0
- package/src/components/studio/StudioInspector.vue +595 -0
- package/src/components/studio/StudioJsonEditor.vue +191 -0
- package/src/components/studio/StudioLayers.vue +145 -0
- package/src/components/studio/StudioSettings.vue +514 -0
- package/src/components/studio/StudioSidebar.vue +29 -0
- package/src/components/studio/StudioToolbar.vue +222 -0
- package/src/components/studio/fieldLabels.ts +224 -0
- package/src/components/studio/inspectors/DiagramEdgeEditor.vue +77 -0
- package/src/components/studio/inspectors/DiagramNodeEditor.vue +117 -0
- package/src/components/studio/nodes/StudioDiagramNode.vue +138 -0
- package/src/composables/useAuth.ts +87 -0
- package/src/composables/useEditor.ts +224 -0
- package/src/composables/useElementState.ts +81 -0
- package/src/composables/useFlexLayout.ts +122 -0
- package/src/composables/useKeyboard.ts +45 -0
- package/src/composables/useLumina.ts +32 -0
- package/src/composables/useStudio.ts +87 -0
- package/src/composables/useSwipeNav.ts +53 -0
- package/src/composables/useTransition.ts +373 -0
- package/src/core/Lumina.ts +819 -0
- package/src/core/animationConfig.ts +251 -0
- package/src/core/compression.ts +34 -0
- package/src/core/elementController.ts +170 -0
- package/src/core/elementId.ts +27 -0
- package/src/core/elementResolver.ts +207 -0
- package/src/core/events.ts +53 -0
- package/src/core/fonts.ts +100 -0
- package/src/core/presets.ts +231 -0
- package/src/core/prompts.ts +272 -0
- package/src/core/schema.ts +478 -0
- package/src/core/speaker-channel.ts +250 -0
- package/src/core/store.ts +461 -0
- package/src/core/theme.ts +666 -0
- package/src/core/types.ts +1611 -0
- package/src/directives/vStudio.ts +45 -0
- package/src/index.ts +175 -0
- package/src/main.ts +17 -0
- package/src/router/index.ts +92 -0
- package/src/style/main.css +462 -0
- package/src/utils/deep.ts +127 -0
- package/src/utils/firebase.ts +184 -0
- package/src/utils/streaming.ts +134 -0
- package/src/views/DashboardView.vue +32 -0
- package/src/views/DeckView.vue +289 -0
- package/src/views/HomeView.vue +17 -0
- package/src/views/SiteLayout.vue +21 -0
- package/src/views/StudioView.vue +61 -0
- package/src/vite-env.d.ts +6 -0
- 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>
|