ep-lib-ts 1.0.24 → 1.0.26

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 (137) hide show
  1. package/dist/BgAudio-BOuJmZ4Z.js +4 -0
  2. package/dist/DisplayBox-hI9I354I.js +4 -0
  3. package/dist/EpAlert-CNC4jPvV.js +4 -0
  4. package/dist/EpAudio-BFzs1CCB.js +4 -0
  5. package/dist/EpBadge-LjMj7s1q.js +4 -0
  6. package/dist/EpBarChart-mFktWWHN.js +4 -0
  7. package/dist/EpBtn-3_tn7E6D.js +4 -0
  8. package/dist/EpCard-CwLnvlZs.js +4 -0
  9. package/dist/EpChip-BmJNCeuv.js +4 -0
  10. package/dist/EpConclusion-Bo5-jNPy.js +4 -0
  11. package/dist/EpContentSlider-CHgd9CBo.js +4 -0
  12. package/dist/EpDarkmode-DdqwsLJI.js +48 -0
  13. package/dist/EpDescription-Kbh-pnvx.js +4 -0
  14. package/dist/EpDivider-xLnjVUkj.js +4 -0
  15. package/dist/EpEdu-DI6qOWw1.js +4 -0
  16. package/dist/EpFlex-mQrhJu8J.js +4 -0
  17. package/dist/EpFunnelChart-CTbZegv2.js +4 -0
  18. package/dist/EpHeader-MY25ggLC.js +4 -0
  19. package/dist/{EpHover-jrnI89yN.js → EpHover-CF0mr0kn.js} +1 -1
  20. package/dist/EpIcon-CMHojBr5.js +4 -0
  21. package/dist/EpIframe-E_puwUIb.js +4 -0
  22. package/dist/EpImg-C5Kwf7od.js +4 -0
  23. package/dist/{EpInput-DzvG0ONW.js → EpInput-Cfl4JH1l.js} +22 -22
  24. package/dist/EpInstructions-nM-IK120.js +4 -0
  25. package/dist/EpIntroduction-DiF_d3pZ.js +4 -0
  26. package/dist/EpLineChart-BkQwacog.js +4 -0
  27. package/dist/EpLink-BP6HIdnn.js +4 -0
  28. package/dist/EpLinkVersion-ChbNAqrS.js +4 -0
  29. package/dist/{EpList-_qae9uHP.js → EpList-BL9yIb5h.js} +1 -1
  30. package/dist/EpModal-CDjsyRvM.js +4 -0
  31. package/dist/{EpNothing-CDSj0X4K.js → EpNothing-B0xLzA9P.js} +1 -1
  32. package/dist/EpObjective-Bt3hflqk.js +4 -0
  33. package/dist/EpPieChart-Dv8DGZSF.js +4 -0
  34. package/dist/EpQuestion-lEHBGz0S.js +4 -0
  35. package/dist/EpQuote-B1YA7A6I.js +4 -0
  36. package/dist/EpRadio-C8r7s7W-.js +4 -0
  37. package/dist/EpRadioSummative-Cv6MYTv6.js +4 -0
  38. package/dist/EpReading-DQcDGfZb.js +4 -0
  39. package/dist/EpResource-DyyoUvuJ.js +4 -0
  40. package/dist/EpScope-BqyU2wlf.js +4 -0
  41. package/dist/EpSection-DOd8aziF.js +4 -0
  42. package/dist/EpSelect-FIb6SyJU.js +32 -0
  43. package/dist/EpSkeleton-B1XRyOwZ.js +4 -0
  44. package/dist/EpSoftware-D6X8AHJK.js +4 -0
  45. package/dist/EpSpecificObjective-DkH5m09k.js +4 -0
  46. package/dist/EpSpinner-DTecXUJS.js +4 -0
  47. package/dist/EpSummativeTable-Cd7jQAbl.js +4 -0
  48. package/dist/EpSvg-Cl7JQ9X8.js +4 -0
  49. package/dist/EpTable-BF4JWCJY.js +4 -0
  50. package/dist/EpTerm-Dgll69TG.js +4 -0
  51. package/dist/EpText-D_iQAE-U.js +4 -0
  52. package/dist/EpTimeLine-DWjocTaz.js +4 -0
  53. package/dist/EpVideo-B1b7SFoO.js +4 -0
  54. package/dist/EpVideoPanopto-BrZDfrND.js +4 -0
  55. package/dist/EpWordDef-DRxF8rWC.js +4 -0
  56. package/dist/components/basics/EpChip.vue.d.ts +1 -1
  57. package/dist/components/basics/EpIcon.vue.d.ts +1 -1
  58. package/dist/components/charts/EpFunnelChart.vue.d.ts +1 -1
  59. package/dist/components/charts/EpPieChart.vue.d.ts +1 -1
  60. package/dist/components/educationals/EpConclusion.vue.d.ts +39 -0
  61. package/dist/components/educationals/EpDescription.vue.d.ts +39 -0
  62. package/dist/components/educationals/EpInstructions.vue.d.ts +36 -0
  63. package/dist/components/educationals/EpIntroduction.vue.d.ts +39 -0
  64. package/dist/components/educationals/EpObjective.vue.d.ts +39 -0
  65. package/dist/components/educationals/EpSpecificObjective.vue.d.ts +40 -0
  66. package/dist/components/forms/EpSelect.vue.d.ts +15 -86
  67. package/dist/components/interactions/EpAccordeon.vue.d.ts +1 -0
  68. package/dist/components/interactions/EpContentSlider.vue.d.ts +4 -0
  69. package/dist/components/signages/EpHeader.vue.d.ts +4 -0
  70. package/dist/components/signages/EpSkeleton.vue.d.ts +6 -2
  71. package/dist/ep-lib-ts.js +46 -40
  72. package/dist/ep-lib-ts.umd.cjs +70 -52
  73. package/dist/{index-nKuHdZUR.js → index-BDcKL8U6.js} +4833 -4538
  74. package/dist/index.d.ts +7 -1
  75. package/dist/style.css +1 -1
  76. package/dist/types/Answer.d.ts +17 -0
  77. package/package.json +2 -2
  78. package/src/components/basics/EpFlex.vue +1 -0
  79. package/src/components/basics/EpSection.vue +5 -9
  80. package/src/components/educationals/EpConclusion.vue +38 -0
  81. package/src/components/educationals/EpDescription.vue +38 -0
  82. package/src/components/educationals/EpInstructions.vue +48 -0
  83. package/src/components/educationals/EpIntroduction.vue +38 -0
  84. package/src/components/educationals/EpObjective.vue +41 -0
  85. package/src/components/educationals/EpReading.vue +1 -1
  86. package/src/components/educationals/EpSpecificObjective.vue +42 -0
  87. package/src/components/forms/EpSelect.vue +18 -154
  88. package/src/components/interactions/EpAccordeon.vue +5 -4
  89. package/src/components/interactions/EpContentSlider.vue +132 -97
  90. package/src/components/interactions/EpDarkmode.vue +22 -40
  91. package/src/components/signages/EpHeader.vue +68 -46
  92. package/src/components/signages/EpSkeleton.vue +8 -4
  93. package/dist/BgAudio-BjiZt_j3.js +0 -4
  94. package/dist/DisplayBox-DZa_LWHr.js +0 -4
  95. package/dist/EpAlert-CIOmWSIc.js +0 -4
  96. package/dist/EpAudio-B3cP0yQP.js +0 -4
  97. package/dist/EpBadge-Rn_GnxQe.js +0 -4
  98. package/dist/EpBarChart-D3XffoUi.js +0 -4
  99. package/dist/EpBtn-DHEEdI-A.js +0 -4
  100. package/dist/EpCard-CKZOUaVF.js +0 -4
  101. package/dist/EpChip-ClMvRgwG.js +0 -4
  102. package/dist/EpContentSlider-BPQRgnys.js +0 -4
  103. package/dist/EpDarkmode-4w7onxHI.js +0 -26
  104. package/dist/EpDivider-CAdkeSwX.js +0 -4
  105. package/dist/EpEdu-Ccx2WVen.js +0 -4
  106. package/dist/EpFlex-BObUghJr.js +0 -4
  107. package/dist/EpFunnelChart-Pe4XXTya.js +0 -4
  108. package/dist/EpHeader-DvJyyMGC.js +0 -4
  109. package/dist/EpIcon-BfZrj1D0.js +0 -4
  110. package/dist/EpIframe-DpKYSJNh.js +0 -4
  111. package/dist/EpImg-B_oxNdE8.js +0 -4
  112. package/dist/EpLineChart-D1McKT4Z.js +0 -4
  113. package/dist/EpLink-Bad9NyI9.js +0 -4
  114. package/dist/EpLinkVersion-on-9nSh-.js +0 -4
  115. package/dist/EpModal-Ca6mOjLn.js +0 -4
  116. package/dist/EpPieChart-Bl-OovwP.js +0 -4
  117. package/dist/EpQuestion-_cynbj44.js +0 -4
  118. package/dist/EpQuote-DSGsPnu9.js +0 -4
  119. package/dist/EpRadio-BCYQ80gI.js +0 -4
  120. package/dist/EpRadioSummative-KuZyk9G2.js +0 -4
  121. package/dist/EpReading-BZJk9RUD.js +0 -4
  122. package/dist/EpResource-MAdgbl2P.js +0 -4
  123. package/dist/EpScope-C2BEnXHN.js +0 -4
  124. package/dist/EpSection-DIbMpikL.js +0 -4
  125. package/dist/EpSelect-afhma1pl.js +0 -43
  126. package/dist/EpSkeleton-DdosLRVb.js +0 -4
  127. package/dist/EpSoftware-DpNVZY3o.js +0 -4
  128. package/dist/EpSpinner-9KW8OFR4.js +0 -4
  129. package/dist/EpSummativeTable-CXjHg8Dh.js +0 -4
  130. package/dist/EpSvg-Dnr8vgDv.js +0 -4
  131. package/dist/EpTable-BRt9Ps0H.js +0 -4
  132. package/dist/EpTerm-B3bSXeXd.js +0 -4
  133. package/dist/EpText-CB8XAfzb.js +0 -4
  134. package/dist/EpTimeLine-BUxl5jo5.js +0 -4
  135. package/dist/EpVideo-DxEYZmn1.js +0 -4
  136. package/dist/EpVideoPanopto-BtGdfGz9.js +0 -4
  137. package/dist/EpWordDef-DUa6sNjb.js +0 -4
