ai-research-survey

Systematic scan of agentic development research. What's signal, what's noise.
git clone https://git.shiptheloop.com/ai-research-survey.git
Log | Files | Refs

search-filter.ts (2298B)


      1 export interface FilterState {
      2   search: string;
      3   year: string;
      4   archetype: string;
      5   tag: string;
      6   minScore: number;
      7   maxScore: number;
      8 }
      9 
     10 export function createFilters(
     11   archetypes: string[],
     12   tags: string[],
     13   onChange: (state: FilterState) => void
     14 ): HTMLElement {
     15   const div = document.createElement('div');
     16   div.className = 'filters';
     17 
     18   div.innerHTML = `
     19     <input type="text" id="f-search" placeholder="Search titles...">
     20     <select id="f-year"><option value="">All years</option></select>
     21     <select id="f-archetype"><option value="">All archetypes</option></select>
     22     <select id="f-tag"><option value="">All tags</option></select>
     23     <label style="font-size:0.8rem;color:var(--text-dim)">Score:
     24       <input type="number" id="f-min" value="0" min="0" max="100" style="width:50px"> –
     25       <input type="number" id="f-max" value="100" min="0" max="100" style="width:50px">
     26     </label>
     27     <span class="filter-count" id="f-count"></span>
     28   `;
     29 
     30   // Populate selects
     31   const yearSel = div.querySelector('#f-year') as HTMLSelectElement;
     32   for (let y = 2026; y >= 2017; y--) {
     33     yearSel.innerHTML += `<option value="${y}">${y}</option>`;
     34   }
     35 
     36   const archSel = div.querySelector('#f-archetype') as HTMLSelectElement;
     37   archetypes.forEach(a => archSel.innerHTML += `<option value="${a}">${a}</option>`);
     38 
     39   const tagSel = div.querySelector('#f-tag') as HTMLSelectElement;
     40   tags.forEach(t => tagSel.innerHTML += `<option value="${t}">${t}</option>`);
     41 
     42   function emit() {
     43     onChange({
     44       search: (div.querySelector('#f-search') as HTMLInputElement).value.toLowerCase(),
     45       year: (div.querySelector('#f-year') as HTMLSelectElement).value,
     46       archetype: (div.querySelector('#f-archetype') as HTMLSelectElement).value,
     47       tag: (div.querySelector('#f-tag') as HTMLSelectElement).value,
     48       minScore: parseInt((div.querySelector('#f-min') as HTMLInputElement).value) || 0,
     49       maxScore: parseInt((div.querySelector('#f-max') as HTMLInputElement).value) || 100,
     50     });
     51   }
     52 
     53   div.addEventListener('input', emit);
     54   div.addEventListener('change', emit);
     55 
     56   return div;
     57 }
     58 
     59 export function updateFilterCount(container: HTMLElement, count: number, total: number) {
     60   const el = container.querySelector('#f-count');
     61   if (el) el.textContent = `${count} / ${total}`;
     62 }

Impressum · Datenschutz