lumina-slides 9.0.4 → 9.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lumina-slides.js +21984 -19455
- package/dist/lumina-slides.umd.cjs +223 -223
- package/dist/style.css +1 -1
- package/package.json +3 -1
- package/src/components/LandingPage.vue +1 -1
- package/src/components/LuminaDeck.vue +237 -232
- package/src/components/base/LuminaElement.vue +2 -0
- package/src/components/layouts/LayoutFeatures.vue +123 -123
- package/src/components/layouts/LayoutFlex.vue +212 -172
- package/src/components/layouts/LayoutStatement.vue +5 -2
- package/src/components/layouts/LayoutSteps.vue +108 -108
- package/src/components/parts/FlexHtml.vue +65 -0
- package/src/components/parts/FlexImage.vue +81 -54
- package/src/components/site/SiteDocs.vue +3313 -3182
- package/src/components/site/SiteExamples.vue +66 -66
- package/src/components/studio/EditorLayoutChart.vue +18 -0
- package/src/components/studio/EditorLayoutCustom.vue +18 -0
- package/src/components/studio/EditorLayoutVideo.vue +18 -0
- package/src/components/studio/LuminaStudioEmbed.vue +68 -0
- package/src/components/studio/StudioEmbedRoot.vue +19 -0
- package/src/components/studio/StudioInspector.vue +1113 -7
- package/src/components/studio/StudioSettings.vue +658 -7
- package/src/components/studio/StudioToolbar.vue +20 -2
- package/src/composables/useElementState.ts +12 -1
- package/src/composables/useFlexLayout.ts +128 -122
- package/src/core/Lumina.ts +174 -113
- package/src/core/animationConfig.ts +10 -0
- package/src/core/elementController.ts +18 -0
- package/src/core/elementResolver.ts +4 -2
- package/src/core/schema.ts +503 -478
- package/src/core/store.ts +465 -465
- package/src/core/types.ts +59 -14
- package/src/index.ts +2 -2
- package/src/utils/templateInterpolation.ts +52 -52
- package/src/views/DeckView.vue +313 -313
|
@@ -1,66 +1,66 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div class="min-h-screen pt-32 px-8 max-w-7xl mx-auto pb-24">
|
|
3
|
-
<!-- Unified Header -->
|
|
4
|
-
<div class="text-center mb-16 max-w-3xl mx-auto">
|
|
5
|
-
<h1 class="text-4xl md:text-5xl font-black mb-4 tracking-tight text-white">Interactive Examples</h1>
|
|
6
|
-
<p class="text-lg text-white/50 leading-relaxed">Collection of templates and semantic layouts built with the
|
|
7
|
-
Lumina Engine.</p>
|
|
8
|
-
</div>
|
|
9
|
-
|
|
10
|
-
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
|
11
|
-
<div v-for="deck in decks" :key="deck.id"
|
|
12
|
-
class="group relative rounded-2xl overflow-hidden border border-white/10 bg-white/5 hover:border-blue-500/50 transition duration-500 cursor-pointer block"
|
|
13
|
-
@click="router.push({ name: 'deck', params: { id: deck.id } })">
|
|
14
|
-
<div
|
|
15
|
-
class="aspect-video bg-gradient-to-br from-gray-800 to-black group-hover:scale-105 transition duration-700 flex items-center justify-center">
|
|
16
|
-
<span class="text-4xl">{{ deck.icon }}</span>
|
|
17
|
-
</div>
|
|
18
|
-
<div class="p-6 relative z-10 bg-black/80 backdrop-blur-sm -mt-2">
|
|
19
|
-
<h3 class="text-xl font-bold mb-2">{{ deck.title }}</h3>
|
|
20
|
-
<p class="text-sm text-white/60 mb-4 h-10">{{ deck.description }}</p>
|
|
21
|
-
<div
|
|
22
|
-
class="flex items-center text-blue-400 text-sm font-bold uppercase tracking-wider group-hover:translate-x-2 transition">
|
|
23
|
-
View Demo <span class="ml-2">→</span>
|
|
24
|
-
</div>
|
|
25
|
-
</div>
|
|
26
|
-
</div>
|
|
27
|
-
</div>
|
|
28
|
-
</div>
|
|
29
|
-
</template>
|
|
30
|
-
|
|
31
|
-
<script setup lang="ts">
|
|
32
|
-
import { useRouter } from 'vue-router';
|
|
33
|
-
|
|
34
|
-
const router = useRouter();
|
|
35
|
-
|
|
36
|
-
const decks = [
|
|
37
|
-
{ id: 'deck', title: 'Feature Showcase', description: 'A comprehensive tour of all major features.', icon: '🚀' },
|
|
38
|
-
{ id: 'layout-element-control', title: 'Element Control', description: '
|
|
39
|
-
{ id: 'layout-template-tags', title: 'Template Tags', description: '{{key}} placeholders in slide content, resolved from engine.data. Updates reactively.', icon: '🏷️' },
|
|
40
|
-
{ id: 'animation-presets', title: 'Animation: Presets', description: 'Built-in presets: fadeUp, scaleIn, spring. Use with
|
|
41
|
-
{ id: 'animation-stagger', title: 'Animation: Stagger', description: 'Stagger modes: center-out, wave, random.
|
|
42
|
-
{ id: 'animation-timeline', title: 'Animation: Timeline', description: 'Remotion-style: scrub 0–1, keyframes per element, seekTo and playTimeline.', icon: '⏯️' },
|
|
43
|
-
{ id: 'layout-statement', title: 'Statement Layout', description: 'Bold typography
|
|
44
|
-
{ id: 'layout-half', title: 'Split Layout', description: 'Classic text and image pairing.', icon: '🌗' },
|
|
45
|
-
{ id: 'layout-features', title: 'Feature Grid', description: 'Responsive grids for feature lists.', icon: '🍱' },
|
|
46
|
-
{ id: 'layout-timeline', title: 'Timeline', description: 'Vertical chronological sequence.', icon: '⏱️' },
|
|
47
|
-
{ id: 'layout-steps', title: 'Process Steps', description: 'Horizontal sequential flow.', icon: '👣' },
|
|
48
|
-
{ id: 'layout-flex-demo', title: 'Flex Layout', description: 'Flow-based composition for LLMs.', icon: '🧬' },
|
|
49
|
-
{ id: 'layout-video', title: 'Video & Media', description: 'Cinematic backgrounds and video elements.', icon: '🎬' },
|
|
50
|
-
{ id: 'layout-chart', title: 'Chart Layout', description: 'Data visualization with Chart.js.', icon: '📊' },
|
|
51
|
-
{ id: 'layout-custom', title: 'Custom HTML', description: 'Full control with raw HTML/CSS.', icon: '🎨' },
|
|
52
|
-
{ id: 'layout-embedded', title: 'Embedded Widget', description: 'Container-sized, perfect for embedding.', icon: '🧩' },
|
|
53
|
-
{ id: 'theme-default', title: 'Theme: Default', description: 'Clean blue on dark. Professional.', icon: '💎' },
|
|
54
|
-
{ id: 'theme-ocean', title: 'Theme: Ocean', description: 'Cyan on slate. Calm and professional.', icon: '🌊' },
|
|
55
|
-
{ id: 'theme-midnight', title: 'Theme: Midnight', description: 'Indigo on black. Bold and dramatic.', icon: '🌙' },
|
|
56
|
-
{ id: 'theme-forest', title: 'Theme: Forest', description: 'Emerald greens for eco-friendly vibes.', icon: '🌲' },
|
|
57
|
-
{ id: 'theme-cyber', title: 'Theme: Cyber', description: 'Neon pink futuristic with sci-fi fonts.', icon: '🤖' },
|
|
58
|
-
{ id: 'theme-latte', title: 'Theme: Latte', description: 'Light mode with warm amber accents.', icon: '☕' },
|
|
59
|
-
{ id: 'theme-sunset', title: 'Theme: Sunset', description: 'Orange to rose gradient warmth.', icon: '🌅' },
|
|
60
|
-
{ id: 'theme-monochrome', title: 'Theme: Monochrome', description: 'Pure black and white elegance.', icon: '⚫' },
|
|
61
|
-
{ id: 'theme-custom-example', title: 'Custom Theme', description: 'Full ThemeConfig with 80+ options.', icon: '🔧' },
|
|
62
|
-
];
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
defineEmits(['select-deck']);
|
|
66
|
-
</script>
|
|
1
|
+
<template>
|
|
2
|
+
<div class="min-h-screen pt-32 px-8 max-w-7xl mx-auto pb-24">
|
|
3
|
+
<!-- Unified Header -->
|
|
4
|
+
<div class="text-center mb-16 max-w-3xl mx-auto">
|
|
5
|
+
<h1 class="text-4xl md:text-5xl font-black mb-4 tracking-tight text-white">Interactive Examples</h1>
|
|
6
|
+
<p class="text-lg text-white/50 leading-relaxed">Collection of templates and semantic layouts built with the
|
|
7
|
+
Lumina Engine.</p>
|
|
8
|
+
</div>
|
|
9
|
+
|
|
10
|
+
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
|
11
|
+
<div v-for="deck in decks" :key="deck.id"
|
|
12
|
+
class="group relative rounded-2xl overflow-hidden border border-white/10 bg-white/5 hover:border-blue-500/50 transition duration-500 cursor-pointer block"
|
|
13
|
+
@click="router.push({ name: 'deck', params: { id: deck.id } })">
|
|
14
|
+
<div
|
|
15
|
+
class="aspect-video bg-gradient-to-br from-gray-800 to-black group-hover:scale-105 transition duration-700 flex items-center justify-center">
|
|
16
|
+
<span class="text-4xl">{{ deck.icon }}</span>
|
|
17
|
+
</div>
|
|
18
|
+
<div class="p-6 relative z-10 bg-black/80 backdrop-blur-sm -mt-2">
|
|
19
|
+
<h3 class="text-xl font-bold mb-2">{{ deck.title }}</h3>
|
|
20
|
+
<p class="text-sm text-white/60 mb-4 h-10">{{ deck.description }}</p>
|
|
21
|
+
<div
|
|
22
|
+
class="flex items-center text-blue-400 text-sm font-bold uppercase tracking-wider group-hover:translate-x-2 transition">
|
|
23
|
+
View Demo <span class="ml-2">→</span>
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
26
|
+
</div>
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
</template>
|
|
30
|
+
|
|
31
|
+
<script setup lang="ts">
|
|
32
|
+
import { useRouter } from 'vue-router';
|
|
33
|
+
|
|
34
|
+
const router = useRouter();
|
|
35
|
+
|
|
36
|
+
const decks = [
|
|
37
|
+
{ id: 'deck', title: 'Feature Showcase', description: 'A comprehensive tour of all major features. Elements cascade-reveal by default on every slide enter.', icon: '🚀' },
|
|
38
|
+
{ id: 'layout-element-control', title: 'Element Control', description: 'Default cascade on enter. Override with elementControl.defaultVisible, slide.reveal, or meta.initialElementState.', icon: '🎭' },
|
|
39
|
+
{ id: 'layout-template-tags', title: 'Template Tags', description: '{{key}} placeholders in slide content, resolved from engine.data. Updates reactively.', icon: '🏷️' },
|
|
40
|
+
{ id: 'animation-presets', title: 'Animation: Presets', description: 'Built-in presets: fadeUp, scaleIn, spring. Use with slide.reveal or element().animate().', icon: '✨' },
|
|
41
|
+
{ id: 'animation-stagger', title: 'Animation: Stagger', description: 'Stagger modes: center-out, wave, random. Configure via slide.reveal or meta.reveal.', icon: '〰️' },
|
|
42
|
+
{ id: 'animation-timeline', title: 'Animation: Timeline', description: 'Remotion-style: scrub 0–1, keyframes per element, seekTo and playTimeline. Opts out of cascade.', icon: '⏯️' },
|
|
43
|
+
{ id: 'layout-statement', title: 'Statement Layout', description: 'Bold typography. Elements cascade-reveal on enter; reset and replay when returning.', icon: '📢' },
|
|
44
|
+
{ id: 'layout-half', title: 'Split Layout', description: 'Classic text and image pairing. Cascade on enter.', icon: '🌗' },
|
|
45
|
+
{ id: 'layout-features', title: 'Feature Grid', description: 'Responsive grids for feature lists. Cascade on enter.', icon: '🍱' },
|
|
46
|
+
{ id: 'layout-timeline', title: 'Timeline', description: 'Vertical chronological sequence with cascade on enter.', icon: '⏱️' },
|
|
47
|
+
{ id: 'layout-steps', title: 'Process Steps', description: 'Horizontal sequential flow with cascade on enter.', icon: '👣' },
|
|
48
|
+
{ id: 'layout-flex-demo', title: 'Flex Layout', description: 'Flow-based composition for LLMs. Cascade on enter.', icon: '🧬' },
|
|
49
|
+
{ id: 'layout-video', title: 'Video & Media', description: 'Cinematic backgrounds and video elements.', icon: '🎬' },
|
|
50
|
+
{ id: 'layout-chart', title: 'Chart Layout', description: 'Data visualization with Chart.js.', icon: '📊' },
|
|
51
|
+
{ id: 'layout-custom', title: 'Custom HTML', description: 'Full control with raw HTML/CSS.', icon: '🎨' },
|
|
52
|
+
{ id: 'layout-embedded', title: 'Embedded Widget', description: 'Container-sized, perfect for embedding.', icon: '🧩' },
|
|
53
|
+
{ id: 'theme-default', title: 'Theme: Default', description: 'Clean blue on dark. Professional.', icon: '💎' },
|
|
54
|
+
{ id: 'theme-ocean', title: 'Theme: Ocean', description: 'Cyan on slate. Calm and professional.', icon: '🌊' },
|
|
55
|
+
{ id: 'theme-midnight', title: 'Theme: Midnight', description: 'Indigo on black. Bold and dramatic.', icon: '🌙' },
|
|
56
|
+
{ id: 'theme-forest', title: 'Theme: Forest', description: 'Emerald greens for eco-friendly vibes.', icon: '🌲' },
|
|
57
|
+
{ id: 'theme-cyber', title: 'Theme: Cyber', description: 'Neon pink futuristic with sci-fi fonts.', icon: '🤖' },
|
|
58
|
+
{ id: 'theme-latte', title: 'Theme: Latte', description: 'Light mode with warm amber accents.', icon: '☕' },
|
|
59
|
+
{ id: 'theme-sunset', title: 'Theme: Sunset', description: 'Orange to rose gradient warmth.', icon: '🌅' },
|
|
60
|
+
{ id: 'theme-monochrome', title: 'Theme: Monochrome', description: 'Pure black and white elegance.', icon: '⚫' },
|
|
61
|
+
{ id: 'theme-custom-example', title: 'Custom Theme', description: 'Full ThemeConfig with 80+ options.', icon: '🔧' },
|
|
62
|
+
];
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
defineEmits(['select-deck']);
|
|
66
|
+
</script>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="w-full h-full">
|
|
3
|
+
<EditorNode :path="`slides.${slideIndex}`" :label="data.type" class="w-full h-full">
|
|
4
|
+
<LayoutChart :data="data" />
|
|
5
|
+
</EditorNode>
|
|
6
|
+
</div>
|
|
7
|
+
</template>
|
|
8
|
+
|
|
9
|
+
<script setup lang="ts">
|
|
10
|
+
import type { SlideChart } from '../../core/types';
|
|
11
|
+
import EditorNode from './EditorNode.vue';
|
|
12
|
+
import LayoutChart from '../layouts/LayoutChart.vue';
|
|
13
|
+
|
|
14
|
+
defineProps<{
|
|
15
|
+
data: SlideChart;
|
|
16
|
+
slideIndex: number;
|
|
17
|
+
}>();
|
|
18
|
+
</script>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="w-full h-full">
|
|
3
|
+
<EditorNode :path="`slides.${slideIndex}`" :label="data.type" class="w-full h-full">
|
|
4
|
+
<LayoutCustom :data="data" />
|
|
5
|
+
</EditorNode>
|
|
6
|
+
</div>
|
|
7
|
+
</template>
|
|
8
|
+
|
|
9
|
+
<script setup lang="ts">
|
|
10
|
+
import type { SlideCustom } from '../../core/types';
|
|
11
|
+
import EditorNode from './EditorNode.vue';
|
|
12
|
+
import LayoutCustom from '../layouts/LayoutCustom.vue';
|
|
13
|
+
|
|
14
|
+
defineProps<{
|
|
15
|
+
data: SlideCustom;
|
|
16
|
+
slideIndex: number;
|
|
17
|
+
}>();
|
|
18
|
+
</script>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="w-full h-full">
|
|
3
|
+
<EditorNode :path="`slides.${slideIndex}`" :label="data.type" class="w-full h-full">
|
|
4
|
+
<LayoutVideo :data="data" />
|
|
5
|
+
</EditorNode>
|
|
6
|
+
</div>
|
|
7
|
+
</template>
|
|
8
|
+
|
|
9
|
+
<script setup lang="ts">
|
|
10
|
+
import type { SlideVideo } from '../../core/types';
|
|
11
|
+
import EditorNode from './EditorNode.vue';
|
|
12
|
+
import LayoutVideo from '../layouts/LayoutVideo.vue';
|
|
13
|
+
|
|
14
|
+
defineProps<{
|
|
15
|
+
data: SlideVideo;
|
|
16
|
+
slideIndex: number;
|
|
17
|
+
}>();
|
|
18
|
+
</script>
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="flex flex-col w-full h-screen bg-black text-white font-sans overflow-hidden">
|
|
3
|
+
<StudioToolbar :embed-mode="true" @save="onSave" />
|
|
4
|
+
<div class="flex flex-1 overflow-hidden relative">
|
|
5
|
+
<StudioSidebar />
|
|
6
|
+
<EditorCanvas />
|
|
7
|
+
<div class="w-72 bg-[#111] border-l border-[#333] flex flex-col">
|
|
8
|
+
<StudioInspector />
|
|
9
|
+
</div>
|
|
10
|
+
<SlideNavigator />
|
|
11
|
+
</div>
|
|
12
|
+
</div>
|
|
13
|
+
</template>
|
|
14
|
+
|
|
15
|
+
<script setup lang="ts">
|
|
16
|
+
import { provide, watch, onMounted } from 'vue';
|
|
17
|
+
import { createStore, StoreKey } from '../../core/store';
|
|
18
|
+
import { createEditor, EditorKey } from '../../composables/useEditor';
|
|
19
|
+
import type { Deck } from '../../core/types';
|
|
20
|
+
import StudioToolbar from './StudioToolbar.vue';
|
|
21
|
+
import StudioSidebar from './StudioSidebar.vue';
|
|
22
|
+
import StudioInspector from './StudioInspector.vue';
|
|
23
|
+
import EditorCanvas from './EditorCanvas.vue';
|
|
24
|
+
import SlideNavigator from './SlideNavigator.vue';
|
|
25
|
+
|
|
26
|
+
const DEFAULT_DECK: Deck = {
|
|
27
|
+
meta: { title: 'Untitled' },
|
|
28
|
+
slides: [{ type: 'statement', title: 'New Slide', subtitle: '' }]
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const props = withDefaults(
|
|
32
|
+
defineProps<{ deck?: Deck | null }>(),
|
|
33
|
+
{ deck: undefined }
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
const emit = defineEmits<{ save: [deck: Deck] }>();
|
|
37
|
+
|
|
38
|
+
const store = createStore({ studio: true });
|
|
39
|
+
provide(StoreKey, store);
|
|
40
|
+
|
|
41
|
+
const editor = createEditor(store);
|
|
42
|
+
provide(EditorKey, editor);
|
|
43
|
+
|
|
44
|
+
function loadInitial() {
|
|
45
|
+
const payload = props.deck ?? DEFAULT_DECK;
|
|
46
|
+
if (payload && Array.isArray((payload as Deck).slides)) {
|
|
47
|
+
store.loadDeck(payload as Deck);
|
|
48
|
+
} else {
|
|
49
|
+
store.loadDeck(DEFAULT_DECK);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
onMounted(loadInitial);
|
|
54
|
+
|
|
55
|
+
watch(
|
|
56
|
+
() => props.deck,
|
|
57
|
+
(newDeck) => {
|
|
58
|
+
if (newDeck && Array.isArray(newDeck.slides)) {
|
|
59
|
+
store.loadDeck(newDeck);
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
{ deep: true }
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
function onSave(deck: Deck) {
|
|
66
|
+
emit('save', deck);
|
|
67
|
+
}
|
|
68
|
+
</script>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<LuminaStudioEmbed :deck="deckRef" @save="onSave" />
|
|
3
|
+
</template>
|
|
4
|
+
|
|
5
|
+
<script setup lang="ts">
|
|
6
|
+
import type { Ref } from 'vue';
|
|
7
|
+
import { bus } from '../../core/events';
|
|
8
|
+
import type { Deck } from '../../core/types';
|
|
9
|
+
import LuminaStudioEmbed from './LuminaStudioEmbed.vue';
|
|
10
|
+
|
|
11
|
+
defineProps<{
|
|
12
|
+
/** Ref to the current deck; engine.load() updates this. */
|
|
13
|
+
deckRef: Ref<Deck | null> | Deck | null;
|
|
14
|
+
}>();
|
|
15
|
+
|
|
16
|
+
function onSave(deck: Deck) {
|
|
17
|
+
bus.emit('save', deck);
|
|
18
|
+
}
|
|
19
|
+
</script>
|