@alphacifer/slidev-addon-theme 0.0.1 → 0.0.2

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.
@@ -1,5 +1,6 @@
1
1
  <script setup lang="ts">
2
2
  import { formatDate } from '@alphacifer/core-utils/dateUtils';
3
+ import { computed } from 'vue';
3
4
 
4
5
  import { useMergedUnoAttrs } from '../../utils/useMergedUnoAttrs';
5
6
 
@@ -14,11 +15,13 @@ const props = defineProps({
14
15
  },
15
16
  });
16
17
 
17
- const formattedDate = formatDate(props.date, {
18
- format: 'dd/MM/yyyy',
18
+ const formattedDate = computed(() => {
19
+ return formatDate(props.date ?? new Date(), {
20
+ format: 'dd/MM/yyyy',
21
+ });
19
22
  });
20
23
 
21
- const { className, forwardedAttrs } = useMergedUnoAttrs('slidev-addon-date');
24
+ const { className, forwardedAttrs } = useMergedUnoAttrs('alpha-date');
22
25
  </script>
23
26
 
24
27
  <template>
@@ -5,15 +5,16 @@ defineOptions({
5
5
  inheritAttrs: false,
6
6
  });
7
7
 
8
- defineProps({
9
- startDelay: {
10
- type: Number,
11
- default: 11_500,
12
- },
8
+ interface IQnAProps {
9
+ readonly startDelay?: number;
10
+ }
11
+
12
+ withDefaults(defineProps<IQnAProps>(), {
13
+ startDelay: 11_500,
13
14
  });
14
15
 
15
16
  const { className, forwardedAttrs } = useMergedUnoAttrs(
16
- 'slidev-addon-qna flex items-center gap-8 text-8xl font-bold color-[#2b90b6]',
17
+ 'alpha-qna flex items-center gap-8 text-8xl font-bold color-[#2b90b6]',
17
18
  );
18
19
  </script>
19
20
 
@@ -21,9 +22,12 @@ const { className, forwardedAttrs } = useMergedUnoAttrs(
21
22
  <div
22
23
  v-bind="forwardedAttrs()"
23
24
  :class="className()"
25
+ aria-label="Questions and answers"
26
+ role="img"
24
27
  >
25
28
  <span
26
29
  v-motion
30
+ aria-hidden="true"
27
31
  :initial="{
28
32
  opacity: 0,
29
33
  x: -500,
@@ -44,6 +48,7 @@ const { className, forwardedAttrs } = useMergedUnoAttrs(
44
48
  </span>
45
49
  <span
46
50
  v-motion
51
+ aria-hidden="true"
47
52
  :initial="{
48
53
  opacity: 1,
49
54
  y: -1_000
@@ -65,6 +70,7 @@ const { className, forwardedAttrs } = useMergedUnoAttrs(
65
70
  </span>
66
71
  <span
67
72
  v-motion
73
+ aria-hidden="true"
68
74
  :initial="{ opacity: 0, x: 500, rotate: 360 }"
69
75
  :enter="{
70
76
  opacity: 1,
@@ -24,11 +24,9 @@ const props = defineProps({
24
24
  });
25
25
 
26
26
  const { className, forwardedAttrs } = useMergedUnoAttrs(
27
- 'slidev-addon-quote flex flex-col',
27
+ 'alpha-quote flex flex-col',
28
28
  );
29
- const titleClasses = computed(() => {
30
- return mergeUno('text-center', props.titleClass);
31
- });
29
+ const titleClasses = computed(() => mergeUno('text-center', props.titleClass));
32
30
  </script>
33
31
 
34
32
  <template>
@@ -5,21 +5,20 @@ defineOptions({
5
5
  inheritAttrs: false,
6
6
  });
7
7
 
8
- defineProps({
9
- title: {
10
- type: String,
11
- required: true,
12
- },
13
- });
8
+ interface IReflectedTitleProps {
9
+ readonly title: string;
10
+ }
11
+
12
+ defineProps<IReflectedTitleProps>();
14
13
 
15
14
  const { className, forwardedAttrs } = useMergedUnoAttrs(`
16
- slidev-addon-reflected-title
15
+ alpha-reflected-title
17
16
  relative
18
17
  text-5xl
19
18
  font-bold
20
19
  tracking-tight
21
20
  !text-[#a5f3fc]
22
- after:content-[var(--title)]
21
+ after:content-[attr(data-title)]
23
22
  after:block
24
23
  after:mt-2
25
24
  after:absolute
@@ -40,10 +39,8 @@ const { className, forwardedAttrs } = useMergedUnoAttrs(`
40
39
  <template>
41
40
  <h1
42
41
  v-bind="forwardedAttrs()"
43
- :style="{
44
- '--title': `'${title}'`,
45
- }"
46
42
  :class="className()"
43
+ :data-title="title"
47
44
  >
48
45
  {{ title }}
49
46
  </h1>
@@ -1,4 +1,6 @@
1
1
  <script setup lang="ts">
2
+ import type { PropType } from 'vue';
3
+
2
4
  import { useMergedUnoAttrs } from '../../utils/useMergedUnoAttrs';
3
5
 
4
6
  defineOptions({
@@ -12,7 +14,7 @@ const props = defineProps({
12
14
  default: 'Alpha',
13
15
  },
14
16
  team: {
15
- type: Array,
17
+ type: Array as PropType<string[]>,
16
18
  required: false,
17
19
  default: () => [],
18
20
  },
@@ -23,7 +25,7 @@ const props = defineProps({
23
25
  });
24
26
 
25
27
  const { className, forwardedAttrs } = useMergedUnoAttrs(() => [
26
- 'slidev-addon-speaker flex absolute bottom-[15px] right-[30px] flex-col',
28
+ 'alpha-speaker flex absolute bottom-[15px] right-[30px] flex-col',
27
29
  props.team.length ? 'text-left gap-2' : undefined,
28
30
  ]);
29
31
  </script>
@@ -5,76 +5,30 @@ defineOptions({
5
5
  inheritAttrs: false,
6
6
  });
7
7
 
8
- defineProps({
9
- center: {
10
- type: Boolean,
11
- default: false,
12
- },
13
- idle: {
14
- type: Boolean,
15
- default: false,
16
- },
8
+ interface ITransitionHeadingProps {
9
+ readonly center?: boolean;
10
+ readonly idle?: boolean;
11
+ }
12
+
13
+ const props = withDefaults(defineProps<ITransitionHeadingProps>(), {
14
+ center: false,
15
+ idle: false,
17
16
  });
18
17
 
19
- const { className, forwardedAttrs } = useMergedUnoAttrs(`
20
- shifting-heading
21
- absolute
22
- z-1
23
- start-[var(--shifting-heading-inline,3.5rem)]
24
- top-[var(--shifting-heading-top,2.5rem)]
25
- w-max
26
- translate-x-0
27
- translate-y-0
28
- origin-left
29
- `);
18
+ const { className, forwardedAttrs } = useMergedUnoAttrs(() => [
19
+ 'alpha-transition-heading transition-all duration-700 ease-in-out absolute whitespace-nowrap',
20
+ {
21
+ 'top-[50%] left-[50%] translate-[-50%,-50%]': props.center,
22
+ 'top-[2.5rem] left-[3.5rem] translate-[0,0]': props.idle || !props.center,
23
+ },
24
+ ]);
30
25
  </script>
31
26
 
32
27
  <template>
33
28
  <div
34
29
  v-bind="forwardedAttrs()"
35
30
  :class="className()"
36
- :data-shifting-heading-state="center && !idle ? 'centered' : 'shifted'"
37
31
  >
38
32
  <slot />
39
33
  </div>
40
34
  </template>
41
-
42
- <style>
43
- .shifting-heading {
44
- max-width: calc(
45
- 100% - var(--shifting-heading-inline, 3.5rem) -
46
- var(--shifting-heading-inline, 3.5rem)
47
- );
48
- transition:
49
- inset-inline-start var(--shifting-heading-duration, 700ms) ease-in-out,
50
- top var(--shifting-heading-duration, 700ms) ease-in-out,
51
- transform var(--shifting-heading-duration, 700ms) ease-in-out;
52
- will-change: inset-inline-start, top, transform;
53
- }
54
-
55
- .shifting-heading > :is(h1, h2, h3, h4, h5, h6) {
56
- max-width: 100%;
57
- margin: 0;
58
- overflow-wrap: anywhere;
59
- text-wrap: balance;
60
- }
61
-
62
- .shifting-heading[data-shifting-heading-state='centered'] {
63
- inset-inline-start: 50%;
64
- top: 50%;
65
- text-align: center;
66
- transform: translate(-50%, -50%);
67
- transform-origin: center;
68
- }
69
-
70
- :where([dir='rtl'])
71
- .shifting-heading[data-shifting-heading-state='centered'] {
72
- transform: translate(50%, -50%);
73
- }
74
-
75
- @media (prefers-reduced-motion: reduce) {
76
- .shifting-heading {
77
- transition-duration: 1ms;
78
- }
79
- }
80
- </style>
@@ -1,12 +1,6 @@
1
1
  <script setup lang="ts">
2
2
  import type { MotionVariants, Variant } from '@vueuse/motion';
3
3
 
4
- import { useMergedUnoAttrs } from '../../utils/useMergedUnoAttrs';
5
-
6
- defineOptions({
7
- inheritAttrs: false,
8
- });
9
-
10
4
  const { animation } = defineProps({
11
5
  animation: {
12
6
  type: Boolean,
@@ -60,18 +54,10 @@ const getMotionProps = ({
60
54
  initial,
61
55
  };
62
56
  };
63
-
64
- const { className, forwardedAttrs } = useMergedUnoAttrs(
65
- 'slidev-addon-thanks-content relative h-full w-full',
66
- );
67
57
  </script>
68
58
 
69
59
  <template>
70
- <div
71
- v-bind="forwardedAttrs()"
72
- :class="className()"
73
- >
74
- <ThanksSquare
60
+ <ThanksSquare
75
61
  v-motion
76
62
  v-bind="getMotionProps({
77
63
  enter: {
@@ -85,9 +71,9 @@ const { className, forwardedAttrs } = useMergedUnoAttrs(
85
71
  y: -100,
86
72
  },
87
73
  })"
88
- class="absolute w-[150px] h-[150px] rotate-45 top-[50%] left-[40%] z-10"
89
- />
90
- <ThanksSquare
74
+ class="alpha-thanks-content absolute w-[150px] h-[150px] rotate-45 top-[50%] left-[40%] z-10"
75
+ />
76
+ <ThanksSquare
91
77
  v-motion
92
78
  v-bind="getMotionProps({
93
79
  initial: {
@@ -105,9 +91,9 @@ const { className, forwardedAttrs } = useMergedUnoAttrs(
105
91
  }
106
92
  },
107
93
  })"
108
- class="w-[100px] h-[100px] top-[20%] rotate-45 left-[48%] translate-x-[-50%] translate-y-[-50%] opacity-[0.4]"
109
- />
110
- <ThanksSquare
94
+ class="alpha-thanks-content w-[100px] h-[100px] top-[20%] rotate-45 left-[48%] translate-x-[-50%] translate-y-[-50%] opacity-[0.4]"
95
+ />
96
+ <ThanksSquare
111
97
  v-motion
112
98
  v-bind="getMotionProps({
113
99
  initial: {
@@ -125,9 +111,9 @@ const { className, forwardedAttrs } = useMergedUnoAttrs(
125
111
  }
126
112
  },
127
113
  })"
128
- class="w-[100px] h-[100px] top-[45%] rotate-45 left-[22%] translate-x-[-50%] translate-y-[-50%] opacity-[0.4]"
129
- />
130
- <ThanksSquare
114
+ class="alpha-thanks-content w-[100px] h-[100px] top-[45%] rotate-45 left-[22%] translate-x-[-50%] translate-y-[-50%] opacity-[0.4]"
115
+ />
116
+ <ThanksSquare
131
117
  v-motion
132
118
  v-bind="getMotionProps({
133
119
  initial: {
@@ -145,9 +131,9 @@ const { className, forwardedAttrs } = useMergedUnoAttrs(
145
131
  }
146
132
  },
147
133
  })"
148
- class="w-[100px] h-[100px] bottom-0 rotate-45 left-[48%] translate-x-[-50%] translate-y-[-50%] opacity-[0.4]"
149
- />
150
- <ThanksOutlineSquare
134
+ class="alpha-thanks-content w-[100px] h-[100px] bottom-0 rotate-45 left-[48%] translate-x-[-50%] translate-y-[-50%] opacity-[0.4]"
135
+ />
136
+ <ThanksOutlineSquare
151
137
  v-motion
152
138
  v-bind="getMotionProps({
153
139
  initial: {
@@ -165,9 +151,9 @@ const { className, forwardedAttrs } = useMergedUnoAttrs(
165
151
  },
166
152
  },
167
153
  })"
168
- class="w-[120px] h-[120px] rotate-45 top-[25%] left-[31%]"
169
- />
170
- <ThanksOutlineSquare
154
+ class="alpha-thanks-content w-[120px] h-[120px] rotate-45 top-[25%] left-[31%]"
155
+ />
156
+ <ThanksOutlineSquare
171
157
  v-motion
172
158
  v-bind="getMotionProps({
173
159
  initial: {
@@ -185,9 +171,9 @@ const { className, forwardedAttrs } = useMergedUnoAttrs(
185
171
  },
186
172
  },
187
173
  })"
188
- class="w-[70px] h-[70px] rotate-45 top-[52%] left-[30%]"
189
- />
190
- <ThanksOutlineSquare
174
+ class="alpha-thanks-content w-[70px] h-[70px] rotate-45 top-[52%] left-[30%]"
175
+ />
176
+ <ThanksOutlineSquare
191
177
  v-motion
192
178
  v-bind="getMotionProps({
193
179
  initial: {
@@ -205,31 +191,30 @@ const { className, forwardedAttrs } = useMergedUnoAttrs(
205
191
  },
206
192
  },
207
193
  })"
208
- class="w-[100px] h-[100px] rotate-45 top-[42%] left-[43%]"
209
- />
194
+ class="alpha-thanks-content w-[100px] h-[100px] rotate-45 top-[42%] left-[43%]"
195
+ />
210
196
 
211
- <div
212
- v-motion
213
- v-bind="getMotionProps({
214
- initial: {
215
- x: -80,
216
- opacity: 0,
217
- },
218
- enter: {
219
- x: -130,
220
- y: -46,
221
- opacity: 1,
222
- transition: {
223
- delay: 2_800,
224
- duration: 1_000,
225
- }
226
- },
227
- })"
228
- class="color-[#2b90b6] text-3xl absolute top-[50%] left-[69%] translate-x-[-50%] translate-y-[-50%]"
229
- >
230
- Thank You
231
- <br />
232
- for your attention!
233
- </div>
197
+ <div
198
+ v-motion
199
+ v-bind="getMotionProps({
200
+ initial: {
201
+ x: -80,
202
+ opacity: 0,
203
+ },
204
+ enter: {
205
+ x: -130,
206
+ y: -46,
207
+ opacity: 1,
208
+ transition: {
209
+ delay: 2_800,
210
+ duration: 1_000,
211
+ }
212
+ },
213
+ })"
214
+ class="alpha-thanks-content color-[#2b90b6] text-3xl absolute top-[50%] left-[69%] translate-x-[-50%] translate-y-[-50%]"
215
+ >
216
+ Thank You
217
+ <br />
218
+ for your attention!
234
219
  </div>