@@ -1,142 +1,177 @@
1
1
  <script setup lang="ts">
2
- import { ref, computed, defineAsyncComponent, toRefs, Suspense } from "vue";
3
- import { type SlidesType } from "../../types/Slides"
2
+ import { ref, computed, defineAsyncComponent, watch, onMounted, nextTick, ComponentPublicInstance } from "vue";
3
+ import { type SlidesType } from "../../types/Slides";
4
4
  import { useComponent } from "../../composables/useComponent";
5
5
  import { useRenderText } from "../../composables/useRenderText";
6
- import { mdiArrowLeft } from "@mdi/js";
7
- import { mdiArrowRight } from "@mdi/js";
6
+ import { mdiArrowLeft, mdiArrowRight } from "@mdi/js";
8
7
  import EpIcon from "../basics/EpIcon.vue";
9
-
8
+ import EpSkeleton from "../signages/EpSkeleton.vue";
10
9
 
11
10
  interface Props {
12
11
  slides: SlidesType[];
13
- loading?:string,
14
- noData?:string
12
+ loading?: string;
13
+ noData?: string;
14
+ mediaPosition?: 'left' | 'right';
15
15
  }
16
16
 
17
17
  const props = withDefaults(defineProps<Props>(), {
18
- loading:"...loading",
19
- noData:"no data"
20
-
21
- })
22
-
18
+ loading: "...loading",
19
+ noData: "No data available",
20
+ mediaPosition: "left",
21
+ });
23
22
 
