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,3267 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="min-h-screen pt-32 px-6 md:px-12 max-w-8xl mx-auto flex flex-col md:flex-row gap-16">
|
|
3
|
+
<!-- Sidebar Navigation -->
|
|
4
|
+
<aside class="w-full md:w-64 flex-shrink-0 hidden md:block">
|
|
5
|
+
<div class="sticky top-32 space-y-10">
|
|
6
|
+
<div v-for="(group, i) in navigation" :key="i">
|
|
7
|
+
<!-- Group Title -->
|
|
8
|
+
<h3 class="text-xs font-bold uppercase tracking-widest text-white/30 mb-4 pl-3">
|
|
9
|
+
{{ group.title }}
|
|
10
|
+
</h3>
|
|
11
|
+
|
|
12
|
+
<!-- Links -->
|
|
13
|
+
<ul class="space-y-1 relative border-l border-white/5">
|
|
14
|
+
<li v-for="item in group.items" :key="item.id">
|
|
15
|
+
<button @click="activeSection = item.id; scrollToTop()" :class="[
|
|
16
|
+
'group w-full text-left px-4 py-2 text-sm transition-all duration-300 border-l-2 -ml-[1px]',
|
|
17
|
+
activeSection === item.id
|
|
18
|
+
? 'border-blue-500 text-white font-medium bg-blue-500/5'
|
|
19
|
+
: 'border-transparent text-white/50 hover:text-white hover:border-white/20'
|
|
20
|
+
]">
|
|
21
|
+
{{ item.label }}
|
|
22
|
+
</button>
|
|
23
|
+
</li>
|
|
24
|
+
</ul>
|
|
25
|
+
</div>
|
|
26
|
+
</div>
|
|
27
|
+
</aside>
|
|
28
|
+
|
|
29
|
+
<!-- Main Content Area -->
|
|
30
|
+
<main class="flex-1 w-full min-w-0 pb-32">
|
|
31
|
+
<Transition name="fade" mode="out-in">
|
|
32
|
+
<div :key="activeSection" class="doc-content max-w-6xl">
|
|
33
|
+
|
|
34
|
+
<!-- MEDIA & VIDEO -->
|
|
35
|
+
<div v-if="activeSection === 'media'">
|
|
36
|
+
<h1>Media & Video</h1>
|
|
37
|
+
<p class="lead">Lumina supports video backgrounds on any slide, and video elements in Half and Flex layouts.</p>
|
|
38
|
+
|
|
39
|
+
<h2>Video object (VideoProperties)</h2>
|
|
40
|
+
<p>Use <code>{ type: "video", src, poster?, autoplay?, loop?, muted?, controls?, className? }</code>. For <strong>backgrounds</strong>, wrap in <code>background: { type: "video", src, ... }</code> and optionally set <code>opacity</code> on the slide. For <strong>Half</strong>, use <code>video: { type: "video", src, autoplay?, muted?, loop? }</code> instead of <code>image</code>. For <strong>Flex</strong>, use an element <code>{ type: "video", src, controls?, size?, fill?, fit? }</code>.</p>
|
|
41
|
+
|
|
42
|
+
<h2>Video Backgrounds</h2>
|
|
43
|
+
<p>Set <code>background</code> on any slide to a video object. Works on <strong>all layouts</strong>. You can add <code>opacity</code> for an overlay effect.</p>
|
|
44
|
+
|
|
45
|
+
<div class="my-8">
|
|
46
|
+
<LivePreview :initial-code="EXAMPLES.video" />
|
|
47
|
+
</div>
|
|
48
|
+
|
|
49
|
+
<h2>Video Elements</h2>
|
|
50
|
+
<p>In Half and Flex layouts, you can use <code>video</code> instead of <code>image</code> (Half) or a <code>type: "video"</code> element (Flex).</p>
|
|
51
|
+
|
|
52
|
+
<h3>In Half Layout</h3>
|
|
53
|
+
<div class="my-6">
|
|
54
|
+
<LivePreview :initial-code="EXAMPLES.video_half" />
|
|
55
|
+
</div>
|
|
56
|
+
|
|
57
|
+
<h3>In Flex Layout</h3>
|
|
58
|
+
<div class="my-6">
|
|
59
|
+
<LivePreview :initial-code="EXAMPLES.video_flex" />
|
|
60
|
+
</div>
|
|
61
|
+
</div>
|
|
62
|
+
|
|
63
|
+
<!-- INTRODUCTION -->
|
|
64
|
+
<div v-else-if="activeSection === 'intro'">
|
|
65
|
+
<h1>Introduction</h1>
|
|
66
|
+
<p class="lead text-2xl text-white font-light">
|
|
67
|
+
Lumina is a high-performance, Universal Presentation Engine.
|
|
68
|
+
</p>
|
|
69
|
+
<p>
|
|
70
|
+
Unlike traditional tools that trap your content in proprietary file formats, Lumina defines
|
|
71
|
+
presentations as <strong>pure JSON data</strong>. This approach enables programmatic
|
|
72
|
+
generation, easy version control, and dynamic storytelling experiences.
|
|
73
|
+
</p>
|
|
74
|
+
|
|
75
|
+
<div class="grid grid-cols-1 md:grid-cols-2 gap-6 my-12 not-prose">
|
|
76
|
+
<div
|
|
77
|
+
class="group p-8 bg-white/[0.02] hover:bg-white/[0.04] rounded-2xl border border-white/5 hover:border-white/10 transition-all duration-500 hover:-translate-y-1 shadow-lg hover:shadow-2xl hover:shadow-blue-500/5">
|
|
78
|
+
<div
|
|
79
|
+
class="w-12 h-12 rounded-full bg-yellow-500/10 flex items-center justify-center mb-6">
|
|
80
|
+
<i class="ph-thin ph-lightning text-xl text-yellow-400"></i>
|
|
81
|
+
</div>
|
|
82
|
+
<h3
|
|
83
|
+
class="text-xl font-bold mb-2 text-white group-hover:text-yellow-400 transition-colors">
|
|
84
|
+
Fast by default</h3>
|
|
85
|
+
<p class="text-sm text-white/50 leading-relaxed">Bundles Vue 3 and GSAP internally to
|
|
86
|
+
ensure instant load times and buttery smooth 60fps animations.</p>
|
|
87
|
+
</div>
|
|
88
|
+
|
|
89
|
+
<div
|
|
90
|
+
class="group p-8 bg-white/[0.02] hover:bg-white/[0.04] rounded-2xl border border-white/5 hover:border-white/10 transition-all duration-500 hover:-translate-y-1 shadow-lg hover:shadow-2xl hover:shadow-blue-500/5">
|
|
91
|
+
<div
|
|
92
|
+
class="w-12 h-12 rounded-full bg-blue-500/10 flex items-center justify-center mb-6">
|
|
93
|
+
<i class="ph-thin ph-code text-xl text-blue-400"></i>
|
|
94
|
+
</div>
|
|
95
|
+
<h3
|
|
96
|
+
class="text-xl font-bold mb-2 text-white group-hover:text-blue-400 transition-colors">
|
|
97
|
+
Declarative JSON</h3>
|
|
98
|
+
<p class="text-sm text-white/50 leading-relaxed">Manage your content as code. Git-diff
|
|
99
|
+
your presentations. Generate decks from APIs.</p>
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
102
|
+
</div>
|
|
103
|
+
|
|
104
|
+
<!-- INSTALLATION -->
|
|
105
|
+
<div v-else-if="activeSection === 'install'">
|
|
106
|
+
<h1>Installation</h1>
|
|
107
|
+
<p>Lumina is available as a Universal NPM package. It works in any JavaScript environment
|
|
108
|
+
(Vanilla, React, Vue, Svelte, etc.). Vue and GSAP are bundled; Chart.js is an optional peer only if you use <code>type: "chart"</code> slides.</p>
|
|
109
|
+
|
|
110
|
+
<div class="not-prose my-8">
|
|
111
|
+
<div class="bg-[#0f0f0f] border border-white/10 rounded-xl overflow-hidden shadow-2xl">
|
|
112
|
+
<div class="flex items-center px-4 py-2 border-b border-white/5 bg-white/[0.02]">
|
|
113
|
+
<div class="flex gap-1.5">
|
|
114
|
+
<div class="w-2.5 h-2.5 rounded-full bg-red-500/50"></div>
|
|
115
|
+
<div class="w-2.5 h-2.5 rounded-full bg-yellow-500/50"></div>
|
|
116
|
+
<div class="w-2.5 h-2.5 rounded-full bg-green-500/50"></div>
|
|
117
|
+
</div>
|
|
118
|
+
<div class="ml-4 text-xs text-white/30 font-mono">Terminal</div>
|
|
119
|
+
</div>
|
|
120
|
+
<div class="p-6 overflow-x-auto space-y-2">
|
|
121
|
+
<code class="font-mono text-sm block">
|
|
122
|
+
<span class="text-purple-400">npm</span> install lumina-slides
|
|
123
|
+
</code>
|
|
124
|
+
<code class="font-mono text-sm text-white/50 block">
|
|
125
|
+
<span class="text-gray-500"># Optional, only for chart slides:</span> npm install chart.js
|
|
126
|
+
</code>
|
|
127
|
+
</div>
|
|
128
|
+
</div>
|
|
129
|
+
</div>
|
|
130
|
+
|
|
131
|
+
<h3>Requirements</h3>
|
|
132
|
+
<ul>
|
|
133
|
+
<li><strong>Node.js 18+</strong> for development.</li>
|
|
134
|
+
<li><strong>Vue 3 and GSAP</strong> are bundled; no separate install.</li>
|
|
135
|
+
<li><strong>Chart.js ^4</strong> (optional): install only if your deck uses <code>type: "chart"</code>.</li>
|
|
136
|
+
</ul>
|
|
137
|
+
</div>
|
|
138
|
+
|
|
139
|
+
<!-- SETUP -->
|
|
140
|
+
<div v-else-if="activeSection === 'setup'">
|
|
141
|
+
<h1>Quick Start</h1>
|
|
142
|
+
<p>Import the stylesheet and initialize the engine in your main entry file.
|
|
143
|
+
</p>
|
|
144
|
+
|
|
145
|
+
<pre class="language-js"><code><span class="text-purple-400">import</span> { Lumina } <span class="text-purple-400">from</span> 'lumina-slides';
|
|
146
|
+
<span class="text-purple-400">import</span> 'lumina-slides/style.css';
|
|
147
|
+
|
|
148
|
+
<span class="text-gray-500">// Initialize (theme, loop, navigation, touch, etc.)</span>
|
|
149
|
+
<span class="text-blue-400">const</span> engine = <span class="text-blue-400">new</span> Lumina('#app', {
|
|
150
|
+
theme: <span class="text-green-400">'ocean'</span>,
|
|
151
|
+
loop: <span class="text-yellow-400">true</span>,
|
|
152
|
+
navigation: <span class="text-yellow-400">true</span>,
|
|
153
|
+
touch: <span class="text-yellow-400">true</span>
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
<span class="text-gray-500">// Load your deck</span>
|
|
157
|
+
engine.load(myDeckData);</code></pre>
|
|
158
|
+
</div>
|
|
159
|
+
|
|
160
|
+
<!-- DECK STRUCTURE -->
|
|
161
|
+
<div v-else-if="activeSection === 'deck'">
|
|
162
|
+
<h1>Deck Structure</h1>
|
|
163
|
+
<p>A deck is a JSON object with <code>meta</code> and <code>slides</code>. Both are required.</p>
|
|
164
|
+
|
|
165
|
+
<pre><code>{
|
|
166
|
+
<span class="text-blue-400">"meta"</span>: {
|
|
167
|
+
<span class="text-blue-400">"title"</span>: <span class="text-green-400">"My Presentation"</span>,
|
|
168
|
+
<span class="text-blue-400">"author"</span>: <span class="text-green-400">"Dev Team"</span>,
|
|
169
|
+
<span class="text-gray-500">// Optional: theme preset or ThemeConfig</span>
|
|
170
|
+
<span class="text-blue-400">"theme"</span>: <span class="text-green-400">"ocean"</span>,
|
|
171
|
+
<span class="text-gray-500">// Optional: start elements hidden (see Element Control)</span>
|
|
172
|
+
<span class="text-blue-400">"initialElementState"</span>: { <span class="text-green-400">"s0-tag"</span>: { <span class="text-blue-400">"visible"</span>: <span class="text-yellow-400">false</span> } },
|
|
173
|
+
<span class="text-blue-400">"elementControl"</span>: { <span class="text-blue-400">"defaultVisible"</span>: <span class="text-yellow-400">false</span> },
|
|
174
|
+
<span class="text-gray-500">// Optional: animation overrides (durationIn, revealDelayMs, etc.)</span>
|
|
175
|
+
<span class="text-blue-400">"effects"</span>: { <span class="text-blue-400">"durationIn"</span>: <span class="text-cyan-400">1</span> }
|
|
176
|
+
},
|
|
177
|
+
<span class="text-blue-400">"slides"</span>: [
|
|
178
|
+
{ <span class="text-blue-400">"type"</span>: <span class="text-green-400">"statement"</span>, <span class="text-blue-400">"title"</span>: <span class="text-green-400">"Hello"</span>, <span class="text-blue-400">"subtitle"</span>: <span class="text-green-400">"World"</span> }
|
|
179
|
+
<span class="text-gray-500">// Each slide: type, and props per layout (title, image, timeline, ...)</span>
|
|
180
|
+
]
|
|
181
|
+
}</code></pre>
|
|
182
|
+
|
|
183
|
+
<h3>Common slide-level properties</h3>
|
|
184
|
+
<p>Any slide can include: <code>sizing</code> (<code>"viewport"</code> | <code>"container"</code>), <code>background</code> (image URL or <code>{ type: "video", src, ... }</code>), <code>notes</code> (speaker notes), <code>class</code>, <code>timelineTracks</code> (for keyframe animations; see <em>Timeline (keyframes)</em>). Layout-specific props (e.g. <code>image</code>, <code>timeline</code>, <code>features</code>) are described in each layout reference.</p>
|
|
185
|
+
</div>
|
|
186
|
+
|
|
187
|
+
<!-- SLIDE LAYOUTS -->
|
|
188
|
+
<div v-else-if="activeSection === 'slides'">
|
|
189
|
+
<h1>Slide Layouts</h1>
|
|
190
|
+
<p>Lumina includes responsive layouts for common scenarios. Each layout has a reference section with a full property table.</p>
|
|
191
|
+
|
|
192
|
+
<div class="grid grid-cols-1 gap-12 mt-12 not-prose">
|
|
193
|
+
<!-- Statement -->
|
|
194
|
+
<div class="p-8 rounded-2xl bg-white/[0.02] border border-white/5 shadow-2xl">
|
|
195
|
+
<div class="flex items-center gap-4 mb-6">
|
|
196
|
+
<div
|
|
197
|
+
class="w-10 h-10 rounded-lg bg-blue-500/20 text-blue-400 flex items-center justify-center font-bold text-lg">
|
|
198
|
+
1</div>
|
|
199
|
+
<div>
|
|
200
|
+
<h2 class="text-2xl font-bold text-white mb-1">Statement</h2>
|
|
201
|
+
<p class="text-sm text-white/50">High impact text for big ideas. Ideal for
|
|
202
|
+
section headers or punchlines.</p>
|
|
203
|
+
</div>
|
|
204
|
+
</div>
|
|
205
|
+
<div class="prose prose-invert max-w-none prose-pre:bg-black/50 prose-pre:border-none">
|
|
206
|
+
<pre><code>{
|
|
207
|
+
<span class="text-blue-400">"type"</span>: <span class="text-green-400">"statement"</span>,
|
|
208
|
+
<span class="text-blue-400">"tag"</span>: <span class="text-green-400">"Optional label"</span>,
|
|
209
|
+
<span class="text-blue-400">"title"</span>: <span class="text-green-400">"Hello World"</span>,
|
|
210
|
+
<span class="text-blue-400">"subtitle"</span>: <span class="text-green-400">"This is a statement slide."</span>
|
|
211
|
+
}</code></pre>
|
|
212
|
+
</div>
|
|
213
|
+
<p class="text-sm text-white/50 mt-4">Properties: <code>title</code> (required), <code>tag</code>, <code>subtitle</code> (optional).</p>
|
|
214
|
+
</div>
|
|
215
|
+
|
|
216
|
+
<!-- Half -->
|
|
217
|
+
<div class="p-8 rounded-2xl bg-white/[0.02] border border-white/5 shadow-2xl">
|
|
218
|
+
<div class="flex items-center gap-4 mb-6">
|
|
219
|
+
<div
|
|
220
|
+
class="w-10 h-10 rounded-lg bg-purple-500/20 text-purple-400 flex items-center justify-center font-bold text-lg">
|
|
221
|
+
2</div>
|
|
222
|
+
<div>
|
|
223
|
+
<h2 class="text-2xl font-bold text-white mb-1">Half / Split</h2>
|
|
224
|
+
<p class="text-sm text-white/50">Image or video on one side, content on the other. <code>imageSide</code>: <code>left</code> | <code>right</code>. Use <code>image</code> or <code>video</code> (<code>{ type: "video", src, autoplay?, muted?, loop?, controls? }</code>). Optional: <code>tag</code>, <code>cta</code> (button label).</p>
|
|
225
|
+
</div>
|
|
226
|
+
</div>
|
|
227
|
+
<div class="prose prose-invert max-w-none prose-pre:bg-black/50 prose-pre:border-none">
|
|
228
|
+
<pre><code>{
|
|
229
|
+
<span class="text-blue-400">"type"</span>: <span class="text-green-400">"half"</span>,
|
|
230
|
+
<span class="text-blue-400">"imageSide"</span>: <span class="text-green-400">"right"</span>,
|
|
231
|
+
<span class="text-blue-400">"image"</span>: <span class="text-green-400">"/assets/demo.jpg"</span>,
|
|
232
|
+
<span class="text-blue-400">"tag"</span>: <span class="text-green-400">"Optional"</span>,
|
|
233
|
+
<span class="text-blue-400">"title"</span>: <span class="text-green-400">"Split Layout"</span>,
|
|
234
|
+
<span class="text-blue-400">"paragraphs"</span>: [<span class="text-green-400">"Content goes here."</span>],
|
|
235
|
+
<span class="text-blue-400">"cta"</span>: <span class="text-green-400">"Learn More"</span>
|
|
236
|
+
}</code></pre>
|
|
237
|
+
</div>
|
|
238
|
+
</div>
|
|
239
|
+
|
|
240
|
+
<!-- Features -->
|
|
241
|
+
<div class="p-8 rounded-2xl bg-white/[0.02] border border-white/5 shadow-2xl">
|
|
242
|
+
<div class="flex items-center gap-4 mb-6">
|
|
243
|
+
<div
|
|
244
|
+
class="w-10 h-10 rounded-lg bg-yellow-500/20 text-yellow-400 flex items-center justify-center font-bold text-lg">
|
|
245
|
+
3</div>
|
|
246
|
+
<div>
|
|
247
|
+
<h2 class="text-2xl font-bold text-white mb-1">Features</h2>
|
|
248
|
+
<p class="text-sm text-white/50">A responsive grid of feature cards. Each item: <code>title</code>, <code>desc</code> (or <code>description</code>), <code>icon</code> (e.g. <code>fa-bolt</code>, <code>star</code>, <code>zap</code>); optional <code>class</code>, <code>id</code>. Optional section <code>description</code>.</p>
|
|
249
|
+
</div>
|
|
250
|
+
</div>
|
|
251
|
+
<div class="prose prose-invert max-w-none prose-pre:bg-black/50 prose-pre:border-none">
|
|
252
|
+
<pre><code>{
|
|
253
|
+
<span class="text-blue-400">"type"</span>: <span class="text-green-400">"features"</span>,
|
|
254
|
+
<span class="text-blue-400">"title"</span>: <span class="text-green-400">"Core Features"</span>,
|
|
255
|
+
<span class="text-blue-400">"description"</span>: <span class="text-green-400">"Optional"</span>,
|
|
256
|
+
<span class="text-blue-400">"features"</span>: [
|
|
257
|
+
{ <span class="text-blue-400">"class"</span>: <span class="text-green-400">""</span>, <span class="text-blue-400">"title"</span>: <span class="text-green-400">"Fast"</span>, <span class="text-blue-400">"desc"</span>: <span class="text-green-400">"60fps"</span>, <span class="text-blue-400">"icon"</span>: <span class="text-green-400">"fa-bolt"</span> }
|
|
258
|
+
]
|
|
259
|
+
}</code></pre>
|
|
260
|
+
</div>
|
|
261
|
+
</div>
|
|
262
|
+
|
|
263
|
+
<!-- Timeline -->
|
|
264
|
+
<div class="p-8 rounded-2xl bg-white/[0.02] border border-white/5 shadow-2xl">
|
|
265
|
+
<div class="flex items-center gap-4 mb-6">
|
|
266
|
+
<div
|
|
267
|
+
class="w-10 h-10 rounded-lg bg-green-500/20 text-green-400 flex items-center justify-center font-bold text-lg">
|
|
268
|
+
4</div>
|
|
269
|
+
<div>
|
|
270
|
+
<h2 class="text-2xl font-bold text-white mb-1">Timeline</h2>
|
|
271
|
+
<p class="text-sm text-white/50">Chronological events in a vertical layout. Each item: <code>date</code>, <code>title</code>, <code>description</code>; optional <code>icon</code>, <code>id</code>.</p>
|
|
272
|
+
</div>
|
|
273
|
+
</div>
|
|
274
|
+
<div class="prose prose-invert max-w-none prose-pre:bg-black/50 prose-pre:border-none">
|
|
275
|
+
<pre><code>{
|
|
276
|
+
<span class="text-blue-400">"type"</span>: <span class="text-green-400">"timeline"</span>,
|
|
277
|
+
<span class="text-blue-400">"title"</span>: <span class="text-green-400">"History"</span>,
|
|
278
|
+
<span class="text-blue-400">"subtitle"</span>: <span class="text-green-400">"Optional"</span>,
|
|
279
|
+
<span class="text-blue-400">"timeline"</span>: [
|
|
280
|
+
{ <span class="text-blue-400">"date"</span>: <span class="text-green-400">"2024"</span>, <span class="text-blue-400">"title"</span>: <span class="text-green-400">"Launch"</span>, <span class="text-blue-400">"description"</span>: <span class="text-green-400">"V1 Released"</span> }
|
|
281
|
+
]
|
|
282
|
+
}</code></pre>
|
|
283
|
+
</div>
|
|
284
|
+
</div>
|
|
285
|
+
|
|
286
|
+
<!-- Flex -->
|
|
287
|
+
<div class="p-8 rounded-2xl bg-white/[0.02] border border-white/5 shadow-2xl">
|
|
288
|
+
<div class="flex items-center gap-4 mb-6">
|
|
289
|
+
<div
|
|
290
|
+
class="w-10 h-10 rounded-lg bg-cyan-500/20 text-cyan-400 flex items-center justify-center font-bold text-lg">
|
|
291
|
+
5</div>
|
|
292
|
+
<div>
|
|
293
|
+
<h2 class="text-2xl font-bold text-white mb-1">Flex</h2>
|
|
294
|
+
<p class="text-sm text-white/50">Flow-based layout with size tokens (<code>half</code>, <code>third</code>, …). Elements: <code>title</code>, <code>text</code>, <code>bullets</code>, <code>image</code>, <code>video</code>, <code>button</code>, <code>content</code>, <code>timeline</code>, <code>stepper</code>, <code>spacer</code>. See <em>Flex</em> in Layouts.</p>
|
|
295
|
+
</div>
|
|
296
|
+
</div>
|
|
297
|
+
<div class="prose prose-invert max-w-none prose-pre:bg-black/50 prose-pre:border-none">
|
|
298
|
+
<pre><code>{
|
|
299
|
+
<span class="text-blue-400">"type"</span>: <span class="text-green-400">"flex"</span>,
|
|
300
|
+
<span class="text-blue-400">"direction"</span>: <span class="text-green-400">"horizontal"</span>,
|
|
301
|
+
<span class="text-blue-400">"elements"</span>: [
|
|
302
|
+
{ <span class="text-blue-400">"type"</span>: <span class="text-green-400">"image"</span>, <span class="text-blue-400">"src"</span>: <span class="text-green-400">"/img.jpg"</span>, <span class="text-blue-400">"size"</span>: <span class="text-green-400">"half"</span>, <span class="text-blue-400">"fill"</span>: <span class="text-yellow-400">true</span> },
|
|
303
|
+
{ <span class="text-blue-400">"type"</span>: <span class="text-green-400">"content"</span>, <span class="text-blue-400">"size"</span>: <span class="text-green-400">"half"</span>, <span class="text-blue-400">"elements"</span>: [
|
|
304
|
+
{ <span class="text-blue-400">"type"</span>: <span class="text-green-400">"title"</span>, <span class="text-blue-400">"text"</span>: <span class="text-green-400">"Hello"</span> },
|
|
305
|
+
{ <span class="text-blue-400">"type"</span>: <span class="text-green-400">"bullets"</span>, <span class="text-blue-400">"items"</span>: [<span class="text-green-400">"A"</span>, <span class="text-green-400">"B"</span>] }
|
|
306
|
+
]}
|
|
307
|
+
]
|
|
308
|
+
}</code></pre>
|
|
309
|
+
</div>
|
|
310
|
+
</div>
|
|
311
|
+
|
|
312
|
+
<p class="text-white/60 mt-8">Also: <strong>Chart</strong> (<code>bar</code>, <code>line</code>, <code>pie</code>, <code>doughnut</code>), <strong>Custom HTML</strong>, <strong>Video</strong> (full-screen), <strong>Diagram</strong> (Vue Flow nodes/edges), <strong>Free</strong> (absolutely positioned text/image/box with <code>timelineTracks</code>). See the Layouts section for property tables.</p>
|
|
313
|
+
</div>
|
|
314
|
+
</div>
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
<!-- SIZING / EMBEDDING -->
|
|
318
|
+
<div v-else-if="activeSection === 'sizing'">
|
|
319
|
+
<h1>Embedding & Sizing</h1>
|
|
320
|
+
<p>By default, Lumina slides take up the full viewport height (<code>100vh</code>) to create an
|
|
321
|
+
immersive experience.</p>
|
|
322
|
+
<p>However, if you want to embed a slide inside a smaller container (e.g., a dashboard widget or
|
|
323
|
+
a blog post card), you can change the sizing mode.</p>
|
|
324
|
+
|
|
325
|
+
<h3>Container Mode</h3>
|
|
326
|
+
<p>Set the <code>sizing</code> property to <code>'container'</code> in your slide data. This
|
|
327
|
+
tells the engine to respect the parent container's height instead of forcing full screen.
|
|
328
|
+
</p>
|
|
329
|
+
|
|
330
|
+
<pre><code>{
|
|
331
|
+
<span class="text-blue-400">"type"</span>: <span class="text-green-400">"timeline"</span>,
|
|
332
|
+
<span class="text-blue-400">"sizing"</span>: <span class="text-green-400">"container"</span>, <span class="text-gray-500">// Default is "viewport"</span>
|
|
333
|
+
<span class="text-blue-400">"title"</span>: <span class="text-green-400">"Project History"</span>,
|
|
334
|
+
<span class="text-blue-400">"timeline"</span>: [...]
|
|
335
|
+
}</code></pre>
|
|
336
|
+
|
|
337
|
+
<div class="mt-8 p-4 bg-yellow-500/10 border border-yellow-500/20 rounded-lg">
|
|
338
|
+
<h4 class="text-yellow-400 font-bold mb-2"><i class="ph-thin ph-lightbulb mr-2"></i>Pro Tip
|
|
339
|
+
</h4>
|
|
340
|
+
<p class="text-sm text-yellow-200/80 m-0">When using 'container' mode, ensure the parent
|
|
341
|
+
element has a defined height (e.g., <code>h-96</code> or fixed pixels), otherwise the
|
|
342
|
+
slide content might collapse or expand unexpectedly.</p>
|
|
343
|
+
</div>
|
|
344
|
+
</div>
|
|
345
|
+
|
|
346
|
+
<!-- CONFIGURATION -->
|
|
347
|
+
<div v-else-if="activeSection === 'config'">
|
|
348
|
+
<h1>Configuration</h1>
|
|
349
|
+
<p>Pass options to <code>new Lumina(selector, options)</code>. All properties are optional.</p>
|
|
350
|
+
|
|
351
|
+
<h3>Core</h3>
|
|
352
|
+
<ul>
|
|
353
|
+
<li><code>theme</code> — Preset name (<code>default</code>, <code>ocean</code>, <code>midnight</code>, <code>forest</code>, <code>cyber</code>, <code>latte</code>, <code>sunset</code>, <code>monochrome</code>) or a <code>ThemeConfig</code> object.</li>
|
|
354
|
+
<li><code>loop</code> — Loop back to the first slide after the last. Default: <code>false</code>.</li>
|
|
355
|
+
<li><code>navigation</code>, <code>keyboard</code>, <code>touch</code> — Enable/disable navigation. Defaults: <code>true</code>.</li>
|
|
356
|
+
<li><code>selector</code> — Override the mount selector (default from constructor).</li>
|
|
357
|
+
<li><code>debug</code> — Enable debug logs. Default: <code>false</code>.</li>
|
|
358
|
+
<li><code>studio</code> — Enable Studio (page builder) mode. Default: <code>false</code>.</li>
|
|
359
|
+
</ul>
|
|
360
|
+
|
|
361
|
+
<h3>elementControl</h3>
|
|
362
|
+
<p>For reveal-on-demand: <code>elementControl: { defaultVisible: false }</code> makes all elements start hidden. Override per id with <code>meta.initialElementState</code>. See <em>Element Control</em>.</p>
|
|
363
|
+
|
|
364
|
+
<h3>animation</h3>
|
|
365
|
+
<p>Override timings and eases. Same keys can be set in <code>deck.meta.effects</code> or <code>slide.meta.effects</code>; precedence: slide > meta > options > defaults.</p>
|
|
366
|
+
<ul>
|
|
367
|
+
<li><code>enabled</code>, <code>type</code> (<code>fade</code> | <code>slide</code> | <code>zoom</code> | <code>cascade</code>), <code>durationIn</code>, <code>durationOut</code>, <code>stagger</code>, <code>ease</code>, <code>easeOut</code>, <code>entranceReveal</code></li>
|
|
368
|
+
<li><code>revealDelayMs</code>, <code>revealDuration</code>, <code>revealEase</code> — for <code>revealInSequence</code></li>
|
|
369
|
+
<li><code>elementDuration</code>, <code>elementEase</code> — for <code>element(id).animate()</code></li>
|
|
370
|
+
</ul>
|
|
371
|
+
|
|
372
|
+
<h3>ui</h3>
|
|
373
|
+
<pre><code>ui: {
|
|
374
|
+
<span class="text-blue-400">visible</span>: <span class="text-yellow-400">true</span>,
|
|
375
|
+
<span class="text-blue-400">showProgressBar</span>: <span class="text-yellow-400">true</span>,
|
|
376
|
+
<span class="text-blue-400">showSlideCount</span>: <span class="text-yellow-400">true</span>,
|
|
377
|
+
<span class="text-blue-400">showControls</span>: <span class="text-yellow-400">true</span> <span class="text-gray-500">// Next/Prev arrows</span>
|
|
378
|
+
}</code></pre>
|
|
379
|
+
|
|
380
|
+
<h3>keys</h3>
|
|
381
|
+
<p>Custom key bindings: <code>keys: { next: ['ArrowRight',' '], prev: ['ArrowLeft'] }</code>.</p>
|
|
382
|
+
</div>
|
|
383
|
+
|
|
384
|
+
<!-- EVENTS -->
|
|
385
|
+
<div v-else-if="activeSection === 'events'">
|
|
386
|
+
<h1>Events & API</h1>
|
|
387
|
+
<p>Subscribe with <code>engine.on(event, handler)</code>; unsubscribe with <code>engine.off(event, handler)</code> using the same function reference.</p>
|
|
388
|
+
|
|
389
|
+
<h3>ready</h3>
|
|
390
|
+
<p>Fired when a deck is successfully loaded. Payload: the <code>Deck</code> object. Register <code>ready</code> (and <code>slideChange</code>) <strong>before</strong> <code>engine.load(deck)</code> when using element control or <code>revealInSequence</code>.</p>
|
|
391
|
+
|
|
392
|
+
<h3>slideChange</h3>
|
|
393
|
+
<p>Fired when the active slide changes. Payload: <code>{ index, previousIndex, slide }</code>.</p>
|
|
394
|
+
|
|
395
|
+
<h3>action</h3>
|
|
396
|
+
<p>Fired on user interactions (e.g. button clicks). Payload: <code>{ type, label?, value?, origin? }</code>. For buttons, <code>type</code> is often <code>"button"</code>; <code>label</code> and <code>value</code> (or <code>action</code>) come from the element. For <code>slide-update</code> (e.g. diagram): <code>slideIndex</code>, <code>patch</code> (e.g. <code>{ nodes, edges }</code>).</p>
|
|
397
|
+
|
|
398
|
+
<h3>error</h3>
|
|
399
|
+
<p>Fired when an internal error occurs. Payload: <code>Error</code>. Use <code>engine.emitError(err)</code> to forward errors from your app.</p>
|
|
400
|
+
|
|
401
|
+
<h3>Additional events</h3>
|
|
402
|
+
<p>Lifecycle and features: <code>patch</code> (<code>{ diff }</code> when <code>engine.patch()</code>), <code>destroy</code> (on <code>engine.destroy()</code>), <code>navigate</code> (<code>{ direction, fromIndex, toIndex }</code> when <code>next</code>/<code>prev</code>/<code>goTo</code> change the slide), <code>themeChange</code> (<code>{ theme }</code>), <code>speakerNotesOpen</code>, <code>speakerNotesClose</code>, <code>timelineSeek</code> (<code>{ progress, slideIndex }</code>), <code>timelineComplete</code> (<code>{ slideIndex }</code>), <code>revealStart</code> (<code>{ slideIndex, elementIds }</code>), <code>revealComplete</code> (<code>{ slideIndex }</code>), <code>revealElement</code> (<code>{ slideIndex, elementId, index }</code>).</p>
|
|
403
|
+
|
|
404
|
+
<pre><code>engine.<span class="text-yellow-400">on</span>('ready', (deck) => { <span class="text-gray-500">/* deck loaded */</span> });
|
|
405
|
+
engine.<span class="text-yellow-400">on</span>('slideChange', ({ index, slide }) => {
|
|
406
|
+
console.log(<span class="text-green-400">`Slide ${index}: ${slide.type}`</span>);
|
|
407
|
+
});
|
|
408
|
+
engine.<span class="text-yellow-400">on</span>('action', (p) => {
|
|
409
|
+
if (p.type === <span class="text-green-400">'button'</span> && p.value) window.open(p.value, <span class="text-green-400">'_blank'</span>);
|
|
410
|
+
});
|
|
411
|
+
engine.<span class="text-yellow-400">on</span>('error', (err) => console.error(err));
|
|
412
|
+
engine.<span class="text-yellow-400">on</span>('patch', ({ diff }) => console.log(<span class="text-green-400">'Patched'</span>, diff));
|
|
413
|
+
engine.<span class="text-yellow-400">on</span>('navigate', ({ direction, toIndex }) => console.log(direction, toIndex));</code></pre>
|
|
414
|
+
|
|
415
|
+
<h3>Navigation & state</h3>
|
|
416
|
+
<p><code>engine.next()</code>, <code>engine.prev()</code>, <code>engine.goTo(index)</code>, <code>engine.currentSlideIndex</code>, <code>engine.exportState()</code> (for LLM context: <code>{ status, currentSlide: { index, type, title }, narrative, engagementLevel, history }</code>), <code>engine.destroy()</code>.</p>
|
|
417
|
+
</div>
|
|
418
|
+
|
|
419
|
+
<!-- ELEMENT CONTROL -->
|
|
420
|
+
<div v-else-if="activeSection === 'element-control'">
|
|
421
|
+
<h1>Element Control (Reveal on Demand)</h1>
|
|
422
|
+
<p class="lead">Start with elements hidden and reveal them in sequence: ideal for blank slides that
|
|
423
|
+
fill in as you speak, or for effects driven by <code>engine.element(id)</code>.</p>
|
|
424
|
+
|
|
425
|
+
<h2>How element ids are assigned</h2>
|
|
426
|
+
<p>Each controllable element has a <strong>stable id</strong> used in <code>engine.element(id)</code>, <code>meta.initialElementState</code>, and <code>engine.getElementById(id)</code>. Layouts wrap content in <code>LuminaElement</code> with <code>:id="resolveId(data, slideIndex, path)"</code>, which is written as <code>data-lumina-id</code> in the DOM.</p>
|
|
427
|
+
|
|
428
|
+
<p><strong>Resolution order</strong> (in <code>resolveId</code>):</p>
|
|
429
|
+
<ol class="list-decimal list-inside mb-6 space-y-1 text-white/70">
|
|
430
|
+
<li><strong>Slide root</strong> (path <code>[]</code> or <code>['slide']</code>): <code>slide.id</code> if present, otherwise <code>s{N}-slide</code>.</li>
|
|
431
|
+
<li><strong>Object with <code>id</code></strong>: if the value at that path is an object with <code>id: string</code> (e.g. <code>features[0].id</code>, a diagram node), that <code>id</code> is used.</li>
|
|
432
|
+
<li><strong><code>slide.ids</code></strong>: if the path has a single segment (e.g. <code>tag</code>) and <code>slide.ids.tag</code> exists, that value is used.</li>
|
|
433
|
+
<li><strong>Fallback</strong>: <code>elemId(slideIndex, ...path)</code> → format <code>s{N}-{path0}-{path1}-...</code> (e.g. <code>s0-tag</code>, <code>s1-features-2</code>, <code>s2-elements-0-elements-1</code>).</li>
|
|
434
|
+
</ol>
|
|
435
|
+
|
|
436
|
+
<p><strong>Ids by slide type</strong> (when there is no <code>id</code> or <code>slide.ids</code>):</p>
|
|
437
|
+
<div class="overflow-x-auto mb-6">
|
|
438
|
+
<table class="w-full text-sm border border-white/10 rounded-lg">
|
|
439
|
+
<thead><tr class="border-b border-white/10"><th class="text-left py-2 px-3 text-white/90">Type</th><th class="text-left py-2 px-3 text-white/90">Paths (path → id fallback)</th></tr></thead>
|
|
440
|
+
<tbody class="text-white/70">
|
|
441
|
+
<tr class="border-b border-white/5"><td class="py-2 px-3 font-mono">statement</td><td class="py-2 px-3"><code>tag</code>→s{N}-tag, <code>title</code>→s{N}-title, <code>subtitle</code>→s{N}-subtitle</td></tr>
|
|
442
|
+
<tr class="border-b border-white/5"><td class="py-2 px-3 font-mono">features</td><td class="py-2 px-3"><code>header</code>→s{N}-header, <code>features.i</code>→s{N}-features-{i}</td></tr>
|
|
443
|
+
<tr class="border-b border-white/5"><td class="py-2 px-3 font-mono">half</td><td class="py-2 px-3"><code>media</code>, <code>tag</code>, <code>title</code>, <code>paragraphs</code>, <code>cta</code> → s{N}-media, s{N}-tag, etc.</td></tr>
|
|
444
|
+
<tr class="border-b border-white/5"><td class="py-2 px-3 font-mono">timeline</td><td class="py-2 px-3"><code>title</code>, <code>subtitle</code>, <code>timeline.i</code> → s{N}-title, s{N}-subtitle, s{N}-timeline-{i}</td></tr>
|
|
445
|
+
<tr class="border-b border-white/5"><td class="py-2 px-3 font-mono">steps</td><td class="py-2 px-3"><code>header</code>, <code>steps.i</code> → s{N}-header, s{N}-steps-{i}</td></tr>
|
|
446
|
+
<tr class="border-b border-white/5"><td class="py-2 px-3 font-mono">flex</td><td class="py-2 px-3"><code>elements.i</code> → s{N}-elements-{i}; nested <code>elements.i.elements.j</code> → s{N}-elements-{i}-elements-{j}</td></tr>
|
|
447
|
+
<tr class="border-b border-white/5"><td class="py-2 px-3 font-mono">chart</td><td class="py-2 px-3"><code>title</code>, <code>subtitle</code>, <code>chart</code> → s{N}-title, s{N}-subtitle, s{N}-chart</td></tr>
|
|
448
|
+
<tr class="border-b border-white/5"><td class="py-2 px-3 font-mono">video</td><td class="py-2 px-3"><code>video</code>, <code>title</code> → s{N}-video, s{N}-title</td></tr>
|
|
449
|
+
<tr class="border-b border-white/5"><td class="py-2 px-3 font-mono">diagram</td><td class="py-2 px-3"><code>nodes.i</code>, <code>edges.i</code>; if the node has <code>id</code>, it is used</td></tr>
|
|
450
|
+
<tr><td class="py-2 px-3 font-mono">free</td><td class="py-2 px-3"><code>elements.i</code> → s{N}-elements-0, s{N}-elements-1, …</td></tr>
|
|
451
|
+
</tbody>
|
|
452
|
+
</table>
|
|
453
|
+
</div>
|
|
454
|
+
|
|
455
|
+
<p>To see a slide's ids at runtime: <code>engine.elements(slideIndex)</code>. To use by path: <code>engine.element(slideIndex, "tag")</code> or <code>engine.element(slideIndex, "features.0")</code>; the id is resolved with the same rules.</p>
|
|
456
|
+
|
|
457
|
+
<h2>Option 1: meta.initialElementState</h2>
|
|
458
|
+
<p>Define in the deck which elements start hidden. Ids follow the pattern
|
|
459
|
+
<code>s{index}-{path}</code> (e.g. <code>s0-tag</code>, <code>s0-title</code>,
|
|
460
|
+
<code>s1-features-0</code>). <code>engine.elements(slideIndex)</code> lists all ids for a slide.
|
|
461
|
+
</p>
|
|
462
|
+
|
|
463
|
+
<pre><code>{
|
|
464
|
+
<span class="text-blue-400">"meta"</span>: {
|
|
465
|
+
<span class="text-blue-400">"title"</span>: <span class="text-green-400">"Reveal on Demand"</span>,
|
|
466
|
+
<span class="text-blue-400">"initialElementState"</span>: {
|
|
467
|
+
<span class="text-green-400">"s0-tag"</span>: { <span class="text-blue-400">"visible"</span>: <span class="text-yellow-400">false</span> },
|
|
468
|
+
<span class="text-green-400">"s0-title"</span>: { <span class="text-blue-400">"visible"</span>: <span class="text-yellow-400">false</span> },
|
|
469
|
+
<span class="text-green-400">"s0-subtitle"</span>: { <span class="text-blue-400">"visible"</span>: <span class="text-yellow-400">false</span> }
|
|
470
|
+
}
|
|
471
|
+
},
|
|
472
|
+
<span class="text-blue-400">"slides"</span>: [
|
|
473
|
+
{ <span class="text-blue-400">"type"</span>: <span class="text-green-400">"statement"</span>, <span class="text-blue-400">"tag"</span>: <span class="text-green-400">"…"</span>, <span class="text-blue-400">"title"</span>: <span class="text-green-400">"…"</span>, <span class="text-blue-400">"subtitle"</span>: <span class="text-green-400">"…"</span> }
|
|
474
|
+
]
|
|
475
|
+
}</code></pre>
|
|
476
|
+
|
|
477
|
+
<h2>Option 2: elementControl.defaultVisible</h2>
|
|
478
|
+
<p>To hide <strong>all</strong> elements on all slides: pass
|
|
479
|
+
<code>elementControl: { defaultVisible: false }</code> when creating Lumina. Those you set in
|
|
480
|
+
<code>meta.initialElementState</code> override this (e.g. to keep some visible).
|
|
481
|
+
</p>
|
|
482
|
+
|
|
483
|
+
<pre><code>const engine = new Lumina('#app', {
|
|
484
|
+
<span class="text-blue-400">elementControl</span>: { <span class="text-blue-400">defaultVisible</span>: <span class="text-yellow-400">false</span> }
|
|
485
|
+
});
|
|
486
|
+
engine.load(deck);</code></pre>
|
|
487
|
+
|
|
488
|
+
<h2>Automatic reveal in sequence</h2>
|
|
489
|
+
<p>After loading the deck, use <code>engine.element(id).show()</code> (and optionally
|
|
490
|
+
<code>.animate()</code>) to reveal. With <code>ready</code> and <code>setTimeout</code> you can
|
|
491
|
+
chain the sequence:
|
|
492
|
+
</p>
|
|
493
|
+
|
|
494
|
+
<pre><code>engine.<span class="text-yellow-400">on</span>('ready', () => {
|
|
495
|
+
const ids = [<span class="text-green-400">'s0-tag'</span>, <span class="text-green-400">'s0-title'</span>, <span class="text-green-400">'s0-subtitle'</span>];
|
|
496
|
+
ids.forEach((id, i) => {
|
|
497
|
+
setTimeout(() => engine.element(id).show(), (i + 1) * 700);
|
|
498
|
+
});
|
|
499
|
+
});
|
|
500
|
+
engine.load(deck);</code></pre>
|
|
501
|
+
|
|
502
|
+
<h2>Step-by-step: using the controller correctly (avoiding null elements)</h2>
|
|
503
|
+
<p><code>engine.getElementById(id)</code> returns <code>null</code> if the element is not mounted (e.g. its slide is not the current one). If you call <code>engine.element(id).show()</code> or <code>.animate()</code> when the node is null, the library does nothing with GSAP (no-op) and no error is thrown; but the effect is not visible. For reveal to work, the element must exist in the DOM when you call <code>.show()</code>. This is the pattern that works.</p>
|
|
504
|
+
|
|
505
|
+
<p><strong>1. Register <code>ready</code> and <code>slideChange</code> before <code>engine.load(deck)</code>.</strong> That way, when the deck finishes loading or you change slides, your callbacks are already registered.</p>
|
|
506
|
+
|
|
507
|
+
<p><strong>2. In <code>ready</code>:</strong> the first slide is already mounted. Use <code>setTimeout</code> before each <code>engine.element(id).show()</code> to allow time for render and transitions (e.g. 700 ms per element).</p>
|
|
508
|
+
|
|
509
|
+
<p><strong>3. In <code>slideChange</code>:</strong> when entering a slide with controlled elements, that slide's DOM mounts on change. Use <code>setTimeout</code> again before each <code>.show()</code> for that slide.</p>
|
|
510
|
+
|
|
511
|
+
<p><strong>4. Order in your code:</strong> <code>new Lumina(...)</code> → <code>engine.on('ready', ...)</code> → <code>engine.on('slideChange', ...)</code> → <code>engine.load(deck)</code>.</p>
|
|
512
|
+
|
|
513
|
+
<p>Full example (used by the <code>layout-element-control</code> demo):</p>
|
|
514
|
+
|
|
515
|
+
<pre><code>const engine = new Lumina(<span class="text-green-400">'#app'</span>, { <span class="text-blue-400">loop</span>: <span class="text-yellow-400">true</span>, <span class="text-blue-400">navigation</span>: <span class="text-yellow-400">true</span> });
|
|
516
|
+
|
|
517
|
+
<span class="text-gray-500">// 1. ready: first slide mounted; setTimeout so the DOM is ready</span>
|
|
518
|
+
engine.<span class="text-yellow-400">on</span>(<span class="text-green-400">'ready'</span>, () => {
|
|
519
|
+
[<span class="text-green-400">'s0-tag'</span>, <span class="text-green-400">'s0-title'</span>, <span class="text-green-400">'s0-subtitle'</span>].forEach((id, i) => {
|
|
520
|
+
setTimeout(() => engine.element(id).show(), (i + 1) * 700);
|
|
521
|
+
});
|
|
522
|
+
});
|
|
523
|
+
|
|
524
|
+
<span class="text-gray-500">// 2. slideChange: on slide 1, reveal its elements with the same delay</span>
|
|
525
|
+
engine.<span class="text-yellow-400">on</span>(<span class="text-green-400">'slideChange'</span>, ({ index }) => {
|
|
526
|
+
if (index === 1) {
|
|
527
|
+
[<span class="text-green-400">'s1-tag'</span>, <span class="text-green-400">'s1-title'</span>, <span class="text-green-400">'s1-subtitle'</span>].forEach((id, i) => {
|
|
528
|
+
setTimeout(() => engine.element(id).show(), (i + 1) * 700);
|
|
529
|
+
});
|
|
530
|
+
}
|
|
531
|
+
});
|
|
532
|
+
|
|
533
|
+
<span class="text-gray-500">// 3. Load always after the listeners</span>
|
|
534
|
+
engine.load(deck);</code></pre>
|
|
535
|
+
|
|
536
|
+
<p>With this order and the <code>setTimeout</code>s, elements exist when <code>.show()</code> is called and you avoid null references in animations.</p>
|
|
537
|
+
|
|
538
|
+
<p class="not-prose mt-8">
|
|
539
|
+
<router-link to="/deck/layout-element-control"
|
|
540
|
+
class="inline-flex items-center gap-2 px-5 py-2.5 rounded-xl bg-blue-500/20 text-blue-400 border border-blue-500/40 hover:bg-blue-500/30 transition font-medium">
|
|
541
|
+
<i class="ph-thin ph-play-circle"></i> View demo: Element Control
|
|
542
|
+
</router-link>
|
|
543
|
+
</p>
|
|
544
|
+
</div>
|
|
545
|
+
|
|
546
|
+
<!-- ANIMATIONS: revealInSequence, presets, stagger -->
|
|
547
|
+
<div v-else-if="activeSection === 'animations'">
|
|
548
|
+
<h1>Animations</h1>
|
|
549
|
+
<p class="lead">Control entrances with <code>revealInSequence</code>, built-in presets, and stagger modes. Use with <code>meta.initialElementState</code> or <code>elementControl.defaultVisible: false</code> to start hidden.</p>
|
|
550
|
+
|
|
551
|
+
<h2>revealInSequence</h2>
|
|
552
|
+
<p>Reveals slide elements one by one with optional stagger and animation. Register <code>ready</code> and <code>slideChange</code> before <code>load</code>; then call <code>engine.revealInSequence(slideIndex?, options)</code>.</p>
|
|
553
|
+
|
|
554
|
+
<pre><code>engine.<span class="text-yellow-400">on</span>(<span class="text-green-400">'ready'</span>, () => engine.revealInSequence(<span class="text-yellow-400">0</span>, { <span class="text-blue-400">delayMs</span>: <span class="text-cyan-400">500</span>, <span class="text-blue-400">preset</span>: <span class="text-green-400">'fadeUp'</span> }));
|
|
555
|
+
engine.<span class="text-yellow-400">on</span>(<span class="text-green-400">'slideChange'</span>, (e) => engine.revealInSequence(e.index, { <span class="text-blue-400">delayMs</span>: <span class="text-cyan-400">400</span> }));
|
|
556
|
+
engine.load(deck);</code></pre>
|
|
557
|
+
|
|
558
|
+
<p><strong>Options:</strong> <code>delayMs</code>, <code>staggerMode</code> (<code>sequential</code> | <code>center-out</code> | <code>ends-in</code> | <code>wave</code> | <code>random</code>), <code>preset</code>, <code>from</code>/<code>to</code>, <code>duration</code>, <code>ease</code>, <code>hideFirst</code>, <code>only</code>, <code>exclude</code>.</p>
|
|
559
|
+
|
|
560
|
+
<h2>Presets</h2>
|
|
561
|
+
<p>Use <code>preset</code> in <code>revealInSequence</code> or <code>element(id).animate({ preset: 'fadeUp' })</code>. Built-in: <code>fadeUp</code>, <code>fadeIn</code>, <code>scaleIn</code>, <code>slideLeft</code>, <code>slideRight</code>, <code>zoomIn</code>, <code>blurIn</code>, <code>spring</code>, <code>drop</code>, <code>fadeOut</code>.</p>
|
|
562
|
+
|
|
563
|
+
<h2>Stagger modes</h2>
|
|
564
|
+
<p><code>staggerMode</code> controls the order in which elements are revealed: <code>sequential</code> (default), <code>center-out</code>, <code>ends-in</code>, <code>wave</code>, <code>random</code>. For <code>random</code>, use <code>randomSeed</code> for deterministic order.</p>
|
|
565
|
+
|
|
566
|
+
<p class="not-prose mt-8 flex flex-wrap gap-4">
|
|
567
|
+
<router-link to="/deck/animation-presets"
|
|
568
|
+
class="inline-flex items-center gap-2 px-5 py-2.5 rounded-xl bg-blue-500/20 text-blue-400 border border-blue-500/40 hover:bg-blue-500/30 transition font-medium">
|
|
569
|
+
<i class="ph-thin ph-play-circle"></i> Animation: Presets
|
|
570
|
+
</router-link>
|
|
571
|
+
<router-link to="/deck/animation-stagger"
|
|
572
|
+
class="inline-flex items-center gap-2 px-5 py-2.5 rounded-xl bg-blue-500/20 text-blue-400 border border-blue-500/40 hover:bg-blue-500/30 transition font-medium">
|
|
573
|
+
<i class="ph-thin ph-play-circle"></i> Animation: Stagger
|
|
574
|
+
</router-link>
|
|
575
|
+
</p>
|
|
576
|
+
</div>
|
|
577
|
+
|
|
578
|
+
<!-- TIMELINE (Remotion-style keyframes) -->
|
|
579
|
+
<div v-else-if="activeSection === 'timeline-keyframes'">
|
|
580
|
+
<h1>Timeline (Remotion-style keyframes)</h1>
|
|
581
|
+
<p class="lead">Drive element state from a progress 0–1 with <code>slide.timelineTracks</code>. Use <code>engine.seekTo(progress)</code> to scrub or <code>engine.playTimeline(duration)</code> to play. Works with any layout; the <code>free</code> layout is for absolutely positioned storytelling.</p>
|
|
582
|
+
|
|
583
|
+
<h2>timelineTracks</h2>
|
|
584
|
+
<p>Per-slide, define <code>timelineTracks: { [elementId]: { "0": { opacity, x, y, scale, rotate?, visible? }, "0.3": {...}, "1": {...} } }</code>. Keys are progress strings 0–1; values are interpolated linearly. Supported: <code>opacity</code>, <code>x</code>, <code>y</code>, <code>scale</code>, <code>rotate</code>, <code>visible</code>.</p>
|
|
585
|
+
|
|
586
|
+
<pre><code>{
|
|
587
|
+
<span class="text-blue-400">"type"</span>: <span class="text-green-400">"statement"</span>,
|
|
588
|
+
<span class="text-blue-400">"title"</span>: <span class="text-green-400">"Keyframes"</span>,
|
|
589
|
+
<span class="text-blue-400">"subtitle"</span>: <span class="text-green-400">"Scrub or play."</span>,
|
|
590
|
+
<span class="text-blue-400">"timelineTracks"</span>: {
|
|
591
|
+
<span class="text-green-400">"s0-tag"</span>: { <span class="text-green-400">"0"</span>: { <span class="text-blue-400">opacity</span>: <span class="text-cyan-400">0</span>, <span class="text-blue-400">y</span>: <span class="text-cyan-400">20</span> }, <span class="text-green-400">"0.2"</span>: { <span class="text-blue-400">opacity</span>: <span class="text-cyan-400">1</span>, <span class="text-blue-400">y</span>: <span class="text-cyan-400">0</span> }, <span class="text-green-400">"1"</span>: { <span class="text-blue-400">opacity</span>: <span class="text-cyan-400">1</span> } },
|
|
592
|
+
<span class="text-green-400">"s0-title"</span>: { <span class="text-green-400">"0"</span>: { <span class="text-blue-400">opacity</span>: <span class="text-cyan-400">0</span>, <span class="text-blue-400">x</span>: <span class="text-cyan-400">-30</span> }, <span class="text-green-400">"0.4"</span>: { <span class="text-blue-400">opacity</span>: <span class="text-cyan-400">1</span>, <span class="text-blue-400">x</span>: <span class="text-cyan-400">0</span> }, <span class="text-green-400">"1"</span>: { <span class="text-blue-400">opacity</span>: <span class="text-cyan-400">1</span> } }
|
|
593
|
+
}
|
|
594
|
+
}</code></pre>
|
|
595
|
+
|
|
596
|
+
<h2>API</h2>
|
|
597
|
+
<ul>
|
|
598
|
+
<li><code>engine.seekTo(progress, slideIndex?)</code> — scrub to 0–1. Updates <code>engine.timelineProgress</code>.</li>
|
|
599
|
+
<li><code>engine.playTimeline(durationSeconds?, slideIndex?)</code> — returns <code>[Promise, cancel]</code>. Plays from 0 to 1 over the given seconds (default 5).</li>
|
|
600
|
+
<li><code>element(id).animateToProgress(progress, keyframes)</code> — apply keyframes for one element manually.</li>
|
|
601
|
+
</ul>
|
|
602
|
+
|
|
603
|
+
<h2>Free layout</h2>
|
|
604
|
+
<p><code>type: "free"</code> with <code>elements: [{ type: "text"|"image"|"box", text?, src?, width?, height?, fontSize?, color?, backgroundColor?, ... }]</code>. Elements are absolutely positioned; <code>x</code>, <code>y</code> in <code>timelineTracks</code> act as translate. Ids: <code>s{N}-elements-0</code>, <code>s{N}-elements-1</code>, etc.</p>
|
|
605
|
+
|
|
606
|
+
<p class="not-prose mt-8">
|
|
607
|
+
<router-link to="/deck/animation-timeline"
|
|
608
|
+
class="inline-flex items-center gap-2 px-5 py-2.5 rounded-xl bg-blue-500/20 text-blue-400 border border-blue-500/40 hover:bg-blue-500/30 transition font-medium">
|
|
609
|
+
<i class="ph-thin ph-play-circle"></i> Animation: Timeline (keyframes)
|
|
610
|
+
</router-link>
|
|
611
|
+
</p>
|
|
612
|
+
</div>
|
|
613
|
+
|
|
614
|
+
<!-- THEMING -->
|
|
615
|
+
<div v-else-if="activeSection === 'theming'">
|
|
616
|
+
<h1>Theming</h1>
|
|
617
|
+
<p class="lead">Customize colors, fonts, and visual style with built-in presets or create your
|
|
618
|
+
own theme.</p>
|
|
619
|
+
|
|
620
|
+
<!-- Theme Presets Section -->
|
|
621
|
+
<div class="my-12">
|
|
622
|
+
<h2 class="text-2xl font-bold text-white mb-6">Built-in Presets</h2>
|
|
623
|
+
<p class="text-white/60 mb-8">Lumina comes with 8 beautiful theme presets. Pass the preset
|
|
624
|
+
name as a string to instantly apply a complete look.</p>
|
|
625
|
+
|
|
626
|
+
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 not-prose">
|
|
627
|
+
<!-- Default Theme -->
|
|
628
|
+
<div
|
|
629
|
+
class="rounded-xl overflow-hidden border border-white/10 group hover:border-blue-500/50 transition-all duration-300">
|
|
630
|
+
<div class="h-32 p-6 flex items-center justify-center" style="background: #030303;">
|
|
631
|
+
<span class="text-2xl font-bold" style="color: #3b82f6;">Lumina</span>
|
|
632
|
+
</div>
|
|
633
|
+
<div class="p-4 bg-black/50">
|
|
634
|
+
<div class="flex items-center justify-between mb-2">
|
|
635
|
+
<h3 class="font-bold text-white">default</h3>
|
|
636
|
+
<div class="flex gap-1">
|
|
637
|
+
<span class="w-4 h-4 rounded-full" style="background: #3b82f6;"></span>
|
|
638
|
+
<span class="w-4 h-4 rounded-full" style="background: #030303;"></span>
|
|
639
|
+
</div>
|
|
640
|
+
</div>
|
|
641
|
+
<p class="text-xs text-white/50">Clean blue on dark. Professional and modern.
|
|
642
|
+
</p>
|
|
643
|
+
</div>
|
|
644
|
+
</div>
|
|
645
|
+
|
|
646
|
+
<!-- Ocean Theme -->
|
|
647
|
+
<div
|
|
648
|
+
class="rounded-xl overflow-hidden border border-white/10 group hover:border-cyan-500/50 transition-all duration-300">
|
|
649
|
+
<div class="h-32 p-6 flex items-center justify-center" style="background: #0f172a;">
|
|
650
|
+
<span class="text-2xl font-bold" style="color: #06b6d4;">Lumina</span>
|
|
651
|
+
</div>
|
|
652
|
+
<div class="p-4 bg-black/50">
|
|
653
|
+
<div class="flex items-center justify-between mb-2">
|
|
654
|
+
<h3 class="font-bold text-white">ocean</h3>
|
|
655
|
+
<div class="flex gap-1">
|
|
656
|
+
<span class="w-4 h-4 rounded-full" style="background: #06b6d4;"></span>
|
|
657
|
+
<span class="w-4 h-4 rounded-full" style="background: #0f172a;"></span>
|
|
658
|
+
</div>
|
|
659
|
+
</div>
|
|
660
|
+
<p class="text-xs text-white/50">Cyan accents on slate. Calm and focused.</p>
|
|
661
|
+
</div>
|
|
662
|
+
</div>
|
|
663
|
+
|
|
664
|
+
<!-- Midnight Theme -->
|
|
665
|
+
<div
|
|
666
|
+
class="rounded-xl overflow-hidden border border-white/10 group hover:border-indigo-500/50 transition-all duration-300">
|
|
667
|
+
<div class="h-32 p-6 flex items-center justify-center" style="background: #000000;">
|
|
668
|
+
<span class="text-2xl font-bold" style="color: #6366f1;">Lumina</span>
|
|
669
|
+
</div>
|
|
670
|
+
<div class="p-4 bg-black/50">
|
|
671
|
+
<div class="flex items-center justify-between mb-2">
|
|
672
|
+
<h3 class="font-bold text-white">midnight</h3>
|
|
673
|
+
<div class="flex gap-1">
|
|
674
|
+
<span class="w-4 h-4 rounded-full" style="background: #6366f1;"></span>
|
|
675
|
+
<span class="w-4 h-4 rounded-full" style="background: #000000;"></span>
|
|
676
|
+
</div>
|
|
677
|
+
</div>
|
|
678
|
+
<p class="text-xs text-white/50">Indigo on pure black. Bold and dramatic.</p>
|
|
679
|
+
</div>
|
|
680
|
+
</div>
|
|
681
|
+
|
|
682
|
+
<!-- Forest Theme -->
|
|
683
|
+
<div
|
|
684
|
+
class="rounded-xl overflow-hidden border border-white/10 group hover:border-emerald-500/50 transition-all duration-300">
|
|
685
|
+
<div class="h-32 p-6 flex items-center justify-center" style="background: #022c22;">
|
|
686
|
+
<span class="text-2xl font-bold" style="color: #10b981;">Lumina</span>
|
|
687
|
+
</div>
|
|
688
|
+
<div class="p-4 bg-black/50">
|
|
689
|
+
<div class="flex items-center justify-between mb-2">
|
|
690
|
+
<h3 class="font-bold text-white">forest</h3>
|
|
691
|
+
<div class="flex gap-1">
|
|
692
|
+
<span class="w-4 h-4 rounded-full" style="background: #10b981;"></span>
|
|
693
|
+
<span class="w-4 h-4 rounded-full" style="background: #022c22;"></span>
|
|
694
|
+
</div>
|
|
695
|
+
</div>
|
|
696
|
+
<p class="text-xs text-white/50">Emerald green tones. Natural and fresh.</p>
|
|
697
|
+
</div>
|
|
698
|
+
</div>
|
|
699
|
+
|
|
700
|
+
<!-- Cyber Theme -->
|
|
701
|
+
<div
|
|
702
|
+
class="rounded-xl overflow-hidden border border-white/10 group hover:border-pink-500/50 transition-all duration-300">
|
|
703
|
+
<div class="h-32 p-6 flex items-center justify-center" style="background: #18181b;">
|
|
704
|
+
<span class="text-2xl font-bold"
|
|
705
|
+
style="color: #f472b6; font-family: 'Orbitron', sans-serif;">Lumina</span>
|
|
706
|
+
</div>
|
|
707
|
+
<div class="p-4 bg-black/50">
|
|
708
|
+
<div class="flex items-center justify-between mb-2">
|
|
709
|
+
<h3 class="font-bold text-white">cyber</h3>
|
|
710
|
+
<div class="flex gap-1">
|
|
711
|
+
<span class="w-4 h-4 rounded-full" style="background: #f472b6;"></span>
|
|
712
|
+
<span class="w-4 h-4 rounded-full" style="background: #18181b;"></span>
|
|
713
|
+
</div>
|
|
714
|
+
</div>
|
|
715
|
+
<p class="text-xs text-white/50">Neon pink futuristic. Sci-fi vibes.</p>
|
|
716
|
+
</div>
|
|
717
|
+
</div>
|
|
718
|
+
|
|
719
|
+
<!-- Latte Theme -->
|
|
720
|
+
<div
|
|
721
|
+
class="rounded-xl overflow-hidden border border-white/10 group hover:border-amber-500/50 transition-all duration-300">
|
|
722
|
+
<div class="h-32 p-6 flex items-center justify-center" style="background: #fffbeb;">
|
|
723
|
+
<span class="text-2xl font-bold"
|
|
724
|
+
style="color: #d97706; font-family: 'Playfair Display', serif;">Lumina</span>
|
|
725
|
+
</div>
|
|
726
|
+
<div class="p-4 bg-black/50">
|
|
727
|
+
<div class="flex items-center justify-between mb-2">
|
|
728
|
+
<h3 class="font-bold text-white">latte</h3>
|
|
729
|
+
<div class="flex gap-1">
|
|
730
|
+
<span class="w-4 h-4 rounded-full" style="background: #d97706;"></span>
|
|
731
|
+
<span class="w-4 h-4 rounded-full" style="background: #fffbeb;"></span>
|
|
732
|
+
</div>
|
|
733
|
+
</div>
|
|
734
|
+
<p class="text-xs text-white/50">Light mode with warm amber. Elegant.</p>
|
|
735
|
+
</div>
|
|
736
|
+
</div>
|
|
737
|
+
|
|
738
|
+
<!-- Sunset Theme -->
|
|
739
|
+
<div
|
|
740
|
+
class="rounded-xl overflow-hidden border border-white/10 group hover:border-orange-500/50 transition-all duration-300">
|
|
741
|
+
<div class="h-32 p-6 flex items-center justify-center"
|
|
742
|
+
style="background: linear-gradient(135deg, #1c1917 0%, #292524 100%);">
|
|
743
|
+
<span class="text-2xl font-bold"
|
|
744
|
+
style="background: linear-gradient(to right, #f97316, #f43f5e); -webkit-background-clip: text; -webkit-text-fill-color: transparent;">Lumina</span>
|
|
745
|
+
</div>
|
|
746
|
+
<div class="p-4 bg-black/50">
|
|
747
|
+
<div class="flex items-center justify-between mb-2">
|
|
748
|
+
<h3 class="font-bold text-white">sunset</h3>
|
|
749
|
+
<div class="flex gap-1">
|
|
750
|
+
<span class="w-4 h-4 rounded-full" style="background: #f97316;"></span>
|
|
751
|
+
<span class="w-4 h-4 rounded-full" style="background: #f43f5e;"></span>
|
|
752
|
+
</div>
|
|
753
|
+
</div>
|
|
754
|
+
<p class="text-xs text-white/50">Orange to rose gradient. Warm and vibrant.</p>
|
|
755
|
+
</div>
|
|
756
|
+
</div>
|
|
757
|
+
|
|
758
|
+
<!-- Monochrome Theme -->
|
|
759
|
+
<div
|
|
760
|
+
class="rounded-xl overflow-hidden border border-white/10 group hover:border-white/50 transition-all duration-300">
|
|
761
|
+
<div class="h-32 p-6 flex items-center justify-center" style="background: #000000;">
|
|
762
|
+
<span class="text-2xl font-bold" style="color: #ffffff;">Lumina</span>
|
|
763
|
+
</div>
|
|
764
|
+
<div class="p-4 bg-black/50">
|
|
765
|
+
<div class="flex items-center justify-between mb-2">
|
|
766
|
+
<h3 class="font-bold text-white">monochrome</h3>
|
|
767
|
+
<div class="flex gap-1">
|
|
768
|
+
<span class="w-4 h-4 rounded-full" style="background: #ffffff;"></span>
|
|
769
|
+
<span class="w-4 h-4 rounded-full" style="background: #000000;"></span>
|
|
770
|
+
</div>
|
|
771
|
+
</div>
|
|
772
|
+
<p class="text-xs text-white/50">Pure black and white. Timeless elegance.</p>
|
|
773
|
+
</div>
|
|
774
|
+
</div>
|
|
775
|
+
</div>
|
|
776
|
+
</div>
|
|
777
|
+
|
|
778
|
+
<!-- Using Presets -->
|
|
779
|
+
<div class="my-12">
|
|
780
|
+
<h2 class="text-2xl font-bold text-white mb-6">Using a Preset</h2>
|
|
781
|
+
<p class="text-white/60 mb-4">Pass the preset name as a string to the <code>theme</code>
|
|
782
|
+
option:</p>
|
|
783
|
+
|
|
784
|
+
<pre><code><span class="text-blue-400">const</span> engine = <span class="text-blue-400">new</span> Lumina('#app', {
|
|
785
|
+
theme: <span class="text-green-400">'ocean'</span> <span class="text-gray-500">// 'midnight', 'forest', 'cyber', 'latte', 'sunset', 'monochrome'</span>
|
|
786
|
+
});
|
|
787
|
+
|
|
788
|
+
engine.load(myDeck);</code></pre>
|
|
789
|
+
</div>
|
|
790
|
+
|
|
791
|
+
<!-- CSS Variables -->
|
|
792
|
+
<div class="my-12">
|
|
793
|
+
<h2 class="text-2xl font-bold text-white mb-6">Complete Theme Configuration</h2>
|
|
794
|
+
<p class="text-white/60 mb-8">Lumina v9 introduces 80+ CSS custom properties for full visual
|
|
795
|
+
customization.
|
|
796
|
+
Configure via <code>themeConfig</code> in your deck JSON or engine options.</p>
|
|
797
|
+
|
|
798
|
+
<!-- COLORS SECTION -->
|
|
799
|
+
<div class="mb-12">
|
|
800
|
+
<h3 class="text-xl font-bold text-white mb-4 flex items-center gap-2">
|
|
801
|
+
<span
|
|
802
|
+
class="w-8 h-8 rounded-lg bg-blue-500/20 flex items-center justify-center text-blue-400">🎨</span>
|
|
803
|
+
Colors (25+ tokens)
|
|
804
|
+
</h3>
|
|
805
|
+
<div class="overflow-x-auto border border-white/10 rounded-lg">
|
|
806
|
+
<table class="w-full text-left text-sm text-gray-400">
|
|
807
|
+
<thead class="bg-white/5 text-white font-bold">
|
|
808
|
+
<tr>
|
|
809
|
+
<th class="p-3 border-b border-white/10">Property</th>
|
|
810
|
+
<th class="p-3 border-b border-white/10">CSS Variable</th>
|
|
811
|
+
<th class="p-3 border-b border-white/10">Description</th>
|
|
812
|
+
</tr>
|
|
813
|
+
</thead>
|
|
814
|
+
<tbody class="divide-y divide-white/5">
|
|
815
|
+
<tr>
|
|
816
|
+
<td colspan="3"
|
|
817
|
+
class="p-2 text-xs text-blue-400 bg-blue-500/5 font-bold">Core
|
|
818
|
+
Colors</td>
|
|
819
|
+
</tr>
|
|
820
|
+
<tr>
|
|
821
|
+
<td class="p-3 font-mono text-green-400">primary</td>
|
|
822
|
+
<td class="p-3 font-mono text-white/50">--lumina-color-primary</td>
|
|
823
|
+
<td class="p-3">Main brand/accent color</td>
|
|
824
|
+
</tr>
|
|
825
|
+
<tr>
|
|
826
|
+
<td class="p-3 font-mono text-green-400">secondary</td>
|
|
827
|
+
<td class="p-3 font-mono text-white/50">--lumina-color-secondary</td>
|
|
828
|
+
<td class="p-3">Complementary brand color</td>
|
|
829
|
+
</tr>
|
|
830
|
+
<tr>
|
|
831
|
+
<td class="p-3 font-mono text-green-400">accent</td>
|
|
832
|
+
<td class="p-3 font-mono text-white/50">--lumina-color-accent</td>
|
|
833
|
+
<td class="p-3">Tertiary/accent highlights</td>
|
|
834
|
+
</tr>
|
|
835
|
+
<tr>
|
|
836
|
+
<td class="p-3 font-mono text-green-400">background</td>
|
|
837
|
+
<td class="p-3 font-mono text-white/50">--lumina-color-background</td>
|
|
838
|
+
<td class="p-3">Main slide background</td>
|
|
839
|
+
</tr>
|
|
840
|
+
<tr>
|
|
841
|
+
<td class="p-3 font-mono text-green-400">surface</td>
|
|
842
|
+
<td class="p-3 font-mono text-white/50">--lumina-color-surface</td>
|
|
843
|
+
<td class="p-3">Cards, panels, elevated surfaces</td>
|
|
844
|
+
</tr>
|
|
845
|
+
<tr>
|
|
846
|
+
<td class="p-3 font-mono text-green-400">text</td>
|
|
847
|
+
<td class="p-3 font-mono text-white/50">--lumina-color-text</td>
|
|
848
|
+
<td class="p-3">Primary text color</td>
|
|
849
|
+
</tr>
|
|
850
|
+
<tr>
|
|
851
|
+
<td class="p-3 font-mono text-green-400">textSecondary</td>
|
|
852
|
+
<td class="p-3 font-mono text-white/50">--lumina-color-text-secondary
|
|
853
|
+
</td>
|
|
854
|
+
<td class="p-3">Secondary body text</td>
|
|
855
|
+
</tr>
|
|
856
|
+
<tr>
|
|
857
|
+
<td class="p-3 font-mono text-green-400">muted</td>
|
|
858
|
+
<td class="p-3 font-mono text-white/50">--lumina-color-muted</td>
|
|
859
|
+
<td class="p-3">Subdued text, captions</td>
|
|
860
|
+
</tr>
|
|
861
|
+
<tr>
|
|
862
|
+
<td colspan="3"
|
|
863
|
+
class="p-2 text-xs text-yellow-400 bg-yellow-500/5 font-bold">
|
|
864
|
+
Semantic Colors</td>
|
|
865
|
+
</tr>
|
|
866
|
+
<tr>
|
|
867
|
+
<td class="p-3 font-mono text-green-400">success</td>
|
|
868
|
+
<td class="p-3 font-mono text-white/50">--lumina-color-success</td>
|
|
869
|
+
<td class="p-3">Positive actions (#22c55e)</td>
|
|
870
|
+
</tr>
|
|
871
|
+
<tr>
|
|
872
|
+
<td class="p-3 font-mono text-green-400">warning</td>
|
|
873
|
+
<td class="p-3 font-mono text-white/50">--lumina-color-warning</td>
|
|
874
|
+
<td class="p-3">Caution states (#eab308)</td>
|
|
875
|
+
</tr>
|
|
876
|
+
<tr>
|
|
877
|
+
<td class="p-3 font-mono text-green-400">danger</td>
|
|
878
|
+
<td class="p-3 font-mono text-white/50">--lumina-color-danger</td>
|
|
879
|
+
<td class="p-3">Errors, destructive (#ef4444)</td>
|
|
880
|
+
</tr>
|
|
881
|
+
<tr>
|
|
882
|
+
<td class="p-3 font-mono text-green-400">info</td>
|
|
883
|
+
<td class="p-3 font-mono text-white/50">--lumina-color-info</td>
|
|
884
|
+
<td class="p-3">Informational highlights</td>
|
|
885
|
+
</tr>
|
|
886
|
+
<tr>
|
|
887
|
+
<td colspan="3"
|
|
888
|
+
class="p-2 text-xs text-purple-400 bg-purple-500/5 font-bold">UI
|
|
889
|
+
Colors</td>
|
|
890
|
+
</tr>
|
|
891
|
+
<tr>
|
|
892
|
+
<td class="p-3 font-mono text-green-400">border</td>
|
|
893
|
+
<td class="p-3 font-mono text-white/50">--lumina-color-border</td>
|
|
894
|
+
<td class="p-3">Default border color</td>
|
|
895
|
+
</tr>
|
|
896
|
+
<tr>
|
|
897
|
+
<td class="p-3 font-mono text-green-400">borderSubtle</td>
|
|
898
|
+
<td class="p-3 font-mono text-white/50">--lumina-color-border-subtle
|
|
899
|
+
</td>
|
|
900
|
+
<td class="p-3">Subtle/light borders</td>
|
|
901
|
+
</tr>
|
|
902
|
+
<tr>
|
|
903
|
+
<td class="p-3 font-mono text-green-400">shadow</td>
|
|
904
|
+
<td class="p-3 font-mono text-white/50">--lumina-shadow-color</td>
|
|
905
|
+
<td class="p-3">Shadow color for elevation</td>
|
|
906
|
+
</tr>
|
|
907
|
+
<tr>
|
|
908
|
+
<td colspan="3"
|
|
909
|
+
class="p-2 text-xs text-pink-400 bg-pink-500/5 font-bold">Gradient
|
|
910
|
+
Colors</td>
|
|
911
|
+
</tr>
|
|
912
|
+
<tr>
|
|
913
|
+
<td class="p-3 font-mono text-green-400">gradientFrom</td>
|
|
914
|
+
<td class="p-3 font-mono text-white/50">--lumina-gradient-from</td>
|
|
915
|
+
<td class="p-3">Gradient start color</td>
|
|
916
|
+
</tr>
|
|
917
|
+
<tr>
|
|
918
|
+
<td class="p-3 font-mono text-green-400">gradientVia</td>
|
|
919
|
+
<td class="p-3 font-mono text-white/50">--lumina-gradient-via</td>
|
|
920
|
+
<td class="p-3">Gradient middle (optional)</td>
|
|
921
|
+
</tr>
|
|
922
|
+
<tr>
|
|
923
|
+
<td class="p-3 font-mono text-green-400">gradientTo</td>
|
|
924
|
+
<td class="p-3 font-mono text-white/50">--lumina-gradient-to</td>
|
|
925
|
+
<td class="p-3">Gradient end color</td>
|
|
926
|
+
</tr>
|
|
927
|
+
</tbody>
|
|
928
|
+
</table>
|
|
929
|
+
</div>
|
|
930
|
+
</div>
|
|
931
|
+
|
|
932
|
+
<!-- EFFECTS SECTION -->
|
|
933
|
+
<div class="mb-12">
|
|
934
|
+
<h3 class="text-xl font-bold text-white mb-4 flex items-center gap-2">
|
|
935
|
+
<span
|
|
936
|
+
class="w-8 h-8 rounded-lg bg-purple-500/20 flex items-center justify-center text-purple-400">✨</span>
|
|
937
|
+
Effects
|
|
938
|
+
</h3>
|
|
939
|
+
<div class="overflow-x-auto border border-white/10 rounded-lg">
|
|
940
|
+
<table class="w-full text-left text-sm text-gray-400">
|
|
941
|
+
<thead class="bg-white/5 text-white font-bold">
|
|
942
|
+
<tr>
|
|
943
|
+
<th class="p-3 border-b border-white/10">Property</th>
|
|
944
|
+
<th class="p-3 border-b border-white/10">Type</th>
|
|
945
|
+
<th class="p-3 border-b border-white/10">Values</th>
|
|
946
|
+
<th class="p-3 border-b border-white/10">Default</th>
|
|
947
|
+
</tr>
|
|
948
|
+
</thead>
|
|
949
|
+
<tbody class="divide-y divide-white/5">
|
|
950
|
+
<tr>
|
|
951
|
+
<td colspan="4"
|
|
952
|
+
class="p-2 text-xs text-pink-400 bg-pink-500/5 font-bold">Gradients
|
|
953
|
+
</td>
|
|
954
|
+
</tr>
|
|
955
|
+
<tr>
|
|
956
|
+
<td class="p-3 font-mono text-green-400">useGradients</td>
|
|
957
|
+
<td class="p-3 text-purple-400">boolean</td>
|
|
958
|
+
<td class="p-3">true / false</td>
|
|
959
|
+
<td class="p-3">true</td>
|
|
960
|
+
</tr>
|
|
961
|
+
<tr>
|
|
962
|
+
<td class="p-3 font-mono text-green-400">gradientDirection</td>
|
|
963
|
+
<td class="p-3 text-purple-400">enum</td>
|
|
964
|
+
<td class="p-3 font-mono text-xs">'to-t' | 'to-b' | 'to-l' | 'to-r' |
|
|
965
|
+
'to-tl' | 'to-tr' | 'to-bl' | 'to-br'</td>
|
|
966
|
+
<td class="p-3">'to-br'</td>
|
|
967
|
+
</tr>
|
|
968
|
+
<tr>
|
|
969
|
+
<td colspan="4"
|
|
970
|
+
class="p-2 text-xs text-blue-400 bg-blue-500/5 font-bold">Shadows
|
|
971
|
+
</td>
|
|
972
|
+
</tr>
|
|
973
|
+
<tr>
|
|
974
|
+
<td class="p-3 font-mono text-green-400">useShadows</td>
|
|
975
|
+
<td class="p-3 text-purple-400">boolean</td>
|
|
976
|
+
<td class="p-3">true / false</td>
|
|
977
|
+
<td class="p-3">true</td>
|
|
978
|
+
</tr>
|
|
979
|
+
<tr>
|
|
980
|
+
<td class="p-3 font-mono text-green-400">shadowIntensity</td>
|
|
981
|
+
<td class="p-3 text-purple-400">enum</td>
|
|
982
|
+
<td class="p-3 font-mono text-xs">'none' | 'sm' | 'md' | 'lg' | 'xl' |
|
|
983
|
+
'2xl'</td>
|
|
984
|
+
<td class="p-3">'md'</td>
|
|
985
|
+
</tr>
|
|
986
|
+
<tr>
|
|
987
|
+
<td class="p-3 font-mono text-green-400">shadowColor</td>
|
|
988
|
+
<td class="p-3 text-purple-400">string</td>
|
|
989
|
+
<td class="p-3">Any CSS color (rgba works best)</td>
|
|
990
|
+
<td class="p-3">rgba(0,0,0,0.25)</td>
|
|
991
|
+
</tr>
|
|
992
|
+
<tr>
|
|
993
|
+
<td colspan="4"
|
|
994
|
+
class="p-2 text-xs text-cyan-400 bg-cyan-500/5 font-bold">
|
|
995
|
+
Glassmorphism</td>
|
|
996
|
+
</tr>
|
|
997
|
+
<tr>
|
|
998
|
+
<td class="p-3 font-mono text-green-400">useGlass</td>
|
|
999
|
+
<td class="p-3 text-purple-400">boolean</td>
|
|
1000
|
+
<td class="p-3">true / false (frosted glass panels)</td>
|
|
1001
|
+
<td class="p-3">true</td>
|
|
1002
|
+
</tr>
|
|
1003
|
+
<tr>
|
|
1004
|
+
<td class="p-3 font-mono text-green-400">glassOpacity</td>
|
|
1005
|
+
<td class="p-3 text-purple-400">number</td>
|
|
1006
|
+
<td class="p-3">0 to 1 (panel background opacity)</td>
|
|
1007
|
+
<td class="p-3">0.03</td>
|
|
1008
|
+
</tr>
|
|
1009
|
+
<tr>
|
|
1010
|
+
<td class="p-3 font-mono text-green-400">glassBlur</td>
|
|
1011
|
+
<td class="p-3 text-purple-400">string</td>
|
|
1012
|
+
<td class="p-3">CSS blur value (e.g., '20px')</td>
|
|
1013
|
+
<td class="p-3">'20px'</td>
|
|
1014
|
+
</tr>
|
|
1015
|
+
<tr>
|
|
1016
|
+
<td class="p-3 font-mono text-green-400">glassBorderOpacity</td>
|
|
1017
|
+
<td class="p-3 text-purple-400">number</td>
|
|
1018
|
+
<td class="p-3">0 to 1 (subtle border opacity)</td>
|
|
1019
|
+
<td class="p-3">0.05</td>
|
|
1020
|
+
</tr>
|
|
1021
|
+
<tr>
|
|
1022
|
+
<td colspan="4"
|
|
1023
|
+
class="p-2 text-xs text-orange-400 bg-orange-500/5 font-bold">
|
|
1024
|
+
Ambient Orb</td>
|
|
1025
|
+
</tr>
|
|
1026
|
+
<tr>
|
|
1027
|
+
<td class="p-3 font-mono text-green-400">useOrb</td>
|
|
1028
|
+
<td class="p-3 text-purple-400">boolean</td>
|
|
1029
|
+
<td class="p-3">true / false (background glow)</td>
|
|
1030
|
+
<td class="p-3">true</td>
|
|
1031
|
+
</tr>
|
|
1032
|
+
<tr>
|
|
1033
|
+
<td class="p-3 font-mono text-green-400">orbOpacity</td>
|
|
1034
|
+
<td class="p-3 text-purple-400">number</td>
|
|
1035
|
+
<td class="p-3">0 to 1</td>
|
|
1036
|
+
<td class="p-3">0.4</td>
|
|
1037
|
+
</tr>
|
|
1038
|
+
<tr>
|
|
1039
|
+
<td class="p-3 font-mono text-green-400">orbBlur</td>
|
|
1040
|
+
<td class="p-3 text-purple-400">string</td>
|
|
1041
|
+
<td class="p-3">CSS blur value</td>
|
|
1042
|
+
<td class="p-3">'120px'</td>
|
|
1043
|
+
</tr>
|
|
1044
|
+
<tr>
|
|
1045
|
+
<td class="p-3 font-mono text-green-400">orbSize</td>
|
|
1046
|
+
<td class="p-3 text-purple-400">string</td>
|
|
1047
|
+
<td class="p-3">CSS size (vw, vh, px, %)</td>
|
|
1048
|
+
<td class="p-3">'60vw'</td>
|
|
1049
|
+
</tr>
|
|
1050
|
+
<tr>
|
|
1051
|
+
<td colspan="4"
|
|
1052
|
+
class="p-2 text-xs text-green-400 bg-green-500/5 font-bold">
|
|
1053
|
+
Animations</td>
|
|
1054
|
+
</tr>
|
|
1055
|
+
<tr>
|
|
1056
|
+
<td class="p-3 font-mono text-green-400">animationsEnabled</td>
|
|
1057
|
+
<td class="p-3 text-purple-400">boolean</td>
|
|
1058
|
+
<td class="p-3">Master toggle for all animations</td>
|
|
1059
|
+
<td class="p-3">true</td>
|
|
1060
|
+
</tr>
|
|
1061
|
+
<tr>
|
|
1062
|
+
<td class="p-3 font-mono text-green-400">transitionDuration</td>
|
|
1063
|
+
<td class="p-3 text-purple-400">string</td>
|
|
1064
|
+
<td class="p-3">CSS duration (e.g., '0.3s')</td>
|
|
1065
|
+
<td class="p-3">'0.3s'</td>
|
|
1066
|
+
</tr>
|
|
1067
|
+
<tr>
|
|
1068
|
+
<td class="p-3 font-mono text-green-400">transitionEasing</td>
|
|
1069
|
+
<td class="p-3 text-purple-400">string</td>
|
|
1070
|
+
<td class="p-3">CSS easing function</td>
|
|
1071
|
+
<td class="p-3">cubic-bezier(0.16,1,0.3,1)</td>
|
|
1072
|
+
</tr>
|
|
1073
|
+
<tr>
|
|
1074
|
+
<td class="p-3 font-mono text-green-400">hoverScale</td>
|
|
1075
|
+
<td class="p-3 text-purple-400">number</td>
|
|
1076
|
+
<td class="p-3">Scale on hover (1.0 = no scale)</td>
|
|
1077
|
+
<td class="p-3">1.05</td>
|
|
1078
|
+
</tr>
|
|
1079
|
+
</tbody>
|
|
1080
|
+
</table>
|
|
1081
|
+
</div>
|
|
1082
|
+
</div>
|
|
1083
|
+
|
|
1084
|
+
<!-- COMPONENTS SECTION -->
|
|
1085
|
+
<div class="mb-12">
|
|
1086
|
+
<h3 class="text-xl font-bold text-white mb-4 flex items-center gap-2">
|
|
1087
|
+
<span
|
|
1088
|
+
class="w-8 h-8 rounded-lg bg-green-500/20 flex items-center justify-center text-green-400">🧩</span>
|
|
1089
|
+
Component Tokens
|
|
1090
|
+
</h3>
|
|
1091
|
+
<div class="overflow-x-auto border border-white/10 rounded-lg">
|
|
1092
|
+
<table class="w-full text-left text-sm text-gray-400">
|
|
1093
|
+
<thead class="bg-white/5 text-white font-bold">
|
|
1094
|
+
<tr>
|
|
1095
|
+
<th class="p-3 border-b border-white/10">Property</th>
|
|
1096
|
+
<th class="p-3 border-b border-white/10">CSS Variable</th>
|
|
1097
|
+
<th class="p-3 border-b border-white/10">Default</th>
|
|
1098
|
+
</tr>
|
|
1099
|
+
</thead>
|
|
1100
|
+
<tbody class="divide-y divide-white/5">
|
|
1101
|
+
<tr>
|
|
1102
|
+
<td colspan="3"
|
|
1103
|
+
class="p-2 text-xs text-blue-400 bg-blue-500/5 font-bold">Buttons
|
|
1104
|
+
</td>
|
|
1105
|
+
</tr>
|
|
1106
|
+
<tr>
|
|
1107
|
+
<td class="p-3 font-mono text-green-400">buttonRadius</td>
|
|
1108
|
+
<td class="p-3 font-mono text-white/50">--lumina-button-radius</td>
|
|
1109
|
+
<td class="p-3">9999px (pill)</td>
|
|
1110
|
+
</tr>
|
|
1111
|
+
<tr>
|
|
1112
|
+
<td class="p-3 font-mono text-green-400">buttonPadding</td>
|
|
1113
|
+
<td class="p-3 font-mono text-white/50">--lumina-button-padding</td>
|
|
1114
|
+
<td class="p-3">0.75rem 1.5rem</td>
|
|
1115
|
+
</tr>
|
|
1116
|
+
<tr>
|
|
1117
|
+
<td class="p-3 font-mono text-green-400">buttonFontWeight</td>
|
|
1118
|
+
<td class="p-3 font-mono text-white/50">--lumina-button-font-weight</td>
|
|
1119
|
+
<td class="p-3">700</td>
|
|
1120
|
+
</tr>
|
|
1121
|
+
<tr>
|
|
1122
|
+
<td class="p-3 font-mono text-green-400">buttonTextTransform</td>
|
|
1123
|
+
<td class="p-3 font-mono text-white/50">--lumina-button-text-transform
|
|
1124
|
+
</td>
|
|
1125
|
+
<td class="p-3">none</td>
|
|
1126
|
+
</tr>
|
|
1127
|
+
<tr>
|
|
1128
|
+
<td colspan="3"
|
|
1129
|
+
class="p-2 text-xs text-purple-400 bg-purple-500/5 font-bold">Cards
|
|
1130
|
+
</td>
|
|
1131
|
+
</tr>
|
|
1132
|
+
<tr>
|
|
1133
|
+
<td class="p-3 font-mono text-green-400">cardRadius</td>
|
|
1134
|
+
<td class="p-3 font-mono text-white/50">--lumina-card-radius</td>
|
|
1135
|
+
<td class="p-3">1.5rem</td>
|
|
1136
|
+
</tr>
|
|
1137
|
+
<tr>
|
|
1138
|
+
<td class="p-3 font-mono text-green-400">cardPadding</td>
|
|
1139
|
+
<td class="p-3 font-mono text-white/50">--lumina-card-padding</td>
|
|
1140
|
+
<td class="p-3">2rem</td>
|
|
1141
|
+
</tr>
|
|
1142
|
+
<tr>
|
|
1143
|
+
<td class="p-3 font-mono text-green-400">cardBorderWidth</td>
|
|
1144
|
+
<td class="p-3 font-mono text-white/50">--lumina-card-border-width</td>
|
|
1145
|
+
<td class="p-3">1px</td>
|
|
1146
|
+
</tr>
|
|
1147
|
+
<tr>
|
|
1148
|
+
<td colspan="3"
|
|
1149
|
+
class="p-2 text-xs text-cyan-400 bg-cyan-500/5 font-bold">Timeline
|
|
1150
|
+
</td>
|
|
1151
|
+
</tr>
|
|
1152
|
+
<tr>
|
|
1153
|
+
<td class="p-3 font-mono text-green-400">timelineNodeSize</td>
|
|
1154
|
+
<td class="p-3 font-mono text-white/50">--lumina-timeline-node-size</td>
|
|
1155
|
+
<td class="p-3">1rem</td>
|
|
1156
|
+
</tr>
|
|
1157
|
+
<tr>
|
|
1158
|
+
<td class="p-3 font-mono text-green-400">timelineLineWidth</td>
|
|
1159
|
+
<td class="p-3 font-mono text-white/50">--lumina-timeline-line-width
|
|
1160
|
+
</td>
|
|
1161
|
+
<td class="p-3">2px</td>
|
|
1162
|
+
</tr>
|
|
1163
|
+
<tr>
|
|
1164
|
+
<td class="p-3 font-mono text-green-400">timelineNodeColor</td>
|
|
1165
|
+
<td class="p-3 font-mono text-white/50">--lumina-timeline-node-color
|
|
1166
|
+
</td>
|
|
1167
|
+
<td class="p-3">(uses primary)</td>
|
|
1168
|
+
</tr>
|
|
1169
|
+
<tr>
|
|
1170
|
+
<td colspan="3"
|
|
1171
|
+
class="p-2 text-xs text-pink-400 bg-pink-500/5 font-bold">
|
|
1172
|
+
Tags/Badges</td>
|
|
1173
|
+
</tr>
|
|
1174
|
+
<tr>
|
|
1175
|
+
<td class="p-3 font-mono text-green-400">tagPadding</td>
|
|
1176
|
+
<td class="p-3 font-mono text-white/50">--lumina-tag-padding</td>
|
|
1177
|
+
<td class="p-3">0.25rem 1rem</td>
|
|
1178
|
+
</tr>
|
|
1179
|
+
<tr>
|
|
1180
|
+
<td class="p-3 font-mono text-green-400">tagRadius</td>
|
|
1181
|
+
<td class="p-3 font-mono text-white/50">--lumina-tag-radius</td>
|
|
1182
|
+
<td class="p-3">9999px</td>
|
|
1183
|
+
</tr>
|
|
1184
|
+
<tr>
|
|
1185
|
+
<td class="p-3 font-mono text-green-400">tagFontSize</td>
|
|
1186
|
+
<td class="p-3 font-mono text-white/50">--lumina-tag-font-size</td>
|
|
1187
|
+
<td class="p-3">0.75rem</td>
|
|
1188
|
+
</tr>
|
|
1189
|
+
</tbody>
|
|
1190
|
+
</table>
|
|
1191
|
+
</div>
|
|
1192
|
+
</div>
|
|
1193
|
+
|
|
1194
|
+
<!-- TYPOGRAPHY SECTION -->
|
|
1195
|
+
<div class="mb-12">
|
|
1196
|
+
<h3 class="text-xl font-bold text-white mb-4 flex items-center gap-2">
|
|
1197
|
+
<span
|
|
1198
|
+
class="w-8 h-8 rounded-lg bg-yellow-500/20 flex items-center justify-center text-yellow-400">🔤</span>
|
|
1199
|
+
Typography
|
|
1200
|
+
</h3>
|
|
1201
|
+
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
1202
|
+
<div class="border border-white/10 rounded-lg p-4">
|
|
1203
|
+
<h4 class="text-white font-bold mb-3">Font Families</h4>
|
|
1204
|
+
<div class="space-y-2 text-sm">
|
|
1205
|
+
<div><code class="text-green-400">heading</code>: <span
|
|
1206
|
+
class="text-white/60">Headings (default: Outfit)</span></div>
|
|
1207
|
+
<div><code class="text-green-400">body</code>: <span
|
|
1208
|
+
class="text-white/60">Body text (default: Outfit)</span></div>
|
|
1209
|
+
<div><code class="text-green-400">mono</code>: <span
|
|
1210
|
+
class="text-white/60">Code (default: monospace)</span></div>
|
|
1211
|
+
</div>
|
|
1212
|
+
</div>
|
|
1213
|
+
<div class="border border-white/10 rounded-lg p-4">
|
|
1214
|
+
<h4 class="text-white font-bold mb-3">Font Sizes (--lumina-text-*)</h4>
|
|
1215
|
+
<div class="space-y-1 text-sm text-white/60">
|
|
1216
|
+
<div>xs: 0.75rem | sm: 0.875rem | base: 1rem</div>
|
|
1217
|
+
<div>lg: 1.125rem | xl: 1.25rem | 2xl: 1.5rem</div>
|
|
1218
|
+
<div>3xl: 1.875rem | 4xl: 2.25rem | 5xl: 3rem</div>
|
|
1219
|
+
<div>6xl: 3.75rem | 7xl: 4.5rem</div>
|
|
1220
|
+
</div>
|
|
1221
|
+
</div>
|
|
1222
|
+
<div class="border border-white/10 rounded-lg p-4">
|
|
1223
|
+
<h4 class="text-white font-bold mb-3">Font Weights (--lumina-font-weight-*)</h4>
|
|
1224
|
+
<div class="space-y-1 text-sm text-white/60">
|
|
1225
|
+
<div>light: 300 | normal: 400 | medium: 500</div>
|
|
1226
|
+
<div>semibold: 600 | bold: 800 | extrabold: 900</div>
|
|
1227
|
+
</div>
|
|
1228
|
+
</div>
|
|
1229
|
+
<div class="border border-white/10 rounded-lg p-4">
|
|
1230
|
+
<h4 class="text-white font-bold mb-3">Line Heights (--lumina-leading-*)</h4>
|
|
1231
|
+
<div class="space-y-1 text-sm text-white/60">
|
|
1232
|
+
<div>tight: 1.1 | snug: 1.25 | normal: 1.5</div>
|
|
1233
|
+
<div>relaxed: 1.625 | loose: 2</div>
|
|
1234
|
+
</div>
|
|
1235
|
+
</div>
|
|
1236
|
+
</div>
|
|
1237
|
+
</div>
|
|
1238
|
+
|
|
1239
|
+
<!-- SPACING SECTION -->
|
|
1240
|
+
<div class="mb-12">
|
|
1241
|
+
<h3 class="text-xl font-bold text-white mb-4 flex items-center gap-2">
|
|
1242
|
+
<span
|
|
1243
|
+
class="w-8 h-8 rounded-lg bg-cyan-500/20 flex items-center justify-center text-cyan-400">📏</span>
|
|
1244
|
+
Spacing & Border Radius
|
|
1245
|
+
</h3>
|
|
1246
|
+
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
1247
|
+
<div class="border border-white/10 rounded-lg p-4">
|
|
1248
|
+
<h4 class="text-white font-bold mb-3">Spacing (--lumina-space-*)</h4>
|
|
1249
|
+
<div class="space-y-1 text-sm text-white/60">
|
|
1250
|
+
<div>none: 0 | xs: 0.25rem | sm: 0.5rem</div>
|
|
1251
|
+
<div>md: 1rem | lg: 1.5rem | xl: 2rem</div>
|
|
1252
|
+
<div>2xl: 3rem | 3xl: 4rem | 4xl: 6rem</div>
|
|
1253
|
+
</div>
|
|
1254
|
+
</div>
|
|
1255
|
+
<div class="border border-white/10 rounded-lg p-4">
|
|
1256
|
+
<h4 class="text-white font-bold mb-3">Border Radius (--lumina-radius-*)</h4>
|
|
1257
|
+
<div class="space-y-1 text-sm text-white/60">
|
|
1258
|
+
<div>none: 0 | sm: 0.25rem | md: 0.5rem</div>
|
|
1259
|
+
<div>lg: 0.75rem | xl: 1rem | 2xl: 1.5rem</div>
|
|
1260
|
+
<div>3xl: 2rem | full: 9999px</div>
|
|
1261
|
+
</div>
|
|
1262
|
+
</div>
|
|
1263
|
+
</div>
|
|
1264
|
+
</div>
|
|
1265
|
+
|
|
1266
|
+
<!-- JSON Example -->
|
|
1267
|
+
<div class="mt-8">
|
|
1268
|
+
<h3 class="text-xl font-bold text-white mb-4">Full themeConfig Example</h3>
|
|
1269
|
+
<pre><code><span class="text-gray-500">// In your deck JSON</span>
|
|
1270
|
+
{
|
|
1271
|
+
<span class="text-blue-400">"meta"</span>: {
|
|
1272
|
+
<span class="text-blue-400">"theme"</span>: <span class="text-green-400">"default"</span>,
|
|
1273
|
+
<span class="text-blue-400">"themeConfig"</span>: {
|
|
1274
|
+
<span class="text-blue-400">"colors"</span>: {
|
|
1275
|
+
<span class="text-blue-400">"primary"</span>: <span class="text-green-400">"#8b5cf6"</span>,
|
|
1276
|
+
<span class="text-blue-400">"secondary"</span>: <span class="text-green-400">"#ec4899"</span>,
|
|
1277
|
+
<span class="text-blue-400">"gradientFrom"</span>: <span class="text-green-400">"#8b5cf6"</span>,
|
|
1278
|
+
<span class="text-blue-400">"gradientTo"</span>: <span class="text-green-400">"#ec4899"</span>
|
|
1279
|
+
},
|
|
1280
|
+
<span class="text-blue-400">"effects"</span>: {
|
|
1281
|
+
<span class="text-blue-400">"useGradients"</span>: <span class="text-yellow-400">true</span>,
|
|
1282
|
+
<span class="text-blue-400">"useGlass"</span>: <span class="text-yellow-400">true</span>,
|
|
1283
|
+
<span class="text-blue-400">"glassOpacity"</span>: <span class="text-yellow-400">0.05</span>,
|
|
1284
|
+
<span class="text-blue-400">"useOrb"</span>: <span class="text-yellow-400">true</span>,
|
|
1285
|
+
<span class="text-blue-400">"orbOpacity"</span>: <span class="text-yellow-400">0.4</span>
|
|
1286
|
+
},
|
|
1287
|
+
<span class="text-blue-400">"components"</span>: {
|
|
1288
|
+
<span class="text-blue-400">"cardRadius"</span>: <span class="text-green-400">"1.5rem"</span>,
|
|
1289
|
+
<span class="text-blue-400">"buttonRadius"</span>: <span class="text-green-400">"9999px"</span>
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
}
|
|
1293
|
+
}</code></pre>
|
|
1294
|
+
</div>
|
|
1295
|
+
</div>
|
|
1296
|
+
|
|
1297
|
+
<!-- Custom Theme Object -->
|
|
1298
|
+
<div class="my-12">
|
|
1299
|
+
<h2 class="text-2xl font-bold text-white mb-6">Custom Theme Configuration</h2>
|
|
1300
|
+
<p class="text-white/60 mb-4">Pass a configuration object for full control over colors and
|
|
1301
|
+
fonts:</p>
|
|
1302
|
+
|
|
1303
|
+
<pre><code><span class="text-blue-400">const</span> engine = <span class="text-blue-400">new</span> Lumina('#app', {
|
|
1304
|
+
theme: {
|
|
1305
|
+
colors: {
|
|
1306
|
+
primary: <span class="text-green-400">'#ec4899'</span>, <span class="text-gray-500">// Pink accent</span>
|
|
1307
|
+
background: <span class="text-green-400">'#1a1a2e'</span>, <span class="text-gray-500">// Dark purple bg</span>
|
|
1308
|
+
text: <span class="text-green-400">'#eaeaea'</span>, <span class="text-gray-500">// Light text</span>
|
|
1309
|
+
muted: <span class="text-green-400">'#888888'</span> <span class="text-gray-500">// Subdued text</span>
|
|
1310
|
+
},
|
|
1311
|
+
fonts: {
|
|
1312
|
+
heading: <span class="text-green-400">'Outfit, sans-serif'</span>,
|
|
1313
|
+
body: <span class="text-green-400">'Inter, sans-serif'</span>,
|
|
1314
|
+
mono: <span class="text-green-400">'Fira Code, monospace'</span>
|
|
1315
|
+
}
|
|
1316
|
+
}
|
|
1317
|
+
});</code></pre>
|
|
1318
|
+
</div>
|
|
1319
|
+
|
|
1320
|
+
<!-- Partial Override -->
|
|
1321
|
+
<div class="my-12">
|
|
1322
|
+
<h2 class="text-2xl font-bold text-white mb-6">Partial Overrides</h2>
|
|
1323
|
+
<p class="text-white/60 mb-4">You don't need to specify every property. Lumina merges your
|
|
1324
|
+
values with the default theme:</p>
|
|
1325
|
+
|
|
1326
|
+
<pre><code><span class="text-gray-500">// Only change the primary color</span>
|
|
1327
|
+
<span class="text-blue-400">const</span> engine = <span class="text-blue-400">new</span> Lumina('#app', {
|
|
1328
|
+
theme: {
|
|
1329
|
+
colors: {
|
|
1330
|
+
primary: <span class="text-green-400">'#f59e0b'</span> <span class="text-gray-500">// Amber accent</span>
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1333
|
+
});
|
|
1334
|
+
|
|
1335
|
+
<span class="text-gray-500">// Everything else uses defaults!</span></code></pre>
|
|
1336
|
+
</div>
|
|
1337
|
+
|
|
1338
|
+
<!-- Font Loading -->
|
|
1339
|
+
<div class="my-12">
|
|
1340
|
+
<h2 class="text-2xl font-bold text-white mb-6">Custom Fonts</h2>
|
|
1341
|
+
<p class="text-white/60 mb-4">For custom fonts, load them via Google Fonts or your own
|
|
1342
|
+
stylesheet first:</p>
|
|
1343
|
+
|
|
1344
|
+
<pre
|
|
1345
|
+
class="language-html"><code><span class="text-gray-500"><!-- In your HTML head --></span>
|
|
1346
|
+
<span class="text-blue-400"><link</span> rel=<span class="text-green-400">"preconnect"</span> href=<span class="text-green-400">"https://fonts.googleapis.com"</span><span class="text-blue-400">></span>
|
|
1347
|
+
<span class="text-blue-400"><link</span> href=<span class="text-green-400">"https://fonts.googleapis.com/css2?family=Outfit:wght@400;700&family=Rajdhani&display=swap"</span> rel=<span class="text-green-400">"stylesheet"</span><span class="text-blue-400">></span></code></pre>
|
|
1348
|
+
|
|
1349
|
+
<p class="text-white/60 mt-4 mb-4">Then reference them in your theme config:</p>
|
|
1350
|
+
|
|
1351
|
+
<pre><code><span class="text-blue-400">const</span> engine = <span class="text-blue-400">new</span> Lumina('#app', {
|
|
1352
|
+
theme: {
|
|
1353
|
+
fonts: {
|
|
1354
|
+
heading: <span class="text-green-400">'Outfit, sans-serif'</span>,
|
|
1355
|
+
body: <span class="text-green-400">'Rajdhani, sans-serif'</span>
|
|
1356
|
+
}
|
|
1357
|
+
}
|
|
1358
|
+
});</code></pre>
|
|
1359
|
+
</div>
|
|
1360
|
+
|
|
1361
|
+
<!-- Tips -->
|
|
1362
|
+
<div class="mt-8 p-4 bg-yellow-500/10 border border-yellow-500/20 rounded-lg">
|
|
1363
|
+
<h4 class="text-yellow-400 font-bold mb-2"><i class="fa-solid fa-lightbulb mr-2"></i>Pro
|
|
1364
|
+
Tips</h4>
|
|
1365
|
+
<ul class="text-sm text-yellow-200/80 space-y-2 m-0 list-none">
|
|
1366
|
+
<li>🎨 <strong>Brand colors:</strong> Set <code>primary</code> to your brand color for
|
|
1367
|
+
instant recognition</li>
|
|
1368
|
+
<li>🌙 <strong>Dark vs Light:</strong> Use <code>latte</code> preset for light mode
|
|
1369
|
+
presentations</li>
|
|
1370
|
+
<li>📱 <strong>Accessibility:</strong> Ensure sufficient contrast between
|
|
1371
|
+
<code>text</code> and <code>background</code>
|
|
1372
|
+
</li>
|
|
1373
|
+
<li>🔤 <strong>Performance:</strong> Only load font weights you actually use (400, 700)
|
|
1374
|
+
</li>
|
|
1375
|
+
</ul>
|
|
1376
|
+
</div>
|
|
1377
|
+
</div>
|
|
1378
|
+
|
|
1379
|
+
<!-- SPEAKER NOTES -->
|
|
1380
|
+
<div v-else-if="activeSection === 'speaker-notes'">
|
|
1381
|
+
<h1>Speaker Notes</h1>
|
|
1382
|
+
<p class="lead">Open a separate presenter view with notes, timer, and bidirectional navigation
|
|
1383
|
+
controls.</p>
|
|
1384
|
+
|
|
1385
|
+
<h2>Adding Notes to Slides</h2>
|
|
1386
|
+
<p>Add the <code>notes</code> property to any slide. Notes are only visible in the presenter
|
|
1387
|
+
view, not on the main display.</p>
|
|
1388
|
+
|
|
1389
|
+
<pre><code>{
|
|
1390
|
+
<span class="text-blue-400">"type"</span>: <span class="text-green-400">"statement"</span>,
|
|
1391
|
+
<span class="text-blue-400">"title"</span>: <span class="text-green-400">"Welcome"</span>,
|
|
1392
|
+
<span class="text-blue-400">"subtitle"</span>: <span class="text-green-400">"An introduction to our platform"</span>,
|
|
1393
|
+
<span class="text-blue-400">"notes"</span>: <span class="text-green-400">"Greet the audience. Mention key stakeholders. Time: 2 minutes."</span>
|
|
1394
|
+
}</code></pre>
|
|
1395
|
+
|
|
1396
|
+
<h2>Opening the Presenter View</h2>
|
|
1397
|
+
<p>Call <code>openSpeakerNotes()</code> on your Lumina instance to open the presenter window.
|
|
1398
|
+
</p>
|
|
1399
|
+
|
|
1400
|
+
<pre><code><span class="text-blue-400">const</span> engine = <span class="text-blue-400">new</span> Lumina('#app');
|
|
1401
|
+
engine.load(deckData);
|
|
1402
|
+
|
|
1403
|
+
<span class="text-gray-500">// Open presenter view</span>
|
|
1404
|
+
engine.<span class="text-yellow-400">openSpeakerNotes</span>();
|
|
1405
|
+
|
|
1406
|
+
<span class="text-gray-500">// Check if open</span>
|
|
1407
|
+
<span class="text-blue-400">if</span> (engine.isSpeakerNotesOpen) {
|
|
1408
|
+
console.log('Presenter view active');
|
|
1409
|
+
}
|
|
1410
|
+
|
|
1411
|
+
<span class="text-gray-500">// Close programmatically</span>
|
|
1412
|
+
engine.<span class="text-yellow-400">closeSpeakerNotes</span>();</code></pre>
|
|
1413
|
+
|
|
1414
|
+
<h3>Presenter View Features</h3>
|
|
1415
|
+
<ul>
|
|
1416
|
+
<li><strong>Current Notes</strong> — Formatted notes for the current slide</li>
|
|
1417
|
+
<li><strong>Next Slide Preview</strong> — Title and type of the upcoming slide</li>
|
|
1418
|
+
<li><strong>Timer</strong> — Start/pause/reset presentation timer</li>
|
|
1419
|
+
<li><strong>Navigation</strong> — Synced controls (changes reflect in main window)</li>
|
|
1420
|
+
<li><strong>Connection Status</strong> — Visual indicator of sync state</li>
|
|
1421
|
+
</ul>
|
|
1422
|
+
|
|
1423
|
+
<h3>Keyboard Shortcuts (Presenter View)</h3>
|
|
1424
|
+
<div class="overflow-x-auto border border-white/10 rounded-lg my-6">
|
|
1425
|
+
<table class="w-full text-left text-sm text-gray-400">
|
|
1426
|
+
<thead class="bg-white/5 text-white font-bold">
|
|
1427
|
+
<tr>
|
|
1428
|
+
<th class="p-3 border-b border-white/10">Key</th>
|
|
1429
|
+
<th class="p-3 border-b border-white/10">Action</th>
|
|
1430
|
+
</tr>
|
|
1431
|
+
</thead>
|
|
1432
|
+
<tbody class="divide-y divide-white/5">
|
|
1433
|
+
<tr>
|
|
1434
|
+
<td class="p-3 font-mono">→ / Space / Enter</td>
|
|
1435
|
+
<td class="p-3">Next slide</td>
|
|
1436
|
+
</tr>
|
|
1437
|
+
<tr>
|
|
1438
|
+
<td class="p-3 font-mono">← / Backspace</td>
|
|
1439
|
+
<td class="p-3">Previous slide</td>
|
|
1440
|
+
</tr>
|
|
1441
|
+
<tr>
|
|
1442
|
+
<td class="p-3 font-mono">T</td>
|
|
1443
|
+
<td class="p-3">Toggle timer</td>
|
|
1444
|
+
</tr>
|
|
1445
|
+
<tr>
|
|
1446
|
+
<td class="p-3 font-mono">R</td>
|
|
1447
|
+
<td class="p-3">Reset timer</td>
|
|
1448
|
+
</tr>
|
|
1449
|
+
</tbody>
|
|
1450
|
+
</table>
|
|
1451
|
+
</div>
|
|
1452
|
+
|
|
1453
|
+
<div class="mt-8 p-4 bg-blue-500/10 border border-blue-500/20 rounded-lg">
|
|
1454
|
+
<h4 class="text-blue-400 font-bold mb-2"><i class="fa-solid fa-lightbulb mr-2"></i>Pro Tip
|
|
1455
|
+
</h4>
|
|
1456
|
+
<p class="text-sm text-blue-200/80 m-0">Position the presenter window on your secondary
|
|
1457
|
+
monitor while the presentation runs on the main display. Navigation from either window
|
|
1458
|
+
stays synchronized.</p>
|
|
1459
|
+
</div>
|
|
1460
|
+
</div>
|
|
1461
|
+
|
|
1462
|
+
|
|
1463
|
+
<!-- AGENTS: INTRO -->
|
|
1464
|
+
<div v-else-if="activeSection === 'agents-intro'">
|
|
1465
|
+
<h1>The Agent Protocol</h1>
|
|
1466
|
+
<p class="lead">Lumina is the first presentation engine designed for <strong>Agentic
|
|
1467
|
+
AI</strong>.</p>
|
|
1468
|
+
<p>Large Language Models (LLMs) are great at "What" (Content) but struggle with "How"
|
|
1469
|
+
(Pixel-perfect CSS).
|
|
1470
|
+
Lumina solves this by acting as a <strong>Semantic Interface Layer</strong>.</p>
|
|
1471
|
+
|
|
1472
|
+
<div class="grid grid-cols-1 md:grid-cols-2 gap-8 my-12 not-prose">
|
|
1473
|
+
<div
|
|
1474
|
+
class="bg-gray-900 border border-purple-500/20 rounded-xl p-8 relative overflow-hidden">
|
|
1475
|
+
<div class="absolute top-0 right-0 p-4 opacity-20">
|
|
1476
|
+
<i class="fa-solid fa-robot text-6xl text-purple-500"></i>
|
|
1477
|
+
</div>
|
|
1478
|
+
<h3 class="text-purple-400 font-bold mb-4">The Agent's Job</h3>
|
|
1479
|
+
<ul class="space-y-3 text-sm text-gray-400">
|
|
1480
|
+
<li class="flex gap-2"><i class="fa-solid fa-check text-green-500"></i> Generate
|
|
1481
|
+
Text Content</li>
|
|
1482
|
+
<li class="flex gap-2"><i class="fa-solid fa-check text-green-500"></i> Determine
|
|
1483
|
+
Structure</li>
|
|
1484
|
+
<li class="flex gap-2"><i class="fa-solid fa-check text-green-500"></i> Choose
|
|
1485
|
+
Semantic Layouts</li>
|
|
1486
|
+
</ul>
|
|
1487
|
+
</div>
|
|
1488
|
+
<div class="bg-gray-900 border border-blue-500/20 rounded-xl p-8 relative overflow-hidden">
|
|
1489
|
+
<div class="absolute top-0 right-0 p-4 opacity-20">
|
|
1490
|
+
<i class="fa-solid fa-layer-group text-6xl text-blue-500"></i>
|
|
1491
|
+
</div>
|
|
1492
|
+
<h3 class="text-blue-400 font-bold mb-4">Lumina's Job</h3>
|
|
1493
|
+
<ul class="space-y-3 text-sm text-gray-400">
|
|
1494
|
+
<li class="flex gap-2"><i class="fa-solid fa-check text-blue-500"></i> 60fps
|
|
1495
|
+
Animations</li>
|
|
1496
|
+
<li class="flex gap-2"><i class="fa-solid fa-check text-blue-500"></i> Responsive
|
|
1497
|
+
Typography</li>
|
|
1498
|
+
<li class="flex gap-2"><i class="fa-solid fa-check text-blue-500"></i> Interactive
|
|
1499
|
+
State</li>
|
|
1500
|
+
</ul>
|
|
1501
|
+
</div>
|
|
1502
|
+
</div>
|
|
1503
|
+
|
|
1504
|
+
<h2>The Protocol</h2>
|
|
1505
|
+
<p>Agents communicate with Lumina via a JSON format that is strict enough for deterministic
|
|
1506
|
+
rendering but loose enough for LLMs.</p>
|
|
1507
|
+
</div>
|
|
1508
|
+
|
|
1509
|
+
<!-- AGENTS: TOKENS -->
|
|
1510
|
+
<div v-else-if="activeSection === 'agents-tokens'">
|
|
1511
|
+
<h1>Token Optimization</h1>
|
|
1512
|
+
<p class="lead">Reduce output size with short property aliases. Less characters = faster
|
|
1513
|
+
rendering and lower costs.</p>
|
|
1514
|
+
|
|
1515
|
+
<div class="not-prose grid gap-6 mt-8">
|
|
1516
|
+
<div class="bg-[#0A0A0A] border border-white/10 rounded-xl p-6">
|
|
1517
|
+
<h3 class="text-sm font-bold text-gray-500 uppercase tracking-widest mb-4">Standard JSON
|
|
1518
|
+
<span class="text-white/30 font-normal normal-case ml-2">~95 characters</span>
|
|
1519
|
+
</h3>
|
|
1520
|
+
<pre class="!mb-0 !p-0 !bg-transparent !border-none"><code>{
|
|
1521
|
+
"type": "statement",
|
|
1522
|
+
"title": "Quarterly Review",
|
|
1523
|
+
"subtitle": "Growth is exceeding expectations."
|
|
1524
|
+
}</code></pre>
|
|
1525
|
+
</div>
|
|
1526
|
+
|
|
1527
|
+
<div class="bg-[#0A0A0A] border border-green-500/20 rounded-xl p-6 relative">
|
|
1528
|
+
<span
|
|
1529
|
+
class="absolute top-4 right-4 text-xs font-bold text-green-400 bg-green-500/10 px-2 py-1 rounded">
|
|
1530
|
+
~25% Shorter
|
|
1531
|
+
</span>
|
|
1532
|
+
<h3 class="text-sm font-bold text-gray-500 uppercase tracking-widest mb-4">Optimized
|
|
1533
|
+
JSON <span class="text-white/30 font-normal normal-case ml-2">~70 characters</span>
|
|
1534
|
+
</h3>
|
|
1535
|
+
<pre class="!mb-0 !p-0 !bg-transparent !border-none"><code>{
|
|
1536
|
+
"type": "statement",
|
|
1537
|
+
"t": "Quarterly Review",
|
|
1538
|
+
"s": "Growth is exceeding expectations."
|
|
1539
|
+
}</code></pre>
|
|
1540
|
+
</div>
|
|
1541
|
+
</div>
|
|
1542
|
+
|
|
1543
|
+
<div class="my-8">
|
|
1544
|
+
<h2 class="text-xl font-bold text-white mb-4">Supported Aliases</h2>
|
|
1545
|
+
<p class="text-white/60 mb-4">Both full property names and aliases work interchangeably. Mix
|
|
1546
|
+
and match as needed.</p>
|
|
1547
|
+
|
|
1548
|
+
<div class="overflow-x-auto border border-white/10 rounded-lg">
|
|
1549
|
+
<table class="w-full text-left text-sm text-gray-400">
|
|
1550
|
+
<thead class="bg-white/5 text-white font-bold">
|
|
1551
|
+
<tr>
|
|
1552
|
+
<th class="p-3 border-b border-white/10">Full Key</th>
|
|
1553
|
+
<th class="p-3 border-b border-white/10">Alias</th>
|
|
1554
|
+
<th class="p-3 border-b border-white/10">Used In</th>
|
|
1555
|
+
</tr>
|
|
1556
|
+
</thead>
|
|
1557
|
+
<tbody class="divide-y divide-white/5">
|
|
1558
|
+
<tr>
|
|
1559
|
+
<td class="p-3 font-mono">title</td>
|
|
1560
|
+
<td class="p-3 font-mono text-green-400">t</td>
|
|
1561
|
+
<td class="p-3 text-white/50">All layouts</td>
|
|
1562
|
+
</tr>
|
|
1563
|
+
<tr>
|
|
1564
|
+
<td class="p-3 font-mono">subtitle</td>
|
|
1565
|
+
<td class="p-3 font-mono text-green-400">s</td>
|
|
1566
|
+
<td class="p-3 text-white/50">Statement, Timeline, Steps</td>
|
|
1567
|
+
</tr>
|
|
1568
|
+
<tr>
|
|
1569
|
+
<td class="p-3 font-mono">description</td>
|
|
1570
|
+
<td class="p-3 font-mono text-green-400">d</td>
|
|
1571
|
+
<td class="p-3 text-white/50">Features, Timeline items, Steps items</td>
|
|
1572
|
+
</tr>
|
|
1573
|
+
<tr>
|
|
1574
|
+
<td class="p-3 font-mono">features</td>
|
|
1575
|
+
<td class="p-3 font-mono text-green-400">fs</td>
|
|
1576
|
+
<td class="p-3 text-white/50">Features layout</td>
|
|
1577
|
+
</tr>
|
|
1578
|
+
<tr>
|
|
1579
|
+
<td class="p-3 font-mono">timeline</td>
|
|
1580
|
+
<td class="p-3 font-mono text-green-400">tl</td>
|
|
1581
|
+
<td class="p-3 text-white/50">Timeline layout</td>
|
|
1582
|
+
</tr>
|
|
1583
|
+
<tr>
|
|
1584
|
+
<td class="p-3 font-mono">steps</td>
|
|
1585
|
+
<td class="p-3 font-mono text-green-400">st</td>
|
|
1586
|
+
<td class="p-3 text-white/50">Steps layout</td>
|
|
1587
|
+
</tr>
|
|
1588
|
+
<tr>
|
|
1589
|
+
<td class="p-3 font-mono">paragraphs</td>
|
|
1590
|
+
<td class="p-3 font-mono text-green-400">p</td>
|
|
1591
|
+
<td class="p-3 text-white/50">Half layout</td>
|
|
1592
|
+
</tr>
|
|
1593
|
+
<tr>
|
|
1594
|
+
<td class="p-3 font-mono">image</td>
|
|
1595
|
+
<td class="p-3 font-mono text-green-400">img</td>
|
|
1596
|
+
<td class="p-3 text-white/50">Half layout</td>
|
|
1597
|
+
</tr>
|
|
1598
|
+
<tr>
|
|
1599
|
+
<td class="p-3 font-mono">imageSide</td>
|
|
1600
|
+
<td class="p-3 font-mono text-green-400">side</td>
|
|
1601
|
+
<td class="p-3 text-white/50">Half layout</td>
|
|
1602
|
+
</tr>
|
|
1603
|
+
</tbody>
|
|
1604
|
+
</table>
|
|
1605
|
+
</div>
|
|
1606
|
+
</div>
|
|
1607
|
+
|
|
1608
|
+
<div class="mt-8 p-4 bg-blue-500/10 border border-blue-500/20 rounded-lg">
|
|
1609
|
+
<h4 class="text-blue-400 font-bold mb-2"><i class="fa-solid fa-info-circle mr-2"></i>How It
|
|
1610
|
+
Works</h4>
|
|
1611
|
+
<p class="text-sm text-blue-200/80 m-0">Lumina's normalizer automatically expands aliases to
|
|
1612
|
+
full property names before rendering. You can use standard JSON for readability or
|
|
1613
|
+
aliases for efficiency—both produce identical results.</p>
|
|
1614
|
+
</div>
|
|
1615
|
+
</div>
|
|
1616
|
+
|
|
1617
|
+
<!-- AGENTS: STREAMING -->
|
|
1618
|
+
<div v-else-if="activeSection === 'agents-streaming'">
|
|
1619
|
+
<h1>Streaming & Realtime</h1>
|
|
1620
|
+
<p>Lumina enables a <strong>"Type & See"</strong> experience. Using our partial parser, you can
|
|
1621
|
+
feed raw LLM streams directly into the engine.</p>
|
|
1622
|
+
|
|
1623
|
+
<div class="not-prose my-12">
|
|
1624
|
+
<div
|
|
1625
|
+
class="bg-[#050505] border border-white/10 rounded-2xl overflow-hidden shadow-2xl flex flex-col h-[800px] relative group">
|
|
1626
|
+
|
|
1627
|
+
<!-- CTA Overlay (Top Right) -->
|
|
1628
|
+
<div class="absolute top-4 right-4 z-20">
|
|
1629
|
+
<button @click="runDemo"
|
|
1630
|
+
class="px-5 py-1.5 rounded-full bg-blue-500 hover:bg-blue-400 text-white font-bold text-xs shadow-lg shadow-blue-500/20 transition-all transform hover:scale-105 flex items-center gap-2">
|
|
1631
|
+
<i class="fa-solid fa-play"></i> Simulate AI Stream
|
|
1632
|
+
</button>
|
|
1633
|
+
</div>
|
|
1634
|
+
|
|
1635
|
+
<!-- Editor (Top, Fixed Height) -->
|
|
1636
|
+
<div
|
|
1637
|
+
class="w-full h-48 flex flex-col bg-gray-900 border-b border-white/10 relative z-10">
|
|
1638
|
+
<div
|
|
1639
|
+
class="bg-white/5 px-4 py-2 text-xs font-bold text-white/50 flex justify-between items-center">
|
|
1640
|
+
<span>LLM JSON OUTPUT</span>
|
|
1641
|
+
<span class="text-xs text-white/20 mr-32" v-if="demoStarted">Receiving
|
|
1642
|
+
Tokens...</span>
|
|
1643
|
+
</div>
|
|
1644
|
+
<textarea v-model="demoInput"
|
|
1645
|
+
class="flex-1 bg-transparent p-6 font-mono text-sm text-green-400 resize-none focus:outline-none"
|
|
1646
|
+
placeholder='Waiting for tokens...'></textarea>
|
|
1647
|
+
</div>
|
|
1648
|
+
|
|
1649
|
+
<!-- Preview (Bottom, Flex) -->
|
|
1650
|
+
<div class="w-full flex-1 relative bg-black min-h-[300px]">
|
|
1651
|
+
<div id="streaming-demo-container" class="w-full h-full"></div>
|
|
1652
|
+
<div v-if="!demoStarted"
|
|
1653
|
+
class="absolute inset-0 flex items-center justify-center text-white/20">
|
|
1654
|
+
<div class="text-center">
|
|
1655
|
+
<i class="fa-solid fa-tv text-4xl mb-4"></i>
|
|
1656
|
+
<p class="text-sm">Preview UI Render</p>
|
|
1657
|
+
</div>
|
|
1658
|
+
</div>
|
|
1659
|
+
</div>
|
|
1660
|
+
|
|
1661
|
+
</div>
|
|
1662
|
+
</div>
|
|
1663
|
+
</div>
|
|
1664
|
+
|
|
1665
|
+
<!-- AGENTS: LAYOUT GALLERY -->
|
|
1666
|
+
<div v-else-if="activeSection === 'agents-layouts'">
|
|
1667
|
+
<h1>Layout Gallery</h1>
|
|
1668
|
+
<p>Lumina provides 5 core layouts optimized for different types of information. Click <strong><i
|
|
1669
|
+
class="fa-solid fa-play text-blue-400"></i> Visualize</strong> to load them into the
|
|
1670
|
+
<a @click.prevent="activeSection = 'agents-streaming'; scroll('streaming-demo-container')"
|
|
1671
|
+
href="#" class="text-blue-400 hover:underline">Streaming Demo</a>.
|
|
1672
|
+
</p>
|
|
1673
|
+
|
|
1674
|
+
<div class="space-y-12 mt-12">
|
|
1675
|
+
|
|
1676
|
+
<!-- Statement -->
|
|
1677
|
+
<div class="bg-[#0A0A0A] border border-white/10 rounded-xl overflow-hidden p-6">
|
|
1678
|
+
<div class="flex justify-between items-center mb-4">
|
|
1679
|
+
<h3 class="text-xl font-bold text-white flex items-center gap-3">
|
|
1680
|
+
<span
|
|
1681
|
+
class="px-2 py-0.5 rounded bg-blue-500/10 text-blue-400 text-xs uppercase font-bold">Statement</span>
|
|
1682
|
+
</h3>
|
|
1683
|
+
<button @click="loadIntoDemo(EXAMPLES.statement)"
|
|
1684
|
+
class="px-3 py-1.5 rounded-lg bg-white/5 hover:bg-white/10 text-xs font-bold text-white/50 hover:text-white transition flex items-center gap-2 border border-white/5">
|
|
1685
|
+
<i class="fa-solid fa-play text-blue-400"></i> Visualize
|
|
1686
|
+
</button>
|
|
1687
|
+
</div>
|
|
1688
|
+
<p class="text-sm text-gray-400 mb-4">Best for: Titles, Quotes, Big Ideas.</p>
|
|
1689
|
+
<pre class="!mb-0 !bg-black/50"><code>{{ EXAMPLES.statement }}</code></pre>
|
|
1690
|
+
</div>
|
|
1691
|
+
|
|
1692
|
+
<!-- Features -->
|
|
1693
|
+
<div class="bg-[#0A0A0A] border border-white/10 rounded-xl overflow-hidden p-6">
|
|
1694
|
+
<div class="flex justify-between items-center mb-4">
|
|
1695
|
+
<h3 class="text-xl font-bold text-white flex items-center gap-3">
|
|
1696
|
+
<span
|
|
1697
|
+
class="px-2 py-0.5 rounded bg-yellow-500/10 text-yellow-400 text-xs uppercase font-bold">Features</span>
|
|
1698
|
+
</h3>
|
|
1699
|
+
<button @click="loadIntoDemo(EXAMPLES.features)"
|
|
1700
|
+
class="px-3 py-1.5 rounded-lg bg-white/5 hover:bg-white/10 text-xs font-bold text-white/50 hover:text-white transition flex items-center gap-2 border border-white/5">
|
|
1701
|
+
<i class="fa-solid fa-play text-yellow-400"></i> Visualize
|
|
1702
|
+
</button>
|
|
1703
|
+
</div>
|
|
1704
|
+
<p class="text-sm text-gray-400 mb-4">Best for: Lists, Grids, Stats, Benefits.</p>
|
|
1705
|
+
<pre class="!mb-0 !bg-black/50"><code>{{ EXAMPLES.features }}</code></pre>
|
|
1706
|
+
</div>
|
|
1707
|
+
|
|
1708
|
+
<!-- Timeline -->
|
|
1709
|
+
<div class="bg-[#0A0A0A] border border-white/10 rounded-xl overflow-hidden p-6">
|
|
1710
|
+
<div class="flex justify-between items-center mb-4">
|
|
1711
|
+
<h3 class="text-xl font-bold text-white flex items-center gap-3">
|
|
1712
|
+
<span
|
|
1713
|
+
class="px-2 py-0.5 rounded bg-green-500/10 text-green-400 text-xs uppercase font-bold">Timeline</span>
|
|
1714
|
+
</h3>
|
|
1715
|
+
<button @click="loadIntoDemo(EXAMPLES.timeline)"
|
|
1716
|
+
class="px-3 py-1.5 rounded-lg bg-white/5 hover:bg-white/10 text-xs font-bold text-white/50 hover:text-white transition flex items-center gap-2 border border-white/5">
|
|
1717
|
+
<i class="fa-solid fa-play text-green-400"></i> Visualize
|
|
1718
|
+
</button>
|
|
1719
|
+
</div>
|
|
1720
|
+
<p class="text-sm text-gray-400 mb-4">Best for: Roadmaps, History, Changelogs.</p>
|
|
1721
|
+
<pre class="!mb-0 !bg-black/50"><code>{{ EXAMPLES.timeline }}</code></pre>
|
|
1722
|
+
</div>
|
|
1723
|
+
|
|
1724
|
+
</div>
|
|
1725
|
+
</div>
|
|
1726
|
+
|
|
1727
|
+
<div v-else-if="activeSection === 'agents-auto'">
|
|
1728
|
+
<h1>Auto-Layouts</h1>
|
|
1729
|
+
<p>Sometimes the Agent doesn't know which layout is best. Just use <code>type: 'auto'</code>.
|
|
1730
|
+
</p>
|
|
1731
|
+
<p>Lumina analyzes the content structure to pick the best view automatically.</p>
|
|
1732
|
+
|
|
1733
|
+
<div class="p-6 bg-blue-500/10 border border-blue-500/20 rounded-xl my-8">
|
|
1734
|
+
<h3 class="text-blue-400 font-bold mb-2">Detection Priority</h3>
|
|
1735
|
+
<ul class="list-disc list-inside text-sm text-blue-200/80 space-y-1">
|
|
1736
|
+
<li>If <code>timeline</code> array exists -> <strong>Timeline Layout</strong></li>
|
|
1737
|
+
<li>If <code>steps</code> array exists -> <strong>Steps Layout</strong></li>
|
|
1738
|
+
<li>If <code>features</code> array exists -> <strong>Features Layout</strong></li>
|
|
1739
|
+
<li>If <code>image</code> exists -> <strong>Half Layout</strong></li>
|
|
1740
|
+
<li>Otherwise -> <strong>Statement Layout</strong></li>
|
|
1741
|
+
</ul>
|
|
1742
|
+
</div>
|
|
1743
|
+
|
|
1744
|
+
<h3>Example: Multi-Slide Auto Detection</h3>
|
|
1745
|
+
<p class="text-sm text-gray-400 mb-4">Each slide uses <code>type: "auto"</code> but renders
|
|
1746
|
+
differently based on its content structure.</p>
|
|
1747
|
+
|
|
1748
|
+
<pre><code>{
|
|
1749
|
+
<span class="text-blue-400">"slides"</span>: [
|
|
1750
|
+
<span class="text-gray-500">// Renders as Statement (no special arrays detected)</span>
|
|
1751
|
+
{
|
|
1752
|
+
<span class="text-blue-400">"type"</span>: <span class="text-green-400">"auto"</span>,
|
|
1753
|
+
<span class="text-blue-400">"title"</span>: <span class="text-green-400">"Welcome to Our Platform"</span>,
|
|
1754
|
+
<span class="text-blue-400">"subtitle"</span>: <span class="text-green-400">"The future of presentations"</span>
|
|
1755
|
+
},
|
|
1756
|
+
<span class="text-gray-500">// Renders as Features (features array detected)</span>
|
|
1757
|
+
{
|
|
1758
|
+
<span class="text-blue-400">"type"</span>: <span class="text-green-400">"auto"</span>,
|
|
1759
|
+
<span class="text-blue-400">"title"</span>: <span class="text-green-400">"Why Choose Us"</span>,
|
|
1760
|
+
<span class="text-blue-400">"features"</span>: [
|
|
1761
|
+
{ <span class="text-blue-400">"title"</span>: <span class="text-green-400">"Fast"</span>, <span class="text-blue-400">"desc"</span>: <span class="text-green-400">"60fps animations"</span>, <span class="text-blue-400">"icon"</span>: <span class="text-green-400">"fa-bolt"</span> },
|
|
1762
|
+
{ <span class="text-blue-400">"title"</span>: <span class="text-green-400">"Simple"</span>, <span class="text-blue-400">"desc"</span>: <span class="text-green-400">"JSON-first"</span>, <span class="text-blue-400">"icon"</span>: <span class="text-green-400">"fa-code"</span> },
|
|
1763
|
+
{ <span class="text-blue-400">"title"</span>: <span class="text-green-400">"Smart"</span>, <span class="text-blue-400">"desc"</span>: <span class="text-green-400">"AI-ready"</span>, <span class="text-blue-400">"icon"</span>: <span class="text-green-400">"fa-brain"</span> }
|
|
1764
|
+
]
|
|
1765
|
+
},
|
|
1766
|
+
<span class="text-gray-500">// Renders as Timeline (timeline array detected)</span>
|
|
1767
|
+
{
|
|
1768
|
+
<span class="text-blue-400">"type"</span>: <span class="text-green-400">"auto"</span>,
|
|
1769
|
+
<span class="text-blue-400">"title"</span>: <span class="text-green-400">"Our Journey"</span>,
|
|
1770
|
+
<span class="text-blue-400">"timeline"</span>: [
|
|
1771
|
+
{ <span class="text-blue-400">"date"</span>: <span class="text-green-400">"2023"</span>, <span class="text-blue-400">"title"</span>: <span class="text-green-400">"Concept"</span>, <span class="text-blue-400">"description"</span>: <span class="text-green-400">"The idea was born"</span> },
|
|
1772
|
+
{ <span class="text-blue-400">"date"</span>: <span class="text-green-400">"2024"</span>, <span class="text-blue-400">"title"</span>: <span class="text-green-400">"Launch"</span>, <span class="text-blue-400">"description"</span>: <span class="text-green-400">"V1.0 released"</span> }
|
|
1773
|
+
]
|
|
1774
|
+
},
|
|
1775
|
+
<span class="text-gray-500">// Renders as Steps (steps array detected)</span>
|
|
1776
|
+
{
|
|
1777
|
+
<span class="text-blue-400">"type"</span>: <span class="text-green-400">"auto"</span>,
|
|
1778
|
+
<span class="text-blue-400">"title"</span>: <span class="text-green-400">"Getting Started"</span>,
|
|
1779
|
+
<span class="text-blue-400">"steps"</span>: [
|
|
1780
|
+
{ <span class="text-blue-400">"step"</span>: <span class="text-yellow-400">1</span>, <span class="text-blue-400">"title"</span>: <span class="text-green-400">"Install"</span>, <span class="text-blue-400">"description"</span>: <span class="text-green-400">"npm install lumina-slides"</span> },
|
|
1781
|
+
{ <span class="text-blue-400">"step"</span>: <span class="text-yellow-400">2</span>, <span class="text-blue-400">"title"</span>: <span class="text-green-400">"Import"</span>, <span class="text-blue-400">"description"</span>: <span class="text-green-400">"Import Lumina class"</span> },
|
|
1782
|
+
{ <span class="text-blue-400">"step"</span>: <span class="text-yellow-400">3</span>, <span class="text-blue-400">"title"</span>: <span class="text-green-400">"Create"</span>, <span class="text-blue-400">"description"</span>: <span class="text-green-400">"Define your slides"</span> }
|
|
1783
|
+
]
|
|
1784
|
+
},
|
|
1785
|
+
<span class="text-gray-500">// Renders as Half (image property detected)</span>
|
|
1786
|
+
{
|
|
1787
|
+
<span class="text-blue-400">"type"</span>: <span class="text-green-400">"auto"</span>,
|
|
1788
|
+
<span class="text-blue-400">"title"</span>: <span class="text-green-400">"Visual Storytelling"</span>,
|
|
1789
|
+
<span class="text-blue-400">"image"</span>: <span class="text-green-400">"https://images.unsplash.com/..."</span>,
|
|
1790
|
+
<span class="text-blue-400">"paragraphs"</span>: [<span class="text-green-400">"Combine text and visuals seamlessly."</span>]
|
|
1791
|
+
}
|
|
1792
|
+
]
|
|
1793
|
+
}</code></pre>
|
|
1794
|
+
|
|
1795
|
+
<div class="mt-8 p-4 bg-yellow-500/10 border border-yellow-500/20 rounded-lg">
|
|
1796
|
+
<h4 class="text-yellow-400 font-bold mb-2"><i class="fa-solid fa-lightbulb mr-2"></i>Pro Tip
|
|
1797
|
+
</h4>
|
|
1798
|
+
<p class="text-sm text-yellow-200/80 m-0">Using <code>type: "auto"</code> simplifies prompt
|
|
1799
|
+
engineering for AI agents. The LLM only needs to provide the data structure, and Lumina
|
|
1800
|
+
will handle the visual representation automatically.</p>
|
|
1801
|
+
</div>
|
|
1802
|
+
</div>
|
|
1803
|
+
|
|
1804
|
+
<!-- AGENTS: STATE -->
|
|
1805
|
+
<div v-else-if="activeSection === 'agents-state'">
|
|
1806
|
+
<h1>State & Feedback Loop</h1>
|
|
1807
|
+
<p>Use <code>engine.exportState()</code> to get the current state for your LLM or agent. It returns a frozen object with <code>status</code>, <code>currentSlide</code> (<code>{ index, id, type, title }</code>), <code>narrative</code> (e.g. "User is on slide 3. Session: clicked 'Learn More' → next."), <code>engagementLevel</code> ("High" or "Low"), and <code>history</code> (recorded actions). Add this to your prompt for context-aware replies.</p>
|
|
1808
|
+
<pre><code><span class="text-blue-400">const</span> state = engine.exportState();
|
|
1809
|
+
<span class="text-gray-500">// "User is on slide ${state.currentSlide.index + 1} (${state.currentSlide.type}). ${state.narrative}"</span></code></pre>
|
|
1810
|
+
</div>
|
|
1811
|
+
|
|
1812
|
+
<!-- REF: STATEMENT -->
|
|
1813
|
+
<div v-else-if="activeSection === 'ref-statement'">
|
|
1814
|
+
<h1>Statement Slide</h1>
|
|
1815
|
+
<p class="lead">Used for high-impact titles, opening covers, or emphatic quotes. It is designed
|
|
1816
|
+
to be punchy and minimal.</p>
|
|
1817
|
+
|
|
1818
|
+
<div class="my-8">
|
|
1819
|
+
<h2 class="text-xl font-bold text-white mb-4">Configuration</h2>
|
|
1820
|
+
<div class="overflow-x-auto border border-white/10 rounded-lg">
|
|
1821
|
+
<table class="w-full text-left text-sm text-gray-400">
|
|
1822
|
+
<thead class="bg-white/5 text-white font-bold">
|
|
1823
|
+
<tr>
|
|
1824
|
+
<th class="p-3 border-b border-white/10">Property</th>
|
|
1825
|
+
<th class="p-3 border-b border-white/10">Type</th>
|
|
1826
|
+
<th class="p-3 border-b border-white/10">Description</th>
|
|
1827
|
+
</tr>
|
|
1828
|
+
</thead>
|
|
1829
|
+
<tbody class="divide-y divide-white/5">
|
|
1830
|
+
<tr>
|
|
1831
|
+
<td class="p-3 font-mono text-purple-400">type</td>
|
|
1832
|
+
<td class="p-3 font-mono text-xs">"statement"</td>
|
|
1833
|
+
<td class="p-3">Required. Identifies the layout.</td>
|
|
1834
|
+
</tr>
|
|
1835
|
+
<tr>
|
|
1836
|
+
<td class="p-3 font-mono text-blue-400">title</td>
|
|
1837
|
+
<td class="p-3 font-mono text-xs">string</td>
|
|
1838
|
+
<td class="p-3">Main headline. Keep it short (3-6 words).</td>
|
|
1839
|
+
</tr>
|
|
1840
|
+
<tr>
|
|
1841
|
+
<td class="p-3 font-mono text-blue-400">subtitle</td>
|
|
1842
|
+
<td class="p-3 font-mono text-xs">string?</td>
|
|
1843
|
+
<td class="p-3">Optional supporting text.</td>
|
|
1844
|
+
</tr>
|
|
1845
|
+
<tr>
|
|
1846
|
+
<td class="p-3 font-mono text-blue-400">tag</td>
|
|
1847
|
+
<td class="p-3 font-mono text-xs">string?</td>
|
|
1848
|
+
<td class="p-3">Small eyebrow tag above the title.</td>
|
|
1849
|
+
</tr>
|
|
1850
|
+
<tr>
|
|
1851
|
+
<td class="p-3 font-mono text-cyan-400">notes</td>
|
|
1852
|
+
<td class="p-3 font-mono text-xs">string?</td>
|
|
1853
|
+
<td class="p-3">Speaker notes (available on any slide via <code>SlideBase</code>).</td>
|
|
1854
|
+
</tr>
|
|
1855
|
+
</tbody>
|
|
1856
|
+
</table>
|
|
1857
|
+
</div>
|
|
1858
|
+
</div>
|
|
1859
|
+
|
|
1860
|
+
<div class="my-8">
|
|
1861
|
+
<h2 class="text-xl font-bold text-white mb-4">Example</h2>
|
|
1862
|
+
<LivePreview :initial-code="EXAMPLES.statement" />
|
|
1863
|
+
</div>
|
|
1864
|
+
</div>
|
|
1865
|
+
|
|
1866
|
+
<!-- REF: HALF -->
|
|
1867
|
+
<div v-else-if="activeSection === 'ref-half'">
|
|
1868
|
+
<h1>Half / Split Slide</h1>
|
|
1869
|
+
<p class="lead">Image or video on one side, text on the other. Ideal for product showcases or "about me" sections. <strong>One of <code>image</code> or <code>video</code> is required.</strong></p>
|
|
1870
|
+
|
|
1871
|
+
<div class="my-8">
|
|
1872
|
+
<h2 class="text-xl font-bold text-white mb-4">Configuration</h2>
|
|
1873
|
+
<div class="overflow-x-auto border border-white/10 rounded-lg">
|
|
1874
|
+
<table class="w-full text-left text-sm text-gray-400">
|
|
1875
|
+
<thead class="bg-white/5 text-white font-bold">
|
|
1876
|
+
<tr>
|
|
1877
|
+
<th class="p-3 border-b border-white/10">Property</th>
|
|
1878
|
+
<th class="p-3 border-b border-white/10">Type</th>
|
|
1879
|
+
<th class="p-3 border-b border-white/10">Description</th>
|
|
1880
|
+
</tr>
|
|
1881
|
+
</thead>
|
|
1882
|
+
<tbody class="divide-y divide-white/5">
|
|
1883
|
+
<tr>
|
|
1884
|
+
<td class="p-3 font-mono text-purple-400">type</td>
|
|
1885
|
+
<td class="p-3 font-mono text-xs">"half"</td>
|
|
1886
|
+
<td class="p-3">Required.</td>
|
|
1887
|
+
</tr>
|
|
1888
|
+
<tr>
|
|
1889
|
+
<td class="p-3 font-mono text-blue-400">image</td>
|
|
1890
|
+
<td class="p-3 font-mono text-xs">string?</td>
|
|
1891
|
+
<td class="p-3">Image URL. Omit if using <code>video</code>.</td>
|
|
1892
|
+
</tr>
|
|
1893
|
+
<tr>
|
|
1894
|
+
<td class="p-3 font-mono text-blue-400">video</td>
|
|
1895
|
+
<td class="p-3 font-mono text-xs">VideoProperties?</td>
|
|
1896
|
+
<td class="p-3"><code>{ type: "video", src, autoplay?, muted?, loop? }</code>. Use instead of <code>image</code>.</td>
|
|
1897
|
+
</tr>
|
|
1898
|
+
<tr>
|
|
1899
|
+
<td class="p-3 font-mono text-blue-400">imageSide</td>
|
|
1900
|
+
<td class="p-3 font-mono text-xs">"left" | "right"</td>
|
|
1901
|
+
<td class="p-3">Which side the media is on. Default: "left".</td>
|
|
1902
|
+
</tr>
|
|
1903
|
+
<tr>
|
|
1904
|
+
<td class="p-3 font-mono text-blue-400">tag</td>
|
|
1905
|
+
<td class="p-3 font-mono text-xs">string?</td>
|
|
1906
|
+
<td class="p-3">Optional eyebrow label above the title.</td>
|
|
1907
|
+
</tr>
|
|
1908
|
+
<tr>
|
|
1909
|
+
<td class="p-3 font-mono text-blue-400">title</td>
|
|
1910
|
+
<td class="p-3 font-mono text-xs">string</td>
|
|
1911
|
+
<td class="p-3">Headline text.</td>
|
|
1912
|
+
</tr>
|
|
1913
|
+
<tr>
|
|
1914
|
+
<td class="p-3 font-mono text-blue-400">paragraphs</td>
|
|
1915
|
+
<td class="p-3 font-mono text-xs">string[]</td>
|
|
1916
|
+
<td class="p-3">Array of text blocks.</td>
|
|
1917
|
+
</tr>
|
|
1918
|
+
<tr>
|
|
1919
|
+
<td class="p-3 font-mono text-blue-400">cta</td>
|
|
1920
|
+
<td class="p-3 font-mono text-xs">string?</td>
|
|
1921
|
+
<td class="p-3">Optional button label.</td>
|
|
1922
|
+
</tr>
|
|
1923
|
+
</tbody>
|
|
1924
|
+
</table>
|
|
1925
|
+
</div>
|
|
1926
|
+
</div>
|
|
1927
|
+
|
|
1928
|
+
<div class="my-8">
|
|
1929
|
+
<h2 class="text-xl font-bold text-white mb-4">Example</h2>
|
|
1930
|
+
<LivePreview :initial-code="EXAMPLES.half" />
|
|
1931
|
+
</div>
|
|
1932
|
+
</div>
|
|
1933
|
+
|
|
1934
|
+
<!-- REF: FEATURES -->
|
|
1935
|
+
<div v-else-if="activeSection === 'ref-features'">
|
|
1936
|
+
<h1>Features Slide</h1>
|
|
1937
|
+
<p class="lead">Displays a grid of cards, perfect for listing benefits, stats, or services.</p>
|
|
1938
|
+
|
|
1939
|
+
<div class="my-8">
|
|
1940
|
+
<h2 class="text-xl font-bold text-white mb-4">Configuration</h2>
|
|
1941
|
+
<div class="overflow-x-auto border border-white/10 rounded-lg">
|
|
1942
|
+
<table class="w-full text-left text-sm text-gray-400">
|
|
1943
|
+
<thead class="bg-white/5 text-white font-bold">
|
|
1944
|
+
<tr>
|
|
1945
|
+
<th class="p-3 border-b border-white/10">Property</th>
|
|
1946
|
+
<th class="p-3 border-b border-white/10">Type</th>
|
|
1947
|
+
<th class="p-3 border-b border-white/10">Description</th>
|
|
1948
|
+
</tr>
|
|
1949
|
+
</thead>
|
|
1950
|
+
<tbody class="divide-y divide-white/5">
|
|
1951
|
+
<tr>
|
|
1952
|
+
<td class="p-3 font-mono text-purple-400">type</td>
|
|
1953
|
+
<td class="p-3 font-mono text-xs">"features"</td>
|
|
1954
|
+
<td class="p-3">Required.</td>
|
|
1955
|
+
</tr>
|
|
1956
|
+
<tr>
|
|
1957
|
+
<td class="p-3 font-mono text-blue-400">title</td>
|
|
1958
|
+
<td class="p-3 font-mono text-xs">string</td>
|
|
1959
|
+
<td class="p-3">Section header.</td>
|
|
1960
|
+
</tr>
|
|
1961
|
+
<tr>
|
|
1962
|
+
<td class="p-3 font-mono text-blue-400">description</td>
|
|
1963
|
+
<td class="p-3 font-mono text-xs">string?</td>
|
|
1964
|
+
<td class="p-3">Optional context.</td>
|
|
1965
|
+
</tr>
|
|
1966
|
+
<tr>
|
|
1967
|
+
<td class="p-3 font-mono text-blue-400">features</td>
|
|
1968
|
+
<td class="p-3 font-mono text-xs">FeatureItem[]</td>
|
|
1969
|
+
<td class="p-3">Array: <code>{ class?, title, desc, icon?, id? }</code>. <code>class</code> can be <code>""</code>; <code>desc</code> or <code>description</code>.</td>
|
|
1970
|
+
</tr>
|
|
1971
|
+
</tbody>
|
|
1972
|
+
</table>
|
|
1973
|
+
</div>
|
|
1974
|
+
</div>
|
|
1975
|
+
|
|
1976
|
+
<div class="my-8">
|
|
1977
|
+
<h2 class="text-xl font-bold text-white mb-4">Example</h2>
|
|
1978
|
+
<LivePreview :initial-code="EXAMPLES.features" />
|
|
1979
|
+
</div>
|
|
1980
|
+
</div>
|
|
1981
|
+
|
|
1982
|
+
<!-- REF: TIMELINE -->
|
|
1983
|
+
<div v-else-if="activeSection === 'ref-timeline'">
|
|
1984
|
+
<h1>Timeline Slide</h1>
|
|
1985
|
+
<p class="lead">Vertical chronological list for events, roadmaps, or history. Do not confuse with <em>Timeline (keyframes)</em> for <code>slide.timelineTracks</code>.</p>
|
|
1986
|
+
|
|
1987
|
+
<div class="my-8">
|
|
1988
|
+
<h2 class="text-xl font-bold text-white mb-4">Configuration</h2>
|
|
1989
|
+
<div class="overflow-x-auto border border-white/10 rounded-lg">
|
|
1990
|
+
<table class="w-full text-left text-sm text-gray-400">
|
|
1991
|
+
<thead class="bg-white/5 text-white font-bold">
|
|
1992
|
+
<tr>
|
|
1993
|
+
<th class="p-3 border-b border-white/10">Property</th>
|
|
1994
|
+
<th class="p-3 border-b border-white/10">Type</th>
|
|
1995
|
+
<th class="p-3 border-b border-white/10">Description</th>
|
|
1996
|
+
</tr>
|
|
1997
|
+
</thead>
|
|
1998
|
+
<tbody class="divide-y divide-white/5">
|
|
1999
|
+
<tr>
|
|
2000
|
+
<td class="p-3 font-mono text-purple-400">type</td>
|
|
2001
|
+
<td class="p-3 font-mono text-xs">"timeline"</td>
|
|
2002
|
+
<td class="p-3">Required.</td>
|
|
2003
|
+
</tr>
|
|
2004
|
+
<tr>
|
|
2005
|
+
<td class="p-3 font-mono text-blue-400">title</td>
|
|
2006
|
+
<td class="p-3 font-mono text-xs">string</td>
|
|
2007
|
+
<td class="p-3">Header.</td>
|
|
2008
|
+
</tr>
|
|
2009
|
+
<tr>
|
|
2010
|
+
<td class="p-3 font-mono text-blue-400">subtitle</td>
|
|
2011
|
+
<td class="p-3 font-mono text-xs">string?</td>
|
|
2012
|
+
<td class="p-3">Optional.</td>
|
|
2013
|
+
</tr>
|
|
2014
|
+
<tr>
|
|
2015
|
+
<td class="p-3 font-mono text-blue-400">timeline</td>
|
|
2016
|
+
<td class="p-3 font-mono text-xs">TimelineItem[]</td>
|
|
2017
|
+
<td class="p-3">Array: <code>{ date, title, description, icon?, id? }</code>. Aliases: <code>t</code>→title, <code>desc</code>→description.</td>
|
|
2018
|
+
</tr>
|
|
2019
|
+
</tbody>
|
|
2020
|
+
</table>
|
|
2021
|
+
</div>
|
|
2022
|
+
</div>
|
|
2023
|
+
|
|
2024
|
+
<div class="my-8">
|
|
2025
|
+
<h2 class="text-xl font-bold text-white mb-4">Example</h2>
|
|
2026
|
+
<LivePreview :initial-code="EXAMPLES.timeline" />
|
|
2027
|
+
</div>
|
|
2028
|
+
</div>
|
|
2029
|
+
|
|
2030
|
+
<!-- REF: STEPS -->
|
|
2031
|
+
<div v-else-if="activeSection === 'ref-steps'">
|
|
2032
|
+
<h1>Steps Slide</h1>
|
|
2033
|
+
<p class="lead">Used for tutorials, "how-to" guides, or process flows.</p>
|
|
2034
|
+
|
|
2035
|
+
<div class="my-8">
|
|
2036
|
+
<h2 class="text-xl font-bold text-white mb-4">Configuration</h2>
|
|
2037
|
+
<div class="overflow-x-auto border border-white/10 rounded-lg">
|
|
2038
|
+
<table class="w-full text-left text-sm text-gray-400">
|
|
2039
|
+
<thead class="bg-white/5 text-white font-bold">
|
|
2040
|
+
<tr>
|
|
2041
|
+
<th class="p-3 border-b border-white/10">Property</th>
|
|
2042
|
+
<th class="p-3 border-b border-white/10">Type</th>
|
|
2043
|
+
<th class="p-3 border-b border-white/10">Description</th>
|
|
2044
|
+
</tr>
|
|
2045
|
+
</thead>
|
|
2046
|
+
<tbody class="divide-y divide-white/5">
|
|
2047
|
+
<tr>
|
|
2048
|
+
<td class="p-3 font-mono text-purple-400">type</td>
|
|
2049
|
+
<td class="p-3 font-mono text-xs">"steps"</td>
|
|
2050
|
+
<td class="p-3">Required.</td>
|
|
2051
|
+
</tr>
|
|
2052
|
+
<tr>
|
|
2053
|
+
<td class="p-3 font-mono text-blue-400">title</td>
|
|
2054
|
+
<td class="p-3 font-mono text-xs">string</td>
|
|
2055
|
+
<td class="p-3">Process name.</td>
|
|
2056
|
+
</tr>
|
|
2057
|
+
<tr>
|
|
2058
|
+
<td class="p-3 font-mono text-blue-400">subtitle</td>
|
|
2059
|
+
<td class="p-3 font-mono text-xs">string?</td>
|
|
2060
|
+
<td class="p-3">Optional.</td>
|
|
2061
|
+
</tr>
|
|
2062
|
+
<tr>
|
|
2063
|
+
<td class="p-3 font-mono text-blue-400">steps</td>
|
|
2064
|
+
<td class="p-3 font-mono text-xs">StepItem[]</td>
|
|
2065
|
+
<td class="p-3">Array: <code>{ step, title, description?, icon?, id? }</code>. <code>step</code> is e.g. <code>"01"</code>.</td>
|
|
2066
|
+
</tr>
|
|
2067
|
+
</tbody>
|
|
2068
|
+
</table>
|
|
2069
|
+
</div>
|
|
2070
|
+
</div>
|
|
2071
|
+
|
|
2072
|
+
<div class="my-8">
|
|
2073
|
+
<h2 class="text-xl font-bold text-white mb-4">Example</h2>
|
|
2074
|
+
<LivePreview :initial-code="EXAMPLES.steps" />
|
|
2075
|
+
</div>
|
|
2076
|
+
</div>
|
|
2077
|
+
|
|
2078
|
+
<!-- REF: FLEX -->
|
|
2079
|
+
<div v-else-if="activeSection === 'ref-flex'">
|
|
2080
|
+
<h1>Flex Layout</h1>
|
|
2081
|
+
<p class="lead">Flow-based layout for composing slides using semantic sizing. No coordinates
|
|
2082
|
+
needed—perfect for LLM generation.</p>
|
|
2083
|
+
|
|
2084
|
+
<div class="my-8">
|
|
2085
|
+
<h2 class="text-xl font-bold text-white mb-4">Slide Options</h2>
|
|
2086
|
+
<div class="overflow-x-auto border border-white/10 rounded-lg">
|
|
2087
|
+
<table class="w-full text-left text-sm text-gray-400">
|
|
2088
|
+
<thead class="bg-white/5 text-white font-bold">
|
|
2089
|
+
<tr>
|
|
2090
|
+
<th class="p-3 border-b border-white/10">Property</th>
|
|
2091
|
+
<th class="p-3 border-b border-white/10">Type</th>
|
|
2092
|
+
<th class="p-3 border-b border-white/10">Description</th>
|
|
2093
|
+
</tr>
|
|
2094
|
+
</thead>
|
|
2095
|
+
<tbody class="divide-y divide-white/5">
|
|
2096
|
+
<tr>
|
|
2097
|
+
<td class="p-3 font-mono text-purple-400">type</td>
|
|
2098
|
+
<td class="p-3 font-mono text-xs">"flex"</td>
|
|
2099
|
+
<td class="p-3">Required.</td>
|
|
2100
|
+
</tr>
|
|
2101
|
+
<tr>
|
|
2102
|
+
<td class="p-3 font-mono text-blue-400">direction</td>
|
|
2103
|
+
<td class="p-3 font-mono text-xs">"horizontal" | "vertical"</td>
|
|
2104
|
+
<td class="p-3">Main flow direction. Default: "horizontal".</td>
|
|
2105
|
+
</tr>
|
|
2106
|
+
<tr>
|
|
2107
|
+
<td class="p-3 font-mono text-blue-400">gap</td>
|
|
2108
|
+
<td class="p-3 font-mono text-xs">SpacingToken</td>
|
|
2109
|
+
<td class="p-3">Gap between elements. Default: "none".</td>
|
|
2110
|
+
</tr>
|
|
2111
|
+
<tr>
|
|
2112
|
+
<td class="p-3 font-mono text-blue-400">padding</td>
|
|
2113
|
+
<td class="p-3 font-mono text-xs">SpacingToken</td>
|
|
2114
|
+
<td class="p-3">Container padding. Default: "none".</td>
|
|
2115
|
+
</tr>
|
|
2116
|
+
<tr>
|
|
2117
|
+
<td class="p-3 font-mono text-blue-400">halign</td>
|
|
2118
|
+
<td class="p-3 font-mono text-xs">"left" | "center" | "right"</td>
|
|
2119
|
+
<td class="p-3">Horizontal alignment of the flex group. Default: "left".</td>
|
|
2120
|
+
</tr>
|
|
2121
|
+
<tr>
|
|
2122
|
+
<td class="p-3 font-mono text-blue-400">valign</td>
|
|
2123
|
+
<td class="p-3 font-mono text-xs">"top" | "center" | "bottom"</td>
|
|
2124
|
+
<td class="p-3">Vertical alignment of the flex group. Default: "top".</td>
|
|
2125
|
+
</tr>
|
|
2126
|
+
<tr>
|
|
2127
|
+
<td class="p-3 font-mono text-blue-400">elements</td>
|
|
2128
|
+
<td class="p-3 font-mono text-xs">FlexElement[]</td>
|
|
2129
|
+
<td class="p-3">Array of flex elements in flow order. Each can have <code>size</code> (FlexSize).</td>
|
|
2130
|
+
</tr>
|
|
2131
|
+
</tbody>
|
|
2132
|
+
</table>
|
|
2133
|
+
</div>
|
|
2134
|
+
</div>
|
|
2135
|
+
|
|
2136
|
+
<div class="my-8">
|
|
2137
|
+
<h2 class="text-xl font-bold text-white mb-4">Size Tokens</h2>
|
|
2138
|
+
<p>Each element can have a <code>size</code> property to control how much space it occupies:
|
|
2139
|
+
</p>
|
|
2140
|
+
<div class="grid grid-cols-2 md:grid-cols-4 gap-4 my-6 not-prose">
|
|
2141
|
+
<div class="p-4 bg-white/5 rounded-lg text-center"><code>auto</code><br><span
|
|
2142
|
+
class="text-xs text-white/40">flexible</span></div>
|
|
2143
|
+
<div class="p-4 bg-white/5 rounded-lg text-center"><code>quarter</code><br><span
|
|
2144
|
+
class="text-xs text-white/40">25%</span></div>
|
|
2145
|
+
<div class="p-4 bg-white/5 rounded-lg text-center"><code>third</code><br><span
|
|
2146
|
+
class="text-xs text-white/40">33%</span></div>
|
|
2147
|
+
<div class="p-4 bg-white/5 rounded-lg text-center"><code>half</code><br><span
|
|
2148
|
+
class="text-xs text-white/40">50%</span></div>
|
|
2149
|
+
<div class="p-4 bg-white/5 rounded-lg text-center"><code>two-thirds</code><br><span
|
|
2150
|
+
class="text-xs text-white/40">66%</span></div>
|
|
2151
|
+
<div class="p-4 bg-white/5 rounded-lg text-center"><code>three-quarters</code><br><span
|
|
2152
|
+
class="text-xs text-white/40">75%</span></div>
|
|
2153
|
+
<div class="p-4 bg-white/5 rounded-lg text-center"><code>full</code><br><span
|
|
2154
|
+
class="text-xs text-white/40">100%</span></div>
|
|
2155
|
+
</div>
|
|
2156
|
+
</div>
|
|
2157
|
+
|
|
2158
|
+
<div class="my-8">
|
|
2159
|
+
<h2 class="text-xl font-bold text-white mb-4">Element Types</h2>
|
|
2160
|
+
<div class="overflow-x-auto border border-white/10 rounded-lg">
|
|
2161
|
+
<table class="w-full text-left text-sm text-gray-400">
|
|
2162
|
+
<thead class="bg-white/5 text-white font-bold">
|
|
2163
|
+
<tr>
|
|
2164
|
+
<th class="p-3 border-b border-white/10">Type</th>
|
|
2165
|
+
<th class="p-3 border-b border-white/10">Properties</th>
|
|
2166
|
+
<th class="p-3 border-b border-white/10">Description</th>
|
|
2167
|
+
</tr>
|
|
2168
|
+
</thead>
|
|
2169
|
+
<tbody class="divide-y divide-white/5">
|
|
2170
|
+
<tr>
|
|
2171
|
+
<td class="p-3 font-mono text-cyan-400">content</td>
|
|
2172
|
+
<td class="p-3 font-mono text-xs">elements, valign, halign, gap, padding
|
|
2173
|
+
</td>
|
|
2174
|
+
<td class="p-3">Container that groups child elements vertically.</td>
|
|
2175
|
+
</tr>
|
|
2176
|
+
<tr>
|
|
2177
|
+
<td class="p-3 font-mono text-cyan-400">image</td>
|
|
2178
|
+
<td class="p-3 font-mono text-xs">src, alt?, fill?, fit?, rounded?</td>
|
|
2179
|
+
<td class="p-3">Visual media element.</td>
|
|
2180
|
+
</tr>
|
|
2181
|
+
<tr>
|
|
2182
|
+
<td class="p-3 font-mono text-cyan-400">title</td>
|
|
2183
|
+
<td class="p-3 font-mono text-xs">text, size?, align?</td>
|
|
2184
|
+
<td class="p-3">Large heading (lg | xl | 2xl | 3xl).</td>
|
|
2185
|
+
</tr>
|
|
2186
|
+
<tr>
|
|
2187
|
+
<td class="p-3 font-mono text-cyan-400">text</td>
|
|
2188
|
+
<td class="p-3 font-mono text-xs">text, align?, muted?</td>
|
|
2189
|
+
<td class="p-3">Body paragraph text.</td>
|
|
2190
|
+
</tr>
|
|
2191
|
+
<tr>
|
|
2192
|
+
<td class="p-3 font-mono text-cyan-400">bullets</td>
|
|
2193
|
+
<td class="p-3 font-mono text-xs">items: string[]</td>
|
|
2194
|
+
<td class="p-3">Unordered bullet list.</td>
|
|
2195
|
+
</tr>
|
|
2196
|
+
<tr>
|
|
2197
|
+
<td class="p-3 font-mono text-cyan-400">ordered</td>
|
|
2198
|
+
<td class="p-3 font-mono text-xs">items: string[]</td>
|
|
2199
|
+
<td class="p-3">Numbered list.</td>
|
|
2200
|
+
</tr>
|
|
2201
|
+
<tr>
|
|
2202
|
+
<td class="p-3 font-mono text-cyan-400">button</td>
|
|
2203
|
+
<td class="p-3 font-mono text-xs">label, action?, variant?, fullWidth?</td>
|
|
2204
|
+
<td class="p-3">CTA button (primary | secondary | outline | ghost).</td>
|
|
2205
|
+
</tr>
|
|
2206
|
+
<tr>
|
|
2207
|
+
<td class="p-3 font-mono text-cyan-400">timeline</td>
|
|
2208
|
+
<td class="p-3 font-mono text-xs">items: TimelineItem[], compact?</td>
|
|
2209
|
+
<td class="p-3">Embedded timeline.</td>
|
|
2210
|
+
</tr>
|
|
2211
|
+
<tr>
|
|
2212
|
+
<td class="p-3 font-mono text-cyan-400">stepper</td>
|
|
2213
|
+
<td class="p-3 font-mono text-xs">items: StepItem[], compact?</td>
|
|
2214
|
+
<td class="p-3">Embedded step process.</td>
|
|
2215
|
+
</tr>
|
|
2216
|
+
<tr>
|
|
2217
|
+
<td class="p-3 font-mono text-cyan-400">spacer</td>
|
|
2218
|
+
<td class="p-3 font-mono text-xs">size?: SpacingToken</td>
|
|
2219
|
+
<td class="p-3">Adds visual spacing.</td>
|
|
2220
|
+
</tr>
|
|
2221
|
+
</tbody>
|
|
2222
|
+
</table>
|
|
2223
|
+
</div>
|
|
2224
|
+
</div>
|
|
2225
|
+
|
|
2226
|
+
<div class="my-8">
|
|
2227
|
+
<h2 class="text-xl font-bold text-white mb-4">Content Container</h2>
|
|
2228
|
+
<p>Use <code>content</code> to group related elements with alignment control:</p>
|
|
2229
|
+
<div class="overflow-x-auto border border-white/10 rounded-lg mt-6">
|
|
2230
|
+
<table class="w-full text-left text-sm text-gray-400">
|
|
2231
|
+
<thead class="bg-white/5 text-white font-bold">
|
|
2232
|
+
<tr>
|
|
2233
|
+
<th class="p-3 border-b border-white/10">Property</th>
|
|
2234
|
+
<th class="p-3 border-b border-white/10">Values</th>
|
|
2235
|
+
<th class="p-3 border-b border-white/10">Default</th>
|
|
2236
|
+
</tr>
|
|
2237
|
+
</thead>
|
|
2238
|
+
<tbody class="divide-y divide-white/5">
|
|
2239
|
+
<tr>
|
|
2240
|
+
<td class="p-3 font-mono text-blue-400">valign</td>
|
|
2241
|
+
<td class="p-3 font-mono text-xs">top | center | bottom</td>
|
|
2242
|
+
<td class="p-3">center</td>
|
|
2243
|
+
</tr>
|
|
2244
|
+
<tr>
|
|
2245
|
+
<td class="p-3 font-mono text-blue-400">halign</td>
|
|
2246
|
+
<td class="p-3 font-mono text-xs">left | center | right</td>
|
|
2247
|
+
<td class="p-3">left</td>
|
|
2248
|
+
</tr>
|
|
2249
|
+
<tr>
|
|
2250
|
+
<td class="p-3 font-mono text-blue-400">gap</td>
|
|
2251
|
+
<td class="p-3 font-mono text-xs">none | xs | sm | md | lg | xl | 2xl</td>
|
|
2252
|
+
<td class="p-3">md</td>
|
|
2253
|
+
</tr>
|
|
2254
|
+
<tr>
|
|
2255
|
+
<td class="p-3 font-mono text-blue-400">padding</td>
|
|
2256
|
+
<td class="p-3 font-mono text-xs">none | xs | sm | md | lg | xl | 2xl</td>
|
|
2257
|
+
<td class="p-3">lg</td>
|
|
2258
|
+
</tr>
|
|
2259
|
+
</tbody>
|
|
2260
|
+
</table>
|
|
2261
|
+
</div>
|
|
2262
|
+
</div>
|
|
2263
|
+
|
|
2264
|
+
<div class="my-8">
|
|
2265
|
+
<h2 class="text-xl font-bold text-white mb-4">Example</h2>
|
|
2266
|
+
<LivePreview :initial-code="EXAMPLES.flex" />
|
|
2267
|
+
</div>
|
|
2268
|
+
</div>
|
|
2269
|
+
|
|
2270
|
+
<!-- REF: CHART -->
|
|
2271
|
+
<div v-else-if="activeSection === 'ref-chart'">
|
|
2272
|
+
<h1>Chart Slide</h1>
|
|
2273
|
+
<p class="lead">Visualize data extracted from CSV/Excel files. Perfect for LLM-generated reports
|
|
2274
|
+
and dashboards.</p>
|
|
2275
|
+
|
|
2276
|
+
<div class="my-8">
|
|
2277
|
+
<h2 class="text-xl font-bold text-white mb-4">Configuration</h2>
|
|
2278
|
+
<div class="overflow-x-auto border border-white/10 rounded-lg">
|
|
2279
|
+
<table class="w-full text-left text-sm text-gray-400">
|
|
2280
|
+
<thead class="bg-white/5 text-white font-bold">
|
|
2281
|
+
<tr>
|
|
2282
|
+
<th class="p-3 border-b border-white/10">Property</th>
|
|
2283
|
+
<th class="p-3 border-b border-white/10">Type</th>
|
|
2284
|
+
<th class="p-3 border-b border-white/10">Description</th>
|
|
2285
|
+
</tr>
|
|
2286
|
+
</thead>
|
|
2287
|
+
<tbody class="divide-y divide-white/5">
|
|
2288
|
+
<tr>
|
|
2289
|
+
<td class="p-3 font-mono text-purple-400">type</td>
|
|
2290
|
+
<td class="p-3 font-mono text-xs">"chart"</td>
|
|
2291
|
+
<td class="p-3">Required.</td>
|
|
2292
|
+
</tr>
|
|
2293
|
+
<tr>
|
|
2294
|
+
<td class="p-3 font-mono text-blue-400">chartType</td>
|
|
2295
|
+
<td class="p-3 font-mono text-xs">"bar" | "line" | "pie" | "doughnut"</td>
|
|
2296
|
+
<td class="p-3">Type of chart to render.</td>
|
|
2297
|
+
</tr>
|
|
2298
|
+
<tr>
|
|
2299
|
+
<td class="p-3 font-mono text-blue-400">title</td>
|
|
2300
|
+
<td class="p-3 font-mono text-xs">string?</td>
|
|
2301
|
+
<td class="p-3">Chart title (optional).</td>
|
|
2302
|
+
</tr>
|
|
2303
|
+
<tr>
|
|
2304
|
+
<td class="p-3 font-mono text-blue-400">subtitle</td>
|
|
2305
|
+
<td class="p-3 font-mono text-xs">string?</td>
|
|
2306
|
+
<td class="p-3">Subtitle text (optional).</td>
|
|
2307
|
+
</tr>
|
|
2308
|
+
<tr>
|
|
2309
|
+
<td class="p-3 font-mono text-blue-400">data</td>
|
|
2310
|
+
<td class="p-3 font-mono text-xs">ChartData</td>
|
|
2311
|
+
<td class="p-3">Object with <code>labels</code> and <code>datasets</code>.
|
|
2312
|
+
</td>
|
|
2313
|
+
</tr>
|
|
2314
|
+
</tbody>
|
|
2315
|
+
</table>
|
|
2316
|
+
</div>
|
|
2317
|
+
</div>
|
|
2318
|
+
|
|
2319
|
+
<div class="my-8">
|
|
2320
|
+
<h2 class="text-xl font-bold text-white mb-4">Data Structure</h2>
|
|
2321
|
+
<div class="overflow-x-auto border border-white/10 rounded-lg">
|
|
2322
|
+
<table class="w-full text-left text-sm text-gray-400">
|
|
2323
|
+
<thead class="bg-white/5 text-white font-bold">
|
|
2324
|
+
<tr>
|
|
2325
|
+
<th class="p-3 border-b border-white/10">Property</th>
|
|
2326
|
+
<th class="p-3 border-b border-white/10">Type</th>
|
|
2327
|
+
<th class="p-3 border-b border-white/10">Description</th>
|
|
2328
|
+
</tr>
|
|
2329
|
+
</thead>
|
|
2330
|
+
<tbody class="divide-y divide-white/5">
|
|
2331
|
+
<tr>
|
|
2332
|
+
<td class="p-3 font-mono text-cyan-400">data.labels</td>
|
|
2333
|
+
<td class="p-3 font-mono text-xs">string[]</td>
|
|
2334
|
+
<td class="p-3">X-axis labels or pie segment names.</td>
|
|
2335
|
+
</tr>
|
|
2336
|
+
<tr>
|
|
2337
|
+
<td class="p-3 font-mono text-cyan-400">data.datasets</td>
|
|
2338
|
+
<td class="p-3 font-mono text-xs">Dataset[]</td>
|
|
2339
|
+
<td class="p-3">Each with <code>label</code>, <code>values</code>, and
|
|
2340
|
+
optional <code>color</code>.</td>
|
|
2341
|
+
</tr>
|
|
2342
|
+
<tr>
|
|
2343
|
+
<td class="p-3 font-mono text-cyan-400">dataset.color</td>
|
|
2344
|
+
<td class="p-3 font-mono text-xs">string?</td>
|
|
2345
|
+
<td class="p-3"><code>c:p</code> (primary), <code>c:s</code> (secondary),
|
|
2346
|
+
<code>c:m</code> (muted), or hex.
|
|
2347
|
+
</td>
|
|
2348
|
+
</tr>
|
|
2349
|
+
</tbody>
|
|
2350
|
+
</table>
|
|
2351
|
+
</div>
|
|
2352
|
+
</div>
|
|
2353
|
+
|
|
2354
|
+
<!-- Chart Types Section -->
|
|
2355
|
+
<div class="my-12">
|
|
2356
|
+
<h2 class="text-2xl font-bold text-white mb-6">Chart Types</h2>
|
|
2357
|
+
|
|
2358
|
+
<div class="space-y-12">
|
|
2359
|
+
<!-- Bar Chart -->
|
|
2360
|
+
<div class="p-6 rounded-2xl bg-white/[0.02] border border-white/5">
|
|
2361
|
+
<div class="flex items-center gap-3 mb-4">
|
|
2362
|
+
<div
|
|
2363
|
+
class="w-10 h-10 rounded-lg bg-blue-500/20 text-blue-400 flex items-center justify-center">
|
|
2364
|
+
<i class="fa-solid fa-chart-column"></i>
|
|
2365
|
+
</div>
|
|
2366
|
+
<div>
|
|
2367
|
+
<h3 class="text-xl font-bold text-white">Bar Chart</h3>
|
|
2368
|
+
<p class="text-sm text-white/50">Best for comparing discrete categories</p>
|
|
2369
|
+
</div>
|
|
2370
|
+
</div>
|
|
2371
|
+
<p class="text-white/60 text-sm mb-4">Use bar charts to compare values across
|
|
2372
|
+
categories. Ideal for revenue by quarter, sales by region, or any categorical
|
|
2373
|
+
comparison.</p>
|
|
2374
|
+
<LivePreview initial-code='{
|
|
2375
|
+
"type": "chart",
|
|
2376
|
+
"chartType": "bar",
|
|
2377
|
+
"title": "Sales by Region",
|
|
2378
|
+
"subtitle": "Q4 2024 Performance",
|
|
2379
|
+
"data": {
|
|
2380
|
+
"labels": ["North", "South", "East", "West"],
|
|
2381
|
+
"datasets": [{
|
|
2382
|
+
"label": "Sales ($K)",
|
|
2383
|
+
"values": [420, 380, 510, 290],
|
|
2384
|
+
"color": "c:p"
|
|
2385
|
+
}]
|
|
2386
|
+
}
|
|
2387
|
+
}' />
|
|
2388
|
+
</div>
|
|
2389
|
+
|
|
2390
|
+
<!-- Line Chart -->
|
|
2391
|
+
<div class="p-6 rounded-2xl bg-white/[0.02] border border-white/5">
|
|
2392
|
+
<div class="flex items-center gap-3 mb-4">
|
|
2393
|
+
<div
|
|
2394
|
+
class="w-10 h-10 rounded-lg bg-green-500/20 text-green-400 flex items-center justify-center">
|
|
2395
|
+
<i class="fa-solid fa-chart-line"></i>
|
|
2396
|
+
</div>
|
|
2397
|
+
<div>
|
|
2398
|
+
<h3 class="text-xl font-bold text-white">Line Chart</h3>
|
|
2399
|
+
<p class="text-sm text-white/50">Best for trends over time</p>
|
|
2400
|
+
</div>
|
|
2401
|
+
</div>
|
|
2402
|
+
<p class="text-white/60 text-sm mb-4">Use line charts to show trends and changes
|
|
2403
|
+
over time. Perfect for growth metrics, stock prices, or any time-series data.
|
|
2404
|
+
</p>
|
|
2405
|
+
<LivePreview initial-code='{
|
|
2406
|
+
"type": "chart",
|
|
2407
|
+
"chartType": "line",
|
|
2408
|
+
"title": "Monthly Active Users",
|
|
2409
|
+
"subtitle": "2024 Growth Trend",
|
|
2410
|
+
"data": {
|
|
2411
|
+
"labels": ["Jan", "Feb", "Mar", "Apr", "May", "Jun"],
|
|
2412
|
+
"datasets": [{
|
|
2413
|
+
"label": "Users (K)",
|
|
2414
|
+
"values": [45, 52, 61, 78, 95, 120],
|
|
2415
|
+
"color": "#10b981"
|
|
2416
|
+
}]
|
|
2417
|
+
}
|
|
2418
|
+
}' />
|
|
2419
|
+
</div>
|
|
2420
|
+
|
|
2421
|
+
<!-- Pie Chart -->
|
|
2422
|
+
<div class="p-6 rounded-2xl bg-white/[0.02] border border-white/5">
|
|
2423
|
+
<div class="flex items-center gap-3 mb-4">
|
|
2424
|
+
<div
|
|
2425
|
+
class="w-10 h-10 rounded-lg bg-purple-500/20 text-purple-400 flex items-center justify-center">
|
|
2426
|
+
<i class="fa-solid fa-chart-pie"></i>
|
|
2427
|
+
</div>
|
|
2428
|
+
<div>
|
|
2429
|
+
<h3 class="text-xl font-bold text-white">Pie Chart</h3>
|
|
2430
|
+
<p class="text-sm text-white/50">Best for showing proportions</p>
|
|
2431
|
+
</div>
|
|
2432
|
+
</div>
|
|
2433
|
+
<p class="text-white/60 text-sm mb-4">Use pie charts to show how parts make up a
|
|
2434
|
+
whole. Ideal for market share, budget allocation, or percentage distributions.
|
|
2435
|
+
</p>
|
|
2436
|
+
<LivePreview initial-code='{
|
|
2437
|
+
"type": "chart",
|
|
2438
|
+
"chartType": "pie",
|
|
2439
|
+
"title": "Market Share",
|
|
2440
|
+
"subtitle": "Industry Distribution Q4 2024",
|
|
2441
|
+
"data": {
|
|
2442
|
+
"labels": ["Product A", "Product B", "Product C", "Others"],
|
|
2443
|
+
"datasets": [{
|
|
2444
|
+
"label": "Share %",
|
|
2445
|
+
"values": [35, 28, 22, 15]
|
|
2446
|
+
}]
|
|
2447
|
+
}
|
|
2448
|
+
}' />
|
|
2449
|
+
</div>
|
|
2450
|
+
|
|
2451
|
+
<!-- Doughnut Chart -->
|
|
2452
|
+
<div class="p-6 rounded-2xl bg-white/[0.02] border border-white/5">
|
|
2453
|
+
<div class="flex items-center gap-3 mb-4">
|
|
2454
|
+
<div
|
|
2455
|
+
class="w-10 h-10 rounded-lg bg-amber-500/20 text-amber-400 flex items-center justify-center">
|
|
2456
|
+
<i class="fa-solid fa-circle-notch"></i>
|
|
2457
|
+
</div>
|
|
2458
|
+
<div>
|
|
2459
|
+
<h3 class="text-xl font-bold text-white">Doughnut Chart</h3>
|
|
2460
|
+
<p class="text-sm text-white/50">Modern alternative to pie charts</p>
|
|
2461
|
+
</div>
|
|
2462
|
+
</div>
|
|
2463
|
+
<p class="text-white/60 text-sm mb-4">Similar to pie charts but with a hollow
|
|
2464
|
+
center. The modern look works great for dashboards and can display a metric in
|
|
2465
|
+
the center.</p>
|
|
2466
|
+
<LivePreview initial-code='{
|
|
2467
|
+
"type": "chart",
|
|
2468
|
+
"chartType": "doughnut",
|
|
2469
|
+
"title": "Budget Allocation",
|
|
2470
|
+
"subtitle": "2025 Planned Spend",
|
|
2471
|
+
"data": {
|
|
2472
|
+
"labels": ["Engineering", "Marketing", "Sales", "Operations"],
|
|
2473
|
+
"datasets": [{
|
|
2474
|
+
"label": "Budget",
|
|
2475
|
+
"values": [40, 25, 20, 15]
|
|
2476
|
+
}]
|
|
2477
|
+
}
|
|
2478
|
+
}' />
|
|
2479
|
+
</div>
|
|
2480
|
+
</div>
|
|
2481
|
+
</div>
|
|
2482
|
+
|
|
2483
|
+
<!-- Multiple Datasets Example -->
|
|
2484
|
+
<div class="my-12">
|
|
2485
|
+
<h2 class="text-2xl font-bold text-white mb-6">Advanced: Multiple Datasets</h2>
|
|
2486
|
+
<p class="text-white/60 mb-6">Bar and line charts support multiple datasets for comparisons.
|
|
2487
|
+
Each dataset gets its own color and legend entry.</p>
|
|
2488
|
+
<LivePreview initial-code='{
|
|
2489
|
+
"type": "chart",
|
|
2490
|
+
"chartType": "bar",
|
|
2491
|
+
"title": "Year-over-Year Comparison",
|
|
2492
|
+
"subtitle": "Revenue by Quarter",
|
|
2493
|
+
"data": {
|
|
2494
|
+
"labels": ["Q1", "Q2", "Q3", "Q4"],
|
|
2495
|
+
"datasets": [
|
|
2496
|
+
{
|
|
2497
|
+
"label": "2023",
|
|
2498
|
+
"values": [100, 120, 140, 160],
|
|
2499
|
+
"color": "#6b7280"
|
|
2500
|
+
},
|
|
2501
|
+
{
|
|
2502
|
+
"label": "2024",
|
|
2503
|
+
"values": [120, 150, 180, 220],
|
|
2504
|
+
"color": "c:p"
|
|
2505
|
+
}
|
|
2506
|
+
]
|
|
2507
|
+
},
|
|
2508
|
+
video: `{
|
|
2509
|
+
"type": "statement",
|
|
2510
|
+
"sizing": "container",
|
|
2511
|
+
"meta": { "orbColor": "#ec4899" },
|
|
2512
|
+
"background": {
|
|
2513
|
+
"type": "video",
|
|
2514
|
+
"src": "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerBlazes.mp4",
|
|
2515
|
+
"opacity": 0.4
|
|
2516
|
+
},
|
|
2517
|
+
"tag": "Cinematic",
|
|
2518
|
+
"title": "Video Backgrounds",
|
|
2519
|
+
"subtitle": "Immersive support."
|
|
2520
|
+
}`
|
|
2521
|
+
}' />
|
|
2522
|
+
</div>
|
|
2523
|
+
|
|
2524
|
+
<!-- Color Tokens -->
|
|
2525
|
+
<div class="my-8">
|
|
2526
|
+
<h2 class="text-xl font-bold text-white mb-4">Color Tokens</h2>
|
|
2527
|
+
<div class="overflow-x-auto border border-white/10 rounded-lg">
|
|
2528
|
+
<table class="w-full text-left text-sm text-gray-400">
|
|
2529
|
+
<thead class="bg-white/5 text-white font-bold">
|
|
2530
|
+
<tr>
|
|
2531
|
+
<th class="p-3 border-b border-white/10">Token</th>
|
|
2532
|
+
<th class="p-3 border-b border-white/10">Maps To</th>
|
|
2533
|
+
<th class="p-3 border-b border-white/10">Default</th>
|
|
2534
|
+
</tr>
|
|
2535
|
+
</thead>
|
|
2536
|
+
<tbody class="divide-y divide-white/5">
|
|
2537
|
+
<tr>
|
|
2538
|
+
<td class="p-3 font-mono text-blue-400">c:p</td>
|
|
2539
|
+
<td class="p-3">--lumina-colors-primary</td>
|
|
2540
|
+
<td class="p-3"><span
|
|
2541
|
+
class="inline-block w-4 h-4 rounded bg-blue-500 mr-2"></span>#3b82f6
|
|
2542
|
+
</td>
|
|
2543
|
+
</tr>
|
|
2544
|
+
<tr>
|
|
2545
|
+
<td class="p-3 font-mono text-green-400">c:s</td>
|
|
2546
|
+
<td class="p-3">--lumina-colors-secondary</td>
|
|
2547
|
+
<td class="p-3"><span
|
|
2548
|
+
class="inline-block w-4 h-4 rounded bg-emerald-500 mr-2"></span>#10b981
|
|
2549
|
+
</td>
|
|
2550
|
+
</tr>
|
|
2551
|
+
<tr>
|
|
2552
|
+
<td class="p-3 font-mono text-gray-400">c:m</td>
|
|
2553
|
+
<td class="p-3">--lumina-colors-muted</td>
|
|
2554
|
+
<td class="p-3"><span
|
|
2555
|
+
class="inline-block w-4 h-4 rounded bg-gray-400 mr-2"></span>#9ca3af
|
|
2556
|
+
</td>
|
|
2557
|
+
</tr>
|
|
2558
|
+
<tr>
|
|
2559
|
+
<td class="p-3 font-mono text-pink-400">#ec4899</td>
|
|
2560
|
+
<td class="p-3">Direct hex color</td>
|
|
2561
|
+
<td class="p-3"><span
|
|
2562
|
+
class="inline-block w-4 h-4 rounded bg-pink-500 mr-2"></span>Custom
|
|
2563
|
+
</td>
|
|
2564
|
+
</tr>
|
|
2565
|
+
</tbody>
|
|
2566
|
+
</table>
|
|
2567
|
+
</div>
|
|
2568
|
+
</div>
|
|
2569
|
+
|
|
2570
|
+
<div class="mt-8 p-4 bg-yellow-500/10 border border-yellow-500/20 rounded-lg">
|
|
2571
|
+
<h4 class="text-yellow-400 font-bold mb-2"><i class="fa-solid fa-lightbulb mr-2"></i>Pro
|
|
2572
|
+
Tips
|
|
2573
|
+
</h4>
|
|
2574
|
+
<ul class="text-sm text-yellow-200/80 space-y-2 m-0 list-none">
|
|
2575
|
+
<li>📊 <strong>Bar charts</strong> work best with 4-8 categories</li>
|
|
2576
|
+
<li>📈 <strong>Line charts</strong> need at least 3 data points for smooth curves</li>
|
|
2577
|
+
<li>🥧 <strong>Pie/Doughnut</strong> should have 3-6 segments max for clarity</li>
|
|
2578
|
+
<li>🤖 <strong>LLM Tip:</strong> Have agents extract tabular data from CSVs and generate
|
|
2579
|
+
charts automatically</li>
|
|
2580
|
+
</ul>
|
|
2581
|
+
</div>
|
|
2582
|
+
</div>
|
|
2583
|
+
|
|
2584
|
+
<!-- REF: VIDEO -->
|
|
2585
|
+
<div v-else-if="activeSection === 'ref-video'">
|
|
2586
|
+
<h1>Video Slide</h1>
|
|
2587
|
+
<p class="lead">Full-screen video player with optional title overlay (shown on hover).</p>
|
|
2588
|
+
|
|
2589
|
+
<div class="my-8">
|
|
2590
|
+
<h2 class="text-xl font-bold text-white mb-4">Configuration</h2>
|
|
2591
|
+
<div class="overflow-x-auto border border-white/10 rounded-lg">
|
|
2592
|
+
<table class="w-full text-left text-sm text-gray-400">
|
|
2593
|
+
<thead class="bg-white/5 text-white font-bold">
|
|
2594
|
+
<tr>
|
|
2595
|
+
<th class="p-3 border-b border-white/10">Property</th>
|
|
2596
|
+
<th class="p-3 border-b border-white/10">Type</th>
|
|
2597
|
+
<th class="p-3 border-b border-white/10">Description</th>
|
|
2598
|
+
</tr>
|
|
2599
|
+
</thead>
|
|
2600
|
+
<tbody class="divide-y divide-white/5">
|
|
2601
|
+
<tr>
|
|
2602
|
+
<td class="p-3 font-mono text-purple-400">type</td>
|
|
2603
|
+
<td class="p-3 font-mono text-xs">"video"</td>
|
|
2604
|
+
<td class="p-3">Required.</td>
|
|
2605
|
+
</tr>
|
|
2606
|
+
<tr>
|
|
2607
|
+
<td class="p-3 font-mono text-blue-400">video</td>
|
|
2608
|
+
<td class="p-3 font-mono text-xs">VideoProperties</td>
|
|
2609
|
+
<td class="p-3">Required. <code>src</code>, and optionally <code>poster</code>, <code>autoplay</code>, <code>loop</code>, <code>muted</code>, <code>controls</code>, <code>className</code>.</td>
|
|
2610
|
+
</tr>
|
|
2611
|
+
<tr>
|
|
2612
|
+
<td class="p-3 font-mono text-blue-400">title</td>
|
|
2613
|
+
<td class="p-3 font-mono text-xs">string?</td>
|
|
2614
|
+
<td class="p-3">Caption overlay at bottom-left, visible on hover.</td>
|
|
2615
|
+
</tr>
|
|
2616
|
+
</tbody>
|
|
2617
|
+
</table>
|
|
2618
|
+
</div>
|
|
2619
|
+
</div>
|
|
2620
|
+
|
|
2621
|
+
<div class="my-8">
|
|
2622
|
+
<h2 class="text-xl font-bold text-white mb-4">VideoProperties</h2>
|
|
2623
|
+
<div class="overflow-x-auto border border-white/10 rounded-lg">
|
|
2624
|
+
<table class="w-full text-left text-sm text-gray-400">
|
|
2625
|
+
<thead class="bg-white/5 text-white font-bold">
|
|
2626
|
+
<tr>
|
|
2627
|
+
<th class="p-3 border-b border-white/10">Property</th>
|
|
2628
|
+
<th class="p-3 border-b border-white/10">Type</th>
|
|
2629
|
+
<th class="p-3 border-b border-white/10">Description</th>
|
|
2630
|
+
</tr>
|
|
2631
|
+
</thead>
|
|
2632
|
+
<tbody class="divide-y divide-white/5">
|
|
2633
|
+
<tr><td class="p-3 font-mono text-cyan-400">src</td><td class="p-3 font-mono text-xs">string</td><td class="p-3">Required. Video URL.</td></tr>
|
|
2634
|
+
<tr><td class="p-3 font-mono text-cyan-400">poster</td><td class="p-3 font-mono text-xs">string?</td><td class="p-3">Poster image URL.</td></tr>
|
|
2635
|
+
<tr><td class="p-3 font-mono text-cyan-400">autoplay</td><td class="p-3 font-mono text-xs">boolean?</td><td class="p-3">Default: false.</td></tr>
|
|
2636
|
+
<tr><td class="p-3 font-mono text-cyan-400">loop</td><td class="p-3 font-mono text-xs">boolean?</td><td class="p-3">Default: false.</td></tr>
|
|
2637
|
+
<tr><td class="p-3 font-mono text-cyan-400">muted</td><td class="p-3 font-mono text-xs">boolean?</td><td class="p-3">Default: false. Often true with autoplay for autoplay to work.</td></tr>
|
|
2638
|
+
<tr><td class="p-3 font-mono text-cyan-400">controls</td><td class="p-3 font-mono text-xs">boolean?</td><td class="p-3">Default: false. Show play/seek/volume.</td></tr>
|
|
2639
|
+
<tr><td class="p-3 font-mono text-cyan-400">className</td><td class="p-3 font-mono text-xs">string?</td><td class="p-3">CSS class for the title overlay container.</td></tr>
|
|
2640
|
+
</tbody>
|
|
2641
|
+
</table>
|
|
2642
|
+
</div>
|
|
2643
|
+
</div>
|
|
2644
|
+
|
|
2645
|
+
<div class="my-8">
|
|
2646
|
+
<h2 class="text-xl font-bold text-white mb-4">Example</h2>
|
|
2647
|
+
<LivePreview :initial-code="EXAMPLES.video_slide" />
|
|
2648
|
+
</div>
|
|
2649
|
+
|
|
2650
|
+
<p class="text-white/60 text-sm">Element control ids: <code>s{N}-video</code>, <code>s{N}-title</code>.</p>
|
|
2651
|
+
</div>
|
|
2652
|
+
|
|
2653
|
+
<!-- REF: CUSTOM HTML -->
|
|
2654
|
+
<div v-else-if="activeSection === 'ref-custom'">
|
|
2655
|
+
<h1>Custom HTML Slide</h1>
|
|
2656
|
+
<p class="lead">Full control with raw HTML content. Inject any HTML structure with custom
|
|
2657
|
+
styling.</p>
|
|
2658
|
+
|
|
2659
|
+
<div class="my-8">
|
|
2660
|
+
<h2 class="text-xl font-bold text-white mb-4">Configuration</h2>
|
|
2661
|
+
<div class="overflow-x-auto border border-white/10 rounded-lg">
|
|
2662
|
+
<table class="w-full text-left text-sm text-gray-400">
|
|
2663
|
+
<thead class="bg-white/5 text-white font-bold">
|
|
2664
|
+
<tr>
|
|
2665
|
+
<th class="p-3 border-b border-white/10">Property</th>
|
|
2666
|
+
<th class="p-3 border-b border-white/10">Type</th>
|
|
2667
|
+
<th class="p-3 border-b border-white/10">Description</th>
|
|
2668
|
+
</tr>
|
|
2669
|
+
</thead>
|
|
2670
|
+
<tbody class="divide-y divide-white/5">
|
|
2671
|
+
<tr>
|
|
2672
|
+
<td class="p-3 font-mono text-purple-400">type</td>
|
|
2673
|
+
<td class="p-3 font-mono text-xs">"custom"</td>
|
|
2674
|
+
<td class="p-3">Required.</td>
|
|
2675
|
+
</tr>
|
|
2676
|
+
<tr>
|
|
2677
|
+
<td class="p-3 font-mono text-blue-400">html</td>
|
|
2678
|
+
<td class="p-3 font-mono text-xs">string</td>
|
|
2679
|
+
<td class="p-3">Raw HTML content to render.</td>
|
|
2680
|
+
</tr>
|
|
2681
|
+
<tr>
|
|
2682
|
+
<td class="p-3 font-mono text-blue-400">css</td>
|
|
2683
|
+
<td class="p-3 font-mono text-xs">string?</td>
|
|
2684
|
+
<td class="p-3">Optional scoped CSS styles.</td>
|
|
2685
|
+
</tr>
|
|
2686
|
+
</tbody>
|
|
2687
|
+
</table>
|
|
2688
|
+
</div>
|
|
2689
|
+
</div>
|
|
2690
|
+
|
|
2691
|
+
<div class="my-8">
|
|
2692
|
+
<h2 class="text-xl font-bold text-white mb-4">Basic Example</h2>
|
|
2693
|
+
<p class="text-white/60 mb-6">Render any HTML structure with full styling control.</p>
|
|
2694
|
+
<LivePreview initial-code='{
|
|
2695
|
+
"type": "custom",
|
|
2696
|
+
"html": "<div class=\"custom-slide\"><h1 class=\"custom-title\">Welcome!</h1><p class=\"custom-text\">This is fully custom HTML content.</p><div class=\"custom-grid\"><div class=\"custom-card\">Card 1</div><div class=\"custom-card\">Card 2</div><div class=\"custom-card\">Card 3</div></div></div>",
|
|
2697
|
+
"css": ".custom-slide { display: flex; flex-direction: column; align-items: center; justify-content: center; min-height: 100%; padding: 2rem; } .custom-title { font-size: 3rem; font-weight: bold; margin-bottom: 1rem; background: linear-gradient(90deg, #3b82f6, #8b5cf6); -webkit-background-clip: text; -webkit-text-fill-color: transparent; } .custom-text { font-size: 1.25rem; opacity: 0.7; margin-bottom: 2rem; } .custom-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; } .custom-card { padding: 2rem; background: rgba(255,255,255,0.05); border-radius: 1rem; border: 1px solid rgba(255,255,255,0.1); text-align: center; transition: transform 0.2s; } .custom-card:hover { transform: translateY(-4px); }"
|
|
2698
|
+
}' />
|
|
2699
|
+
</div>
|
|
2700
|
+
|
|
2701
|
+
<div class="my-8">
|
|
2702
|
+
<h2 class="text-xl font-bold text-white mb-4">Use Cases</h2>
|
|
2703
|
+
<ul class="space-y-3 text-white/70">
|
|
2704
|
+
<li><strong>Embedding iframes:</strong> YouTube videos, maps, or external widgets</li>
|
|
2705
|
+
<li><strong>Custom visualizations:</strong> D3.js charts, SVG animations</li>
|
|
2706
|
+
<li><strong>Brand-specific layouts:</strong> Complex designs not covered by built-in
|
|
2707
|
+
layouts</li>
|
|
2708
|
+
<li><strong>Interactive components:</strong> Forms, quizzes, or custom buttons</li>
|
|
2709
|
+
</ul>
|
|
2710
|
+
</div>
|
|
2711
|
+
|
|
2712
|
+
<div class="my-8">
|
|
2713
|
+
<h2 class="text-xl font-bold text-white mb-4">Sanitization</h2>
|
|
2714
|
+
<p class="text-white/70 mb-2">Before rendering, the following are removed for security: <code><script></code> tags, <code>on*</code> attribute handlers (e.g. <code>onclick=</code>), and <code>javascript:</code> URLs. Sanitize or escape user-generated HTML for other XSS vectors if needed.</p>
|
|
2715
|
+
<p class="text-white/60 text-sm">The <code>css</code> string is injected into <code>document.head</code> as a <code><style></code> and removed when the slide unmounts.</p>
|
|
2716
|
+
</div>
|
|
2717
|
+
|
|
2718
|
+
<div class="mt-8 p-4 bg-yellow-500/10 border border-yellow-500/20 rounded-lg">
|
|
2719
|
+
<h4 class="text-yellow-400 font-bold mb-2"><i class="fa-solid fa-lightbulb mr-2"></i>Pro
|
|
2720
|
+
Tips</h4>
|
|
2721
|
+
<ul class="text-sm text-yellow-200/80 space-y-2 m-0 list-none">
|
|
2722
|
+
<li>🎨 <strong>Scoped CSS:</strong> Styles are injected in <code><head></code>; use unique class names to avoid clashes with Lumina.</li>
|
|
2723
|
+
<li>📱 <strong>Responsive:</strong> Use CSS Grid or Flexbox with relative units for
|
|
2724
|
+
mobile support</li>
|
|
2725
|
+
<li>🤖 <strong>LLM Usage:</strong> Custom slides are great when the AI needs complete
|
|
2726
|
+
creative freedom</li>
|
|
2727
|
+
</ul>
|
|
2728
|
+
</div>
|
|
2729
|
+
</div>
|
|
2730
|
+
|
|
2731
|
+
<!-- REF: DIAGRAM -->
|
|
2732
|
+
<div v-else-if="activeSection === 'ref-diagram'">
|
|
2733
|
+
<h1>Diagram Slide</h1>
|
|
2734
|
+
<p class="lead">Interactive node-based diagram using Vue Flow. Supports nodes, edges, and (in Studio) drag-and-drop and inline editing.</p>
|
|
2735
|
+
|
|
2736
|
+
<div class="my-8">
|
|
2737
|
+
<h2 class="text-xl font-bold text-white mb-4">Configuration</h2>
|
|
2738
|
+
<div class="overflow-x-auto border border-white/10 rounded-lg">
|
|
2739
|
+
<table class="w-full text-left text-sm text-gray-400">
|
|
2740
|
+
<thead class="bg-white/5 text-white font-bold">
|
|
2741
|
+
<tr>
|
|
2742
|
+
<th class="p-3 border-b border-white/10">Property</th>
|
|
2743
|
+
<th class="p-3 border-b border-white/10">Type</th>
|
|
2744
|
+
<th class="p-3 border-b border-white/10">Description</th>
|
|
2745
|
+
</tr>
|
|
2746
|
+
</thead>
|
|
2747
|
+
<tbody class="divide-y divide-white/5">
|
|
2748
|
+
<tr>
|
|
2749
|
+
<td class="p-3 font-mono text-purple-400">type</td>
|
|
2750
|
+
<td class="p-3 font-mono text-xs">"diagram"</td>
|
|
2751
|
+
<td class="p-3">Required.</td>
|
|
2752
|
+
</tr>
|
|
2753
|
+
<tr>
|
|
2754
|
+
<td class="p-3 font-mono text-blue-400">nodes</td>
|
|
2755
|
+
<td class="p-3 font-mono text-xs">object[]</td>
|
|
2756
|
+
<td class="p-3">Vue Flow nodes: <code>id</code>, <code>type</code> (default/input), <code>position</code> <code>{x,y}</code>, <code>label</code>, <code>data</code> (e.g. shape, style).</td>
|
|
2757
|
+
</tr>
|
|
2758
|
+
<tr>
|
|
2759
|
+
<td class="p-3 font-mono text-blue-400">edges</td>
|
|
2760
|
+
<td class="p-3 font-mono text-xs">object[]</td>
|
|
2761
|
+
<td class="p-3">Vue Flow edges: <code>id</code>, <code>source</code>, <code>target</code>, <code>sourceHandle</code>, <code>targetHandle</code> (optional).</td>
|
|
2762
|
+
</tr>
|
|
2763
|
+
<tr>
|
|
2764
|
+
<td class="p-3 font-mono text-blue-400">config</td>
|
|
2765
|
+
<td class="p-3 font-mono text-xs">object?</td>
|
|
2766
|
+
<td class="p-3"><code>fitView</code> and other Vue Flow options.</td>
|
|
2767
|
+
</tr>
|
|
2768
|
+
</tbody>
|
|
2769
|
+
</table>
|
|
2770
|
+
</div>
|
|
2771
|
+
</div>
|
|
2772
|
+
<p class="text-white/60 text-sm">Element control: <code>s{N}-nodes-{i}</code>, <code>s{N}-edges-{i}</code>. With <code>studio: true</code>, diagrams are editable (add nodes via palette, drag, connect, resize).</p>
|
|
2773
|
+
</div>
|
|
2774
|
+
|
|
2775
|
+
<!-- REF: FREE -->
|
|
2776
|
+
<div v-else-if="activeSection === 'ref-free'">
|
|
2777
|
+
<h1>Free / Composition Slide</h1>
|
|
2778
|
+
<p class="lead">Absolutely positioned elements (text, image, box) for Remotion-style storytelling. Use <code>timelineTracks</code> to animate <code>x</code>, <code>y</code> (as translate), <code>opacity</code>, etc.</p>
|
|
2779
|
+
|
|
2780
|
+
<div class="my-8">
|
|
2781
|
+
<h2 class="text-xl font-bold text-white mb-4">Configuration</h2>
|
|
2782
|
+
<div class="overflow-x-auto border border-white/10 rounded-lg">
|
|
2783
|
+
<table class="w-full text-left text-sm text-gray-400">
|
|
2784
|
+
<thead class="bg-white/5 text-white font-bold">
|
|
2785
|
+
<tr>
|
|
2786
|
+
<th class="p-3 border-b border-white/10">Property</th>
|
|
2787
|
+
<th class="p-3 border-b border-white/10">Type</th>
|
|
2788
|
+
<th class="p-3 border-b border-white/10">Description</th>
|
|
2789
|
+
</tr>
|
|
2790
|
+
</thead>
|
|
2791
|
+
<tbody class="divide-y divide-white/5">
|
|
2792
|
+
<tr>
|
|
2793
|
+
<td class="p-3 font-mono text-purple-400">type</td>
|
|
2794
|
+
<td class="p-3 font-mono text-xs">"free"</td>
|
|
2795
|
+
<td class="p-3">Required.</td>
|
|
2796
|
+
</tr>
|
|
2797
|
+
<tr>
|
|
2798
|
+
<td class="p-3 font-mono text-blue-400">elements</td>
|
|
2799
|
+
<td class="p-3 font-mono text-xs">FreeElement[]</td>
|
|
2800
|
+
<td class="p-3">Each: <code>type</code> (<code>"text"</code>|<code>"image"</code>|<code>"box"</code>), <code>text?</code>, <code>src?</code>, <code>width?</code>, <code>height?</code>, <code>fontSize?</code>, <code>color?</code>, <code>fontWeight?</code>, <code>backgroundColor?</code> (box), <code>id?</code>.</td>
|
|
2801
|
+
</tr>
|
|
2802
|
+
</tbody>
|
|
2803
|
+
</table>
|
|
2804
|
+
</div>
|
|
2805
|
+
</div>
|
|
2806
|
+
<p class="text-white/60 text-sm">Element ids: <code>s{N}-elements-0</code>, <code>s{N}-elements-1</code>, … (or custom <code>id</code> on each element). Position is driven by <code>slide.timelineTracks</code>; see <em>Timeline (keyframes)</em>.</p>
|
|
2807
|
+
</div>
|
|
2808
|
+
|
|
2809
|
+
<!-- REF: AUTO -->
|
|
2810
|
+
<div v-else-if="activeSection === 'ref-auto'">
|
|
2811
|
+
<h1>Auto Strategy</h1>
|
|
2812
|
+
<p class="lead">Smartly chooses the best layout based on the data structure provided. Useful for
|
|
2813
|
+
AI agents or rapid prototyping.</p>
|
|
2814
|
+
|
|
2815
|
+
<div class="p-6 bg-blue-500/10 border border-blue-500/20 rounded-xl my-8">
|
|
2816
|
+
<h3 class="text-blue-400 font-bold mb-2">How it works</h3>
|
|
2817
|
+
<ul class="list-disc list-inside text-sm text-blue-200/80 space-y-1">
|
|
2818
|
+
<li>If <code>chartType</code> + <code>data.datasets</code> exist ->
|
|
2819
|
+
<strong>Chart</strong>
|
|
2820
|
+
</li>
|
|
2821
|
+
<li>If <code>timeline</code> array exists -> <strong>Timeline</strong></li>
|
|
2822
|
+
<li>If <code>steps</code> array exists -> <strong>Steps</strong></li>
|
|
2823
|
+
<li>If <code>features</code> array exists -> <strong>Features</strong></li>
|
|
2824
|
+
<li>If <code>image</code> exists -> <strong>Half</strong></li>
|
|
2825
|
+
<li>Otherwise -> <strong>Statement</strong></li>
|
|
2826
|
+
</ul>
|
|
2827
|
+
</div>
|
|
2828
|
+
|
|
2829
|
+
<div class="my-8">
|
|
2830
|
+
<h2 class="text-xl font-bold text-white mb-4">Live Examples</h2>
|
|
2831
|
+
<p class="text-sm text-gray-400 mb-6">Use the navigation arrows to see how each slide
|
|
2832
|
+
renders with the same <code>type: "auto"</code> but different data structures.</p>
|
|
2833
|
+
<LivePreview initial-code='{
|
|
2834
|
+
"slides": [
|
|
2835
|
+
{
|
|
2836
|
+
"type": "auto",
|
|
2837
|
+
"title": "Welcome to Lumina",
|
|
2838
|
+
"subtitle": "The AI-Native Presentation Engine"
|
|
2839
|
+
},
|
|
2840
|
+
{
|
|
2841
|
+
"type": "auto",
|
|
2842
|
+
"title": "Core Features",
|
|
2843
|
+
"features": [
|
|
2844
|
+
{ "title": "Fast", "desc": "60fps animations", "icon": "fa-bolt" },
|
|
2845
|
+
{ "title": "Simple", "desc": "JSON-first API", "icon": "fa-code" },
|
|
2846
|
+
{ "title": "Smart", "desc": "AI-ready engine", "icon": "fa-brain" }
|
|
2847
|
+
]
|
|
2848
|
+
},
|
|
2849
|
+
{
|
|
2850
|
+
"type": "auto",
|
|
2851
|
+
"title": "Our Roadmap",
|
|
2852
|
+
"timeline": [
|
|
2853
|
+
{ "date": "Q1", "title": "Alpha", "description": "Core Engine" },
|
|
2854
|
+
{ "date": "Q2", "title": "Beta", "description": "Public Testing" },
|
|
2855
|
+
{ "date": "Q4", "title": "Launch", "description": "V1.0 Release" }
|
|
2856
|
+
]
|
|
2857
|
+
},
|
|
2858
|
+
{
|
|
2859
|
+
"type": "auto",
|
|
2860
|
+
"title": "Getting Started",
|
|
2861
|
+
"steps": [
|
|
2862
|
+
{ "step": "1", "title": "Install", "description": "npm install lumina-slides" },
|
|
2863
|
+
{ "step": "2", "title": "Import", "description": "Import the Lumina class" },
|
|
2864
|
+
{ "step": "3", "title": "Create", "description": "Define your JSON slides" }
|
|
2865
|
+
]
|
|
2866
|
+
},
|
|
2867
|
+
{
|
|
2868
|
+
"type": "auto",
|
|
2869
|
+
"title": "Visual Content",
|
|
2870
|
+
"image": "https://images.unsplash.com/photo-1618005182384-a83a8bd57fbe?q=80&w=800",
|
|
2871
|
+
"paragraphs": ["Auto-detect image slides for visual storytelling."]
|
|
2872
|
+
}
|
|
2873
|
+
]
|
|
2874
|
+
}' />
|
|
2875
|
+
</div>
|
|
2876
|
+
</div>
|
|
2877
|
+
|
|
2878
|
+
</div>
|
|
2879
|
+
</Transition>
|
|
2880
|
+
</main>
|
|
2881
|
+
</div>
|
|
2882
|
+
</template>
|
|
2883
|
+
|
|
2884
|
+
<script setup lang="ts">
|
|
2885
|
+
import { ref, watch, onUnmounted, nextTick } from 'vue';
|
|
2886
|
+
import { Lumina } from '../../core/Lumina';
|
|
2887
|
+
import { parsePartialJson } from '../../utils/streaming';
|
|
2888
|
+
import LivePreview from './LivePreview.vue';
|
|
2889
|
+
|
|
2890
|
+
const activeSection = ref('intro');
|
|
2891
|
+
|
|
2892
|
+
// --- DEMO LOGIC ---
|
|
2893
|
+
const demoInput = ref('');
|
|
2894
|
+
const demoStarted = ref(false);
|
|
2895
|
+
let demoEngine: Lumina | null = null;
|
|
2896
|
+
|
|
2897
|
+
const TARGET_JSON = `{
|
|
2898
|
+
"meta": { "title": "Lumina Demo" },
|
|
2899
|
+
"slides": [
|
|
2900
|
+
{
|
|
2901
|
+
"type": "half",
|
|
2902
|
+
"sizing": "container",
|
|
2903
|
+
"meta": {
|
|
2904
|
+
"orbColor": "#8b5cf6"
|
|
2905
|
+
},
|
|
2906
|
+
"imageSide": "left",
|
|
2907
|
+
"image": "https://images.unsplash.com/photo-1618005182384-a83a8bd57fbe?q=80&w=2000",
|
|
2908
|
+
"tag": "Left Aligned",
|
|
2909
|
+
"title": "Image on Left",
|
|
2910
|
+
"paragraphs": [
|
|
2911
|
+
"The classic split screen. Image on the left, content on the right.",
|
|
2912
|
+
"Perfect for introducing a product or feature where the visual context leads the narrative."
|
|
2913
|
+
],
|
|
2914
|
+
"cta": "Explore Left"
|
|
2915
|
+
},
|
|
2916
|
+
{
|
|
2917
|
+
"type": "statement",
|
|
2918
|
+
"sizing": "container",
|
|
2919
|
+
"meta": {
|
|
2920
|
+
"orbColor": "#ec4899"
|
|
2921
|
+
},
|
|
2922
|
+
"tag": "Minimal",
|
|
2923
|
+
"title": "Impactful Headlines",
|
|
2924
|
+
"subtitle": "The standard statement slide allows for massive typography to drive a point home."
|
|
2925
|
+
},
|
|
2926
|
+
{
|
|
2927
|
+
"type": "features",
|
|
2928
|
+
"sizing": "container",
|
|
2929
|
+
"title": "Grid System",
|
|
2930
|
+
"description": "The features layout automatically arranges cards into a responsive grid.",
|
|
2931
|
+
"features": [
|
|
2932
|
+
{ "title": "Card One", "desc": "Standard card with an icon.", "icon": "fa-bolt" },
|
|
2933
|
+
{ "title": "Card Two", "desc": "Cards scale on hover.", "icon": "fa-star" },
|
|
2934
|
+
{ "title": "Card Three", "desc": "Fully responsive on mobile.", "icon": "fa-mobile" }
|
|
2935
|
+
]
|
|
2936
|
+
},
|
|
2937
|
+
{
|
|
2938
|
+
"type": "timeline",
|
|
2939
|
+
"sizing": "container",
|
|
2940
|
+
"title": "Project History",
|
|
2941
|
+
"subtitle": "A visual journey through our milestones.",
|
|
2942
|
+
"timeline": [
|
|
2943
|
+
{ "date": "Q1 2023", "title": "Inception", "description": "The initial concept was drafted." },
|
|
2944
|
+
{ "date": "Q3 2023", "title": "Prototype", "description": "First functional MVP released." },
|
|
2945
|
+
{ "date": "Q1 2024", "title": "Beta Launch", "description": "Public beta opened to users." }
|
|
2946
|
+
]
|
|
2947
|
+
}
|
|
2948
|
+
]
|
|
2949
|
+
}`;
|
|
2950
|
+
|
|
2951
|
+
async function runDemo() {
|
|
2952
|
+
demoInput.value = '';
|
|
2953
|
+
demoStarted.value = true;
|
|
2954
|
+
|
|
2955
|
+
// Initialize Engine if needed
|
|
2956
|
+
if (!demoEngine) {
|
|
2957
|
+
// Ensure container is cleared to avoid duplicates
|
|
2958
|
+
const container = document.getElementById('streaming-demo-container');
|
|
2959
|
+
if (container) container.innerHTML = '';
|
|
2960
|
+
|
|
2961
|
+
nextTick(() => {
|
|
2962
|
+
demoEngine = new Lumina('#streaming-demo-container', {
|
|
2963
|
+
ui: { visible: true, showControls: true },
|
|
2964
|
+
keyboard: false,
|
|
2965
|
+
animation: { enabled: true, durationIn: 0.5 }
|
|
2966
|
+
});
|
|
2967
|
+
});
|
|
2968
|
+
}
|
|
2969
|
+
|
|
2970
|
+
let i = 0;
|
|
2971
|
+
// Faster typing for examples
|
|
2972
|
+
const interval = setInterval(() => {
|
|
2973
|
+
demoInput.value += TARGET_JSON[i];
|
|
2974
|
+
i++;
|
|
2975
|
+
if (i >= TARGET_JSON.length) clearInterval(interval);
|
|
2976
|
+
}, 10);
|
|
2977
|
+
}
|
|
2978
|
+
|
|
2979
|
+
function loadIntoDemo(json: string) {
|
|
2980
|
+
activeSection.value = 'agents-streaming';
|
|
2981
|
+
window.scrollTo({ top: 0, behavior: 'smooth' });
|
|
2982
|
+
demoInput.value = '';
|
|
2983
|
+
demoStarted.value = true;
|
|
2984
|
+
|
|
2985
|
+
setTimeout(() => {
|
|
2986
|
+
if (!demoEngine) {
|
|
2987
|
+
const container = document.getElementById('streaming-demo-container');
|
|
2988
|
+
if (container) container.innerHTML = '';
|
|
2989
|
+
demoEngine = new Lumina('#streaming-demo-container', {
|
|
2990
|
+
ui: { visible: true },
|
|
2991
|
+
keyboard: false,
|
|
2992
|
+
animation: { enabled: true, durationIn: 0.5 }
|
|
2993
|
+
});
|
|
2994
|
+
}
|
|
2995
|
+
|
|
2996
|
+
let i = 0;
|
|
2997
|
+
const interval = setInterval(() => {
|
|
2998
|
+
demoInput.value += json[i];
|
|
2999
|
+
i++;
|
|
3000
|
+
if (i >= json.length) clearInterval(interval);
|
|
3001
|
+
}, 5);
|
|
3002
|
+
}, 100);
|
|
3003
|
+
}
|
|
3004
|
+
|
|
3005
|
+
const EXAMPLES = {
|
|
3006
|
+
statement: `{
|
|
3007
|
+
"type": "statement",
|
|
3008
|
+
"sizing": "container",
|
|
3009
|
+
"t": "Big Impact",
|
|
3010
|
+
"s": "Created instantly from JSON.",
|
|
3011
|
+
"meta": { "variant": "v:g" }
|
|
3012
|
+
}`,
|
|
3013
|
+
features: `{
|
|
3014
|
+
"type": "features",
|
|
3015
|
+
"sizing": "container",
|
|
3016
|
+
"t": "Core Capabilities",
|
|
3017
|
+
"fs": [
|
|
3018
|
+
{ "t": "Fast", "desc": "60fps", "icon": "bolt" },
|
|
3019
|
+
{ "t": "AI", "desc": "Native", "icon": "robot" },
|
|
3020
|
+
{ "t": "Typed", "desc": "TS", "icon": "code" }
|
|
3021
|
+
]
|
|
3022
|
+
}`,
|
|
3023
|
+
timeline: `{
|
|
3024
|
+
"type": "timeline",
|
|
3025
|
+
"sizing": "container",
|
|
3026
|
+
"t": "Product Roadmap",
|
|
3027
|
+
"tl": [
|
|
3028
|
+
{ "date": "Q1", "t": "Alpha", "desc": "Core Engine" },
|
|
3029
|
+
{ "date": "Q2", "t": "Beta", "desc": "Public API" },
|
|
3030
|
+
{ "date": "Q3", "t": "Launch", "desc": "Global Scale" }
|
|
3031
|
+
]
|
|
3032
|
+
}`,
|
|
3033
|
+
half: `{
|
|
3034
|
+
"type": "half",
|
|
3035
|
+
"sizing": "container",
|
|
3036
|
+
"imageSide": "left",
|
|
3037
|
+
"image": "https://images.unsplash.com/photo-1618005182384-a83a8bd57fbe?q=80&w=2000",
|
|
3038
|
+
"t": "Split Layout",
|
|
3039
|
+
"tag": "Visual",
|
|
3040
|
+
"paragraphs": ["Image on left, text on right."]
|
|
3041
|
+
}`,
|
|
3042
|
+
steps: `{
|
|
3043
|
+
"type": "steps",
|
|
3044
|
+
"sizing": "container",
|
|
3045
|
+
"t": "Process Flow",
|
|
3046
|
+
"steps": [
|
|
3047
|
+
{ "step": "01", "t": "Install", "desc": "npm install" },
|
|
3048
|
+
{ "step": "02", "t": "Import", "desc": "import { Lumina }..." },
|
|
3049
|
+
{ "step": "03", "t": "Launch", "desc": "new Lumina(...)" }
|
|
3050
|
+
]
|
|
3051
|
+
}`,
|
|
3052
|
+
flex: `{
|
|
3053
|
+
"type": "flex",
|
|
3054
|
+
"sizing": "container",
|
|
3055
|
+
"direction": "horizontal",
|
|
3056
|
+
"elements": [
|
|
3057
|
+
{ "type": "image", "src": "./brains.png", "size": "half", "fill": true },
|
|
3058
|
+
{ "type": "content", "size": "half", "valign": "center", "padding": "xl", "gap": "md", "elements": [
|
|
3059
|
+
{ "type": "title", "text": "Visual Story", "size": "2xl" },
|
|
3060
|
+
{ "type": "bullets", "items": ["Image fills height", "Content centered", "No coordinates"] },
|
|
3061
|
+
{ "type": "button", "label": "Learn More", "variant": "primary" }
|
|
3062
|
+
]}
|
|
3063
|
+
]
|
|
3064
|
+
}` ,
|
|
3065
|
+
video: `{
|
|
3066
|
+
"type": "statement",
|
|
3067
|
+
"sizing": "container",
|
|
3068
|
+
"meta": { "orbColor": "#ec4899" },
|
|
3069
|
+
"background": {
|
|
3070
|
+
"type": "video",
|
|
3071
|
+
"src": "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerBlazes.mp4",
|
|
3072
|
+
"opacity": 0.4
|
|
3073
|
+
},
|
|
3074
|
+
"tag": "Cinematic",
|
|
3075
|
+
"title": "Video Backgrounds",
|
|
3076
|
+
"subtitle": "Immersive support."
|
|
3077
|
+
}`,
|
|
3078
|
+
video_half: `{
|
|
3079
|
+
"type": "half",
|
|
3080
|
+
"sizing": "container",
|
|
3081
|
+
"video": {
|
|
3082
|
+
"type": "video",
|
|
3083
|
+
"src": "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ElephantsDream.mp4",
|
|
3084
|
+
"autoplay": true,
|
|
3085
|
+
"muted": true
|
|
3086
|
+
},
|
|
3087
|
+
"title": "Watch This"
|
|
3088
|
+
}`,
|
|
3089
|
+
video_flex: `{
|
|
3090
|
+
"type": "flex",
|
|
3091
|
+
"sizing": "container",
|
|
3092
|
+
"elements": [
|
|
3093
|
+
{
|
|
3094
|
+
"type": "video",
|
|
3095
|
+
"src": "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4",
|
|
3096
|
+
"controls": true,
|
|
3097
|
+
"size": "half"
|
|
3098
|
+
}
|
|
3099
|
+
]
|
|
3100
|
+
}`,
|
|
3101
|
+
video_slide: `{
|
|
3102
|
+
"type": "video",
|
|
3103
|
+
"sizing": "container",
|
|
3104
|
+
"video": {
|
|
3105
|
+
"type": "video",
|
|
3106
|
+
"src": "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerBlazes.mp4",
|
|
3107
|
+
"autoplay": true,
|
|
3108
|
+
"muted": true,
|
|
3109
|
+
"loop": true
|
|
3110
|
+
},
|
|
3111
|
+
"title": "Full-screen video"
|
|
3112
|
+
}`
|
|
3113
|
+
};
|
|
3114
|
+
|
|
3115
|
+
// Watch input and parse
|
|
3116
|
+
watch(demoInput, (val) => {
|
|
3117
|
+
if (!demoEngine) return;
|
|
3118
|
+
const parsed = parsePartialJson(val);
|
|
3119
|
+
if (parsed) {
|
|
3120
|
+
// Handle Deck vs Slide
|
|
3121
|
+
if (parsed.slides && Array.isArray(parsed.slides)) {
|
|
3122
|
+
// Apply sizing: container to all slides if missing
|
|
3123
|
+
parsed.slides.forEach((s: any) => s.sizing = 'container');
|
|
3124
|
+
demoEngine.load(parsed);
|
|
3125
|
+
|
|
3126
|
+
// Auto-advance logic: check if we have a new slide that is ready
|
|
3127
|
+
const availableSlides = parsed.slides.filter((s: any) => s.title || s.type);
|
|
3128
|
+
const targetIndex = availableSlides.length - 1;
|
|
3129
|
+
|
|
3130
|
+
if (targetIndex > demoEngine.currentSlideIndex) {
|
|
3131
|
+
demoEngine.goTo(targetIndex);
|
|
3132
|
+
}
|
|
3133
|
+
} else {
|
|
3134
|
+
// Wrap single slide
|
|
3135
|
+
demoEngine.load({
|
|
3136
|
+
meta: { title: "Demo" },
|
|
3137
|
+
slides: [{ ...parsed, sizing: 'container' }]
|
|
3138
|
+
});
|
|
3139
|
+
}
|
|
3140
|
+
}
|
|
3141
|
+
});
|
|
3142
|
+
|
|
3143
|
+
onUnmounted(() => {
|
|
3144
|
+
if (demoEngine) demoEngine.destroy();
|
|
3145
|
+
});
|
|
3146
|
+
|
|
3147
|
+
|
|
3148
|
+
|
|
3149
|
+
const navigation = [
|
|
3150
|
+
{
|
|
3151
|
+
title: 'Getting Started',
|
|
3152
|
+
items: [
|
|
3153
|
+
{ id: 'intro', label: 'Introduction' },
|
|
3154
|
+
{ id: 'install', label: 'Installation' },
|
|
3155
|
+
{ id: 'setup', label: 'Quick Start' },
|
|
3156
|
+
{ id: 'theming', label: 'Theming & Presets' }
|
|
3157
|
+
]
|
|
3158
|
+
},
|
|
3159
|
+
{
|
|
3160
|
+
title: 'Concepts',
|
|
3161
|
+
items: [
|
|
3162
|
+
{ id: 'deck', label: 'Deck Structure' },
|
|
3163
|
+
{ id: 'slides', label: 'Slide Layouts' },
|
|
3164
|
+
{ id: 'media', label: 'Media & Video' },
|
|
3165
|
+
{ id: 'sizing', label: 'Embedding & Sizing' },
|
|
3166
|
+
{ id: 'agents-intro', label: 'Agent Protocol' },
|
|
3167
|
+
{ id: 'agents-tokens', label: 'Token Optimization' }
|
|
3168
|
+
]
|
|
3169
|
+
},
|
|
3170
|
+
{
|
|
3171
|
+
title: 'Layouts',
|
|
3172
|
+
items: [
|
|
3173
|
+
{ id: 'ref-statement', label: 'Statement' },
|
|
3174
|
+
{ id: 'ref-half', label: 'Half / Split' },
|
|
3175
|
+
{ id: 'ref-features', label: 'Features' },
|
|
3176
|
+
{ id: 'ref-timeline', label: 'Timeline' },
|
|
3177
|
+
{ id: 'ref-steps', label: 'Steps' },
|
|
3178
|
+
{ id: 'ref-flex', label: 'Flex' },
|
|
3179
|
+
{ id: 'ref-chart', label: 'Chart' },
|
|
3180
|
+
{ id: 'ref-video', label: 'Video' },
|
|
3181
|
+
{ id: 'ref-diagram', label: 'Diagram' },
|
|
3182
|
+
{ id: 'ref-free', label: 'Free / Composition' },
|
|
3183
|
+
{ id: 'ref-custom', label: 'Custom HTML' },
|
|
3184
|
+
{ id: 'ref-auto', label: 'Auto Strategy' }
|
|
3185
|
+
]
|
|
3186
|
+
},
|
|
3187
|
+
{
|
|
3188
|
+
title: 'AI & LLM Integration',
|
|
3189
|
+
items: [
|
|
3190
|
+
{ id: 'agents-streaming', label: 'Streaming & Realtime' },
|
|
3191
|
+
{ id: 'agents-intro', label: 'Agent Protocol' },
|
|
3192
|
+
{ id: 'agents-tokens', label: 'Token Optimization' }
|
|
3193
|
+
]
|
|
3194
|
+
},
|
|
3195
|
+
{
|
|
3196
|
+
title: 'Advanced',
|
|
3197
|
+
items: [
|
|
3198
|
+
{ id: 'config', label: 'Configuration' },
|
|
3199
|
+
{ id: 'events', label: 'Events & API' },
|
|
3200
|
+
{ id: 'element-control', label: 'Element Control' },
|
|
3201
|
+
{ id: 'animations', label: 'Animations (reveal, presets, stagger)' },
|
|
3202
|
+
{ id: 'timeline-keyframes', label: 'Timeline (keyframes)' },
|
|
3203
|
+
{ id: 'sizing', label: 'Embedding' },
|
|
3204
|
+
{ id: 'speaker-notes', label: 'Speaker Notes' }
|
|
3205
|
+
]
|
|
3206
|
+
}
|
|
3207
|
+
];
|
|
3208
|
+
|
|
3209
|
+
|
|
3210
|
+
function scroll(id: string) {
|
|
3211
|
+
nextTick(() => {
|
|
3212
|
+
const el = document.getElementById(id);
|
|
3213
|
+
if (el) {
|
|
3214
|
+
el.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
|
3215
|
+
}
|
|
3216
|
+
});
|
|
3217
|
+
}
|
|
3218
|
+
|
|
3219
|
+
function scrollToTop() {
|
|
3220
|
+
window.scrollTo({ top: 0, behavior: 'smooth' });
|
|
3221
|
+
}
|
|
3222
|
+
</script>
|
|
3223
|
+
|
|
3224
|
+
<style scoped>
|
|
3225
|
+
.doc-content h1 {
|
|
3226
|
+
@apply text-4xl md:text-5xl font-black tracking-tight text-white mb-8 leading-tight font-heading;
|
|
3227
|
+
}
|
|
3228
|
+
|
|
3229
|
+
.doc-content h2 {
|
|
3230
|
+
@apply text-2xl md:text-3xl font-bold text-white mt-16 mb-6 tracking-tight font-heading;
|
|
3231
|
+
}
|
|
3232
|
+
|
|
3233
|
+
.doc-content h3 {
|
|
3234
|
+
@apply text-[20px] font-extrabold text-white mb-[15px] mt-8 font-heading;
|
|
3235
|
+
}
|
|
3236
|
+
|
|
3237
|
+
.doc-content p {
|
|
3238
|
+
@apply text-lg text-white/70 leading-relaxed mb-6 font-sans;
|
|
3239
|
+
}
|
|
3240
|
+
|
|
3241
|
+
.doc-content p.lead {
|
|
3242
|
+
@apply text-2xl text-white font-light mb-10 leading-relaxed;
|
|
3243
|
+
}
|
|
3244
|
+
|
|
3245
|
+
.doc-content ul {
|
|
3246
|
+
@apply list-disc list-outside ml-6 mb-8 text-white/70;
|
|
3247
|
+
}
|
|
3248
|
+
|
|
3249
|
+
.doc-content li {
|
|
3250
|
+
@apply mb-2 pl-2 marker:text-blue-500 text-lg;
|
|
3251
|
+
}
|
|
3252
|
+
|
|
3253
|
+
.doc-content code {
|
|
3254
|
+
@apply font-mono text-sm bg-blue-500/10 text-blue-300 px-1.5 py-0.5 rounded border border-blue-500/20;
|
|
3255
|
+
}
|
|
3256
|
+
|
|
3257
|
+
.doc-content pre {
|
|
3258
|
+
@apply bg-[#0A0A0A] border border-white/10 rounded-xl p-5 overflow-x-auto mb-10 shadow-2xl;
|
|
3259
|
+
}
|
|
3260
|
+
|
|
3261
|
+
.doc-content pre code {
|
|
3262
|
+
@apply bg-transparent p-0 text-white/90 border-none text-sm leading-relaxed;
|
|
3263
|
+
}
|
|
3264
|
+
|
|
3265
|
+
/* Specific overrides for the "not-prose" areas if needed, though scoped css shouldn't leak usually.
|
|
3266
|
+
But since we use .doc-content class, we are safe. */
|
|
3267
|
+
</style>
|