235
220
  </template>
@@ -6,7 +6,7 @@ defineOptions({
6
6
  });
7
7
 
8
8
  const { className, forwardedAttrs } = useMergedUnoAttrs(
9
- 'slidev-addon-thanks-outline-square absolute rounded-2xl border-2 border-color-cyan-500',
9
+ 'alpha-thanks-outline-square absolute rounded-2xl border-2 border-color-cyan-500',
10
10
  );
11
11
  </script>
12
12
 
@@ -6,7 +6,7 @@ defineOptions({
6
6
  });
7
7
 
8
8
  const { className, forwardedAttrs } = useMergedUnoAttrs(
9
- 'slidev-addon-thanks-square absolute bg-gradient-to-br from-cyan-500 to-blue-500 rounded-3xl',
9
+ 'alpha-thanks-square absolute bg-gradient-to-br from-cyan-500 to-blue-500 rounded-3xl',
10
10
  );
11
11
  </script>
12
12
 
@@ -19,7 +19,7 @@ const style = computed(() => {
19
19
  });
20
20
 
21
21
  const { className, forwardedAttrs } = useMergedUnoAttrs(
22
- 'slidev-layout bg-center h-full grid place-content-center',
22
+ 'alpha-bg-center slidev-layout bg-center h-full grid place-content-center',
23
23
  );