24
- const currentIndex = ref<number>(0)
23
+ const currentIndex = ref(0);
24
+ const isLoading = ref(false);
25
+ const slideRefs = ref<(HTMLElement | null)[]>([]);
25
26
 
26
27
  const currentSlide = computed(() => {
27
- if (!props.slides) {
28
- return { title: props.noData, img: '', uid: 2, content: "", component:null }
28
+ if (!props.slides || props.slides.length === 0) {
29
+ return { title: props.noData, img: '', uid: 2, content: "", component: null };
29
30
  }
30
- if (props.slides.length === 0) {
31
- return { title: props.noData, img: '', uid: 2, content: "", component:null }
32
- }
33
- return props.slides[currentIndex.value]
34
- })
31
+ return props.slides[currentIndex.value];
32
+ });
35
33
 
36
34
  const hasTextContent = computed(() => {
37
- return currentSlide.value.content.trim().length > 0
38
- })
35
+ const content = currentSlide.value.content;
36
+ return content && content.trim().length > 0;
37
+ });
39
38
 
40
39
  const currentSlideMediaContent = computed(() => {
41
40
  if (currentSlide.value.img) {
42
- return defineAsyncComponent(() => import('../basics/EpImg.vue'))
41
+ return defineAsyncComponent(() => import('../basics/EpImg.vue'));
43
42
  }
44
43
  if (currentSlide.value.component) {
45
- const componentToLoad = useComponent(currentSlide.value.component?.type)
46
- return defineAsyncComponent(() => import(`../${componentToLoad.path}/${componentToLoad.name}.vue`))
44
+ const componentToLoad = useComponent(currentSlide.value.component?.type);
45
+ return defineAsyncComponent(() => import(`../${componentToLoad.path}/${componentToLoad.name}.vue`));
47
46
  }
48
- return null
49
- })
47
+ return null;
48
+ });
49
+
50
+ const max = computed(() => currentIndex.value < props.slides.length - 1);
50
51
 
