slidev-theme-practicum 0.1.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.
Files changed (88) hide show
  1. package/README.md +270 -0
  2. package/components/DebugGrid.vue +50 -0
  3. package/components/DecorLibrary.vue +1117 -0
  4. package/components/Header.vue +124 -0
  5. package/components/Image.vue +82 -0
  6. package/components/ImageRenderer.vue +126 -0
  7. package/components/Logo.vue +142 -0
  8. package/components/Person.vue +89 -0
  9. package/components/Slide.vue +324 -0
  10. package/components/Slot.vue +419 -0
  11. package/components/Text.vue +216 -0
  12. package/components/Timeline.vue +202 -0
  13. package/composables/decor-catalog.mjs +339 -0
  14. package/composables/decor-config.mjs +488 -0
  15. package/composables/decor-file-store.ts +192 -0
  16. package/composables/decor-http-store.ts +25 -0
  17. package/composables/decor-store.ts +39 -0
  18. package/composables/decor-tuning-overrides.mjs +2 -0
  19. package/composables/decor-workbench.ts +799 -0
  20. package/composables/grid-placement.ts +396 -0
  21. package/composables/image-config.mjs +484 -0
  22. package/composables/layout-authoring.ts +372 -0
  23. package/composables/layout-markdown.mjs +56 -0
  24. package/composables/layout-recipes.ts +347 -0
  25. package/composables/layout-registry.ts +47 -0
  26. package/composables/layout-shorthands.ts +891 -0
  27. package/composables/layout-vnode.ts +43 -0
  28. package/composables/logo-mark.mjs +5 -0
  29. package/composables/slide-layout.ts +43 -0
  30. package/composables/slot-placement.ts +195 -0
  31. package/composables/slot-rules.ts +147 -0
  32. package/composables/text-fit-runtime.ts +577 -0
  33. package/composables/text-priority-fit.mjs +166 -0
  34. package/composables/text-typography.mjs +138 -0
  35. package/composables/theme-foundation.ts +192 -0
  36. package/composables/theme-media.mjs +202 -0
  37. package/composables/use-theme-config.ts +71 -0
  38. package/decor-library.md +10 -0
  39. package/env.d.ts +6 -0
  40. package/example.md +786 -0
  41. package/layouts/collection.vue +5 -0
  42. package/layouts/cover.vue +5 -0
  43. package/layouts/default.vue +5 -0
  44. package/layouts/explainer.vue +5 -0
  45. package/layouts/message.vue +5 -0
  46. package/layouts/none.vue +5 -0
  47. package/layouts/section.vue +5 -0
  48. package/layouts/two-cols.vue +11 -0
  49. package/package.json +84 -0
  50. package/public/decor/decor-1.svg +83 -0
  51. package/public/decor/decor-10.svg +40 -0
  52. package/public/decor/decor-11.svg +162 -0
  53. package/public/decor/decor-12.svg +83 -0
  54. package/public/decor/decor-13.svg +5 -0
  55. package/public/decor/decor-14.svg +7 -0
  56. package/public/decor/decor-15.svg +10 -0
  57. package/public/decor/decor-16.svg +9 -0
  58. package/public/decor/decor-17.png +0 -0
  59. package/public/decor/decor-18.png +0 -0
  60. package/public/decor/decor-19.svg +5 -0
  61. package/public/decor/decor-2.png +0 -0
  62. package/public/decor/decor-3.svg +9 -0
  63. package/public/decor/decor-4.svg +31 -0
  64. package/public/decor/decor-5.png +0 -0
  65. package/public/decor/decor-6.png +0 -0
  66. package/public/decor/decor-7.png +0 -0
  67. package/public/decor/decor-8.svg +21 -0
  68. package/public/decor/decor-9.svg +38 -0
  69. package/public/favicon.svg +11 -0
  70. package/public/photos/photo-1.png +0 -0
  71. package/public/photos/photo-10.png +0 -0
  72. package/public/photos/photo-2.png +0 -0
  73. package/public/photos/photo-3.png +0 -0
  74. package/public/photos/photo-4.png +0 -0
  75. package/public/photos/photo-5.png +0 -0
  76. package/public/photos/photo-6.png +0 -0
  77. package/public/photos/photo-7.png +0 -0
  78. package/public/photos/photo-8.png +0 -0
  79. package/public/photos/photo-9.png +0 -0
  80. package/setup/main.ts +3 -0
  81. package/setup/shiki.ts +10 -0
  82. package/setup/vite-plugins.ts +106 -0
  83. package/slidev-theme-practicum.png +0 -0
  84. package/slidev-theme-practicum.svg +102 -0
  85. package/styles/example.css +0 -0
  86. package/styles/index.css +192 -0
  87. package/styles/vars.css +119 -0
  88. package/types/slidev-client.d.ts +15 -0
