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,212 +1,212 @@
1
- <template>
2
- <BaseSlide :data="data" :slide-index="slideIndex">
3
- <div class="flex-layout w-full h-screen flex flex-col overflow-y-auto lg:overflow-hidden"
4
- :style="containerStyle">
5
- <div :class="['flex-1 flex w-full min-h-full lg:h-full', directionClass]"
6
- :style="mainFlexStyle">
7
- <template v-for="(element, i) in data.elements" :key="i">
8
- <!-- Image Element -->
9
- <LuminaElement v-if="element.type === 'image'" :id="elemId(i)" :class="['flex-item', getSizeClass(element.size), element.class]" :style="{ ...getElementStyle(element), ...(element.style || {}) }">
10
- <FlexImage :src="element.src" :alt="element.alt"
11
- :fill="element.fill" :fit="element.fit" :position="element.position"
12
- :rounded="element.rounded" :href="element.href" :target="element.target"
13
- container-class="w-full h-full min-h-0" :container-style="{}" :style="element.style" />
14
- </LuminaElement>
15
-
16
- <!-- Video Element -->
17
- <LuminaElement v-else-if="element.type === 'video'" :id="elemId(i)"
18
- :class="['flex-item', getSizeClass(element.size), element.class]"
19
- :style="getElementStyle(element)">
20
- <VideoPlayer :class="getRoundedClass(element.rounded, element.fill)" :src="element.src"
21
- :poster="element.poster" :autoplay="element.autoplay ?? false" :loop="element.loop ?? false"
22
- :muted="element.muted ?? false" :controls="element.controls ?? true"
23
- :object-fit="element.fill !== false ? 'cover' : 'contain'" />
24
- </LuminaElement>
25
-
26
- <!-- HTML Element -->
27
- <LuminaElement v-else-if="element.type === 'html'" :id="elemId(i)" :class="['flex-item', getSizeClass(element.size), element.class]" :style="{ ...getElementStyle(element), ...(element.style || {}) }">
28
- <FlexHtml :html="element.html" :class="element.class" :style="element.style" />
29
- </LuminaElement>
30
-
31
- <!-- Content Container (supports nested content) -->
32
- <LuminaElement v-else-if="element.type === 'content'" :id="elemId(i)"
33
- :class="['flex-item flex h-full', element.direction === 'horizontal' ? 'flex-row' : 'flex-col', getSizeClass(element.size), element.class]"
34
- :style="getContentStyle(element)">
35
- <template v-for="(child, j) in element.elements" :key="j">
36
- <!-- Nested content containers (recursive) -->
37
- <LuminaElement v-if="child.type === 'content'" :id="childId(i, j)"
38
- :class="['flex', (child as FlexElementContent).direction === 'horizontal' ? 'flex-row' : 'flex-col']"
39
- :style="getNestedContentStyle(child as FlexElementContent)">
40
- <template v-for="(grandchild, k) in (child as FlexElementContent).elements" :key="k">
41
- <LuminaElement :id="resolveId(props.data, slideIndex.value, ['elements', i, 'elements', j, 'elements', k])">
42
- <!-- Recursively handle nested content -->
43
- <LuminaElement v-if="grandchild.type === 'content'"
44
- :class="['flex', (grandchild as FlexElementContent).direction === 'horizontal' ? 'flex-row' : 'flex-col']"
45
- :style="getNestedContentStyle(grandchild as FlexElementContent)">
46
- <template v-for="(greatGrandchild, l) in (grandchild as FlexElementContent).elements" :key="l">
47
- <LuminaElement :id="resolveId(props.data, slideIndex.value, ['elements', i, 'elements', j, 'elements', k, 'elements', l])">
48
- <component :is="getChildComponent(greatGrandchild.type)" v-bind="greatGrandchild" @action="handleAction" />
49
- </LuminaElement>
50
- </template>
51
- </LuminaElement>
52
- <!-- Regular grandchild elements -->
53
- <component v-else :is="getChildComponent(grandchild.type)" v-bind="grandchild" @action="handleAction" />
54
- </LuminaElement>
55
- </template>
56
- </LuminaElement>
57
- <!-- Regular child elements -->
58
- <LuminaElement v-else :id="childId(i, j)">
59
- <component :is="getChildComponent(child.type)" v-bind="child" @action="handleAction" />
60
- </LuminaElement>
61
- </template>
62
- </LuminaElement>
63
-
64
- <!-- Top-level elements (title, text, bullets, etc.) -->
65
- <LuminaElement v-else :id="elemId(i)" :class="['flex-item', getSizeClass(element.size)]"
66
- :style="{ ...getTopLevelStyle(), width: data.direction === 'vertical' ? '100%' : 'auto' }">
67
- <component :is="getChildComponent(element.type)" v-bind="element" @action="handleAction" />
68
- </LuminaElement>
69
- </template>
70
- </div>
71
- </div>
72
- </BaseSlide>
73
- </template>
74
-
75
- <script setup lang="ts">
76
- import { computed, inject } from 'vue';
77
- import BaseSlide from '../base/BaseSlide.vue';
78
- import VideoPlayer from '../base/VideoPlayer.vue';
79
- import { resolveId } from '../../core/elementResolver';
80
- import { StoreKey } from '../../core/store';
81
- import type { SlideFlex, FlexElement, FlexSize, FlexElementContent } from '../../core/types';
82
- import FlexImage from '../parts/FlexImage.vue';
83
- import FlexTitle from '../parts/FlexTitle.vue';
84
- import FlexText from '../parts/FlexText.vue';
85
- import FlexButton from '../parts/FlexButton.vue';
86
- import FlexBullets from '../parts/FlexBullets.vue';
87
- import FlexOrdered from '../parts/FlexOrdered.vue';
88
- import FlexTimeline from '../parts/FlexTimeline.vue';
89
- import FlexStepper from '../parts/FlexStepper.vue';
90
- import FlexSpacer from '../parts/FlexSpacer.vue';
91
- import FlexHtml from '../parts/FlexHtml.vue';
92
- import { bus } from '../../core/events';
93
- import {
94
- spacingVarMap,
95
- getSizeClass,
96
- getFlexItemStyle,
97
- getFlexContainerStyle,
98
- getTopLevelStyle,
99
- getFlexSlideMainStyle,
100
- getRoundedClass
101
- } from '../../composables/useFlexLayout';
102
-
103
- const props = defineProps<{
104
- data: SlideFlex;
105
- slideIndex?: number;
106
- }>();
107
-
108
- const emit = defineEmits(['action']);
109
- const store = inject(StoreKey);
110
- const slideIndex = computed(() => props.slideIndex ?? store?.state.currentIndex ?? 0);
111
- const elemId = (i: number) => resolveId(props.data, slideIndex.value, ['elements', i]);
112
- const childId = (i: number, j: number) => resolveId(props.data, slideIndex.value, ['elements', i, 'elements', j]);
113
-
114
- const containerStyle = computed(() => ({
115
- padding: spacingVarMap[props.data.padding || 'none'],
116
- }));
117
-
118
- const directionClass = computed(() =>
119
- props.data.direction === 'vertical' ? 'flex-col' : 'flex-col lg:flex-row'
120
- );
121
-
122
- const mainFlexStyle = computed(() => ({
123
- gap: spacingVarMap[props.data.gap || 'none'],
124
- ...getFlexSlideMainStyle(props.data.direction, props.data.halign, props.data.valign),
125
- }));
126
-
127
- // Wrapper for shared logic requiring vertical flag
128
- const getElementStyle = (element: FlexElement & { size?: FlexSize }) => {
129
- return getFlexItemStyle(element, props.data.direction === 'vertical');
130
- };
131
-
132
- const getContentStyle = (element: FlexElementContent & { size?: FlexSize }) => {
133
- const isVertical = props.data.direction === 'vertical';
134
- const contentDirection = element.direction || 'vertical';
135
- return {
136
- ...getFlexItemStyle(element, isVertical),
137
- ...getFlexContainerStyle(element),
138
- // Force full height/width for alignment space
139
- height: isVertical ? 'auto' : '100%',
140
- width: isVertical ? '100%' : 'auto',
141
- minHeight: isVertical ? 'auto' : (contentDirection === 'vertical' ? '100%' : 'auto'),
142
- ...(element.style || {})
143
- };
144
- };
145
-
146
- const getNestedContentStyle = (element: FlexElementContent) => {
147
- return {
148
- ...getFlexContainerStyle(element),
149
- width: '100%',
150
- ...(element.style || {})
151
- };
152
- };
153
-
154
- const handleAction = (payload: any) => {
155
- emit('action', payload);
156
- bus.emit('action', payload);
157
- };
158
-
159
- // ============================================================================
160
- // CHILD ELEMENT COMPONENTS - All using CSS variables
161
- // ============================================================================
162
-
163
-
164
- // Child components extracted to ../parts/
165
-
166
- const getChildComponent = (type: string) => {
167
- const components: Record<string, any> = {
168
- 'title': FlexTitle,
169
- 'text': FlexText,
170
- 'image': FlexImage,
171
- 'video': VideoPlayer,
172
- 'bullets': FlexBullets,
173
- 'ordered': FlexOrdered,
174
- 'button': FlexButton,
175
- 'timeline': FlexTimeline,
176
- 'stepper': FlexStepper,
177
- 'spacer': FlexSpacer,
178
- 'html': FlexHtml,
179
- };
180
- return components[type] || 'div';
181
- };
182
- </script>
183
-
184
- <style scoped>
185
- .flex-layout {
186
- min-height: 100vh;
187
- }
188
-
189
- @media (max-width: 1023px) {
190
- .flex-item {
191
- flex: 0 0 auto !important;
192
- width: 100% !important;
193
- max-width: 100% !important;
194
- max-height: none !important;
195
- min-height: auto !important;
196
- height: auto !important;
197
- }
198
-
199
- /* Images in stacked flex should have a reasonable height */
200
- .flex-item:has(img),
201
- .flex-item img {
202
- height: 40vh !important;
203
- min-height: 300px !important;
204
- }
205
-
206
- .flex-layout {
207
- overflow-y: auto !important;
208
- height: auto !important;
209
- min-height: 100vh;
210
- }
211
- }
212
- </style>
1
+ <template>
2
+ <BaseSlide :data="data" :slide-index="slideIndex">
3
+ <div class="flex-layout w-full h-screen flex flex-col overflow-y-auto lg:overflow-hidden"
4
+ :style="containerStyle">
5
+ <div :class="['flex-1 flex w-full min-h-full lg:h-full', directionClass]"
6
+ :style="mainFlexStyle">
7
+ <template v-for="(element, i) in data.elements" :key="i">
8
+ <!-- Image Element -->
9
+ <LuminaElement v-if="element.type === 'image'" :id="elemId(i)" :class="['flex-item', getSizeClass(element.size), element.class]" :style="{ ...getElementStyle(element), ...(element.style || {}) }">
10
+ <FlexImage :src="element.src" :alt="element.alt"
11
+ :fill="element.fill" :fit="element.fit" :position="element.position"
12
+ :rounded="element.rounded" :href="element.href" :target="element.target"
13
+ container-class="w-full h-full min-h-0" :container-style="{}" :style="element.style" />
14
+ </LuminaElement>
15
+
16
+ <!-- Video Element -->
17
+ <LuminaElement v-else-if="element.type === 'video'" :id="elemId(i)"
18
+ :class="['flex-item', getSizeClass(element.size), element.class]"
19
+ :style="getElementStyle(element)">
20
+ <VideoPlayer :class="getRoundedClass(element.rounded, element.fill)" :src="element.src"
21
+ :poster="element.poster" :autoplay="element.autoplay ?? false" :loop="element.loop ?? false"
22
+ :muted="element.muted ?? false" :controls="element.controls ?? true"
23
+ :object-fit="element.fill !== false ? 'cover' : 'contain'" />
24
+ </LuminaElement>
25
+
26
+ <!-- HTML Element -->
27
+ <LuminaElement v-else-if="element.type === 'html'" :id="elemId(i)" :class="['flex-item', getSizeClass(element.size), element.class]" :style="{ ...getElementStyle(element), ...(element.style || {}) }">
28
+ <FlexHtml :html="element.html" :class="element.class" :style="element.style" />
29
+ </LuminaElement>
30
+
31
+ <!-- Content Container (supports nested content) -->
32
+ <LuminaElement v-else-if="element.type === 'content'" :id="elemId(i)"
33
+ :class="['flex-item flex h-full', element.direction === 'horizontal' ? 'flex-row' : 'flex-col', getSizeClass(element.size), element.class]"
34
+ :style="getContentStyle(element)">
35
+ <template v-for="(child, j) in element.elements" :key="j">
36
+ <!-- Nested content containers (recursive) -->
37
+ <LuminaElement v-if="child.type === 'content'" :id="childId(i, j)"
38
+ :class="['flex', (child as FlexElementContent).direction === 'horizontal' ? 'flex-row' : 'flex-col']"
39
+ :style="getNestedContentStyle(child as FlexElementContent)">
40
+ <template v-for="(grandchild, k) in (child as FlexElementContent).elements" :key="k">
41
+ <LuminaElement :id="resolveId(props.data, slideIndex.value, ['elements', i, 'elements', j, 'elements', k])">
42
+ <!-- Recursively handle nested content -->
43
+ <LuminaElement v-if="grandchild.type === 'content'"
44
+ :class="['flex', (grandchild as FlexElementContent).direction === 'horizontal' ? 'flex-row' : 'flex-col']"
45
+ :style="getNestedContentStyle(grandchild as FlexElementContent)">
46
+ <template v-for="(greatGrandchild, l) in (grandchild as FlexElementContent).elements" :key="l">
47
+ <LuminaElement :id="resolveId(props.data, slideIndex.value, ['elements', i, 'elements', j, 'elements', k, 'elements', l])">
48
+ <component :is="getChildComponent(greatGrandchild.type)" v-bind="greatGrandchild" @action="handleAction" />
49
+ </LuminaElement>
50
+ </template>
51
+ </LuminaElement>
52
+ <!-- Regular grandchild elements -->
53
+ <component v-else :is="getChildComponent(grandchild.type)" v-bind="grandchild" @action="handleAction" />
54
+ </LuminaElement>
55
+ </template>
56
+ </LuminaElement>
57
+ <!-- Regular child elements -->
58
+ <LuminaElement v-else :id="childId(i, j)">
59
+ <component :is="getChildComponent(child.type)" v-bind="child" @action="handleAction" />
60
+ </LuminaElement>
61
+ </template>
62
+ </LuminaElement>
63
+
64
+ <!-- Top-level elements (title, text, bullets, etc.) -->
65
+ <LuminaElement v-else :id="elemId(i)" :class="['flex-item', getSizeClass(element.size)]"
66
+ :style="{ ...getTopLevelStyle(), width: data.direction === 'vertical' ? '100%' : 'auto' }">
67
+ <component :is="getChildComponent(element.type)" v-bind="element" @action="handleAction" />
68
+ </LuminaElement>
69
+ </template>
70
+ </div>
71
+ </div>
72
+ </BaseSlide>
73
+ </template>
74
+
75
+ <script setup lang="ts">
76
+ import { computed, inject } from 'vue';
77
+ import BaseSlide from '../base/BaseSlide.vue';
78
+ import VideoPlayer from '../base/VideoPlayer.vue';
79
+ import { resolveId } from '../../core/elementResolver';
80
+ import { StoreKey } from '../../core/store';
81
+ import type { SlideFlex, FlexElement, FlexSize, FlexElementContent } from '../../core/types';
82
+ import FlexImage from '../parts/FlexImage.vue';
83
+ import FlexTitle from '../parts/FlexTitle.vue';
84
+ import FlexText from '../parts/FlexText.vue';
85
+ import FlexButton from '../parts/FlexButton.vue';
86
+ import FlexBullets from '../parts/FlexBullets.vue';
87
+ import FlexOrdered from '../parts/FlexOrdered.vue';
88
+ import FlexTimeline from '../parts/FlexTimeline.vue';
89
+ import FlexStepper from '../parts/FlexStepper.vue';
90
+ import FlexSpacer from '../parts/FlexSpacer.vue';
91
+ import FlexHtml from '../parts/FlexHtml.vue';
92
+ import { bus } from '../../core/events';
93
+ import {
94
+ spacingVarMap,
95
+ getSizeClass,
96
+ getFlexItemStyle,
97
+ getFlexContainerStyle,
98
+ getTopLevelStyle,
99
+ getFlexSlideMainStyle,
100
+ getRoundedClass
101
+ } from '../../composables/useFlexLayout';
102
+
103
+ const props = defineProps<{
104
+ data: SlideFlex;
105
+ slideIndex?: number;
106
+ }>();
107
+
108
+ const emit = defineEmits(['action']);
109
+ const store = inject(StoreKey);
110
+ const slideIndex = computed(() => props.slideIndex ?? store?.state.currentIndex ?? 0);
111
+ const elemId = (i: number) => resolveId(props.data, slideIndex.value, ['elements', i]);
112
+ const childId = (i: number, j: number) => resolveId(props.data, slideIndex.value, ['elements', i, 'elements', j]);
113
+
114
+ const containerStyle = computed(() => ({
115
+ padding: spacingVarMap[props.data.padding || 'none'],
116
+ }));
117
+
118
+ const directionClass = computed(() =>
119
+ props.data.direction === 'vertical' ? 'flex-col' : 'flex-col lg:flex-row'
120
+ );
121
+
122
+ const mainFlexStyle = computed(() => ({
123
+ gap: spacingVarMap[props.data.gap || 'none'],
124
+ ...getFlexSlideMainStyle(props.data.direction, props.data.halign, props.data.valign),
125
+ }));
126
+
127
+ // Wrapper for shared logic requiring vertical flag
128
+ const getElementStyle = (element: FlexElement & { size?: FlexSize }) => {
129
+ return getFlexItemStyle(element, props.data.direction === 'vertical');
130
+ };
131
+
132
+ const getContentStyle = (element: FlexElementContent & { size?: FlexSize }) => {
133
+ const isVertical = props.data.direction === 'vertical';
134
+ const contentDirection = element.direction || 'vertical';
135
+ return {
136
+ ...getFlexItemStyle(element, isVertical),
137
+ ...getFlexContainerStyle(element),
138
+ // Force full height/width for alignment space
139
+ height: isVertical ? 'auto' : '100%',
140
+ width: isVertical ? '100%' : 'auto',
141
+ minHeight: isVertical ? 'auto' : (contentDirection === 'vertical' ? '100%' : 'auto'),
142
+ ...(element.style || {})
143
+ };
144
+ };
145
+
146
+ const getNestedContentStyle = (element: FlexElementContent) => {
147
+ return {
148
+ ...getFlexContainerStyle(element),
149
+ width: '100%',
150
+ ...(element.style || {})
151
+ };
152
+ };
153
+
154
+ const handleAction = (payload: any) => {
155
+ emit('action', payload);
156
+ bus.emit('action', payload);
157
+ };
158
+
159
+ // ============================================================================
160
+ // CHILD ELEMENT COMPONENTS - All using CSS variables
161
+ // ============================================================================
162
+
163
+
164
+ // Child components extracted to ../parts/
165
+
166
+ const getChildComponent = (type: string) => {
167
+ const components: Record<string, any> = {
168
+ 'title': FlexTitle,
169
+ 'text': FlexText,
170
+ 'image': FlexImage,
171
+ 'video': VideoPlayer,
172
+ 'bullets': FlexBullets,
173
+ 'ordered': FlexOrdered,
174
+ 'button': FlexButton,
175
+ 'timeline': FlexTimeline,
176
+ 'stepper': FlexStepper,
177
+ 'spacer': FlexSpacer,
178
+ 'html': FlexHtml,
179
+ };
180
+ return components[type] || 'div';
181
+ };
182
+ </script>
183
+
184
+ <style scoped>
185
+ .flex-layout {
186
+ min-height: 100vh;
187
+ }
188
+
189
+ @media (max-width: 1023px) {
190
+ .flex-item {
191
+ flex: 0 0 auto !important;
192
+ width: 100% !important;
193
+ max-width: 100% !important;
194
+ max-height: none !important;
195
+ min-height: auto !important;
196
+ height: auto !important;
197
+ }
198
+
199
+ /* Images in stacked flex should have a reasonable height */
200
+ .flex-item:has(img),
201
+ .flex-item img {
202
+ height: 40vh !important;
203
+ min-height: 300px !important;
204
+ }
205
+
206
+ .flex-layout {
207
+ overflow-y: auto !important;
208
+ height: auto !important;
209
+ min-height: 100vh;
210
+ }
211
+ }
212
+ </style>
@@ -3,9 +3,10 @@
3
3
  <div