51
- const max = computed(() => (currentIndex.value + 1) < props.slides.length)
52
- const min = computed(() => (currentIndex.value + 1) > 1)
53
- const next = () => {
52
+ const next = async () => {
53
+ isLoading.value = true;
54
54
  if (max.value) {
55
- currentIndex.value += 1
55
+ currentIndex.value += 1;
56
56
  }
57
- }
57
+ isLoading.value = false;
58
+ };
58
59
 
59
- const prev = () => {
60
- if (min.value) {
61
- currentIndex.value -= 1
60
+ const prev = async () => {
61
+ isLoading.value = true;
62
+ if (currentIndex.value > 0) {
63
+ currentIndex.value -= 1;
62
64
  }
63
- }
65
+ isLoading.value = false;
66
+ };
64
67
 
65
- const goTo = (index: number) => {
66
- currentIndex.value = index
67
- }
68
-
69
- const { slides } = toRefs(props)
68
+ const goTo = (index: number) => currentIndex.value = index;
70
69
 
70
+ const updateSlideRefs = (el: Element | ComponentPublicInstance | null, index: number) => {
71
+ if (el instanceof HTMLElement) {
72
+ slideRefs.value[index] = el;
73
+ } else {
74
+ slideRefs.value[index] = null;
75
+ }
76
+ };
71
77
  </script>
72
78
 
79
+
73
80
  <template>
74
- <div class="bg-stone-100 dark:bg-dark p-5 w-full md:h-custom overflow-hidden dark:border dark:border-base">
75
- <div class="flex justify-between border-b border-black dark:border-white w-auto">
76
- <h5 class="text-lg border-b-4 border-black dark:border-white">
77
- {{ currentSlide.title }}
78
- </h5>
79
- <div class="md:flex items-end pb-1" v-if="slides">
80
- <template v-for="(slide, i) in slides.length" :key="`slide-index-${i}`">
81
- <span
82
- :class="`cursor-pointer h-4 w-4 ml-1 inline-block ${i === currentIndex ? 'bg-primary' : 'bg-base-dark dark:bg-base-light'}`"
83
- @click="goTo(i)"></span>
84
- </template>
85
- <span class="ml-2 text-xs">({{ (currentIndex + 1) }}/{{ slides.length }})</span>
86
- <button :class="`px-2 ${min ? '' : 'opacity-5'}`" @click="prev">
87
- <EpIcon :icon-path="mdiArrowLeft" size="24"></EpIcon>
88
- </button>
89
- <button :class="`mx-2 ${max ? '' : 'opacity-5'}`" @click="next">
90
- <EpIcon :icon-path="mdiArrowRight" size="24"></EpIcon>
91
- </button>
81
+ <div
82
+ class="relative h-[600px] flex flex-col p-6 bg-zinc-100 dark:bg-dark w-full overflow-hidden rounded-lg shadow-xl">
83
+ <!-- Header section with navigation -->
84
+ <div class="flex justify-between items-center pb-3 mb-3 border-b-2 border-gray-600 dark:border-gray-300">
85
+ <h5 class="text-xl font-bold text-primary">{{ currentSlide.title }}</h5>
86
+ <div class="flex items-center space-x-3" v-if="props.slides.length">
87
+ <!-- Bullets -->
88
+ <div class="flex space-x-2">
89
+ <span v-for="(_, i) in props.slides.length" :key="`slide-index-${i}`" @click="goTo(i)" :class="[
90
+ 'w-2 h-2 rounded-full cursor-pointer',
91
+ i === currentIndex ? 'bg-primary' : 'bg-gray-400'
92
+ ]"></span>
93
+ </div>
94
+
95
+ <!-- Controls -->
96
+ <div class="flex space-x-2">
97
+ <button class="nav-btn" @click="prev" :disabled="currentIndex === 0">
98
+ <EpIcon :icon-path="mdiArrowLeft" size="24" />
99
+ </button>
100
+ <button class="nav-btn" @click="next" :disabled="!max">
101
+ <EpIcon :icon-path="mdiArrowRight" size="24" />
102
+ </button>
103
+ </div>
104
+ <span class="text-sm">{{ currentIndex + 1 }} / {{ props.slides.length }}</span>
92
105
  </div>
93
106
  </div>
