slidev-theme-tud-db 0.0.2 → 0.0.4

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,48 @@
1
+ <script setup lang="ts">
2
+ import { computed } from 'vue'
3
+
4
+ // F1-style callout: a coloured left rule + a small uppercase eyebrow label, no
5
+ // fill, no symbol, upright (non-italic) body text. Knobs:
6
+ // label the eyebrow text ("Key Takeaway", "Question", "Problem"…); label=""
7
+ // hides it and leaves a bare ruled aside.
8
+ // color the rule + label colour: a brand keyword (below) or any CSS colour,
9
+ // so e.g. problems read red while takeaways stay blue.
10
+ // size optional overall scale — body text matches the slide's default text
11
+ // size by default; set e.g. size="1.1em" (or a bare number "1.1") to
12
+ // enlarge the whole callout. All spacing is em-based, so it stays
13
+ // vertically balanced at any size.
14
+ // Authoring (MDC block, needs `mdc: true`):
15
+ // ::takeaway{label="Problem" color="red"}
16
+ // A question can hide the fact that nothing was proven.
17
+ // ::
18
+ const props = defineProps({
19
+ label: { type: String, default: 'Key Takeaway' },
20
+ color: { type: String, default: 'blue' },
21
+ size: { type: String, default: '' },
22
+ })
23
+
24
+ // Brand-colour keywords -> theme tokens; anything else is used as a raw CSS colour.
25
+ const TOKENS: Record<string, string> = {
26
+ blue: 'var(--db-heading-blue)',
27
+ navy: 'var(--db-navy)',
28
+ teal: 'var(--db-accent3)',
29
+ green: 'var(--db-accent1)',
30
+ yellow: 'var(--db-accent4)',
31
+ red: 'var(--db-accent5)',
32
+ orange: 'var(--db-accent5)',
33
+ purple: 'var(--db-accent6)',
34
+ }
35
+ const accent = computed(() => TOKENS[props.color?.toLowerCase()] ?? props.color)
36
+
37
+ // A bare number ("1.1") is treated as an em multiplier; otherwise used verbatim.
38
+ const fontSize = computed(() =>
39
+ !props.size ? undefined : /^[\d.]+$/.test(props.size) ? `${props.size}em` : props.size,
40
+ )
41
+ </script>
42
+
43
+ <template>
44
+ <div class="db-takeaway" :style="{ '--tk-accent': accent, fontSize }">
45
+ <div v-if="label" class="db-takeaway__label">{{ label }}</div>
46
+ <div class="db-takeaway__body"><slot /></div>
47
+ </div>
48
+ </template>
package/global-bottom.vue CHANGED
@@ -1,23 +1,45 @@
1
1
  <script setup lang="ts">
2
2
  import { useSlideContext } from '@slidev/client'
3
3
  import { computed } from 'vue'
4
+ import { slideLogos } from './scripts/logo'
4
5
 
5
6
  import ddrgColor from './assets/ddrg-color.svg'
7
+ import ddrgWhite from './assets/ddrg-white.svg'
8
+ import tudWhite from './assets/tud-white.svg'
6
9
  import tudBlack from './assets/tud-black.svg'
7
10
 
8
11
  const { $nav } = useSlideContext()
9
- const showChrome = computed(() => $nav.value?.currentLayout !== 'cover' && $nav.value?.currentLayout !== 'section-num')
12
+ const logos = computed(() => slideLogos[$nav.value.currentPage] ?? {})
10
13
  </script>
11
14
 
12
15
  <template>
13
- <div
14
- :class="{ 'opacity-0': !showChrome }"
15
- class="db-global-chrome absolute inset-0 z-100 pointer-events-none transition-opacity duration-500"
16
- >
17
- <img class="absolute top-[25px] right-[35px] h-[45px]" :src="ddrgColor" alt="Dresden Database Research Group" />
16
+ <div class="absolute inset-0 z-100 pointer-events-none">
17
+ <div class="absolute flex flex-row-reverse items-start gap-[45px] top-[25px] right-[35px]">
18
+ <div class="relative h-[45px]">
19
+ <img
20
+ :class="{ 'opacity-0': logos.ddrg !== 'color' }"
21
+ class="h-full transition-opacity duration-500"
22
+ :src="ddrgColor"
23
+ alt="Dresden Database Research Group"
24
+ />
25
+ <img
26
+ :class="{ 'opacity-0': logos.ddrg !== 'white' }"
27
+ class="absolute inset-0 h-full transition-opacity duration-500"
28
+ :src="ddrgWhite"
29
+ alt="Dresden Database Research Group"
30
+ />
31
+ </div>
32
+ <img
33
+ :class="{ 'opacity-0': !logos.tud }"
34
+ class="h-[45px] transition-opacity duration-500"
35
+ :src="tudWhite"
36
+ alt="TU Dresden"
37
+ />
38
+ </div>
18
39
 
