provisioning-outreach/presentations/pres-prvng/components/Footer.vue

168 lines
4.7 KiB
Vue

<template>
<div>
<!-- Image overlay toggle with M key -->
<transition name="fade">
<div v-if="showImageOverlay" class="fixed bottom-4 right-1 cursor-pointer pointer-events-auto w-auto z-10"
@click="toggleImageOverlay">
<div class="relative">
<img src="/jpl-image.svg" alt="JPL Image"
class="p-1 bg-gray-400 w-80 h-auto shadow-lg rounded-lg hover:shadow-xl transition-shadow" />
<div
class="absolute -bottom-8 left-1/2 transform -translate-x-1/2 text-xs text-gray-400 whitespace-nowrap pointer-events-none">
</div>
</div>
</div>
</transition>
<div class="slide-footer abs-br m-0 px-4 pt-2 pb-0 flex gap-3 items-center">
<!-- Iconos sociales -->
<a href="https://jesusperez.pro" target="_blank" alt="Website"
class="text-lg slidev-icon-btn opacity-50 !border-none !hover:text-white">
<carbon:earth-europe-africa />
</a>
<a href="https://github.com/jesusperezlorenzo" target="_blank" alt="GitHub"
class="text-lg slidev-icon-btn opacity-50 !border-none !hover:text-white">
<carbon-logo-github />
</a>
<!-- Botón Projection Mode - SIN fondo -->
<button @click="toggleProjectionMode" class="projection-btn"
:class="{ 'projection-active': isProjectionMode }"
:title="isProjectionMode ? 'Modo Proyección ON (P/D)' : 'Modo Proyección OFF (P/D)'">
<span class="text-base">{{ isProjectionMode ? '📽️' : '🖥️' }}</span>
</button>
<!-- Texto autor y versión -->
<span class="footer-text">Jesús Pérez · 2025 v1.1</span>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from "vue";
const isProjectionMode = ref(false);
const showImageOverlay = ref(false);
const toggleProjectionMode = () => {
isProjectionMode.value = !isProjectionMode.value;
if (isProjectionMode.value) {
document.documentElement.classList.add("projection-mode");
localStorage.setItem("rust-vibe-projection", "true");
} else {
document.documentElement.classList.remove("projection-mode");
localStorage.setItem("rust-vibe-projection", "false");
}
};
// Toggle image overlay
const toggleImageOverlay = () => {
showImageOverlay.value = !showImageOverlay.value;
};
// Atajos de teclado P, D, y M
const handleKeyPress = (event: KeyboardEvent) => {
const target = event.target as HTMLElement;
// Ignore if typing in input or textarea
if (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA') {
return;
}
// Handle P and D keys for projection mode
if (event.key === 'p' || event.key === 'P' || event.key === 'd' || event.key === 'D') {
event.preventDefault();
toggleProjectionMode();
}
// Handle M key for image overlay toggle
if (event.key === 'm' || event.key === 'M') {
event.preventDefault();
toggleImageOverlay();
}
};
// Sync with localStorage on mount
onMounted(() => {
const saved = localStorage.getItem("rust-vibe-projection");
if (saved === "true") {
isProjectionMode.value = true;
document.documentElement.classList.add("projection-mode");
}
// Añadir listener de teclado global
window.addEventListener('keydown', handleKeyPress);
});
// Cleanup on unmount
onUnmounted(() => {
window.removeEventListener('keydown', handleKeyPress);
});
</script>
<style scoped>
/* Image overlay fade transition */
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.3s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
.fade-enter-to,
.fade-leave-from {
opacity: 1;
}
.slide-footer {
opacity: 0;
transition: opacity 0.3s ease;
z-index: 10;
}
.slide-footer:hover {
opacity: 1;
}
.footer-text {
font-size: 0.65rem;
/* Más pequeño que text-xs */
opacity: 0.5;
}
.projection-btn {
opacity: 0.5;
transition: all 0.3s ease;
background: none !important;
/* SIN fondo, usa el de la slide */
border: none !important;
padding: 0.25rem;
cursor: pointer;
}
.projection-btn:hover {
opacity: 1;
transform: scale(1.15);
}
.projection-btn.projection-active {
opacity: 1;
/* Sin background para que use el de la slide */
}
/* Ocultar en modo presentador */
.slidev-presenter .slide-footer {
display: none;
}
/* Ocultar al imprimir */
@media print {
.slide-footer {
display: none;
}
}
</style>