lumina-slides 9.0.5 → 9.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/README.md +63 -0
  2. package/dist/lumina-slides.js +21750 -19334
  3. package/dist/lumina-slides.umd.cjs +223 -223
  4. package/dist/style.css +1 -1
  5. package/package.json +1 -1
  6. package/src/components/LandingPage.vue +1 -1
  7. package/src/components/LuminaDeck.vue +237 -232
  8. package/src/components/base/LuminaElement.vue +2 -0
  9. package/src/components/layouts/LayoutFeatures.vue +125 -123
  10. package/src/components/layouts/LayoutFlex.vue +212 -212
  11. package/src/components/layouts/LayoutStatement.vue +5 -2
  12. package/src/components/layouts/LayoutSteps.vue +110 -108
  13. package/src/components/parts/FlexHtml.vue +65 -65
  14. package/src/components/parts/FlexImage.vue +81 -81
  15. package/src/components/site/SiteDocs.vue +3313 -3314
  16. package/src/components/site/SiteExamples.vue +66 -66
  17. package/src/components/studio/EditorLayoutChart.vue +18 -0
  18. package/src/components/studio/EditorLayoutCustom.vue +18 -0
  19. package/src/components/studio/EditorLayoutVideo.vue +18 -0
  20. package/src/components/studio/LuminaStudioEmbed.vue +68 -0
  21. package/src/components/studio/StudioEmbedRoot.vue +19 -0
  22. package/src/components/studio/StudioInspector.vue +1113 -7
  23. package/src/components/studio/StudioJsonEditor.vue +10 -3
  24. package/src/components/studio/StudioSettings.vue +658 -7
  25. package/src/components/studio/StudioToolbar.vue +26 -7
  26. package/src/composables/useElementState.ts +12 -1
  27. package/src/composables/useFlexLayout.ts +128 -128
  28. package/src/core/Lumina.ts +174 -113
  29. package/src/core/animationConfig.ts +10 -0
  30. package/src/core/elementController.ts +18 -0
  31. package/src/core/elementResolver.ts +4 -2
  32. package/src/core/schema.ts +503 -503
  33. package/src/core/store.ts +465 -465
  34. package/src/core/types.ts +26 -11
  35. package/src/index.ts +2 -2
  36. package/src/utils/prepareDeckForExport.ts +47 -0
  37. package/src/utils/templateInterpolation.ts +52 -52
  38. package/src/views/DeckView.vue +313 -313
