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,202 @@
1
+ <script setup lang="ts">
2
+ import { computed, shallowRef, type ComponentPublicInstance } from 'vue'
3
+ import { createTextFitRuntime, type ThemeTextSize } from '../composables/text-fit-runtime'
4
+
5
+ const TIMELINE_ACTIVE_YEAR_FALLBACK_SIZE: ThemeTextSize = 9
6
+
7
+ const props = defineProps({
8
+ items: {
9
+ type: Array as () => Array<{ year: string, label: string, active?: boolean }>,
10
+ required: true,
11
+ },
12
+ })
13
+
14
+ const timelineElement = shallowRef<HTMLElement | null>(null)
15
+ const activeYearElement = shallowRef<HTMLElement | null>(null)
16
+ const hasActiveItem = computed(() => props.items.some(item => item.active))
17
+ const activeIndices = computed(() => props.items.flatMap((item, itemIndex) => item.active ? [itemIndex] : []))
18
+ const TIMELINE_ACTIVE_YEAR_MAX_SIZE = computed<ThemeTextSize>(() => 12)
19
+ const textFit = createTextFitRuntime()
20
+
21
+ function assertSingleActiveItem() {
22
+ if (activeIndices.value.length > 1)
23
+ throw new Error('[Timeline] items поддерживает не больше одного active item.')
24
+ }
25
+
26
+ function setYearElement(element: Element | ComponentPublicInstance | null, isActive?: boolean) {
27
+ if (!isActive)
28
+ return
29
+
30
+ assertSingleActiveItem()
31
+ activeYearElement.value = element instanceof HTMLElement ? element : null
32
+ }
33
+
34
+ function resolveActiveYearBounds() {
35
+ const timeline = timelineElement.value
36
+ const activeYear = activeYearElement.value
37
+ const activeItem = activeYear?.parentElement
38
+
39
+ if (!timeline || !activeYear || !activeItem)
40
+ return null
41
+
42
+ const timelineStyle = globalThis.getComputedStyle(timeline)
43
+ const dotSize = Number.parseFloat(timelineStyle.getPropertyValue('--timeline-dot-size')) || 0
44
+ const blockHeight = Number.parseFloat(timelineStyle.getPropertyValue('--timeline-block-height')) || 0
45
+
46
+ return {
47
+ width: activeItem.clientWidth,
48
+ height: Math.max(0, timeline.clientHeight - dotSize - blockHeight),
49
+ }
50
+ }
51
+
52
+ const { size: fittedActiveYearSize } = textFit.useElement({
53
+ target: activeYearElement,
54
+ enabled: computed(() => {
55
+ assertSingleActiveItem()
56
+ return hasActiveItem.value
57
+ }),
58
+ fallbackSize: TIMELINE_ACTIVE_YEAR_FALLBACK_SIZE,
59
+ maxSize: TIMELINE_ACTIVE_YEAR_MAX_SIZE,
60
+ resolveBounds: resolveActiveYearBounds,
61
+ watchSources: [
62
+ () => props.items,
63
+ ],
64
+ })
65
+
66
+ const timelineStyle = computed(() => hasActiveItem.value
67
+ ? {
68
+ '--theme-timeline-active-year-size': `var(--theme-text-size-${fittedActiveYearSize.value})`,
69
+ '--theme-timeline-active-year-line': `var(--theme-text-line-${fittedActiveYearSize.value})`,
70
+ }
71
+ : {})
72
+
73
+ function getItemGridStyle(index: number) {
74
+ const count = props.items.length || 1
75
+ const activeItemIndices = activeIndices.value
76
+
77
+ assertSingleActiveItem()
78
+
79
+ if (count === 3 && activeItemIndices.length === 1) {
80
+ const activeIndex = activeItemIndices[0]
81
+ const spans = props.items.map((_, itemIndex) => itemIndex === activeIndex ? 6 : 3)
82
+ const start = spans.slice(0, index).reduce((sum, span) => sum + span, 1)
83
+
84
+ return {
85
+ gridColumn: `${start} / ${start + spans[index]}`,
86
+ }
87
+ }
88
+
89
+ if (count > 12)
90
+ throw new Error('[Timeline] items поддерживает не больше 12 событий.')
91
+
92
+ const start = Math.floor((index * 12) / count) + 1
93
+ const end = Math.floor(((index + 1) * 12) / count) + 1
94
+
95
+ return {
96
+ gridColumn: `${start} / ${end}`,
97
+ }
98
+ }
99
+ </script>
100
+
101
+ <template>
102
+ <div ref="timelineElement"
103
+ class="Timeline"
104
+ :style="timelineStyle"
105
+ :class="{ 'Timeline_has_active': hasActiveItem }">
106
+ <div class="Timeline-Rail" />
107
+
108
+ <div v-for="(item, index) in items"
109
+ :key="`${item.year}-${index}`"
110
+ class="Timeline-Item"
111
+ :style="getItemGridStyle(index)"
112
+ :class="{ 'Timeline-Item_active': item.active }">
113
+ <div :ref="element => setYearElement(element, item.active)" class="Timeline-Year">{{ item.year }}</div>
114
+ <div class="Timeline-Dot" />
115
+ <div class="Timeline-Label">{{ item.label }}</div>
116
+ </div>
117
+ </div>
118
+ </template>
119
+
120
+ <style scoped>
121
+ .Timeline {
122
+ --timeline-block-height: calc(var(--theme-cell-height) * 2 + var(--theme-grid-gap));
123
+ --timeline-dot-size: calc(var(--theme-grid-module) * 4);
124
+ --theme-timeline-active-year-size: var(--theme-text-size-9);
125
+ --theme-timeline-active-year-line: var(--theme-text-line-9);
126
+ position: relative;
127
+ display: grid;
128
+ grid-template-columns: repeat(var(--theme-grid-columns), minmax(0, 1fr));
129
+ column-gap: var(--theme-grid-gap);
130
+ align-items: end;
131
+ align-content: end;
132
+ min-height: 100%;
133
+ }
134
+
135
+ .Timeline-Rail {
136
+ position: absolute;
137
+ left: calc(var(--theme-margin-left) * -1);
138
+ right: calc(var(--theme-margin-right) * -1);
139
+ bottom: calc(var(--timeline-block-height) + (var(--timeline-dot-size) / 2) - (var(--theme-grid-module) / 2));
140
+ height: var(--theme-grid-module);
141
+ background: color-mix(in srgb, var(--theme-text-muted) 28%, transparent);
142
+ }
143
+
144
+ .Timeline-Item {
145
+ position: relative;
146
+ display: grid;
147
+ grid-template-rows:
148
+ var(--timeline-block-height)
149
+ var(--timeline-dot-size)
150
+ var(--timeline-block-height);
151
+ min-height: calc((var(--timeline-block-height) * 2) + var(--timeline-dot-size));
152
+ }
153
+
154
+ .Timeline-Year {
155
+ min-height: var(--timeline-block-height);
156
+ display: flex;
157
+ align-items: flex-end;
158
+ font-size: var(--theme-text-size-7);
159
+ line-height: var(--theme-text-line-7);
160
+ color: var(--theme-text);
161
+ }
162
+
163
+ .Timeline-Dot {
164
+ width: var(--timeline-dot-size);
165
+ height: var(--timeline-dot-size);
166
+ border: var(--theme-grid-module) solid var(--theme-text);
167
+ border-radius: 50%;
168
+ background: var(--theme-bg);
169
+ align-self: center;
170
+ }
171
+
172
+ .Timeline-Label {
173
+ min-height: var(--timeline-block-height);
174
+ max-width: var(--theme-grid-span-2-width);
175
+ padding-top: var(--theme-slot-margin-3);
176
+ color: var(--theme-text-muted);
177
+ font-size: var(--theme-text-size-2);
178
+ line-height: var(--theme-text-line-2);
179
+ }
180
+
181
+ .Timeline_has_active .Timeline-Year {
182
+ color: var(--theme-text-muted);
183
+ }
184
+
185
+ .Timeline_has_active .Timeline-Dot {
186
+ border-color: var(--theme-text-muted);
187
+ }
188
+
189
+ .Timeline-Item_active .Timeline-Year {
190
+ color: var(--theme-text);
191
+ font-size: var(--theme-timeline-active-year-size);
192
+ line-height: var(--theme-timeline-active-year-line);
193
+ }
194
+
195
+ .Timeline-Item_active .Timeline-Dot {
196
+ border-color: var(--theme-text);
197
+ }
198
+
199
+ .Timeline-Item_active .Timeline-Label {
200
+ color: inherit;
201
+ }
202
+ </style>
@@ -0,0 +1,339 @@
1
+ const PHOTO_DECOR_SIZES = Object.freeze([
2
+ { cols: [4, 6], rows: [4, 6], ratio: [0.85, 1.2] },
3
+ { cols: [5, 12], rows: [3, 8], ratio: [1.15, 4] },
4
+ ])
5
+
6
+ /**
7
+ * @param {number} number
8
+ * @param {string[]} meanings
9
+ * @param {string[]} tones
10
+ * @param {Partial<import('./image-config.mjs').ImageDataInput>} [image]
11
+ */
12
+ function photoDecor(number, meanings, tones, image = {}) {
13
+ return {
14
+ id: `decor-photo-${String(number).padStart(2, '0')}`,
15
+ src: `/photos/photo-${number}.png`,
16
+ sizes: PHOTO_DECOR_SIZES,
17
+ meanings: ['photo', ...meanings],
18
+ tones,
19
+ image: {
20
+ fit: 'cover',
21
+ position: 'center',
22
+ zoom: 1,
23
+ ...image,
24
+ },
25
+ }
26
+ }
27
+
28
+ export const DEFAULT_DECOR_DATA = Object.freeze([
29
+ {
30
+ id: 'decor-cover-band-01',
31
+ src: '/decor/decor-1.svg',
32
+ sizes: [{ cols: [3, 8], rows: [2, 5], ratio: [1, 1.5] }],
33
+ meanings: ['cover', 'hero', 'course'],
34
+ tones: ['green', 'orange', 'blue'],
35
+ image: {
36
+ fit: 'contain',
37
+ position: 'center',
38
+ zoom: 1.05,
39
+ },
40
+ },
41
+ {
42
+ id: 'decor-support-raster-01',
43
+ src: '/decor/decor-2.png',
44
+ sizes: [{ cols: [2, 6], rows: [2, 6], ratio: [0.75, 1.2] }],
45
+ meanings: ['support', 'media'],
46
+ tones: ['orange', 'light', 'warm'],
47
+ image: {
48
+ fit: 'scale-down',
49
+ position: '100% 50%',
50
+ anchor: 'right center',
51
+ backgroundColor: '#f5f5f5',
52
+ },
53
+ },
54
+ {
55
+ id: 'decor-square-orbit-01',
56
+ src: '/decor/decor-3.svg',
57
+ sizes: [{ cols: [3, 5], rows: [3, 5], ratio: [0.8, 1.25] }],
58
+ meanings: ['qa', 'testing', 'practice'],
59
+ tones: ['blue', 'orange', 'green'],
60
+ image: {
61
+ fit: 'contain',
62
+ position: 'center',
63
+ zoom: 1.06,
64
+ },
65
+ },
66
+ {
67
+ id: 'decor-support-wide-01',
68
+ src: '/decor/decor-4.svg',
69
+ sizes: [{ cols: [4, 8], rows: [2, 8], ratio: [1, 4] }],
70
+ meanings: ['support', 'learning'],
71
+ tones: ['green', 'blue', 'orange'],
72
+ image: {
73
+ fit: 'fill',
74
+ position: '50% 50%',
75
+ zoom: 0.9,
76
+ },
77
+ },
78
+ {
79
+ id: 'decor-support-raster-02',
80
+ src: '/decor/decor-5.png',
81
+ sizes: [
82
+ { cols: 6, rows: 5 },
83
+ { cols: 6, rows: 6 },
84
+ { cols: 7, rows: 6 },
85
+ { cols: 7, rows: 7 },
86
+ ],
87
+ meanings: ['support', 'media'],
88
+ tones: ['orange', 'warm'],
89
+ image: {
90
+ fit: 'cover',
91
+ position: '0% 0%',
92
+ anchor: 'right top',
93
+ x: '-15%',
94
+ y: '26.5%',
95
+ backgroundColor: 'var(--theme-color-orange-1)',
96
+ },
97
+ },
98
+ {
99
+ id: 'decor-support-raster-03',
100
+ src: '/decor/decor-6.png',
101
+ sizes: [{ cols: [3, 5], rows: [3, 5], ratio: [0.8, 1.25] }],
102
+ meanings: ['support', 'media'],
103
+ tones: ['orange', 'warm'],
104
+ image: {
105
+ fit: 'contain',
106
+ position: '50% 50%',
107
+ backgroundColor: 'var(--theme-color-orange-0)',
108
+ },
109
+ },
110
+ {
111
+ id: 'decor-media-square-01',
112
+ src: '/decor/decor-7.png',
113
+ sizes: [{ cols: [3, 5], rows: [3, 5], ratio: [0.8, 1.25] }],
114
+ meanings: ['media', 'practice', 'support'],
115
+ tones: ['blue', 'orange', 'green'],
116
+ image: {
117
+ fit: 'contain',
118
+ position: '50% 50%',
119
+ zoom: 0.9,
120
+ backgroundColor: 'var(--theme-color-blue-1)',
121
+ },
122
+ },
123
+ {
124
+ id: 'decor-cover-vertical-01',
125
+ src: '/decor/decor-8.svg',
126
+ sizes: [{ cols: [2, 4], rows: [3, 8], ratio: [0.25, 0.95] }],
127
+ meanings: ['cover', 'hero', 'course'],
128
+ tones: ['orange', 'green', 'blue'],
129
+ image: {
130
+ fit: 'contain',
131
+ position: 'center',
132
+ zoom: 1.08,
133
+ },
134
+ },
135
+ {
136
+ id: 'decor-cover-ribbon-01',
137
+ src: '/decor/decor-9.svg',
138
+ sizes: [{ cols: [4, 8], rows: [2, 4], ratio: [1.4, 4] }],
139
+ meanings: ['cover', 'hero', 'support'],
140
+ tones: ['orange', 'blue', 'green'],
141
+ image: {
142
+ fit: 'contain',
143
+ position: '50% 70%',
144
+ zoom: 1.7,
145
+ },
146
+ },
147
+ {
148
+ id: 'decor-rules-wide-01',
149
+ src: '/decor/decor-10.svg',
150
+ sizes: [{ cols: [4, 12], rows: [3, 6], ratio: [1.4, 4] }],
151
+ meanings: ['rules', 'webinar', 'qa'],
152
+ tones: ['green', 'dark', 'blue', 'orange'],
153
+ image: {
154
+ fit: 'contain',
155
+ position: 'left top',
156
+ anchor: 'left top',
157
+ x: '50%',
158
+ y: '12%',
159
+ zoom: 3,
160
+ color: 'var(--theme-color-dark-0)',
161
+ opacity: 1,
162
+ },
163
+ },
164
+ {
165
+ id: 'decor-agenda-tall-01',
166
+ src: '/decor/decor-11.svg',
167
+ sizes: [{ cols: [3, 4], rows: [8, 12], ratio: [0.25, 0.55] }],
168
+ meanings: ['agenda', 'toc'],
169
+ tones: ['blue', 'orange', 'green', 'dark'],
170
+ image: {
171
+ fit: 'contain',
172
+ position: 'right center',
173
+ zoom: 1,
174
+ opacity: 0.85,
175
+ },
176
+ },
177
+ {
178
+ id: 'decor-signal-tall-01',
179
+ src: '/decor/decor-12.svg',
180
+ sizes: [{ cols: [2, 4], rows: [4, 12], ratio: [0.2, 0.8] }],
181
+ meanings: ['signal', 'cover', 'hero'],
182
+ tones: ['blue', 'orange', 'green'],
183
+ image: {
184
+ fit: 'cover',
185
+ position: '50% 50%',
186
+ zoom: 2,
187
+ },
188
+ },
189
+ {
190
+ id: 'decor-support-compact-01',
191
+ src: '/decor/decor-13.svg',
192
+ sizes: [{ cols: [2, 6], rows: [2, 6], ratio: [0.75, 1.35] }],
193
+ meanings: ['support', 'practice'],
194
+ tones: ['green', 'blue', 'orange'],
195
+ image: {
196
+ fit: 'contain',
197
+ position: '50% 50%',
198
+ zoom: 0.9,
199
+ },
200
+ },
201
+ {
202
+ id: 'decor-panel-vertical-01',
203
+ src: '/decor/decor-14.svg',
204
+ sizes: [{ cols: [3, 5], rows: [4, 7], ratio: [0.45, 0.95] }],
205
+ meanings: ['support', 'rules', 'qa'],
206
+ tones: ['orange', 'blue', 'green'],
207
+ image: {
208
+ fit: 'contain',
209
+ position: '100% 50%',
210
+ anchor: 'right center',
211
+ x: '3%',
212
+ zoom: 0.9,
213
+ },
214
+ },
215
+ {
216
+ id: 'decor-support-wide-02',
217
+ src: '/decor/decor-15.svg',
218
+ sizes: [{ cols: [4, 8], rows: [2, 5], ratio: [1.2, 4] }],
219
+ meanings: ['support', 'learning'],
220
+ tones: ['orange', 'green', 'blue'],
221
+ image: {
222
+ fit: 'contain',
223
+ position: 'center',
224
+ zoom: 1,
225
+ },
226
+ },
227
+ {
228
+ id: 'decor-support-wide-03',
229
+ src: '/decor/decor-16.svg',
230
+ sizes: [{ cols: [5, 9], rows: [2, 4], ratio: [1.4, 4.5] }],
231
+ meanings: ['support', 'learning'],
232
+ tones: ['blue', 'green', 'orange'],
233
+ image: {
234
+ fit: 'contain',
235
+ position: 'center',
236
+ zoom: 1,
237
+ },
238
+ },
239
+ {
240
+ id: 'decor-media-square-02',
241
+ src: '/decor/decor-17.png',
242
+ sizes: [{ cols: [3, 5], rows: [3, 5], ratio: [0.8, 1.25] }],
243
+ meanings: ['media', 'support'],
244
+ tones: ['green', 'orange', 'blue'],
245
+ image: {
246
+ fit: 'contain',
247
+ position: '50% 50%',
248
+ zoom: 0.9,
249
+ backgroundColor: 'var(--theme-color-light-1)',
250
+ },
251
+ },
252
+ {
253
+ id: 'decor-media-square-03',
254
+ src: '/decor/decor-18.png',
255
+ sizes: [{ cols: [3, 6], rows: [3, 6], ratio: [0.75, 1.35] }],
256
+ meanings: ['media', 'support'],
257
+ tones: ['orange', 'blue', 'green'],
258
+ image: {
259
+ fit: 'cover',
260
+ position: '50% 46%',
261
+ x: '-25.5%',
262
+ zoom: 1.6,
263
+ backgroundColor: 'var(--theme-color-dark-1)',
264
+ },
265
+ },
266
+ {
267
+ id: 'decor-support-tall-01',
268
+ src: '/decor/decor-19.svg',
269
+ sizes: [{ cols: [3, 5], rows: [3, 9], ratio: [0.35, 1.1] }],
270
+ meanings: ['support', 'practice'],
271
+ tones: ['blue', 'orange', 'green'],
272
+ image: {
273
+ fit: 'cover',
274
+ position: '50% 50%',
275
+ },
276
+ },
277
+ photoDecor(
278
+ 1,
279
+ ['portrait', 'workspace', 'home', 'learning'],
280
+ ['blue', 'light', 'neutral', 'yellow'],
281
+ { position: '50% 44%', zoom: 1.06 },
282
+ ),
283
+ photoDecor(
284
+ 2,
285
+ ['portrait', 'workspace', 'learning'],
286
+ ['blue', 'green', 'dark', 'cool'],
287
+ { position: '50% 42%', zoom: 1.06 },
288
+ ),
289
+ photoDecor(
290
+ 3,
291
+ ['portrait', 'home', 'learning'],
292
+ ['orange', 'yellow', 'green', 'dark', 'warm'],
293
+ { position: '52% 45%', zoom: 1.04 },
294
+ ),
295
+ photoDecor(
296
+ 4,
297
+ ['portrait', 'workspace', 'learning'],
298
+ ['blue', 'dark', 'neutral'],
299
+ { position: '50% 44%', zoom: 1.06 },
300
+ ),
301
+ photoDecor(
302
+ 5,
303
+ ['portrait', 'outdoor', 'learning'],
304
+ ['blue', 'green', 'light', 'yellow'],
305
+ { position: '48% 44%', zoom: 1.08 },
306
+ ),
307
+ photoDecor(
308
+ 6,
309
+ ['portrait', 'home', 'learning'],
310
+ ['green', 'light', 'yellow', 'neutral'],
311
+ { position: '50% 40%', zoom: 1.04 },
312
+ ),
313
+ photoDecor(
314
+ 7,
315
+ ['portrait', 'home', 'learning'],
316
+ ['orange', 'blue', 'yellow', 'dark', 'warm'],
317
+ { position: '50% 0%', zoom: 1.2 },
318
+ ),
319
+ photoDecor(
320
+ 8,
321
+ ['portrait', 'campus', 'learning'],
322
+ ['orange', 'yellow', 'green', 'neutral', 'warm'],
323
+ { position: '50% 45%', zoom: 1.06 },
324
+ ),
325
+ photoDecor(
326
+ 9,
327
+ ['portrait', 'home', 'learning'],
328
+ ['blue', 'light', 'neutral', 'green'],
329
+ { position: '50% 45%', zoom: 1.05 },
330
+ ),
331
+ photoDecor(
332
+ 10,
333
+ ['portrait', 'home', 'learning'],
334
+ ['orange', 'yellow', 'dark', 'warm'],
335
+ { position: '50% 46%', zoom: 1.08 },
336
+ ),
337
+ ])
338
+
339
+ export const DEFAULT_DECORS = DEFAULT_DECOR_DATA