AdvancedFilters.svelte
1 <script lang="ts"> 2 import { createEventDispatcher } from 'svelte'; 3 const dispatch = createEventDispatcher(); 4 5 let resultadosPorPagina = '10'; 6 // Los valores posibles son 'local' o 'peer' ('peer' se mapea a 'global' en el servidor) 7 let recurso = 'local'; 8 let preferMask = ''; 9 // Desactivamos constraints por defecto para evitar problemas de paginación 10 let constraints = 'false'; 11 let mediaSearch = 'extended_strict'; 12 13 function aplicarFiltros() { 14 dispatch('aplicar', { 15 resultadosPorPagina, 16 recurso, 17 preferMask, 18 constraints, 19 mediaSearch 20 }); 21 } 22 </script> 23 24 <details class="advanced-filters-container"> 25 <summary class="advanced-filters-toggle"> 26 <span class="toggle-text">Filtros avanzados</span> 27 <svg class="toggle-icon" xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> 28 <polyline points="6 9 12 15 18 9"></polyline> 29 </svg> 30 </summary> 31 32 <div class="advanced-filters"> 33 <div class="filters-row"> 34 <div class="filter-control"> 35 <label for="results-per-page">Resultados por página:</label> 36 <select id="results-per-page" bind:value={resultadosPorPagina}> 37 <option value="10">10</option> 38 <option value="20">20</option> 39 <option value="50">50</option> 40 <option value="100">100</option> 41 </select> 42 </div> 43 44 <div class="filter-control"> 45 <label for="resource-type">Recursos:</label> 46 <select id="resource-type" bind:value={recurso}> 47 <option value="local">Índice local</option> 48 <option value="peer">Peer-to-Peer</option> 49 </select> 50 </div> 51 </div> 52 53 <div class="filters-row"> 54 <div class="filter-control"> 55 <label for="prefer-mask">Prefer mask:</label> 56 <input type="text" id="prefer-mask" bind:value={preferMask} placeholder="Palabra clave" /> 57 </div> 58 59 <div class="filter-control"> 60 <label for="constraints">Constraints:</label> 61 <select id="constraints" bind:value={constraints}> 62 <option value="false">Sin restricciones (recomendado)</option> 63 <option value="all">Todas</option> 64 <option value="only_index">Solo indexadas (primera página)</option> 65 </select> 66 </div> 67 68 <div class="filter-control"> 69 <label for="media-search">Media search:</label> 70 <select id="media-search" bind:value={mediaSearch}> 71 <option value="extended_strict">Extended Strict</option> 72 <option value="normal">Normal</option> 73 </select> 74 </div> 75 </div> 76 77 <div class="filters-actions"> 78 <button class="reset-button" on:click={() => { 79 resultadosPorPagina = '10'; 80 recurso = 'local'; 81 preferMask = ''; 82 constraints = 'false'; 83 mediaSearch = 'extended_strict'; 84 }}>Restablecer</button> 85 <button class="apply-button" on:click={aplicarFiltros}>Aplicar filtros</button> 86 </div> 87 </div> 88 </details> 89 90 <style> 91 .advanced-filters-container { 92 width: 100%; 93 } 94 95 .advanced-filters-toggle { 96 display: flex; 97 align-items: center; 98 justify-content: center; 99 gap: var(--space-xs); 100 color: var(--text-secondary); 101 padding: var(--space-sm) var(--space-md); 102 font-size: 0.9rem; 103 cursor: pointer; 104 font-weight: var(--font-weight-medium); 105 position: relative; 106 user-select: none; 107 border-radius: var(--border-radius); 108 transition: all var(--transition-speed); 109 background: var(--bg-primary); 110 border: 1px solid var(--border-color); 111 } 112 113 .advanced-filters-toggle:hover { 114 background: var(--bg-secondary); 115 color: var(--primary); 116 } 117 118 .advanced-filters-toggle:focus { 119 outline: none; 120 box-shadow: var(--focus-shadow); 121 } 122 123 /* Eliminar el marcador nativo del elemento details */ 124 .advanced-filters-toggle::-webkit-details-marker { 125 display: none; 126 } 127 128 .toggle-icon { 129 transition: transform var(--transition-speed); 130 } 131 132 details[open] .toggle-icon { 133 transform: rotate(180deg); 134 } 135 136 .advanced-filters { 137 display: flex; 138 flex-direction: column; 139 gap: var(--space-md); 140 background: var(--bg-primary); 141 padding: var(--space-lg); 142 width: 100%; 143 border-radius: var(--border-radius); 144 border: 1px solid var(--border-color); 145 margin-top: var(--space-xs); 146 box-shadow: var(--card-shadow); 147 } 148 149 .filters-row { 150 display: flex; 151 flex-wrap: wrap; 152 gap: var(--space-lg); 153 width: 100%; 154 } 155 156 .filter-control { 157 display: flex; 158 flex-direction: column; 159 gap: var(--space-xs); 160 flex: 1; 161 min-width: 150px; 162 } 163 164 .filter-control label { 165 font-size: 0.85rem; 166 font-weight: var(--font-weight-medium); 167 color: var(--text-secondary); 168 } 169 170 .filter-control select, 171 .filter-control input { 172 padding: var(--space-sm) var(--space-md); 173 font-size: 0.85rem; 174 border: 1px solid var(--border-color); 175 border-radius: var(--border-radius-sm); 176 background: var(--bg-primary); 177 color: var(--text-color); 178 transition: all var(--transition-speed); 179 } 180 181 .filter-control select:hover, 182 .filter-control input:hover { 183 border-color: var(--primary); 184 } 185 186 .filter-control select:focus, 187 .filter-control input:focus { 188 border-color: var(--primary); 189 box-shadow: var(--focus-shadow); 190 outline: none; 191 } 192 193 .filters-actions { 194 display: flex; 195 justify-content: flex-end; 196 gap: var(--space-md); 197 margin-top: var(--space-sm); 198 } 199 200 .reset-button { 201 background: transparent; 202 color: var(--text-secondary); 203 border: 1px solid var(--border-color); 204 padding: var(--space-sm) var(--space-md); 205 border-radius: var(--border-radius-sm); 206 cursor: pointer; 207 font-size: 0.85rem; 208 font-weight: var(--font-weight-medium); 209 transition: all var(--transition-speed); 210 } 211 212 .reset-button:hover { 213 background: var(--bg-secondary); 214 color: var(--text-color); 215 } 216 217 .apply-button { 218 background: var(--primary); 219 color: white; 220 border: none; 221 padding: var(--space-sm) var(--space-md); 222 border-radius: var(--border-radius-sm); 223 cursor: pointer; 224 font-size: 0.85rem; 225 font-weight: var(--font-weight-medium); 226 transition: all var(--transition-speed); 227 } 228 229 .apply-button:hover { 230 background: var(--primary-dark); 231 } 232 233 .reset-button:active, 234 .apply-button:active { 235 transform: translateY(1px); 236 } 237 238 @media (max-width: 768px) { 239 .filters-row { 240 flex-direction: column; 241 gap: var(--space-sm); 242 } 243 244 .filters-actions { 245 justify-content: center; 246 } 247 } 248 @media (max-width: 768px) { 249 .advanced-filters { 250 flex-direction: column; 251 gap: 0.3rem; 252 } 253 } 254 </style>