4
4
  :class="['flex flex-col justify-center items-center text-center relative', data.sizing === 'container' ? 'h-full' : 'min-h-screen']"
5
5
  :style="{ paddingTop: 'var(--lumina-space-xl)', paddingLeft: 'var(--lumina-space-xl)', paddingRight: 'var(--lumina-space-xl)', paddingBottom: 'calc(var(--lumina-space-xl) + var(--lumina-safe-area-bottom))' }">
6
- <div :class="[data.class || '', 'max-w-5xl z-10']">
6
+ <div :class="[data.class || '', 'flex flex-col items-center max-w-5xl z-10']">
7
7
  <!-- Tag -->
8
- <LuminaElement v-if="data.tag" :id="tagId" tag="span" class="inline-block rounded-full font-medium uppercase" :style="{
8
+ <LuminaElement v-if="data.tag" :id="tagId" tag="span" class="rounded-full font-medium uppercase" :style="{
9
+ display: 'inline-block',
9
10
  color: 'var(--lumina-color-primary)',
10
11
  border: '1px solid var(--lumina-color-border)',
11
12
  backgroundColor: 'rgba(var(--lumina-color-text-rgb), 0.05)',
@@ -24,6 +25,7 @@
24
25
 
25
26
  <!-- Subtitle -->
26
27
  <LuminaElement v-if="data.subtitle" :id="subtitleId" tag="p" class="max-w-3xl mx-auto" :style="{
28
+ display: 'block',
27
29
  color: 'var(--lumina-color-text-safe, var(--lumina-color-text))',
28
30
  opacity: 0.8,
29
31
  fontWeight: 'normal',
@@ -57,6 +59,7 @@ const titleId = computed(() => resolveId(props.data, slideIndex.value, ['title']
57
59
  const subtitleId = computed(() => resolveId(props.data, slideIndex.value, ['subtitle']));
58
60
 
59
61
  const titleStyle = computed(() => ({
62
+ display: 'block',
60
63
  fontSize: props.data.sizing === 'container'
61
64
  ? 'var(--lumina-text-5xl)'
62
65
  : 'clamp(var(--lumina-text-4xl), 10vw, var(--lumina-text-7xl))',