94
- <div class="">
95
- <Transition name="list" mode="out-in">
96
- <div class="md:flex p-4" :key="currentSlide.uid">
97
- <div :class="`w-full ${hasTextContent ? 'mr-5' : ''}`" v-if="currentSlideMediaContent">
98
- <div v-if="currentSlide.img" class="p-4">
99
- <component :is="currentSlideMediaContent" :src="currentSlide.img" cols="11"></component>
100
- </div>
101
- <div v-else-if="currentSlide.component">
107
+
108
+ <!-- Slider content -->
109
+ <div class="flex flex-grow items-center justify-center overflow-hidden mb-4">
110
+ <transition name="slide-fade" mode="out-in">
111
+ <div v-if="props.slides.length > 0" :key="currentSlide.uid"
112
+ :ref="el => updateSlideRefs(el, currentIndex)" :class="[
113
+ 'flex w-full h-full gap-2',
114
+ hasTextContent ? (props.mediaPosition === 'left' ? 'flex-row' : 'flex-row-reverse'): 'justify-center'
115
+ ]">
116
+ <div v-if="isLoading" class="flex items-center justify-center w-full h-full">
117
+ <EpSkeleton :type="'rectangle'" :height="100" :width="100" :loading="true" />
118
+ </div>
119
+
120
+ <div v-else-if="!hasTextContent && !currentSlideMediaContent"
121
+ class="flex items-center justify-center w-full h-full">
122
+ <EpSkeleton class="p-4" :type="'rectangle'" :height="150" :width="150" :loading="true" />
123
+ </div>
124
+
125
+ <!-- Media content -->
126
+ <div v-if="currentSlideMediaContent" class="flex items-center justify-center p-2 md:w-1/2 w-full"
127
+ style="max-height: 100%;">
128
+
129
+ <!--condition is img-->
130
+ <template v-if="currentSlide.img">
131
+ <component :is="currentSlideMediaContent" :src="currentSlide.img" cols="11"
132
+ class="max-h-full max-w-full object-contain" :style="{
133
+ height: 'auto',
134
+ maxHeight: '100%',
135
+ objectFit: 'contain',
136
+ margin: 'auto',
137
+ }"></component>
138
+ </template>
139
+ <template v-else-if="currentSlide.component">
102
140
  <Suspense>
103
-
104
- <component :is="currentSlideMediaContent" v-bind="{ ...currentSlide.component.data }">
105
- </component>
141
+ <component :is="currentSlideMediaContent" v-bind="{ ...currentSlide.component.data }"
142
+ cols="11" class="max-h-full max-w-full object-contain" :style="{
143
+ height: 'auto',
144
+ maxHeight: '100%',
145
+ objectFit: 'contain',
146
+ margin: 'auto',
147
+ }">
148
+ </component>
106
149
  <template #fallback>
107
150
  {{ loading }}
108
151
  </template>
109
152
  </Suspense>
110
-
111
- </div>
153
+ </template>
154
+
155
+
112
156
 
113
157
  </div>
114
- <div class="w-full pt-4" v-if="hasTextContent">
115
- <div class="overflow-y-auto h-96 p-custom" v-html="useRenderText(currentSlide.content)"></div>
116
- </div>
117
- </div>
118
- </Transition>
119
- </div>
120
- </div>
121
- </template>
122
- <style>
123
- .list-enter-active,
124
- .list-leave-active {
125
- transition: all 0.5s ease;
126
- }
127
158
 
128
- .list-enter-from,
129
- .list-leave-to {
130
- opacity: 0;
131
- transform: translateX(30px);
132
- }
133
159
 
134
- .h-custom {
135
- height: 30rem;
136
- }
137
160
 
138
- .p-custom p {
139
- margin-bottom: 1em;
140
- }
141
- </style>
161
+ <!-- Text content -->
162
+ <div v-if="hasTextContent" class="flex-1 p-2 overflow-y-auto md:w-1/2 w-full">
163
+ <div v-html="useRenderText(currentSlide.content)"
164
+ class="text-base leading-relaxed text-black dark:text-white">
165
+ </div>
166
+ </div>
167
+ </div>
168
+ </transition>
169
+ </div>
142
170
 
171
+ <!-- Progress bar -->
172
+ <div class="mt-2 h-2 w-full bg-gray-300 rounded-full">
173
+ <div class="bg-primary h-full rounded-full transition-all duration-300"
174
+ :style="{ width: ((currentIndex + 1) / props.slides.length) * 100 + '%' }"></div>
175
+ </div>
176
+ </div>
177
+ </template>
@@ -1,62 +1,44 @@
1
1
  <script setup lang="ts">
2
2
  import { ref, onMounted } from 'vue';
3
3
  import { useColorMode } from '@vueuse/core'
4
+
4
5
  type UserTheme = 'light' | 'dark';
5
6
  const mode = useColorMode()
6
7
  const emit = defineEmits<{
7
- (e: "update:userMode", userMode:UserTheme): void;
8
+ (e: "update:userMode", userMode: UserTheme): void;
8
9
  }>();
9
10
 
11
+ const getTheme = (): UserTheme => {
12
+ return (localStorage.getItem('user-theme') as UserTheme) || 'light';
13
+ };
14
+
15
+ const userTheme = ref<UserTheme>(getTheme());
10
16
 
