199 lines
5.1 KiB
Vue
Raw Permalink Normal View History

<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-200"
@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>