24
24
  </script>
25
25
 
@@ -13,7 +13,7 @@ defineProps({
13
13
  });
14
14
 
15
15
  const { className, forwardedAttrs } = useMergedUnoAttrs(
16
- 'slidev-layout default toc-layout',
16
+ 'alpha-table-of-contents slidev-layout default toc-layout',
17
17
  );
18
18
  </script>
19
19
 
@@ -1,41 +1,37 @@
1
1
  <script setup lang="ts">
2
2
  import { useSlideContext } from '@slidev/client';
3
- import { computed, Fragment, isVNode, useSlots, type VNode } from 'vue';
3
+ import { ref, shallowRef, useSlots, watch, watchEffect } from 'vue';
4
4
 
5
+ import { collectShiftingIntroNodes } from '../../utils/shiftingHeading/collectShiftingIntroNodes';
5
6
  import { useMergedUnoAttrs } from '../../utils/useMergedUnoAttrs';
6
7
 
7
8
  defineOptions({
8
9
  inheritAttrs: false,
9
10
  });
10
11
 
12
+ const context = useSlideContext();
11
13
  const slots = useSlots();
12
- const { $clicks } = useSlideContext();
14
+ const { $clicks } = context;
13
15
 
14
- function flattenTopLevel(nodes: VNode[]): VNode[] {
15
- return nodes.flatMap((node) => {
16
- if (node.type === Fragment && Array.isArray(node.children))
17
- return flattenTopLevel(node.children.filter(isVNode));
16
+ const delayClass = ref('delay-600');
18
17
 
19
- return node;
20
- });
21
- }
18
+ watch($clicks, (newVal, oldVal) => {
19
+ if (newVal > oldVal) {
20
+ delayClass.value = 'delay-600';
21
+ } else {
22
+ delayClass.value = 'delay-0';
23
+ }
24
+ });
22
25
 