11
17
  const setTheme = (theme: UserTheme) => {
12
18
  localStorage.setItem('user-theme', theme);
13
- mode.value = theme
14
- userTheme.value = theme;
19
+ mode.value = theme;
15
20
  document.documentElement.className = theme;
16
- };
17
-
18
- const getTheme = (): UserTheme => {
19
- const localValue = localStorage.getItem('user-theme') as UserTheme;
20
- mode.value = localValue
21
- return localValue
21
+ userTheme.value = theme;
22
+ emit('update:userMode', theme);
22
23
  };
23
24
 
24
25
  const toggleTheme = (): void => {
25
- const activeTheme = localStorage.getItem('user-theme');
26
- if (activeTheme === 'light') {
27
- setTheme('dark');
28
- } else {
29
- setTheme('light');
30
- }
31
- emit('update:userMode', userTheme.value)
32
- };
33
-
34
- const getMediaPreference = (): UserTheme => {
35
- const hasDarkPreference = window.matchMedia('(prefers-color-scheme: dark)').matches;
36
- if (hasDarkPreference) {
37
- return 'dark';
38
- } else {
39
- return 'light';
40
- }
26
+ const nextTheme = userTheme.value === 'light' ? 'dark' : 'light';
27
+ setTheme(nextTheme);
41
28
  };
42
29
 
43
-
44
-
45
- const userTheme = ref<UserTheme>(getTheme() || getMediaPreference());
46
-
47
30
  onMounted(() => {
48
- setTheme(userTheme.value)
49
- emit("update:userMode", userTheme.value)
31
+ setTheme(userTheme.value);
50
32
  });
51
33
  </script>
52
34
 
53
35
  <template>
54
- <button @click="toggleTheme">
55
- <span v-if="userTheme === 'dark'">
56
- ☀️
57
- </span>
58
- <span v-if="userTheme === 'light'">
59
- 🌙
60
- </span>
61
- </button>
62
- </template>
36
+ <button @click="toggleTheme" class="p-2 rounded-full transition-colors duration-300 hover:bg-gray-700 hover:scale-105">
37
+ <span v-if="userTheme === 'dark'" title="Switch to light mode">
38
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-sun"><circle cx="12" cy="12" r="4"/><path d="M12 2v2"/><path d="M12 20v2"/><path d="m4.93 4.93 1.41 1.41"/><path d="m17.66 17.66 1.41 1.41"/><path d="M2 12h2"/><path d="M20 12h2"/><path d="m6.34 17.66-1.41 1.41"/><path d="m19.07 4.93-1.41 1.41"/></svg>
39
+ </span>
40
+ <span v-else title="Switch to dark mode">
41
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-moon"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"/></svg>
42
+ </span>
43
+ </button>
44
+ </template>
@@ -5,7 +5,7 @@ import { mdiCast } from "@mdi/js";
5
5
  import { mdiTimerOutline } from "@mdi/js";
6
6
  import { mdiChairSchool } from "@mdi/js";
7
7
  import { mdiChevronDown } from "@mdi/js";
8
- import SvgFilter from '../tools/SvgFilter.vue'
8
+ import SvgFilter from "../tools/SvgFilter.vue";
9
9
  import EpIcon from "../basics/EpIcon.vue";
10
10
  import EpChip from "../basics/EpChip.vue";
11
11
 
@@ -19,13 +19,14 @@ interface Props {
19
19
  big?: boolean | null;
20
20
  src?: string | null;
21
21
  synchrone?: boolean;
22
+ hasImg?: boolean;
22
23
  duration?: string | null;
23
24
  assessment?: string | null;
24
- headerImgColor?:string | null;
25
- labels?:{
26
- synchrone?: string;
27
- formatif?: string;
28
- }
25
+ headerImgColor?: string | null;
26
+ labels?: {
27
+ synchrone?: string;
28
+ formatif?: string;
29
+ };
29
30
  }
30
31
 
31
32
  // type, taxonomyLevel, courseCode, courseTitle, title, subtitle, height, src, color, synchrone
@@ -37,17 +38,17 @@ const props = withDefaults(defineProps<Props>(), {
37
38
  src: null,
38
39
  big: false,
39
40
  synchrone: false,
41
+ hasImg: true,
40
42
  duration: null,
41
43
  assessment: null,
42
- labels:()=>{
44
+ labels: () => {
43
45
  return {
44
- synchrone:"Synchrone",
45
- formatif:"Formatif"
46
- }
47
- }
46
+ synchrone: "Synchrone",
47
+ formatif: "Formatif",
48
+ };
49
+ },
48
50
  });
49
51
 
50
-
51
52
  const colorText = computed(() => {
52
53
  return props.color;
53
54
  });
@@ -72,51 +73,72 @@ const bgImg = computed(() => {
72
73
  });