19
40
  <footer
20
- class="db-footer absolute inset-x-0 bottom-0 h-[40px] px-[30px] flex items-center justify-between bg-[var(--db-footer-bg)] pointer-events-auto"
41
+ :class="{ 'opacity-0': !logos.footer }"
42
+ class="db-footer absolute inset-x-0 bottom-0 h-[40px] px-[30px] flex items-center justify-between bg-[var(--db-footer-bg)] pointer-events-auto transition-opacity duration-500"
21
43
  >
22
44
  <img class="h-[25px]" :src="tudBlack" alt="TU Dresden" />
23
45
  <span class="text-[12px] text-[var(--db-text)]">
package/layouts/cover.vue CHANGED
@@ -1,32 +1,15 @@
1
1
  <script setup lang="ts">
2
- // "Titelfolie" — navy band (top, with the DDRG mosaic + both logos) + white
3
- // title area below. Reconstructed as pure vector: the navy is a CSS fill, the
4
- // corner mosaic is `cover-mosaic.svg` (rebuilt from the original DB_template.potx
5
- // title-slide tiles), and the logos are the theme's own white SVGs. No raster.
6
- // Geometry (positions/sizes in pt == px on the 720-wide canvas) is taken from
7
- // slideLayout1.xml ("Titelfolie") so it matches the source template.
2
+ import { useLogo } from '../scripts/logo'
8
3
  import mosaic from '../assets/mosaic.svg'
9
- import tudWhite from '../assets/tud-white.svg'
10
- import ddrgWhite from '../assets/ddrg-white.svg'
4
+
5
+ useLogo({ ddrg: 'white', tud: true })
11
6
  </script>
12
7
 
13
8
  <template>
14
9
  <div class="slidev-layout db-cover p-0">
15
- <!-- navy band: solid fill + vector mosaic + logos, all overlaid -->
10
+ <!-- navy band: solid fill + vector mosaic, logos handled by global-bottom -->
16
11
  <div class="relative w-full h-[345px] bg-[var(--db-navy)] overflow-hidden">
17
12
  <img class="absolute h-full scale-[1.01]" :src="mosaic" alt="" />
18
- <div class="absolute flex gap-[45px] top-[25px] right-[35px]">
19
- <img
20
- class="h-[45px]"
21
- :src="tudWhite"
22
- alt="TU Dresden"
23
- />
24
- <img
25
- class="h-[45px]"
26
- :src="ddrgWhite"
27
- alt="Dresden Database Research Group"
28
- />
29
- </div>
30
13
  </div>
31
14
 
