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.
- package/dist/BgAudio-BOuJmZ4Z.js +4 -0
- package/dist/DisplayBox-hI9I354I.js +4 -0
- package/dist/EpAlert-CNC4jPvV.js +4 -0
- package/dist/EpAudio-BFzs1CCB.js +4 -0
- package/dist/EpBadge-LjMj7s1q.js +4 -0
- package/dist/EpBarChart-mFktWWHN.js +4 -0
- package/dist/EpBtn-3_tn7E6D.js +4 -0
- package/dist/EpCard-CwLnvlZs.js +4 -0
- package/dist/EpChip-BmJNCeuv.js +4 -0
- package/dist/EpConclusion-Bo5-jNPy.js +4 -0
- package/dist/EpContentSlider-CHgd9CBo.js +4 -0
- package/dist/EpDarkmode-DdqwsLJI.js +48 -0
- package/dist/EpDescription-Kbh-pnvx.js +4 -0
- package/dist/EpDivider-xLnjVUkj.js +4 -0
- package/dist/EpEdu-DI6qOWw1.js +4 -0
- package/dist/EpFlex-mQrhJu8J.js +4 -0
- package/dist/EpFunnelChart-CTbZegv2.js +4 -0
- package/dist/EpHeader-MY25ggLC.js +4 -0
- package/dist/{EpHover-jrnI89yN.js → EpHover-CF0mr0kn.js} +1 -1
- package/dist/EpIcon-CMHojBr5.js +4 -0
- package/dist/EpIframe-E_puwUIb.js +4 -0
- package/dist/EpImg-C5Kwf7od.js +4 -0
- package/dist/{EpInput-DzvG0ONW.js → EpInput-Cfl4JH1l.js} +22 -22
- package/dist/EpInstructions-nM-IK120.js +4 -0
- package/dist/EpIntroduction-DiF_d3pZ.js +4 -0
- package/dist/EpLineChart-BkQwacog.js +4 -0
- package/dist/EpLink-BP6HIdnn.js +4 -0
- package/dist/EpLinkVersion-ChbNAqrS.js +4 -0
- package/dist/{EpList-_qae9uHP.js → EpList-BL9yIb5h.js} +1 -1
- package/dist/EpModal-CDjsyRvM.js +4 -0
- package/dist/{EpNothing-CDSj0X4K.js → EpNothing-B0xLzA9P.js} +1 -1
- package/dist/EpObjective-Bt3hflqk.js +4 -0
- package/dist/EpPieChart-Dv8DGZSF.js +4 -0
- package/dist/EpQuestion-lEHBGz0S.js +4 -0
- package/dist/EpQuote-B1YA7A6I.js +4 -0
- package/dist/EpRadio-C8r7s7W-.js +4 -0
- package/dist/EpRadioSummative-Cv6MYTv6.js +4 -0
- package/dist/EpReading-DQcDGfZb.js +4 -0
- package/dist/EpResource-DyyoUvuJ.js +4 -0
- package/dist/EpScope-BqyU2wlf.js +4 -0
- package/dist/EpSection-DOd8aziF.js +4 -0
- package/dist/EpSelect-FIb6SyJU.js +32 -0
- package/dist/EpSkeleton-B1XRyOwZ.js +4 -0
- package/dist/EpSoftware-D6X8AHJK.js +4 -0
- package/dist/EpSpecificObjective-DkH5m09k.js +4 -0
- package/dist/EpSpinner-DTecXUJS.js +4 -0
- package/dist/EpSummativeTable-Cd7jQAbl.js +4 -0
- package/dist/EpSvg-Cl7JQ9X8.js +4 -0
- package/dist/EpTable-BF4JWCJY.js +4 -0
- package/dist/EpTerm-Dgll69TG.js +4 -0
- package/dist/EpText-D_iQAE-U.js +4 -0
- package/dist/EpTimeLine-DWjocTaz.js +4 -0
- package/dist/EpVideo-B1b7SFoO.js +4 -0
- package/dist/EpVideoPanopto-BrZDfrND.js +4 -0
- package/dist/EpWordDef-DRxF8rWC.js +4 -0
- package/dist/components/basics/EpChip.vue.d.ts +1 -1
- package/dist/components/basics/EpIcon.vue.d.ts +1 -1
- package/dist/components/charts/EpFunnelChart.vue.d.ts +1 -1
- package/dist/components/charts/EpPieChart.vue.d.ts +1 -1
- package/dist/components/educationals/EpConclusion.vue.d.ts +39 -0
- package/dist/components/educationals/EpDescription.vue.d.ts +39 -0
- package/dist/components/educationals/EpInstructions.vue.d.ts +36 -0
- package/dist/components/educationals/EpIntroduction.vue.d.ts +39 -0
- package/dist/components/educationals/EpObjective.vue.d.ts +39 -0
- package/dist/components/educationals/EpSpecificObjective.vue.d.ts +40 -0
- package/dist/components/forms/EpSelect.vue.d.ts +15 -86
- package/dist/components/interactions/EpAccordeon.vue.d.ts +1 -0
- package/dist/components/interactions/EpContentSlider.vue.d.ts +4 -0
- package/dist/components/signages/EpHeader.vue.d.ts +4 -0
- package/dist/components/signages/EpSkeleton.vue.d.ts +6 -2
- package/dist/ep-lib-ts.js +46 -40
- package/dist/ep-lib-ts.umd.cjs +70 -52
- package/dist/{index-nKuHdZUR.js → index-BDcKL8U6.js} +4833 -4538
- package/dist/index.d.ts +7 -1
- package/dist/style.css +1 -1
- package/dist/types/Answer.d.ts +17 -0
- package/package.json +2 -2
- package/src/components/basics/EpFlex.vue +1 -0
- package/src/components/basics/EpSection.vue +5 -9
- package/src/components/educationals/EpConclusion.vue +38 -0
- package/src/components/educationals/EpDescription.vue +38 -0
- package/src/components/educationals/EpInstructions.vue +48 -0
- package/src/components/educationals/EpIntroduction.vue +38 -0
- package/src/components/educationals/EpObjective.vue +41 -0
- package/src/components/educationals/EpReading.vue +1 -1
- package/src/components/educationals/EpSpecificObjective.vue +42 -0
- package/src/components/forms/EpSelect.vue +18 -154
- package/src/components/interactions/EpAccordeon.vue +5 -4
- package/src/components/interactions/EpContentSlider.vue +132 -97
- package/src/components/interactions/EpDarkmode.vue +22 -40
- package/src/components/signages/EpHeader.vue +68 -46
- package/src/components/signages/EpSkeleton.vue +8 -4
- package/dist/BgAudio-BjiZt_j3.js +0 -4
- package/dist/DisplayBox-DZa_LWHr.js +0 -4
- package/dist/EpAlert-CIOmWSIc.js +0 -4
- package/dist/EpAudio-B3cP0yQP.js +0 -4
- package/dist/EpBadge-Rn_GnxQe.js +0 -4
- package/dist/EpBarChart-D3XffoUi.js +0 -4
- package/dist/EpBtn-DHEEdI-A.js +0 -4
- package/dist/EpCard-CKZOUaVF.js +0 -4
- package/dist/EpChip-ClMvRgwG.js +0 -4
- package/dist/EpContentSlider-BPQRgnys.js +0 -4
- package/dist/EpDarkmode-4w7onxHI.js +0 -26
- package/dist/EpDivider-CAdkeSwX.js +0 -4
- package/dist/EpEdu-Ccx2WVen.js +0 -4
- package/dist/EpFlex-BObUghJr.js +0 -4
- package/dist/EpFunnelChart-Pe4XXTya.js +0 -4
- package/dist/EpHeader-DvJyyMGC.js +0 -4
- package/dist/EpIcon-BfZrj1D0.js +0 -4
- package/dist/EpIframe-DpKYSJNh.js +0 -4
- package/dist/EpImg-B_oxNdE8.js +0 -4
- package/dist/EpLineChart-D1McKT4Z.js +0 -4
- package/dist/EpLink-Bad9NyI9.js +0 -4
- package/dist/EpLinkVersion-on-9nSh-.js +0 -4
- package/dist/EpModal-Ca6mOjLn.js +0 -4
- package/dist/EpPieChart-Bl-OovwP.js +0 -4
- package/dist/EpQuestion-_cynbj44.js +0 -4
- package/dist/EpQuote-DSGsPnu9.js +0 -4
- package/dist/EpRadio-BCYQ80gI.js +0 -4
- package/dist/EpRadioSummative-KuZyk9G2.js +0 -4
- package/dist/EpReading-BZJk9RUD.js +0 -4
- package/dist/EpResource-MAdgbl2P.js +0 -4
- package/dist/EpScope-C2BEnXHN.js +0 -4
- package/dist/EpSection-DIbMpikL.js +0 -4
- package/dist/EpSelect-afhma1pl.js +0 -43
- package/dist/EpSkeleton-DdosLRVb.js +0 -4
- package/dist/EpSoftware-DpNVZY3o.js +0 -4
- package/dist/EpSpinner-9KW8OFR4.js +0 -4
- package/dist/EpSummativeTable-CXjHg8Dh.js +0 -4
- package/dist/EpSvg-Dnr8vgDv.js +0 -4
- package/dist/EpTable-BRt9Ps0H.js +0 -4
- package/dist/EpTerm-B3bSXeXd.js +0 -4
- package/dist/EpText-CB8XAfzb.js +0 -4
- package/dist/EpTimeLine-BUxl5jo5.js +0 -4
- package/dist/EpVideo-DxEYZmn1.js +0 -4
- package/dist/EpVideoPanopto-BtGdfGz9.js +0 -4
- package/dist/EpWordDef-DUa6sNjb.js +0 -4
|
@@ -1,142 +1,177 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { ref, computed, defineAsyncComponent,
|
|
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:"
|
|
20
|
-
|
|
21
|
-
})
|
|
22
|
-
|
|
18
|
+
loading: "...loading",
|
|
19
|
+
noData: "No data available",
|
|
20
|
+
mediaPosition: "left",
|
|
21
|
+
});
|
|
23
22
|
|
|
24
|
-
const currentIndex = ref
|
|
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
|
-
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
return props.slides[currentIndex.value]
|
|
34
|
-
})
|
|
31
|
+
return props.slides[currentIndex.value];
|
|
32
|
+
});
|
|
35
33
|
|
|
36
34
|
const hasTextContent = computed(() => {
|
|
37
|
-
|
|
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
|
|
52
|
-
|
|
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
|
-
|
|
61
|
-
|
|
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
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
</h5>
|
|
79
|
-
<div class="
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
<
|
|
90
|
-
<
|
|
91
|
-
|
|
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
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
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
|
-
|
|
105
|
-
|
|
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
|
-
|
|
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
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
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
|
|
26
|
-
|
|
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
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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
|
|
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
|
-
|
|
45
|
-
|
|
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
|
-
|
|
80
|
-
|
|
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
|
-
<
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
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
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
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
|
-
</
|
|
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
|
|
29
|
-
<div
|
|
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'">
|
package/dist/BgAudio-BjiZt_j3.js
DELETED
package/dist/EpAlert-CIOmWSIc.js
DELETED
package/dist/EpAudio-B3cP0yQP.js
DELETED
package/dist/EpBadge-Rn_GnxQe.js
DELETED
package/dist/EpBtn-DHEEdI-A.js
DELETED
package/dist/EpCard-CKZOUaVF.js
DELETED
package/dist/EpChip-ClMvRgwG.js
DELETED
|
@@ -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
|
-
};
|
package/dist/EpEdu-Ccx2WVen.js
DELETED