73
74
 
74
75
  const emit = defineEmits<{
75
- (e:"clicked"):void
76
- }>()
76
+ (e: "clicked"): void;
77
+ }>();
77
78
 
78
-
79
- const clickScroll = ():void => {
80
- emit('clicked')
81
- }
79
+ const clickScroll = (): void => {
80
+ emit("clicked");
81
+ };
82
82
 
83
83
  const { title, headerImgColor, big } = toRefs(props);
84
84
  </script>
85
85
 
86
86
  <template>
87
- <section :class="`${big?'h-screen ':''}items-center overflow-hidden relative `" ref="el">
88
- <div :class="styles" :style="`background-image:url('${bgImg}'); filter:url(#${headerImgColor});`"></div>
89
-
90
- <div :class="`relative ${big?'mb-36':''} h-full items-end`">
91
- <div class="flex md:justify-end justify-center pt-5">
92
- <EpChip v-if="synchrone" :prependIcon="mdiCast">{{labels.synchrone}}</EpChip>
93
- <EpChip v-if="duration" :prependIcon="mdiTimerOutline"> {{ duration }}</EpChip>
94
- <EpChip v-if="assessment" :prependIcon="mdiChairSchool">{{labels.formatif}}</EpChip>
95
- </div>
96
- <div class="flex w-full py-24 grow flex h-full items-center">
97
- <div class="mx-auto w-8/12">
98
- <div v-if="title || subtitle"
99
- class="p-4 md:items-center backdrop-blur-md backdrop-brightness-50 backdrop-opacity-75 rounded"
100
- >
101
- <div class="text-center md:text-left">
102
- <h1 v-if="title" class="text-xl font-medium text-white sm:text-3xl">
103
- {{ title }}
104
- </h1>
105
- <h2 v-if="subtitle" class="max-w-xl mt-4 text-xl text-white contrast-50">
106
- {{ subtitle }}
107
- </h2>
108
- </div>
87
+ <header
88
+ v-if="hasImg"
89
+ :class="`${big ? 'h-screen ' : ''}items-center overflow-hidden relative `"
90
+ ref="el"
91
+ >
92
+ <div
93
+ :class="styles"
94
+ :style="`background-image:url('${bgImg}'); filter:url(#${headerImgColor});`"
95
+ ></div>
96
+
97
+ <div :class="`relative ${big ? 'mb-36' : ''} h-full items-end`">
98
+ <div class="flex md:justify-end justify-center pt-5">
99
+ <EpChip v-if="synchrone" :prependIcon="mdiCast">{{ labels.synchrone }}</EpChip>
100
+ <EpChip v-if="duration" :prependIcon="mdiTimerOutline"> {{ duration }}</EpChip>
101
+ <EpChip v-if="assessment" :prependIcon="mdiChairSchool">{{
102
+ labels.formatif
103
+ }}</EpChip>
104
+ </div>
105
+ <div class="flex w-full py-24 grow flex h-full items-center">
106
+ <div class="mx-auto w-8/12">
107
+ <div
108
+ v-if="title || subtitle"
109
+ class="p-4 md:items-center backdrop-blur-md backdrop-brightness-50 backdrop-opacity-75 rounded"
110
+ >
111
+ <div class="text-center md:text-left">
112
+ <h1 v-if="title" class="text-xl font-medium text-white sm:text-3xl">
113
+ {{ title }}
114
+ </h1>
115
+ <h2 v-if="subtitle" class="max-w-xl mt-4 text-xl text-white contrast-50">
116
+ {{ subtitle }}
117
+ </h2>
109
118
  </div>
110
119
  </div>
111
120
  </div>
112
121
  </div>
122
+ </div>
113
123
 
114
- <div v-if="props.big" class="animate-bounce absolute bottom-10 left-1/2">
115
- <div class="mx-auto w-12 bg-white dark:text-black rounded-full p-2" @click="clickScroll">
116
- <EpIcon :iconPath="mdiChevronDown" size="32"></EpIcon>
117
- </div>
124
+ <div v-if="props.big" class="animate-bounce absolute bottom-10 left-1/2">
125
+ <div
126
+ class="mx-auto w-12 bg-white dark:text-black rounded-full p-2"
127
+ @click="clickScroll"
128
+ >
129
+ <EpIcon :iconPath="mdiChevronDown" size="32"></EpIcon>
118
130
  </div>
131
+ </div>
119
132
  <SvgFilter></SvgFilter>