32
15
  <!-- white area: title (#) + subtitle (following text) -->
@@ -1,9 +1,13 @@
1
1
  <script setup lang="ts">
2
+ import { useLogo } from '../scripts/logo'
3
+
2
4
  // "Titel und Inhalt": title + single content column. Chrome via DbFrame.
3
5
  // `codeSize` frontmatter (optional) overrides the code font size for the slide.
4
6
  const props = defineProps({
5
7
  codeSize: { type: String, default: '' },
6
8
  })
9
+
10
+ useLogo({ ddrg: 'color', footer: true })
7
11
  </script>
8
12
 
9
13
  <template>
@@ -2,9 +2,9 @@
2
2
  import { useSlideContext } from '@slidev/client'
3
3
  import { computed } from 'vue'
4
4
 
5
- import mosaic from '../assets/section-mosaic.svg'
6
- import tudWhite from '../assets/tud-white.svg'
7
- import ddrgWhite from '../assets/ddrg-white.svg'
5
+ import { useLogo } from '../scripts/logo'
6
+
7
+ useLogo({ ddrg: 'white', tud: true })
8
8
 
9
9
  // The large glyph in the blue area can be overridden per slide via the `num`
10
10
  // frontmatter, e.g.
@@ -49,18 +49,6 @@ const num = computed(() => {
49
49
  v-if="num !== ''"
50
50
  class="absolute font-700 text-[24rem]/[24rem] pt-8 px-4 bg-white bg-clip-text text-transparent"
51
51
  >{{ num }}</div>
52
- <div class="absolute flex gap-[45px] top-[25px] right-[35px]">
53
- <img
54
- class="h-[45px]"
55
- :src="tudWhite"
56
- alt="TU Dresden"
57
- />
58
- <img
59
- class="h-[45px]"
60
- :src="ddrgWhite"
61
- alt="Dresden Database Research Group"
62
- />
63
- </div>
64
52
  </div>
65
53
 
66
54
  <!-- white area: title (#) + subtitle (following text) -->
@@ -1,18 +1,13 @@
1
1
  <script setup lang="ts">
2
- // "Titelfolie" — navy band (top, with the DDRG mosaic + both logos) + white
3
- // title area below. Reconstructed as pure vector: the navy is a CSS fill, the
4
- // corner mosaic is `cover-mosaic.svg` (rebuilt from the original DB_template.potx
5
- // title-slide tiles), and the logos are the theme's own white SVGs. No raster.
6
- // Geometry (positions/sizes in pt == px on the 720-wide canvas) is taken from
7
- // slideLayout1.xml ("Titelfolie") so it matches the source template.
2
+ import { useLogo } from '../scripts/logo'
8
3
  import mosaic from '../assets/section-mosaic.svg'
9
- import tudWhite from '../assets/tud-white.svg'
10
- import ddrgWhite from '../assets/ddrg-white.svg'
4
+
5
+ useLogo({ ddrg: 'color', footer: true })
11
6
  </script>
12
7
 
13
8
  <template>
14
9
  <div class="slidev-layout db-cover p-0">
15
- <!-- navy band: solid fill + vector mosaic + logos, all overlaid -->
10
+ <!-- blue band: solid fill + vector mosaic -->
16
11
  <div class="relative w-full mt-[95px] h-[250px] bg-[#97c6ff] overflow-hidden">
17
12
  <img class="absolute h-full scale-[1.01]" :src="mosaic" alt="" />
18
13
  </div>
@@ -1,4 +1,6 @@
1
1
  <script setup lang="ts">
2
+ import { useLogo } from '../scripts/logo'
3
+
2
4
  // Like two-cols-header, but the two columns are laid out as a ROW GRID: every
3
5
  // top-level <div> in the `::grid::` slot becomes a cell, filling left, right,
4
6
  // left, right… Because CSS grid rows align across columns, paired items (e.g. a
@@ -19,6 +21,8 @@ const props = defineProps({
19
21
  columns: { type: String, default: '1fr 1fr' },
20
22
  codeSize: { type: String, default: '' },
21
23
  })
24
+
25
+ useLogo({ ddrg: 'color', footer: true })
22
26
  </script>
23
27
 
24
28
  <template>
@@ -1,4 +1,6 @@
1
1
  <script setup lang="ts">
2
+ import { useLogo } from '../scripts/logo'
3
+
2
4
  // "Zwei Inhalte": full-width title (default slot) + two columns. Chrome via DbFrame.
3
5
  // Column ratio is configurable per slide via the `columns` frontmatter, e.g.
4
6
  // layout: two-cols-header
@@ -7,6 +9,8 @@ const props = defineProps({
7
9
  columns: { type: String, default: '1fr 1fr' },
8
10
  codeSize: { type: String, default: '' },
9
11
  })
12
+
13
+ useLogo({ ddrg: 'color', footer: true })
10
14
  </script>
11
15
 
12
16
  <template>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "slidev-theme-tud-db",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "type": "module",
5
5
  "description": "Slidev theme cloning the TU Dresden / Dresden Database Research Group PowerPoint template",
6
6
  "license": "GPL-3.0-or-later",
@@ -24,6 +24,7 @@
24
24
  "components",
25
25
  "global-bottom.vue",
26
26
  "layouts",
27
+ "scripts",
27
28
  "markdown.ts",
28
29
  "setup",
29
30
  "styles",
@@ -0,0 +1,29 @@
1
+ import { reactive, toValue, watchEffect } from 'vue'
2
+ import type { MaybeRefOrGetter } from 'vue'
3
+ import { useSlideContext } from '@slidev/client'
4
+
5
+ function createRegistry<T>() {
6
+ const store = reactive<Record<number, T>>({})
7
+
8
+ function publish(value: MaybeRefOrGetter<T>) {
9
+ const page = toValue(useSlideContext().$page)
10
+ watchEffect(() => {
11
+ store[page] = toValue(value)
12
+ })
13
+ }
14
+
15
+ return { store, publish }
16
+ }
17
+
18
+ export interface SlideLogos {
19
+ ddrg?: 'color' | 'white'
20
+ tud?: boolean
21
+ footer?: boolean
22
+ }
23
+
24
+ const slideLogosReg = createRegistry<SlideLogos>()
25
+ export const slideLogos = slideLogosReg.store
26
+
27
+ export function useLogo(logos: MaybeRefOrGetter<SlideLogos>) {
28
+ slideLogosReg.publish(logos)
29
+ }
@@ -160,6 +160,35 @@
160
160
  font-style: normal; /* keep inline code upright inside the italic aside */
161
161
  }
162
162
 
163
+ /* Rhetorical-question / one-sentence-takeaway callout (<Takeaway> via ::takeaway).
164
+ "F1" style: a coloured left rule fitted to the text height + a small uppercase
165
+ eyebrow label, no fill, no symbol. The accent colour is driven by --tk-accent
166
+ (set inline by the component from its `color` prop), defaulting to brand blue. */
167
+ .slidev-layout.db-default .db-takeaway {
168
+ margin: 0.6em 0;
169
+ /* em-based so the rule stays vertically balanced at any `size`. The tiny
170
+ top/bottom difference offsets the label cap-height vs body baseline insets. */
171
+ padding: 0.28em 0 0.11em 0.85em;
172
+ border-left: 3px solid var(--tk-accent, var(--db-heading-blue));
173
+ }
174
+ .slidev-layout.db-default .db-takeaway__label {
175
+ margin-bottom: 0.3em;
176
+ font-size: 0.72em;
177
+ font-weight: 700;
178
+ letter-spacing: 0.09em;
179
+ line-height: 1.1;
180
+ text-transform: uppercase;
181
+ color: var(--tk-accent, var(--db-heading-blue));
182
+ }
183
+ .slidev-layout.db-default .db-takeaway__body {
184
+ font-size: 1em;
185
+ line-height: 1.2;
186
+ color: var(--db-text-soft);
187
+ }
188
+ .slidev-layout.db-default .db-takeaway__body p { margin: 0; }
189
+ .slidev-layout.db-default .db-takeaway__body strong { font-weight: 700; }
190
+ .slidev-layout.db-default .db-takeaway__body code { font-weight: 500; }
191
+
163
192
  /* Fenced code blocks: box only as wide as its content, not full slide width.
164
193
  fit-content on the WRAPPER so an optional caption + the code share one width.
165
194
  max-width keeps long lines from overflowing the slide. */
@@ -187,9 +216,12 @@
187
216
  are a wide 24px gap between the number and the code, plus the block's 10px
188
217
  left padding before the number. Both are scoped to line-numbered blocks so
189
218
  plain code blocks keep their normal padding. */
190
- .slidev-layout.db-default .slidev-code-line-numbers .slidev-code {
219
+ .slidev-layout.db-default .slidev-code-line-numbers .slidev-code,
220
+ .slidev-layout.db-default .shiki-magic-move-container.slidev-code {
191
221
  /* override the padding *variable* (Slidev applies padding via it, which beats
192
- a plain padding-left here). top right bottom left — only the left shrinks. */
222
+ a plain padding-left here). top right bottom left — only the left shrinks.
223
+ The Magic Move container isn't wrapped in .slidev-code-line-numbers, so it
224
+ needs the same override to keep its gutter rule aligned with plain blocks. */
193
225
  --slidev-code-padding: 4px 10px 4px 6px; /* less space left of the numbers (was 10px) */
194
226
  }
195
227
  .slidev-layout.db-default .slidev-code-line-numbers .slidev-code code .line::before {
@@ -202,6 +234,32 @@
202
234
  margin-right: 7px; /* separator → code (was a plain 8px gap) */
203
235
  }
204
236
 
237
+ /* Magic Move (```md magic-move```) renders line numbers as real
238
+ .shiki-magic-move-line-number elements (each with opacity:0.3), not the
239
+ ::before pseudo the plain blocks use — so the gutter rule above never reaches
240
+ them and the separator was missing. Re-create the same gutter: recolour the
241
+ numbers to match plain line-numbered blocks (gray-400, gray-600 in dark) so
242
+ the border can sit at full opacity instead of the dimmed 0.3. */
243
+ .slidev-layout.db-default .shiki-magic-move-line-number {
244
+ opacity: 1;
245
+ color: rgb(156 163 175);
246
+ /* Mirror the plain block's ::before geometry exactly: a fixed 1ch column,
247
+ right-aligned, so the digit is pinned against the padding instead of
248
+ shrink-wrapped and left-aligned. white-space:normal drops the literal
249
+ trailing spaces Magic Move pads numbers with (e.g. "1 "). */
250
+ box-sizing: border-box;
251
+ width: 1ch;
252
+ text-align: right;
253
+ overflow: visible;
254
+ white-space: normal;
255
+ padding-right: 10px; /* number → separator */
256
+ border-right: 1px solid var(--db-table-rule);
257
+ margin-right: 7px; /* separator → code */
258
+ }
259
+ .dark .slidev-layout.db-default .shiki-magic-move-line-number {
260
+ color: rgb(75 85 99);
261
+ }
262
+
205
263
  /* Optional caption above a code block.
206
264
  Authoring: ```python [What this snippet does] */
207
265
  .slidev-layout.db-default .slidev-code-block-title {