@sp-days-framework/slidev-theme-sykehuspartner 1.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.
@@ -0,0 +1,315 @@
1
+ <template>
2
+ <div class="slidev-layout intro">
3
+ <!-- Standard layout when no image is provided -->
4
+ <div v-if="!hasImage" class="content-wrapper-no-image">
5
+ <div class="text-content-full">
6
+ <div v-if="showBanner" class="banner-container">
7
+ <div class="banner-image banner"></div>
8
+ </div>
9
+ <div class="content-container">
10
+ <slot />
11
+ </div>
12
+ </div>
13
+ </div>
14
+
15
+ <!-- Split layout with image -->
16
+ <div v-else class="content-wrapper" :class="layoutClass">
17
+ <!-- Text content section -->
18
+ <div class="text-content" :style="textContentStyle">
19
+ <div v-if="showBanner" class="banner-container">
20
+ <div class="banner-image banner"></div>
21
+ </div>
22
+ <div class="content-container">
23
+ <slot />
24
+ </div>
25
+ </div>
26
+
27
+ <!-- Image content section -->
28
+ <div class="image-content" :style="imageContentStyle">
29
+ <div class="image-container" :class="imageAlignClass">
30
+ <img
31
+ :src="getImageUrl(props.imageSrc)"
32
+ :style="imageStyle"
33
+ alt="Slide Image"
34
+ >
35
+ </div>
36
+ </div>
37
+ </div>
38
+ </div>
39
+ </template>
40
+
41
+ <script setup>
42
+ import { computed } from 'vue'
43
+ import { getImageUrl } from '../utils/layoutHelper'
44
+
45
+ const props = defineProps({
46
+ bannerEnabled: {
47
+ type: Boolean,
48
+ default: true
49
+ },
50
+ // Image options
51
+ imageSrc: String,
52
+ imageSize: {
53
+ type: String,
54
+ default: '100%'
55
+ },
56
+ imagePosition: {
57
+ type: String,
58
+ default: 'right',
59
+ validator: (value) => ['left', 'right'].includes(value)
60
+ },
61
+ imageRatio: {
62
+ type: String,
63
+ default: '33%'
64
+ },
65
+ // Logo/banner option
66
+ enableLogo: {
67
+ type: Boolean,
68
+ default: true
69
+ }
70
+ })
71
+
72
+ // Check if image is provided in frontmatter or props
73
+ const hasImage = computed(() => {
74
+ // First check frontmatter (for backward compatibility)
75
+ if ($slidev?.configs?.frontmatter?.imageSrc) {
76
+ props.imageSrc = $slidev.configs.frontmatter.imageSrc
77
+ return true
78
+ }
79
+ // Then check props
80
+ return Boolean(props.imageSrc)
81
+ })
82
+
83
+ // Determine if banner should be shown
84
+ const showBanner = computed(() => {
85
+ // First check frontmatter (for backward compatibility)
86
+ if ($slidev?.configs?.frontmatter?.enableLogo !== undefined) {
87
+ return $slidev.configs.frontmatter.enableLogo
88
+ }
89
+ // Then check props
90
+ return props.enableLogo !== undefined ? props.enableLogo : props.bannerEnabled
91
+ })
92
+
93
+ // Calculate layout class based on image position
94
+ const layoutClass = computed(() => {
95
+ // First check frontmatter (for backward compatibility)
96
+ const position = $slidev?.configs?.frontmatter?.imagePosition || props.imagePosition
97
+ return position === 'right' ? 'image-right' : 'image-left'
98
+ })
99
+
100
+ // Calculate image alignment class based on image position
101
+ const imageAlignClass = computed(() => {
102
+ // First check frontmatter (for backward compatibility)
103
+ const position = $slidev?.configs?.frontmatter?.imagePosition || props.imagePosition
104
+ return position === 'right' ? 'align-left' : 'align-right'
105
+ })
106
+
107
+ // Parse image ratio from frontmatter or props
108
+ const imageRatio = computed(() => {
109
+ // First check frontmatter (for backward compatibility)
110
+ const ratio = $slidev?.configs?.frontmatter?.imageRatio || props.imageRatio || '33%'
111
+ // Remove % sign and parse as number
112
+ return parseFloat(ratio.toString().replace('%', ''))
113
+ })
114
+
115
+ // Calculate text content width style
116
+ const textContentStyle = computed(() => {
117
+ const textWidth = 100 - imageRatio.value
118
+ return {
119
+ width: `${textWidth}%`,
120
+ }
121
+ })
122
+
123
+ // Calculate image content width style
124
+ const imageContentStyle = computed(() => {
125
+ return {
126
+ width: `${imageRatio.value}%`,
127
+ }
128
+ })
129
+
130
+ // Calculate image size and scaling
131
+ const imageSize = computed(() => {
132
+ return $slidev?.configs?.frontmatter?.imageSize || props.imageSize || '100%'
133
+ })
134
+
135
+ // Calculate image style
136
+ const imageStyle = computed(() => {
137
+ const size = imageSize.value
138
+ const style = {
139
+ maxWidth: '100%',
140
+ maxHeight: '100%',
141
+ objectFit: 'contain',
142
+ }
143
+
144
+ if (size) {
145
+ if (size.toString().endsWith('%')) {
146
+ const sizeValue = parseFloat(size.toString().replace('%', '')) / 100
147
+ style.maxWidth = `${sizeValue * 100}%`
148
+ style.maxHeight = `${sizeValue * 100}%`
149
+ } else if (!isNaN(Number(size))) {
150
+ style.maxWidth = `${parseFloat(size) * 100}%`
151
+ style.maxHeight = `${parseFloat(size) * 100}%`
152
+ }
153
+ }
154
+
155
+ return style
156
+ })
157
+
158
+ // Using onMounted to handle font sizing after DOM is ready
159
+ import { onMounted, nextTick } from 'vue'
160
+
161
+ // Dynamic font sizing logic
162
+ onMounted(async () => {
163
+ // Wait for content to be rendered
164
+ await nextTick()
165
+
166
+ // Find the h1 element
167
+ const h1 = document.querySelector('.slidev-layout.intro h1')
168
+ if (!h1) return
169
+
170
+ const textLength = h1.textContent?.length || 0
171
+
172
+ // Apply font sizing based on text length
173
+ if (textLength > 30) {
174
+ h1.style.fontSize = '2.5rem'
175
+ } else if (textLength > 20) {
176
+ h1.style.fontSize = '3rem'
177
+ } else {
178
+ h1.style.fontSize = '3.5rem'
179
+ }
180
+ })
181
+ </script>
182
+
183
+ <style scoped>
184
+ .intro {
185
+ height: 100%;
186
+ width: 100%;
187
+ padding: 0;
188
+ display: flex;
189
+ align-items: center;
190
+ justify-content: center;
191
+ overflow: hidden;
192
+ }
193
+
194
+ /* Layout when no image */
195
+ .content-wrapper-no-image {
196
+ display: flex;
197
+ width: 100%;
198
+ height: 100%;
199
+ overflow: hidden;
200
+ }
201
+
202
+ .text-content-full {
203
+ flex: 1;
204
+ position: relative;
205
+ display: flex;
206
+ flex-direction: column;
207
+ justify-content: center;
208
+ padding: 0 2rem;
209
+ min-width: 0;
210
+ }
211
+
212
+ /* Split layout with image */
213
+ .content-wrapper {
214
+ display: flex;
215
+ width: 100%;
216
+ height: 100%;
217
+ align-items: center;
218
+ overflow: hidden;
219
+ }
220
+
221
+ .image-left {
222
+ flex-direction: row-reverse; /* Image on left, text on right */
223
+ }
224
+
225
+ .image-right {
226
+ flex-direction: row; /* Text on left, image on right */
227
+ }
228
+
229
+ /* Text content styling */
230
+ .text-content {
231
+ height: 100%;
232
+ position: relative;
233
+ display: flex;
234
+ flex-direction: column;
235
+ justify-content: center;
236
+ padding: 2rem;
237
+ overflow: hidden;
238
+ text-align: left;
239
+ }
240
+
241
+ /* Image content styling */
242
+ .image-content {
243
+ height: 100%;
244
+ display: flex;
245
+ align-items: center;
246
+ justify-content: center;
247
+ padding: 1rem;
248
+ overflow: hidden;
249
+ }
250
+
251
+ .image-container {
252
+ display: flex;
253
+ height: 100%;
254
+ align-items: center;
255
+ max-width: 100%;
256
+ }
257
+
258
+ .align-left {
259
+ justify-content: flex-start;
260
+ }
261
+
262
+ .align-right {
263
+ justify-content: flex-end;
264
+ }
265
+
266
+ /* Banner styles */
267
+ .banner-container {
268
+ width: 100%;
269
+ margin-bottom: 0.5rem;
270
+ display: flex; /* Using flexbox for better control */
271
+ justify-content: flex-start; /* Always align content to the left for intro */
272
+ margin-left: -0rem;
273
+ max-width: 200px;
274
+ height: 3rem;
275
+ }
276
+
277
+ .banner {
278
+ width: 100%;
279
+ height: 100%;
280
+ }
281
+
282
+ /* Banner styling handled by global CSS */
283
+
284
+ .content-container {
285
+ position: relative;
286
+ z-index: 5;
287
+ }
288
+
289
+ /* Typography adjustments for headers */
290
+ :deep(h1) {
291
+ color: inherit;
292
+ font-size: 4rem; /* Default size that will be overridden by JS */
293
+ line-height: 1.25;
294
+ margin-top: 0;
295
+ word-wrap: break-word;
296
+ overflow-wrap: break-word;
297
+ hyphens: auto;
298
+ max-width: 100%;
299
+ transition: font-size 0.3s ease;
300
+ }
301
+
302
+ :deep(h1)::after {
303
+ content: '';
304
+ display: block;
305
+ width: 20%;
306
+ margin-top: 0.5rem;
307
+ margin-bottom: 1.5rem;
308
+ height: 4px;
309
+ background-color: var(--sp-primary);
310
+ }
311
+
312
+ :deep(h2) {
313
+ color: var(--sp-primary-darkest);
314
+ }
315
+ </style>
@@ -0,0 +1,72 @@
1
+ <template>
2
+ <div class="slidev-layout quote">
3
+ <div v-if="showLogo" class="logo-container">
4
+ <div class="logo-image logo"></div>
5
+ </div>
6
+ <div class="my-auto quote-container">
7
+ <slot />
8
+ </div>
9
+ </div>
10
+ </template>
11
+
12
+ <script setup>
13
+ import { computed } from 'vue'
14
+
15
+ const props = defineProps({
16
+ logo: {
17
+ type: Boolean,
18
+ default: false
19
+ }
20
+ })
21
+
22
+ const showLogo = computed(() => {
23
+ if ($slidev?.configs?.frontmatter?.logo !== undefined) {
24
+ return $slidev.configs.frontmatter.logo
25
+ }
26
+ return props.logo
27
+ })
28
+ </script>
29
+
30
+ <style scoped>
31
+ .quote {
32
+ height: 100%;
33
+ display: flex;
34
+ align-items: center;
35
+ justify-content: center;
36
+ }
37
+
38
+ .quote-container {
39
+ max-width: 80%;
40
+ }
41
+
42
+ :deep(h1) {
43
+ font-size: 2rem;
44
+ color: inherit;
45
+ text-align: center;
46
+ margin-bottom: 2rem;
47
+ }
48
+
49
+ :deep(h2) {
50
+ color: var(--sp-primary);
51
+ font-weight: 600;
52
+ text-align: right;
53
+ max-width: 100%;
54
+ margin-top: 0.5rem;
55
+ }
56
+
57
+ :deep(h3) {
58
+ color: var(--sp-primary-lightest);
59
+ text-align: right;
60
+ max-width: 100%;
61
+ margin-top: 0.25rem;
62
+ }
63
+
64
+ .logo-container {
65
+ position: absolute;
66
+ top: 1rem;
67
+ right: 1rem;
68
+ z-index: 10;
69
+ }
70
+
71
+ /* Logo styling moved to global layout.css */
72
+ </style>
@@ -0,0 +1,140 @@
1
+ <template>
2
+ <div class="slidev-layout section">
3
+ <div v-if="showLogo" class="logo-container">
4
+ <div class="logo-image logo"></div>
5
+ </div>
6
+ <div class="content-wrapper">
7
+ <div class="text-content">
8
+ <div class="content-container" :class="{ 'with-title-line': showTitleLine }">
9
+ <slot />
10
+ </div>
11
+ </div>
12
+ <div v-if="hasImage" class="image-content">
13
+ <img :src="imageUrl" alt="Slide Image">
14
+ </div>
15
+ </div>
16
+ </div>
17
+ </template>
18
+
19
+ <script setup>
20
+ import { computed } from 'vue'
21
+ import { getImageUrl } from '../utils/layoutHelper'
22
+
23
+ const props = defineProps({
24
+ logo: {
25
+ type: Boolean,
26
+ default: true
27
+ }
28
+ })
29
+
30
+ const hasImage = computed(() => {
31
+ return Boolean($slidev?.configs?.frontmatter?.image)
32
+ })
33
+
34
+ const imageUrl = computed(() => {
35
+ const image = $slidev?.configs?.frontmatter?.image
36
+ if (!image) return ''
37
+ return getImageUrl(image)
38
+ })
39
+
40
+ const showLogo = computed(() => {
41
+ if ($slidev?.configs?.frontmatter?.logo !== undefined) {
42
+ return $slidev.configs.frontmatter.logo
43
+ }
44
+ return props.logo
45
+ })
46
+
47
+ const showTitleLine = computed(() => {
48
+ if ($slidev?.configs?.frontmatter?.titleLine !== undefined) {
49
+ return $slidev.configs.frontmatter.titleLine
50
+ }
51
+ return true // Default to showing the line if not specified
52
+ })
53
+ </script>
54
+
55
+ <style scoped>
56
+ .section {
57
+ height: 100%;
58
+ display: flex;
59
+ align-items: center;
60
+ }
61
+
62
+ .content-wrapper {
63
+ display: flex;
64
+ width: 100%;
65
+ height: 100%;
66
+ overflow: hidden; /* Ensure no overflow */
67
+ }
68
+
69
+ .text-content {
70
+ flex: 1;
71
+ position: relative;
72
+ display: flex;
73
+ flex-direction: column;
74
+ justify-content: center;
75
+ align-items: center;
76
+ text-align: center;
77
+ padding: 0 2rem;
78
+ min-width: 0; /* Ensure flexbox can shrink if needed */
79
+ }
80
+
81
+ .content-container {
82
+ position: relative;
83
+ z-index: 5;
84
+ }
85
+
86
+ .image-content {
87
+ flex: 1;
88
+ display: flex;
89
+ align-items: center;
90
+ justify-content: center;
91
+ padding: 1rem;
92
+ max-width: 50%; /* Limit to half the width */
93
+ }
94
+
95
+ .image-content img {
96
+ max-width: 100%;
97
+ max-height: 100%;
98
+ object-fit: contain;
99
+ border-radius: 4px; /* Optional: slightly round the corners */
100
+ box-shadow: 0 4px 8px rgba(0,0,0,0.1); /* Optional: add a subtle shadow */
101
+ }
102
+
103
+
104
+ :deep(h1) {
105
+ color: inherit;
106
+ font-size: 2.75rem;
107
+ line-height: 3rem;
108
+ margin-top: 0;
109
+ }
110
+
111
+
112
+ :deep(h1) {
113
+ position: relative;
114
+ display: inline-block;
115
+ }
116
+
117
+ :deep(.with-title-line h1)::after {
118
+ content: '';
119
+ position: absolute;
120
+ left: 0;
121
+ bottom: -2rem;
122
+ width: 4rem;
123
+ height: 3px;
124
+ margin-bottom: 1.5rem;
125
+ background-color: var(--sp-primary);
126
+ }
127
+
128
+ :deep(h2) {
129
+ color: var(--sp-primary);
130
+ }
131
+
132
+ .logo-container {
133
+ position: absolute;
134
+ top: 1rem;
135
+ right: 1rem;
136
+ z-index: 10;
137
+ }
138
+
139
+ /* Logo styling moved to global layout.css */
140
+ </style>
@@ -0,0 +1,60 @@
1
+ <template>
2
+ <div class="slidev-layout statement">
3
+ <div v-if="showLogo" class="logo-container">
4
+ <div class="logo-image logo"></div>
5
+ </div>
6
+ <div class="content">
7
+ <slot />
8
+ </div>
9
+ </div>
10
+ </template>
11
+
12
+ <script setup>
13
+ import { computed } from 'vue'
14
+
15
+ const props = defineProps({
16
+ logo: {
17
+ type: Boolean,
18
+ default: true
19
+ }
20
+ })
21
+
22
+ const showLogo = computed(() => {
23
+ if ($slidev?.configs?.frontmatter?.logo !== undefined) {
24
+ return $slidev.configs.frontmatter.logo
25
+ }
26
+ return props.logo
27
+ })
28
+ </script>
29
+
30
+ <style scoped>
31
+ .statement {
32
+ height: 100%;
33
+ display: flex;
34
+ flex-direction: column;
35
+ justify-content: center;
36
+ align-items: center;
37
+ text-align: center;
38
+ }
39
+
40
+ .content {
41
+ max-width: 80%;
42
+ }
43
+
44
+ .statement h1 {
45
+ font-size: 3rem;
46
+ }
47
+
48
+ .statement h2 {
49
+ font-size: 2rem;
50
+ }
51
+
52
+ .logo-container {
53
+ position: absolute;
54
+ top: 1rem;
55
+ right: 1rem;
56
+ z-index: 10;
57
+ }
58
+
59
+ /* Logo styling moved to global layout.css */
60
+ </style>
@@ -0,0 +1,103 @@
1
+ <template>
2
+ <div class="slidev-layout three-cols-header">
3
+ <div v-if="showLogo" class="logo-container">
4
+ <div class="logo-image logo"></div>
5
+ </div>
6
+ <div class="header">
7
+ <slot />
8
+ </div>
9
+ <div class="cols-container">
10
+ <div class="col left">
11
+ <slot name="left" />
12
+ </div>
13
+ <div class="col middle">
14
+ <slot name="middle" />
15
+ </div>
16
+ <div class="col right">
17
+ <slot name="right" />
18
+ </div>
19
+ </div>
20
+ </div>
21
+ </template>
22
+
23
+ <script setup>
24
+ import { computed } from 'vue'
25
+
26
+ const props = defineProps({
27
+ logo: {
28
+ type: Boolean,
29
+ default: true
30
+ },
31
+ textAlignment: {
32
+ type: String,
33
+ default: 'center',
34
+ validator: (value) => ['top', 'center', 'bottom'].includes(value)
35
+ }
36
+ })
37
+
38
+ const showLogo = computed(() => {
39
+ if ($slidev?.configs?.frontmatter?.logo !== undefined) {
40
+ return $slidev.configs.frontmatter.logo
41
+ }
42
+ return props.logo
43
+ })
44
+
45
+ // Compute content alignment style based on textAlignment prop
46
+ const contentAlignmentStyle = computed(() => {
47
+ switch (props.textAlignment) {
48
+ case 'top':
49
+ return 'flex-start'
50
+ case 'bottom':
51
+ return 'flex-end'
52
+ case 'center':
53
+ default:
54
+ return 'center'
55
+ }
56
+ })
57
+ </script>
58
+
59
+ <style scoped>
60
+ .three-cols-header {
61
+ display: flex;
62
+ flex-direction: column;
63
+ }
64
+
65
+ .header {
66
+ margin-bottom: 1rem;
67
+ }
68
+
69
+ .cols-container {
70
+ display: flex;
71
+ flex-grow: 1;
72
+ column-gap: 2rem;
73
+ }
74
+
75
+ .col {
76
+ display: flex;
77
+ flex-direction: column;
78
+ width: 33.33%;
79
+ justify-content: v-bind(contentAlignmentStyle);
80
+ }
81
+
82
+ .left {
83
+ padding-right: 0.5rem;
84
+ }
85
+
86
+ .middle {
87
+ padding-left: 0.5rem;
88
+ padding-right: 0.5rem;
89
+ }
90
+
91
+ .right {
92
+ padding-left: 0.5rem;
93
+ }
94
+
95
+ .logo-container {
96
+ position: absolute;
97
+ top: 1rem;
98
+ right: 1rem;
99
+ z-index: 10;
100
+ }
101
+
102
+ /* Logo styling moved to global layout.css */
103
+ </style>