120
- </section>
121
-
133
+ </header>
134
+ <header v-else>
135
+ <div class="text-center md:text-left mt-16 mb-32">
136
+ <h1 v-if="title" class="text-4xl font-bold tracking-tight text-gray-900 dark:text-gray-100">
137
+ {{ title }}
138
+ </h1>
139
+ <h2 v-if="subtitle" class="w-1/2 mt-4 text-gray-500 dark:text-gray-300">
140
+ {{ subtitle }}
141
+ </h2>
142
+ </div>
143
+ </header>
122
144
  </template>
@@ -8,14 +8,15 @@ interface Props {
8
8
  height?:number;
9
9
  width?:number;
10
10
  animation?:string;
11
+ loading?:boolean;
11
12
  }
12
13
 
13
- // define parameter
14
14
  const props = withDefaults(defineProps<Props>(), {
15
15
  type:'rectangle',
16
16
  width:100,
17
17
  height:10,
18
- animation:"animate-pulse"
18
+ animation:"animate-pulse",
19
+ loading:true
19
20
  })
20
21
 
21
22
  const width = props.width/4 +"rem"
@@ -25,8 +26,11 @@ interface Props {
25
26
  </script>
26
27
  <template>
27
28
  <div>
28
- <div class="flex p-2" :class = "animation" >
29
- <div v-if="props.type === 'circle'">
29
+ <div class="flex p-2" :class="animation">
30
+ <div v-if="props.loading">
31
+ <span class="shape block bg-gray-200 rounded-full dark:bg-gray-300"></span>
32
+ </div>
33
+ <div v-else-if="props.type === 'circle'">
30
34
  <span class="shape block bg-gray-200 rounded-full dark:bg-gray-300"></span>
31
35
  </div>
32
36
  <div v-else-if="props.type === 'rectangle'">
@@ -1,4 +0,0 @@
1
- import { S as f } from "./index-nKuHdZUR.js";
2
- export {
3
- f as default
4
- };
@@ -1,4 +0,0 @@
1
- import { T as f } from "./index-nKuHdZUR.js";
2
- export {
3
- f as default
4
- };
@@ -1,4 +0,0 @@
1
- import { O as f } from "./index-nKuHdZUR.js";
2
- export {
3
- f as default
4
- };
@@ -1,4 +0,0 @@
1
- import { E as f } from "./index-nKuHdZUR.js";
2
- export {
3
- f as default
4
- };
@@ -1,4 +0,0 @@
1
- import { c as f } from "./index-nKuHdZUR.js";
2
- export {
3
- f as default
4
- };
@@ -1,4 +0,0 @@
1
- import { o } from "./index-nKuHdZUR.js";
2
- export {
3
- o as default
4
- };
@@ -1,4 +0,0 @@
1
- import { d as f } from "./index-nKuHdZUR.js";
2
- export {
3
- f as default
4
- };
@@ -1,4 +0,0 @@
1
- import { e } from "./index-nKuHdZUR.js";
2
- export {
3
- e as default
4
- };
@@ -1,4 +0,0 @@
1
- import { f } from "./index-nKuHdZUR.js";
2
- export {
3
- f as default
4
- };
@@ -1,4 +0,0 @@
1
- import { z as f } from "./index-nKuHdZUR.js";
2
- export {
3
- f as default
4
- };
@@ -1,26 +0,0 @@
1
- import { defineComponent as i, ref as h, onMounted as p, openBlock as r, createElementBlock as a, createCommentVNode as c } from "vue";
2
- import { A as g } from "./index-nKuHdZUR.js";
3
- const f = { key: 0 }, k = { key: 1 }, C = /* @__PURE__ */ i({
4
- __name: "EpDarkmode",
5
- emits: ["update:userMode"],
6
- setup(_, { emit: l }) {
7
- const s = g(), n = l, o = (e) => {
8
- localStorage.setItem("user-theme", e), s.value = e, t.value = e, document.documentElement.className = e;
9
- }, u = () => {
10
- const e = localStorage.getItem("user-theme");
11
- return s.value = e, e;
12
- }, m = () => {
13
- const e = localStorage.getItem("user-theme");
14
- o(e === "light" ? "dark" : "light"), n("update:userMode", t.value);
15
- }, d = () => window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light", t = h(u() || d());
16
- return p(() => {
17
- o(t.value), n("update:userMode", t.value);
18
- }), (e, v) => (r(), a("button", { onClick: m }, [
19
- t.value === "dark" ? (r(), a("span", f, " ☀️ ")) : c("", !0),
20
- t.value === "light" ? (r(), a("span", k, " 🌙 ")) : c("", !0)
21
- ]));
22
- }
23
- });
24
- export {
25
- C as default
26
- };
@@ -1,4 +0,0 @@
1
- import { g as f } from "./index-nKuHdZUR.js";
2
- export {
3
- f as default
4
- };
@@ -1,4 +0,0 @@
1
- import { s } from "./index-nKuHdZUR.js";
2
- export {
3
- s as default
4
- };