1import{r as x,j as e,d,cj as G,d7 as O,aM as _,eJ as H,et as U,h as V,a5 as J,aI as K,V as W,X,eH as Z,B as Q,aN as Y,n as ee,W as te,K as se}from"./index-C7BCAWyf.js";const A=({className:a,...r})=>e.jsx("nav",{role:"navigation","aria-label":"pagination",className:d("mx-auto flex w-full justify-center",a),...r});A.displayName="Pagination";const R=x.forwardRef(({className:a,...r},i)=>e.jsx("ul",{ref:i,className:d("flex flex-row items-center gap-1",a),...r}));R.displayName="PaginationContent";const f=x.forwardRef(({className:a,...r},i)=>e.jsx("li",{ref:i,className:d("",a),...r}));f.displayName="PaginationItem";const y=({className:a,isActive:r,size:i="icon",...u})=>e.jsx("a",{"aria-current":r?"page":void 0,className:d(G({variant:r?"outline":"ghost",size:i}),a),...u});y.displayName="PaginationLink";const z=({className:a,...r})=>e.jsxs(y,{"aria-label":"Go to previous page",size:"default",className:d("gap-1 pl-2.5",a),...r,children:[e.jsx(O,{className:"h-4 w-4"}),e.jsx("span",{children:"Previous"})]});z.displayName="PaginationPrevious";const B=({className:a,...r})=>e.jsxs(y,{"aria-label":"Go to next page",size:"default",className:d("gap-1 pr-2.5",a),...r,children:[e.jsx("span",{children:"Next"}),e.jsx(_,{className:"h-4 w-4"})]});B.displayName="PaginationNext";const D=({className:a,...r})=>e.jsxs("span",{"aria-hidden":!0,className:d("flex h-9 w-9 items-center justify-center",a),...r,children:[e.jsx(H,{className:"h-4 w-4"}),e.jsx("span",{className:"sr-only",children:"More pages"})]});D.displayName="PaginationEllipsis";const S=25,ae=24,re=a=>{const r=new Map;for(const i of a)for(const u of i.tags??[]){const m=u.trim();m&&r.set(m,(r.get(m)??0)+1)}return Array.from(r.entries()).sort((i,u)=>u[1]-i[1]||i[0].localeCompare(u[0]))},oe=()=>{const{tools:a,loading:r}=U(),[i,u]=V(),[m,v]=x.useState(i.get("q")??""),w=(i.get("q")??"").trim().toLowerCase(),g=(i.get("tag")??"").split(",").map(t=>t.trim()).filter(Boolean),P=parseInt(i.get("page")??"1",10),T=Number.isFinite(P)&&P>0?P:1;x.useEffect(()=>{document.title="AI Tools List · Search 5000+ tools · HackerLabs.ai"},[]),x.useEffect(()=>{if((i.get("q")??"")===m)return;const n=setTimeout(()=>{u(s=>{const o=new URLSearchParams(s);return m.trim()?o.set("q",m.trim()):o.delete("q"),o.delete("page"),o},{replace:!0})},250);return()=>clearTimeout(n)},[m]);const C=t=>{u(n=>{const s=new URLSearchParams(n);return Object.entries(t).forEach(([o,p])=>{p===null||p===""?s.delete(o):s.set(o,p)}),s})},j=t=>C({page:t>1?String(t):null}),I=t=>{const n=new Set(g);n.has(t)?n.delete(t):n.add(t),C({tag:n.size?Array.from(n).join(","):null,page:null})},E=()=>{v(""),C({q:null,tag:null,page:null})},$=x.useMemo(()=>re(a),[a]),M=x.useMemo(()=>$.slice(0,ae),[$]),q=x.useMemo(()=>{if(!a.length)return[];const t=w,n=new Set(g.map(s=>s.toLowerCase()));return a.filter(s=>{if(t&&!`${s.name} ${s.description} ${s.subcategory??""} ${(s.tags??[]).join(" ")}`.toLowerCase().includes(t))return!1;if(n.size){const o=(s.tags??[]).map(p=>p.toLowerCase());for(const p of n)if(!o.includes(p))return!1}return!0})},[a,w,g]),b=q.length,c=Math.max(1,Math.ceil(b/S)),l=Math.min(T,c),h=(l-1)*S,N=q.slice(h,h+S);x.useEffect(()=>{T>c&&j(c)},[c]);const L=w.length>0||g.length>0,F=x.useMemo(()=>{const t=[];for(let s=1;s<=c;s++)s===1||s===c||s>=l-1&&s<=l+1?t.push(s):t[t.length-1]!=="â¦"&&t.push("â¦");return t},[l,c]);return e.jsxs("div",{className:"min-h-screen bg-background",children:[e.jsx(J,{}),e.jsxs("main",{className:"container max-w-5xl py-8 px-4",children:[e.jsxs("header",{className:"mb-6",children:[e.jsx("h1",{className:"font-mono text-2xl sm:text-3xl font-bold text-foreground",children:"AI Tools List"}),e.jsx("p",{className:"mt-1 text-sm text-muted-foreground",children:"One page, every tool. Search by name or keyword, narrow by tag, page through the full catalogue."})]}),e.jsxs("div",{className:"relative mb-4",children:[e.jsx(K,{className:"absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground"}),e.jsx(W,{value:m,onChange:t=>v(t.target.value),placeholder:"Search tools by name, description, or tagâ¦",className:"pl-9 pr-9 h-11 font-mono text-sm","aria-label":"Search tools"}),m&&e.jsx("button",{type:"button",onClick:()=>v(""),className:"absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground","aria-label":"Clear search",children:e.jsx(X,{className:"w-4 h-4"})})]}),M.length>0&&e.jsxs("div",{className:"mb-4",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-2 text-[11px] font-mono uppercase tracking-wider text-muted-foreground",children:[e.jsx(Z,{className:"w-3 h-3"})," Filter by tag"]}),e.jsx("div",{className:"flex flex-wrap gap-1.5",children:M.map(([t,n])=>{const s=g.some(o=>o.toLowerCase()===t.toLowerCase());return e.jsxs("button",{type:"button",onClick:()=>I(t),className:d("inline-flex items-center gap-1 rounded-full border px-2.5 py-0.5 text-[11px] font-mono transition-colors",s?"border-primary bg-primary text-primary-foreground":"border-border bg-card text-muted-foreground hover:border-primary/40 hover:text-foreground"),"aria-pressed":s,children:[e.jsx("span",{children:t}),e.jsx("span",{className:d("text-[10px]",s?"opacity-80":"opacity-60"),children:n})]},t)})})]}),e.jsxs("div",{className:"flex items-center justify-between mb-3 text-xs font-mono text-muted-foreground",children:[e.jsx("div",{children:r?"Loading toolsâ¦":`${b.toLocaleStr
1ing()} tool${b===1?"":"s"}${L?" match your filters":""}`}),L&&e.jsx(Q,{type:"button",variant:"ghost",size:"sm",onClick:E,className:"h-7 text-[11px]",children:"Clear all"})]}),e.jsxs("ol",{className:"divide-y divide-border rounded-md border border-border bg-card overflow-hidden",children:[N.length===0&&!r&&e.jsxs("li",{className:"p-8 text-center text-sm text-muted-foreground",children:["No tools match your search.",L&&e.jsxs(e.Fragment,{children:[" ",e.jsx("button",{type:"button",onClick:E,className:"text-primary hover:underline",children:"Clear filters"})]})]}),N.map((t,n)=>{const s=Y(t.name);return e.jsx("li",{children:e.jsxs("div",{className:"group flex items-start gap-3 px-3 py-2.5 hover:bg-muted/40 transition-colors",children:[e.jsx("div",{className:"w-8 text-right shrink-0 pt-0.5 font-mono text-[11px] text-muted-foreground tabular-nums",children:h+n+1}),e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsxs("div",{className:"flex items-baseline gap-2 flex-wrap",children:[e.jsx(ee,{to:`/tool/${s}`,className:"font-mono font-semibold text-sm text-foreground group-hover:text-primary transition-colors",children:t.name}),t.subcategory&&e.jsx("span",{className:"text-[10px] font-mono uppercase tracking-wider text-muted-foreground",children:t.subcategory}),e.jsx(te,{variant:"secondary",className:"text-[9px] font-mono px-1.5 py-0 h-4",children:t.pricing})]}),e.jsx("p",{className:"mt-0.5 text-xs text-muted-foreground line-clamp-2",children:t.description}),t.tags&&t.tags.length>0&&e.jsx("div",{className:"mt-1.5 flex flex-wrap gap-1",children:t.tags.slice(0,5).map(o=>{const p=g.some(k=>k.toLowerCase()===o.toLowerCase());return e.jsx("button",{type:"button",onClick:k=>{k.preventDefault(),I(o)},className:d("text-[10px] font-mono px-1.5 py-0.5 rounded border transition-colors",p?"border-primary bg-primary/10 text-primary":"border-border bg-background text-muted-foreground hover:border-primary/40 hover:text-foreground"),children:o},o)})})]}),t.url&&e.jsx("a",{href:t.url,target:"_blank",rel:"noopener noreferrer",className:"shrink-0 inline-flex items-center justify-center w-7 h-7 rounded-md border border-border text-muted-foreground hover:text-primary hover:border-primary/40 transition-colors","aria-label":`Open ${t.name}`,title:"Open website",children:e.jsx(se,{className:"w-3.5 h-3.5"})})]})},`${s}-${h+n}`)})]}),c>1&&e.jsxs("div",{className:"mt-6",children:[e.jsx(A,{children:e.jsxs(R,{children:[e.jsx(f,{children:e.jsx(z,{href:"#",onClick:t=>{t.preventDefault(),l>1&&j(l-1)},"aria-disabled":l<=1,className:d(l<=1&&"pointer-events-none opacity-50")})}),F.map((t,n)=>t==="â¦"?e.jsx(f,{children:e.jsx(D,{})},`e-${n}`):e.jsx(f,{children:e.jsx(y,{href:"#",isActive:t===l,onClick:s=>{s.preventDefault(),j(t)},children:t})},t)),e.jsx(f,{children:e.jsx(B,{href:"#",onClick:t=>{t.preventDefault(),l<c&&j(l+1)},"aria-disabled":l>=c,className:d(l>=c&&"pointer-events-none opacity-50")})})]})}),e.jsxs("p",{className:"mt-2 text-center text-[11px] font-mono text-muted-foreground",children:["Page ",l," of ",c," · showing"," ",N.length===0?0:h+1,"â",h+N.length," of ",b.toLocaleString()]})]})]})]})};export{oe as default}; 2//# sourceMappingURL=ToolsList-BhowVzGD.js.map
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.