@@ -0,0 +1,324 @@
1
+ <script setup lang="ts">
2
+ import { computed, defineComponent, h, isVNode, onMounted, onUpdated, shallowRef, useSlots, type PropType, type VNode } from 'vue'
3
+ import { useSlideContext } from '@slidev/client'
4
+ import DebugGrid from './DebugGrid.vue'
5
+ import Header from './Header.vue'
6
+ import Image from './Image.vue'
7
+ import Person from './Person.vue'
8
+ import Slot from './Slot.vue'
9
+ import Text from './Text.vue'
10
+ import Timeline from './Timeline.vue'
11
+ import { createSlideLayout } from '../composables/slide-layout'
12
+ import type { ThemeLayout, ThemeLayoutHeader } from '../composables/layout-registry'
13
+ import { typographElement } from '../composables/text-typography.mjs'
14
+ import { themeVars, type ThemeSlideMode, type ThemeTone } from '../composables/theme-foundation'
15
+ import { provideSlotPlacementSession } from '../composables/slot-placement'
16
+ import { useThemeConfig } from '../composables/use-theme-config'
17
+
18
+ const props = withDefaults(defineProps<{
19
+ as?: string
20
+ layout?: ThemeLayout | ''
21
+ variant?: string
22
+ arrangement?: string
23
+ mode?: ThemeSlideMode
24
+ tone?: ThemeTone | ''
25
+ header?: ThemeLayoutHeader
26
+ }>(), {
27
+ as: 'div',
28
+ layout: '',
29
+ variant: '',
30
+ arrangement: '',
31
+ tone: '',
32
+ })
33
+
34
+ const slots = useSlots()
35
+ const slideElement = shallowRef<HTMLElement | null>(null)
36
+
37
+ const { $frontmatter } = useSlideContext()
38
+ const { debugGrid, defaultTone } = useThemeConfig()
39
+ const slideLayout = createSlideLayout({
40
+ components: {
41
+ Image,
42
+ Person,
43
+ Slot,
44
+ Text,
45
+ Timeline,
46
+ },
47
+ })
48
+
49
+ function compileCurrentAuthoring(children?: readonly VNode[]) {
50
+ return slideLayout.compile({
51
+ props,
52
+ frontmatter: $frontmatter as Record<string, unknown>,
53
+ children,
54
+ defaultTone: defaultTone.value,
55
+ debugGrid: debugGrid.value,
56
+ })
57
+ }
58
+
59
+ const authored = computed(() => compileCurrentAuthoring())
60
+ const resolvedLayout = computed(() => authored.value.layout)
61
+ const isLayoutMode = computed(() => authored.value.mode === 'layout')
62
+ const resolvedVariant = computed(() => authored.value.variant)
63
+ const resolvedHeader = computed(() => authored.value.header)
64
+ const resolvedTheme = computed(() => authored.value.theme)
65
+ const isContrast = computed(() => authored.value.contrast)
66
+ const showDebugGrid = computed(() => authored.value.showDebugGrid)
67
+ provideSlotPlacementSession(slideLayout)
68
+
69
+ function applySlideTypography() {
70
+ typographElement(slideElement.value)
71
+ }
72
+
73
+ onMounted(() => {
74
+ applySlideTypography()
75
+ })
76
+
77
+ onUpdated(() => {
78
+ applySlideTypography()
79
+ })
80
+
81
+ const RenderVNode = defineComponent({
82
+ name: 'RenderVNode',
83
+ props: {
84
+ vnode: {
85
+ type: Object as PropType<VNode>,
86
+ required: true,
87
+ },
88
+ },
89
+ setup(renderProps) {
90
+ return () => renderProps.vnode
91
+ },
92
+ })
93
+
94
+ const slideStyle = computed(() => themeVars('slide', resolvedTheme.value))
95
+
96
+ const LayoutBody = defineComponent({
97
+ name: 'LayoutBody',
98
+ setup(_, { slots: layoutSlots }) {
99
+ return () => {
100
+ const rawChildren = (layoutSlots.default?.() ?? []).filter(isVNode)
101
+ const layoutChildren = compileCurrentAuthoring(rawChildren).children
102
+
103
+ return layoutChildren.map((child, index) => h(RenderVNode, {
104
+ key: child.key ?? `slide-layout-child-${index}`,
105
+ vnode: child,
106
+ }))
107
+ }
108
+ },
109
+ })
110
+
111
+ const slideClass = computed(() => ({
112
+ [`Slide_mode_${resolvedTheme.value.mode}`]: true,
113
+ Slide_layout: isLayoutMode.value,
114
+ [`Slide_layout_${resolvedLayout.value}`]: isLayoutMode.value,
115
+ [`Slide_variant_${resolvedVariant.value}`]: isLayoutMode.value && Boolean(resolvedVariant.value),
116
+ Slide_contrast: isLayoutMode.value && isContrast.value,
117
+ }))
118
+ </script>
119
+
120
+ <template>
121
+ <component :is="as"
122
+ ref="slideElement"
123
+ class="Slide slidev-layout"
124
+ :class="slideClass"
125
+ :style="slideStyle">
126
+ <div class="Slide-Header">
127
+ <slot v-if="!isLayoutMode && slots.header" name="header" />
128
+ <Header v-else-if="resolvedHeader !== 'none'"
129
+ :variant="resolvedHeader === 'cover' ? 'cover' : 'default'"
130
+ :inverted="isContrast" />
131
+ </div>
132
+ <DebugGrid v-if="showDebugGrid" />
133
+ <div class="Slide-Grid">
134
+ <slot v-if="!isLayoutMode" />
135
+ <LayoutBody v-else>
136
+ <slot />
137
+ </LayoutBody>
138
+ </div>
139
+ </component>
140
+ </template>
141
+
142
+ <style scoped>
143
+ .Slide {
144
+ position: relative;
145
+ isolation: isolate;
146
+ color: var(--theme-text);
147
+ background: var(--theme-bg);
148
+ }
149
+
150
+ .Slide-Header {
151
+ position: absolute;
152
+ top: 0;
153
+ left: var(--theme-margin-left);
154
+ right: var(--theme-margin-right);
155
+ height: var(--theme-margin-top);
156
+ z-index: 1;
157
+ display: flex;
158
+ align-items: flex-start;
159
+ }
160
+
161
+ .Slide-Grid {
162
+ position: absolute;
163
+ inset: var(--theme-margin-top) var(--theme-margin-right) var(--theme-margin-bottom) var(--theme-margin-left);
164
+ z-index: 0;
165
+ display: grid;
166
+ width: auto;
167
+ height: auto;
168
+ grid-template-columns: repeat(var(--theme-grid-columns), minmax(0, 1fr));
169
+ grid-template-rows: repeat(var(--theme-grid-rows), minmax(0, 1fr));
170
+ gap: var(--theme-grid-gap);
171
+ }
172
+
173
+ :deep(.Slide-AgendaContent) {
174
+ display: flex;
175
+ min-width: 0;
176
+ flex-direction: column;
177
+ gap: calc(var(--theme-grid-module) * 4);
178
+ }
179
+
180
+ :deep(.Slide-AgendaList) {
181
+ list-style: none;
182
+ margin: 0;
183
+ padding-left: var(--theme-grid-module);
184
+ counter-reset: slide-toc;
185
+ }
186
+
187
+ :deep(.Slide-AgendaList li) {
188
+ display: grid;
189
+ grid-template-columns: calc(var(--theme-grid-module) * 4) minmax(0, 1fr);
190
+ column-gap: calc(var(--theme-grid-module) * 3);
191
+ align-items: start;
192
+ margin-bottom: calc(var(--theme-grid-module) * 2);
193
+ font-size: var(--theme-text-size-5);
194
+ line-height: var(--theme-text-line-5);
195
+ counter-increment: slide-toc;
196
+ }
197
+
198
+ :deep(.Slide-AgendaList li)::before {
199
+ display: grid;
200
+ place-items: center;
201
+ align-self: start;
202
+ width: calc(var(--theme-grid-module) * 4);
203
+ height: calc(var(--theme-grid-module) * 4);
204
+ border-radius: 50%;
205
+ background: var(--theme-color-dark-0);
206
+ color: var(--theme-color-light-0);
207
+ font-size: var(--theme-text-size-0);
208
+ text-align: center;
209
+ content: counter(slide-toc);
210
+ margin-top: calc(var(--theme-grid-module) * 2);
211
+ }
212
+
213
+ .Slide_contrast :deep(.Slide-AgendaList li)::before {
214
+ background: var(--theme-color-light-0);
215
+ color: var(--theme-current-color);
216
+ }
217
+
218
+ :deep(.Slide-DefinitionLabel) {
219
+ margin-bottom: var(--theme-slot-margin-4);
220
+ }
221
+
222
+ :deep(.Slide-TitleSupportsList) {
223
+ max-width: var(--theme-grid-span-6-width);
224
+ padding-left: 0;
225
+ list-style: none;
226
+ color: var(--theme-text-muted);
227
+ }
228
+
229
+ :deep(.Slide-TitleSupportsList li) {
230
+ margin-bottom: calc(var(--theme-grid-module) * 2);
231
+ }
232
+
233
+ :deep(.Slide-TitleSupportsList_size_large li) {
234
+ font-size: var(--theme-text-size-4);
235
+ line-height: var(--theme-text-line-4);
236
+ }
237
+
238
+ :deep(.Slide-TitleBody) {
239
+ max-width: var(--theme-grid-span-6-width);
240
+ color: var(--theme-text);
241
+ font-size: var(--theme-text-size-4);
242
+ line-height: var(--theme-text-line-4);
243
+ }
244
+
245
+ :deep(.Slide-TitleBody :where(p, ul, ol, blockquote)) {
246
+ margin: 0;
247
+ color: inherit;
248
+ font-size: inherit;
249
+ line-height: inherit;
250
+ }
251
+
252
+ :deep(.Slide-TitleBody :where(ul, ol)) {
253
+ padding-left: calc(var(--theme-grid-module) * 4);
254
+ list-style-position: outside;
255
+ }
256
+
257
+ :deep(.Slide-TitleBody ul) {
258
+ list-style-type: disc;
259
+ }
260
+
261
+ :deep(.Slide-TitleBody li) {
262
+ display: list-item;
263
+ padding-left: calc(var(--theme-grid-module) * 2);
264
+ margin-bottom: calc(var(--theme-grid-module) * 2);
265
+ font-size: inherit;
266
+ line-height: inherit;
267
+ }
268
+
269
+ :deep(.Slide-TitleBody ul li)::marker {
270
+ color: currentcolor;
271
+ font-size: inherit;
272
+ content: '●';
273
+ }
274
+
275
+ :deep(.Slide-TitleBody :where(p, ul, ol, blockquote) + :where(p, ul, ol, blockquote)) {
276
+ margin-top: calc(var(--theme-grid-module) * 3);
277
+ }
278
+
279
+ :deep(.Slide-MetricsFeaturedText) {
280
+ max-width: calc(var(--theme-grid-span-6-width) - (var(--theme-slot-margin-4) * 2));
281
+ }
282
+
283
+ :deep(.Slide-PointsTitle) {
284
+ max-width: var(--theme-grid-span-7-width);
285
+ }
286
+
287
+ :deep(.Slide-MetricsFeaturedCopy) {
288
+ display: grid;
289
+ flex: 1;
290
+ grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
291
+ width: 100%;
292
+ height: 100%;
293
+ min-height: 100%;
294
+ }
295
+
296
+ :deep(.Slide-MetricsFeaturedCopyValue),
297
+ :deep(.Slide-MetricsFeaturedCopyLabel) {
298
+ display: flex;
299
+ min-width: 0;
300
+ min-height: 100%;
301
+ }
302
+
303
+ :deep(.Slide-MetricsFeaturedCopyValue) {
304
+ align-items: center;
305
+ justify-content: center;
306
+ text-align: center;
307
+ }
308
+
309
+ :deep(.Slide-MetricsFeaturedCopyLabel) {
310
+ align-items: flex-start;
311
+ justify-content: flex-start;
312
+ }
313
+
314
+ :deep(.Slide-Quote) {
315
+ max-width: var(--theme-grid-span-11-width);
316
+ font-size: var(--theme-text-size-7);
317
+ line-height: var(--theme-text-line-7);
318
+ }
319
+
320
+ :deep(.Slide-Quote p) {
321
+ font-size: inherit;
322
+ line-height: inherit;
323
+ }
324
+ </style>