@@ -1,123 +1,125 @@
1
- <template>
2
- <BaseSlide :data="data" :slide-index="slideIndex">
3
- <div :class="[
4
- 'features-root w-full max-w-full flex flex-col justify-center overflow-x-hidden',
5
- data.sizing === 'container' ? 'min-h-full' : 'min-h-screen'
6
- ]">
7
- <!-- Header: wrapper (header) + title and description as separate controllable elements -->
8
- <LuminaElement :id="headerId" :class="[data.class || '', 'text-center lg:text-left max-w-6xl min-w-0']"
9
- :style="{ marginBottom: 'var(--lumina-space-2xl)' }">
10
- <LuminaElement :id="titleId" tag="h2" class="font-bold break-words" :style="{
11
- fontFamily: 'var(--lumina-font-heading)',
12
- fontSize: data.sizing === 'container' ? 'var(--lumina-text-3xl)' : 'var(--lumina-text-5xl)',
13
- marginBottom: 'var(--lumina-space-md)',
14
- letterSpacing: 'var(--lumina-tracking-tighter)',
15
- color: 'var(--lumina-color-text-safe, var(--lumina-color-text))',
16
- textShadow: '0 2px 10px rgba(0,0,0,0.1)'
17
- }">
18
- {{ data.title }}
19
- </LuminaElement>
20
- <LuminaElement v-if="data.description" :id="descriptionId" tag="p" class="break-words" :style="{
21
- color: 'var(--lumina-color-text-safe, var(--lumina-color-text))',
22
- opacity: 0.9,
23
- fontSize: data.sizing === 'container' ? 'var(--lumina-text-sm)' : 'var(--lumina-text-xl)'
24
- }">
25
- {{ data.description }}
26
- </LuminaElement>
27
- </LuminaElement>
28
-
29
- <!-- Grid -->
30
- <div :class="['features-grid', data.sizing !== 'container' ? 'features-grid--multi' : '']">
31
- <LuminaElement v-for="(feature, i) in data.features" :key="i" :id="featureId(i)"
32
- :class="['glass-panel group min-w-0', feature.class || '']" :style="{
33
- borderRadius: 'var(--lumina-card-radius)',
34
- padding: data.sizing === 'container' ? 'var(--lumina-space-lg)' : 'var(--lumina-card-padding)',
35
- borderTop: '1px solid var(--lumina-color-border-subtle)',
36
- transition: 'all var(--lumina-transition-duration) var(--lumina-transition-easing)'
37
- }">
38
- <!-- Icon -->
39
- <div class="flex items-center justify-center group-hover:scale-110 shrink-0" :style="{
40
- color: 'white',
41
- background: 'linear-gradient(135deg, var(--lumina-color-primary) 0%, var(--lumina-color-secondary) 100%)',
42
- width: data.sizing === 'container' ? 'var(--lumina-space-xl)' : 'var(--lumina-space-2xl)',
43
- height: data.sizing === 'container' ? 'var(--lumina-space-xl)' : 'var(--lumina-space-2xl)',
44
- borderRadius: 'var(--lumina-radius-xl)',
45
- marginBottom: data.sizing === 'container' ? 'var(--lumina-space-md)' : 'var(--lumina-space-lg)',
46
- fontSize: 'var(--lumina-text-xl)',
47
- boxShadow: '0 4px 12px rgba(var(--lumina-color-primary-rgb), 0.3)',
48
- transition: 'all var(--lumina-transition-duration) var(--lumina-transition-easing)'
49
- }">
50
- <i
51
- :class="['ph-thin', (feature.icon || 'star').startsWith('ph-') ? feature.icon : `ph-${feature.icon || 'star'}`]"></i>
52
- </div>
53
- <!-- Title -->
54
- <h3 class="font-bold break-words" :style="{
55
- color: 'var(--lumina-surface-text, var(--lumina-color-text))',
56
- fontSize: data.sizing === 'container' ? 'var(--lumina-text-lg)' : 'var(--lumina-text-2xl)',
57
- marginBottom: 'var(--lumina-space-sm)'
58
- }">
59
- {{ feature.title }}
60
- </h3>
61
- <!-- Description (support both desc and description) -->
62
- <p class="break-words" :style="{
63
- color: 'var(--lumina-color-text-secondary)',
64
- fontSize: data.sizing === 'container' ? 'var(--lumina-text-sm)' : 'var(--lumina-text-base)',
65
- lineHeight: 'var(--lumina-leading-relaxed)',
66
- opacity: 0.8
67
- }">
68
- {{ feature.desc || feature.description || '' }}
69
- </p>
70
- </LuminaElement>
71
- </div>
72
- </div>
73
- </BaseSlide>
74
- </template>
75
-
76
- <script setup lang="ts">
77
- import { computed, inject } from 'vue';
78
- import BaseSlide from '../base/BaseSlide.vue';
79
- import { resolveId } from '../../core/elementResolver';
80
- import { StoreKey } from '../../core/store';
81
- import type { SlideFeatures } from '../../core/types';
82
-
83
- const props = defineProps<{
84
- data: SlideFeatures;
85
- slideIndex?: number;
86
- }>();
87
-
88
- const store = inject(StoreKey);
89
- const slideIndex = computed(() => props.slideIndex ?? store?.state.currentIndex ?? 0);
90
-
91
- const headerId = computed(() => resolveId(props.data, slideIndex.value, ['header']));
92
- const titleId = computed(() => resolveId(props.data, slideIndex.value, ['title']));
93
- const descriptionId = computed(() => resolveId(props.data, slideIndex.value, ['description']));
94
- const featureId = (i: number) => resolveId(props.data, slideIndex.value, ['features', i]);
95
- </script>
96
-
97
- <style scoped>
98
- .features-root {
99
- padding: var(--lumina-space-xl) var(--lumina-space-3xl);
100
- }
101
- @media (max-width: 1023px) {
102
- .features-root { padding-left: var(--lumina-space-xl); padding-right: var(--lumina-space-xl); }
103
- }
104
- @media (max-width: 639px) {
105
- .features-root { padding: var(--lumina-space-lg) var(--lumina-space-md); }
106
- }
107
-
108
- .features-grid {
109
- display: grid;
110
- grid-template-columns: 1fr;
111
- gap: var(--lumina-space-md);
112
- }
113
- .features-grid--multi {
114
- grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
115
- gap: var(--lumina-space-lg);
116
- }
117
- @media (max-width: 639px) {
118
- .features-grid--multi {
119
- grid-template-columns: 1fr;
120
- gap: var(--lumina-space-md);
121
- }
122
- }
123
- </style>
1
+ <template>
2
+ <BaseSlide :data="data" :slide-index="slideIndex">
3
+ <div :class="[
4
+ 'features-root w-full max-w-full flex flex-col justify-center overflow-x-hidden',
5
+ data.sizing === 'container' ? 'min-h-full' : 'min-h-screen'
6
+ ]">
7
+ <!-- Header: wrapper (header) + title and description as separate controllable elements -->
8
+ <LuminaElement :id="headerId" :class="[data.class || '', 'flex flex-col text-center lg:text-left max-w-6xl min-w-0']"
9
+ :style="{ marginBottom: 'var(--lumina-space-2xl)' }">
10
+ <LuminaElement :id="titleId" tag="h2" class="font-bold break-words" :style="{
11
+ display: 'block',
12
+ fontFamily: 'var(--lumina-font-heading)',
13
+ fontSize: data.sizing === 'container' ? 'var(--lumina-text-3xl)' : 'var(--lumina-text-5xl)',
14
+ marginBottom: 'var(--lumina-space-md)',
15
+ letterSpacing: 'var(--lumina-tracking-tighter)',
16
+ color: 'var(--lumina-color-text-safe, var(--lumina-color-text))',
17
+ textShadow: '0 2px 10px rgba(0,0,0,0.1)'
18
+ }">
19
+ {{ data.title }}
20
+ </LuminaElement>
21
+ <LuminaElement v-if="data.description" :id="descriptionId" tag="p" class="break-words" :style="{
22
+ display: 'block',
23
+ color: 'var(--lumina-color-text-safe, var(--lumina-color-text))',
24
+ opacity: 0.9,
25
+ fontSize: data.sizing === 'container' ? 'var(--lumina-text-sm)' : 'var(--lumina-text-xl)'
26
+ }">
27
+ {{ data.description }}
28
+ </LuminaElement>
29
+ </LuminaElement>
30
+
31
+ <!-- Grid -->
32
+ <div :class="['features-grid', data.sizing !== 'container' ? 'features-grid--multi' : '']">
33
+ <LuminaElement v-for="(feature, i) in data.features" :key="i" :id="featureId(i)"
34
+ :class="['glass-panel group min-w-0', feature.class || '']" :style="{
35
+ borderRadius: 'var(--lumina-card-radius)',
36
+ padding: data.sizing === 'container' ? 'var(--lumina-space-lg)' : 'var(--lumina-card-padding)',
37
+ borderTop: '1px solid var(--lumina-color-border-subtle)',
38
+ transition: 'all var(--lumina-transition-duration) var(--lumina-transition-easing)'
39
+ }">
40
+ <!-- Icon -->
41
+ <div class="flex items-center justify-center group-hover:scale-110 shrink-0" :style="{
42
+ color: 'white',
43
+ background: 'linear-gradient(135deg, var(--lumina-color-primary) 0%, var(--lumina-color-secondary) 100%)',
44
+ width: data.sizing === 'container' ? 'var(--lumina-space-xl)' : 'var(--lumina-space-2xl)',
45
+ height: data.sizing === 'container' ? 'var(--lumina-space-xl)' : 'var(--lumina-space-2xl)',
46
+ borderRadius: 'var(--lumina-radius-xl)',
47
+ marginBottom: data.sizing === 'container' ? 'var(--lumina-space-md)' : 'var(--lumina-space-lg)',
48
+ fontSize: 'var(--lumina-text-xl)',
49
+ boxShadow: '0 4px 12px rgba(var(--lumina-color-primary-rgb), 0.3)',
50
+ transition: 'all var(--lumina-transition-duration) var(--lumina-transition-easing)'
51
+ }">
52
+ <i
53
+ :class="['ph-thin', (feature.icon || 'star').startsWith('ph-') ? feature.icon : `ph-${feature.icon || 'star'}`]"></i>
54
+ </div>
55
+ <!-- Title -->
56
+ <h3 class="font-bold break-words" :style="{
57
+ color: 'var(--lumina-surface-text, var(--lumina-color-text))',
58
+ fontSize: data.sizing === 'container' ? 'var(--lumina-text-lg)' : 'var(--lumina-text-2xl)',
59
+ marginBottom: 'var(--lumina-space-sm)'
60
+ }">
61
+ {{ feature.title }}
62
+ </h3>
63
+ <!-- Description (support both desc and description) -->
64
+ <p class="break-words" :style="{
65
+ color: 'var(--lumina-color-text-secondary)',
66
+ fontSize: data.sizing === 'container' ? 'var(--lumina-text-sm)' : 'var(--lumina-text-base)',
67
+ lineHeight: 'var(--lumina-leading-relaxed)',
68
+ opacity: 0.8
69
+ }">
70
+ {{ feature.desc || feature.description || '' }}
71
+ </p>
72
+ </LuminaElement>
73
+ </div>
74
+ </div>
75
+ </BaseSlide>
76
+ </template>
77
+
78
+ <script setup lang="ts">
79
+ import { computed, inject } from 'vue';
80
+ import BaseSlide from '../base/BaseSlide.vue';
81
+ import { resolveId } from '../../core/elementResolver';
82
+ import { StoreKey } from '../../core/store';
83
+ import type { SlideFeatures } from '../../core/types';
84
+
85
+ const props = defineProps<{
86
+ data: SlideFeatures;
87
+ slideIndex?: number;
88
+ }>();
89
+
90
+ const store = inject(StoreKey);
91
+ const slideIndex = computed(() => props.slideIndex ?? store?.state.currentIndex ?? 0);
92
+
93
+ const headerId = computed(() => resolveId(props.data, slideIndex.value, ['header']));
94
+ const titleId = computed(() => resolveId(props.data, slideIndex.value, ['title']));
95
+ const descriptionId = computed(() => resolveId(props.data, slideIndex.value, ['description']));
96
+ const featureId = (i: number) => resolveId(props.data, slideIndex.value, ['features', i]);
97
+ </script>
98
+
99
+ <style scoped>
100
+ .features-root {
101
+ padding: var(--lumina-space-xl) var(--lumina-space-3xl);
102
+ }
103
+ @media (max-width: 1023px) {
104
+ .features-root { padding-left: var(--lumina-space-xl); padding-right: var(--lumina-space-xl); }
105
+ }
106
+ @media (max-width: 639px) {
107
+ .features-root { padding: var(--lumina-space-lg) var(--lumina-space-md); }
108
+ }
109
+
110
+ .features-grid {
111
+ display: grid;
112
+ grid-template-columns: 1fr;
113
+ gap: var(--lumina-space-md);
114
+ }
115
+ .features-grid--multi {
116
+ grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
117
+ gap: var(--lumina-space-lg);
118
+ }
119
+ @media (max-width: 639px) {
120
+ .features-grid--multi {
121
+ grid-template-columns: 1fr;
122
+ gap: var(--lumina-space-md);
123
+ }
124
+ }
125
+ </style>