23
- const nodes = computed(() => {
24
- const children = flattenTopLevel(slots.default?.() ?? []);
25
- const titleIndex = children.findIndex((node) => node.type === 'h1');
26
+ const nodes = shallowRef(collectShiftingIntroNodes([]));
26
27
 
27
- return {
28
- title: titleIndex >= 0 ? children[titleIndex] : null,
29
- contents:
30
- titleIndex >= 0
31
- ? children.filter((_, index) => index !== titleIndex)
32
- : children,
33
- };
28
+ watchEffect(() => {
29
+ const children = slots.default?.() || [];
30
+ nodes.value = collectShiftingIntroNodes(children);
34
31
  });
35
32
 
36
- const isRevealed = computed(() => !nodes.value.title || $clicks.value > 0);
37
33
  const { className, forwardedAttrs } = useMergedUnoAttrs(
38
- 'slidev-layout shifting-intro-layout relative',
34
+ 'alpha-shifting-intro slidev-layout shifting-intro-layout',
39
35
  );
40
36
  </script>
41
37
 
@@ -44,68 +40,41 @@ const { className, forwardedAttrs } = useMergedUnoAttrs(
44
40
  v-bind="forwardedAttrs()"
45
41
  :class="className()"
46
42
  >
43
+ <component
44
+ :is="nodes.title"
45
+ v-if="nodes.title"
46
+ aria-hidden="true"
47
+ class="op-0"
48
+ />
47
49
  <TransitionHeading
48
50
  v-if="nodes.title"
49
- :center="!isRevealed"
50
- :idle="isRevealed"
51
+ :idle="$clicks !== 0"
52
+ :center="$clicks === 0"
51
53
  >
52
54
  <component :is="nodes.title" />
53
55
  </TransitionHeading>
54
-
55
- <VClickGap
56
- v-if="nodes.title"
57
- :size="1"
56
+ <div
57
+ v-click
58
+ class="hidden"
58
59
  />
59
-
60
60
  <div
61
- class="shifting-intro-content"
62
- :class="{ 'is-revealed': isRevealed }"
63
- :aria-hidden="!isRevealed"
64
- :inert="!isRevealed || undefined"
61
+ class="transition-all duration-1000"
62
+ :class="[
63
+ $clicks > 0 ? 'opacity-100' : 'opacity-0',
64
+ delayClass,
65
+ ]"
65
66
  >
66
- <component
67
- :is="content"
68
- v-for="(content, index) in nodes.contents"
69
- :key="content.key ?? index"
70
- />
67
+ <template v-for="(content) in nodes.contents" :key="content.key">
68
+ <component
69
+ v-if="nodes.clickRef.has(content.key)"
70
+ :is="content.node"
71
+ v-click="nodes.clickRef.get(content.key)"
72
+ />
73
+ <component
74
+ v-else
75
+ :is="content.node"
76
+ />
77
+ </template>
71
78
  </div>
72
79
  </div>
73
80
  </template>
74
-
75
- <style>
76
- .shifting-intro-content {
77
- box-sizing: border-box;
78
- min-height: 100%;
79
- padding-top: var(--shifting-heading-content-offset, 4.25rem);
80
- visibility: hidden;
81
- opacity: 0;
82
- transition:
83
- opacity var(--shifting-content-exit-duration, 250ms) ease-out,
84
- visibility 0s linear var(--shifting-content-exit-duration, 250ms);
85
- }
86
-
87
- .shifting-intro-content.is-revealed {
88
- visibility: visible;
89
- opacity: 1;
90
- transition:
91
- opacity var(--shifting-content-duration, 700ms) ease-out
92
- var(--shifting-content-delay, 450ms),
93
- visibility 0s linear;
94
- }
95
-
96
- @media (prefers-reduced-motion: reduce) {
97
- .shifting-intro-content,
98
- .shifting-intro-content.is-revealed {
99
- transition-duration: 1ms;
100
- transition-delay: 0ms;
101
- }
102
- }
103
-
104
- @media print {
105
- .shifting-heading,
106
- .shifting-intro-content,
107
- .shifting-intro-content.is-revealed {
108
- transition: none;
109
- }
110
- }
111
- </style>
@@ -6,7 +6,7 @@ defineOptions({
6
6
  });
7
7
 
8
8
  const { className, forwardedAttrs } = useMergedUnoAttrs(
9
- 'slidev-layout thanks relative',
9
+ 'alpha-thanks slidev-layout thanks',
10
10
  );
11
11
  </script>
12
12
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alphacifer/slidev-addon-theme",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "description": "All Slidev addons for Alpha presentations",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -0,0 +1,74 @@
1
+ import type { Directive, VNode } from 'vue';
2
+
3
+ interface IShiftingIntroContent {
4
+ readonly key: number;
5
+ readonly node: VNode;
6
+ }
7
+
8
+ export interface IShiftingIntroNodes {
9
+ readonly title: VNode | null;
10
+ readonly clickRef: ReadonlyMap<number, number>;
11
+ readonly contents: readonly IShiftingIntroContent[];
12
+ }
13
+
14
+ const CLICK_DIRECTIVE_NAMES = new Set(['click', 'v-click', 'vClick']);
15
+
16
+ const getDirectiveName = (directive: Directive): string | undefined => {
17
+ if (typeof directive === 'function') {
18
+ return directive.name;
19
+ }
20
+
21
+ if ('name' in directive && typeof directive.name === 'string') {
22
+ return directive.name;
23
+ }
24
+
25
+ return undefined;
26
+ };
27
+
28
+ const hasImplicitClickDirective = (node: VNode): boolean => {
29
+ return Boolean(
30
+ node.dirs?.some(({ dir, value }) => {
31
+ const name = getDirectiveName(dir);
32
+ return (
33
+ name !== undefined &&
34
+ CLICK_DIRECTIVE_NAMES.has(name) &&
35
+ value === undefined
36
+ );
37
+ }),
38
+ );
39
+ };
40
+
41
+ /**
42
+ * Separates the first heading from a shifting-intro slot and remaps implicit
43
+ * v-click directives after the layout's internal reveal click.
44
+ */
45
+ export const collectShiftingIntroNodes = (
46
+ children: readonly VNode[],
47
+ ): IShiftingIntroNodes => {
48
+ let title: VNode | null = null;
49
+ let clickIndex = 1;
50
+ const clickRef = new Map<number, number>();
51
+ const contents: IShiftingIntroContent[] = [];
52
+
53
+ children.forEach((node, key) => {
54
+ if (title === null && node.type === 'h1') {
55
+ title = node;
56
+ } else {
57
+ contents.push({
58
+ key,
59
+ node,
60
+ });
61
+ }
62
+
63
+ if (hasImplicitClickDirective(node)) {
64
+ clickIndex += 1;
65
+ clickRef.set(key, clickIndex);
66
+ }
67
+ });
68
+
69
+ return {
70
+ title,
71
+ clickRef,
72
+ contents,
73
+ };
74
+ };