ThemeCustomizer.svelte
1 <script lang="ts"> 2 import { primaryColor } from '$lib/stores'; 3 import { onMount } from 'svelte'; 4 5 let isOpen = false; 6 let colorPicker: HTMLInputElement; 7 8 // Función para abrir el selector de color 9 function toggleColorPicker() { 10 if (!isOpen) { 11 setTimeout(() => { 12 if (colorPicker) colorPicker.click(); 13 }, 50); 14 } 15 isOpen = !isOpen; 16 } 17 18 // Aplicar el color inmediatamente mientras se mueve el selector 19 function handleColorChange(event: Event) { 20 const input = event.target as HTMLInputElement; 21 const newColor = input.value; 22 23 // Actualizar el store - esto desencadenará la suscripción en stores.ts 24 // que manejará correctamente los cambios de color para ambos temas 25 primaryColor.set(newColor); 26 27 // Ya no necesitamos aplicar manualmente las propiedades CSS aquí 28 // ya que la suscripción en stores.ts se encarga de aplicar los colores 29 // considerando si estamos en modo oscuro o claro 30 31 // Guardar en localStorage (este paso sigue siendo necesario) 32 if (typeof window !== 'undefined') { 33 localStorage.setItem('primaryColor', newColor); 34 } 35 } 36 37 // Cerrar el panel al hacer clic fuera 38 function handleClickOutside(event: MouseEvent) { 39 const target = event.target as HTMLElement; 40 if (isOpen && !target.closest('.theme-customizer') && target.id !== 'primary-color') { 41 isOpen = false; 42 } 43 } 44 45 onMount(() => { 46 document.addEventListener('click', handleClickOutside); 47 return () => { 48 document.removeEventListener('click', handleClickOutside); 49 }; 50 }); 51 </script> 52 53 <div class="theme-customizer"> 54 <button 55 class="color-button" 56 on:click={toggleColorPicker} 57 aria-label="Personalizar color" 58 style="background-color: {$primaryColor};" 59 > 60 <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> 61 <circle cx="12" cy="12" r="10"></circle> 62 <circle cx="12" cy="12" r="6"></circle> 63 <circle cx="12" cy="12" r="2"></circle> 64 </svg> 65 </button> 66 67 <input 68 id="primary-color" 69 bind:this={colorPicker} 70 type="color" 71 bind:value={$primaryColor} 72 on:input={handleColorChange} 73 class="color-input" 74 /> 75 </div> 76 77 <style> 78 .theme-customizer { 79 position: relative; 80 display: inline-block; 81 } 82 83 .color-button { 84 width: 40px; 85 height: 40px; 86 border-radius: 50%; 87 border: 2px solid white; 88 cursor: pointer; 89 display: flex; 90 align-items: center; 91 justify-content: center; 92 color: white; 93 box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2); 94 transition: transform 0.2s; 95 } 96 97 .color-button:hover { 98 transform: scale(1.05); 99 } 100 101 .color-input { 102 position: absolute; 103 top: 0; 104 left: 0; 105 opacity: 0; 106 width: 1px; 107 height: 1px; 108 z-index: -1; 109 } 110 </style>