PageSourceSearch

https://app.xlift.ai/assets/LeadsPage-Tu93FEDs.js

js xlift.ai collected 2026-10-05 13:20:21 UTC 14,328 bytes, 7 lines download raw bytes

1import{v as Ee,ai as Fe,au as Re,o as t,A as xe,j as e,C as A,$ as Me,T as f,D as Q,G as d,L as ee,J as qe,X as z,O as se,ag as Ne,W as V,av as Pe,ac as ge,U as $,a5 as G,a4 as B,S as Ue,H as Be,E as me,I as Oe,am as De,ad as We,ab as He,al as _e,Z as Je}from"./index-dE8a1mPK.js";import{S as je}from"./SegmentedControl-CNEtbfTu.js";import{S as we}from"./Select-DebRlW67.js";import{N as Z}from"./NumberInput-EbCp_odp.js";import{S as Y}from"./Switch-Bm85N10X.js";import{I as Ke}from"./IconFileSpreadsheet-DH5pdkbt.js";import{I as Xe}from"./IconDownload-CbNmsJhq.js";import{T as o}from"./Table-5ftamFSf.js";import{C as fe}from"./Checkbox-CVTqs_Fd.js";import{I as Qe}from"./IconExternalLink-DcQXcLz7.js";import{I as Ve}from"./IconRepeat-BAxCrsfr.js";import{I as Ge}from"./IconPlus-B47PY1MC.js";import"./get-env-uyVen0u2.js";import"./OptionsDropdown-wonErrz5.js";import"./CheckIcon-DkMc45y2.js";import"./InputsGroupFieldset-C0syow2C.js";/**
2 * @license @tabler/icons-react v3.43.0 - MIT
3 *
4 * This source code is licensed under the MIT license.
5 * See the LICENSE file in the root directory of this source tree.
6 */const Ze=[["path",{d:"M4 6l9 0",key:"svg-0"}],["path",{d:"M4 12l7 0",key:"svg-1"}],["path",{d:"M4 18l7 0",key:"svg-2"}],["path",{d:"M15 15l3 3l3 -3",key:"svg-3"}],["path",{d:"M18 6l0 12",key:"svg-4"}]],Ye=Ee("outline","sort-descending","SortDescending",Ze),es=[{value:"topic",label:"Users by topic",icon:e.jsx(se,{size:14})},{value:"keyword",label:"Tweet keyword",icon:e.jsx(se,{size:14})},{value:"x-list",label:"X List members",icon:e.jsx(We,{size:14})},{value:"followers",label:"Followers of @",icon:e.jsx(He,{size:14})},{value:"retweeters",label:"Retweeters of tweet",icon:e.jsx(Ve,{size:14})}],ss={topic:{label:"Topic / niche",placeholder:'e.g. "shopify SEO" — finds users who post about this'},keyword:{label:"Keyword",placeholder:'e.g. "shopify dropshipping" — finds authors of tweets matching this'},"x-list":{label:"X List URL or ID",placeholder:"https://x.com/i/lists/12345  or  12345"},followers:{label:"Source handle",placeholder:"@some-account"},retweeters:{label:"Tweet URL or ID",placeholder:"https://x.com/.../status/1234"}};function vs(){var pe;const r=Fe(),{hasFeature:n,planLabel:g}=Re(),T=n("aiLeadScoring"),[u,E]=t.useState("topic"),[m,w]=t.useState(""),[p,I]=t.useState(null),[c,R]=t.useState(200),[x,M]=t.useState(0),[te,Se]=t.useState(0),[ae,be]=t.useState(!0),[re,ye]=t.useState(!1),[ne,ve]=t.useState(!1),[ie,Ce]=t.useState(""),[h,q]=t.useState([]),[k,O]=t.useState(null),[i,N]=t.useState(new Set),[ze,D]=t.useState(!1),[le,oe]=t.useState(!1),[W,ce]=t.useState(!1),de=xe({queryKey:["accounts"],queryFn:()=>$.listAccounts()}),ke=xe({queryKey:["lists"],queryFn:()=>$.listLists()}),v=t.useMemo(()=>{var a;return(((a=de.data)==null?void 0:a.accounts)||[]).filter(l=>l.executionMode==="cookie")},[de.data]);t.useEffect(()=>{!p&&v.length&&I(v[0].id)},[p,v]),t.useEffect(()=>{var S,b;if(!p){O(null);return}const s=v.find(J=>J.id===p);if(!s)return;const a=new Date().toISOString().slice(0,10),l=((S=s.scrapesToday)==null?void 0:S.date)===a&&s.scrapesToday.used||0,j=((b=s.dailyCaps)==null?void 0:b.scrapes)||1500;O({used:l,cap:j,remaining:Math.max(0,j-l),today:a})},[p,v]);const[ue,F]=t.useState("idle"),[Te,P]=t.useState(null),C=t.useRef(null);t.useEffect(()=>()=>{var s;return(s=C.current)==null?void 0:s.close()},[]);function Ie(){var s;(s=C.current)==null||s.close(),F("running"),P(null),q([]),N(new Set),$.scrapeLeadsStream({accountId:p,source:u,query:["keyword","topic","x-list"].includes(u)?m:void 0,handle:u==="followers"?m:void 0,tweetId:u==="retweeters"?m:void 0,cap:Number(c)||200,filters:{minFollowers:Number(x)||0,maxFollowers:Number(te)||0,requireAvatar:ae,requireBio:re,excludeVerified:ne,bioContains:ie}}).then(a=>{C.current=a,a.addEventListener("started",()=>{P({status:"STARTED",runtimeSec:0,itemCount:0})}),a.addEventListener("progress",l=>{try{P(JSON.parse(l.data))}catch{}}),a.addEventListener("done",l=>{var j;try{const S=JSON.parse(l.data);q(S.users||[]),O(S.budget||null),F("done"),G(`Found ${S.count} leads. ${((j=S.budget)==null?void 0:j.remaining)??"?"} scrapes left today.`)}catch{}a.close(),C.current=null}),a.addEventListener("error",l=>
6{if(C.current===null)return;let j="Scrape failed";try{l.data&&(j=JSON.parse(l.data).error||j)}catch{}F("error"),B(j),a.close(),C.current=null})}).catch(a=>{F("error"),B(a)})}function Le(){var s;(s=C.current)==null||s.close(),C.current=null,F("idle"),P(null),De.show({color:"orange",message:"Scrape aborted."})}const L={isPending:ue==="running",mutate:Ie,abort:Le,progress:Te,status:ue};function Ae(s){N(a=>{const l=new Set(a);return l.has(s)?l.delete(s):l.add(s),l})}function $e(){N(s=>s.size===h.length?new Set:new Set(h.map(a=>a.handle)))}const he=ss[u],U=!p,H=!m.trim(),_=k&&k.remaining<=0;return e.jsxs(A,{gap:"md",children:[e.jsxs("div",{children:[e.jsx(Me,{order:2,children:"Leads"}),e.jsx(f,{c:"dimmed",size:"sm",children:"Find people to add to your DM lists. Three sources, capped per scrape, throttled per account."})]}),e.jsx(Q,{withBorder:!0,children:e.jsxs(A,{gap:"sm",children:[e.jsx(je,{value:u,onChange:s=>{E(s),w(""),q([])},data:es.map(s=>({value:s.value,label:e.jsxs(d,{gap:6,wrap:"nowrap",children:[s.icon,e.jsx("span",{children:s.label})]})}))}),e.jsxs(d,{align:"flex-end",wrap:"wrap",gap:"xs",children:[e.jsx(ee,{label:he.label,placeholder:he.placeholder,value:m,onChange:s=>w(s.currentTarget.value),style:{flex:"2 1 240px",minWidth:180}}),e.jsx(we,{label:"Scrape from",placeholder:v.length?"Pick an account":"No cookie-mode accounts",value:p,onChange:I,disabled:!v.length,data:v.map(s=>({value:s.id,label:s.handle?`@${s.handle}`:s.id})),style:{flex:"1 1 180px",minWidth:160}}),e.jsx(Z,{label:"Max results",value:c,onChange:R,min:1,max:1e3,step:50,style:{flex:"1 1 140px",minWidth:120}})]}),e.jsxs(d,{align:"flex-end",wrap:"wrap",gap:"xs",children:[e.jsx(Z,{label:"Min followers",value:x,onChange:M,min:0,step:50,style:{flex:"1 1 140px",minWidth:120}}),e.jsx(Z,{label:"Max followers",value:te,onChange:Se,min:0,step:500,description:"0 = no max",style:{flex:"1 1 140px",minWidth:120}}),e.jsx(ee,{label:"Bio must contain",placeholder:"founder, indie, shopify",description:"Comma-separated; any match",value:ie,onChange:s=>Ce(s.currentTarget.value),style:{flex:"2 1 240px",minWidth:180}})]}),e.jsxs(d,{gap:"lg",children:[e.jsx(Y,{label:"Require avatar",checked:ae,onChange:s=>be(s.currentTarget.checked)}),e.jsx(Y,{label:"Require bio",checked:re,onChange:s=>ye(s.currentTarget.checked)}),e.jsx(Y,{label:"Exclude verified",checked:ne,onChange:s=>ve(s.currentTarget.checked)})]}),k&&e.jsxs(A,{gap:4,children:[e.jsxs(d,{justify:"space-between",children:[e.jsxs(f,{size:"xs",c:"dimmed",children:["Daily budget for this account: ",k.used," / ",k.cap]}),e.jsx(f,{size:"xs",c:"dimmed",children:"resets 00:00 UTC"})]}),e.jsx(qe,{value:k.used/Math.max(k.cap,1)*100,color:_?"red":"blue",size:"xs"})]}),e.jsxs(d,{justify:"space-between",children:[e.jsxs(f,{size:"xs",c:"dimmed",children:[U&&"Connect a cookie-mode account first.",!U&&H&&"Enter a keyword, handle, or tweet URL.",!U&&!H&&_&&"Budget exhausted — try tomorrow."]}),e.jsxs(d,{gap:"xs",children:[L.isPending&&e.jsx(z,{variant:"default",color:"red",onClick:()=>L.abort(),children:"Abort"}),e.jsx(z,{leftSection:e.jsx(se,{size:14}),loading:L.isPending,disabled:U||H||_,onClick:()=>L.mutate(),children:"Scrape"})]})]})]})}),L.isPending&&e.jsx(Q,{withBorder:!0,children:e.jsx(d,{justify:"space-between",wrap:"nowrap",align:"center",children:e.jsxs(d,{gap:"sm",wrap:"nowrap",style:{flex:1,minWidth:0},children:[e.jsx(Ne,{size:28}),e.jsxs(A,{gap:2,style:{minWidth:0},children:[e.jsx(f,{size:"sm",fw:500,children:ts(u,m)}),e.jsx(f,{size:"xs",c:"dimmed",children:as(L.progress)})]})]})})}),h.length>0&&e.jsxs(Q,{withBorder:!0,p:0,children:[e.jsxs(d,{justify:"space-between",p:"md",children:[e.jsxs(d,{gap:"xs",children:[e.jsxs(f,{fw:600,children:[h.length," results"]}),e.jsxs(f,{size:"sm",c:"dimmed",children:[i.size," selected"]})]}),e.jsxs(d,{gap:"xs",children:[(()=>{const s=i.size>0?i.size:h.length,a=s>50,l=s*3;return T?e.jsx(V,{label:a?`Capped at 50 per click — ${i.size>0?"narrow your selection":"select up to 50 to score"} first.`:`Score ${s} ${s===1?"lead":"leads"} 1–100 on fit against your brand. Costs ${l} credits (3 per lead).`,multiline:!0,maw:280,withArrow:!0,children:e.jsxs(z,{variant:"default",leftSection:e.jsx(ge,{size:14}),disabled:!h.length||le||a,loading:le,onClick:async()=>{var S;const j=i.size>0?h.filter(b=>i.has(b.handle)):h;oe(!0);try{const b=await $.scoreLeads({leads:j.map(y=>({handle:y.handle,bio:y.bio||"",followers:y.followers,recentTweets:y.recentTweets||[]}))}),J=new Map((b.scores||[]).map(y=>[y.handle,y]));q(y=>y.map(K=>{const X=J.get(K.handle);
6return X?{...K,aiFitScore:X.score,aiFitReason:X.reason}:K})),ce(!0),G(`Scored ${((S=b.scores)==null?void 0:S.length)||0} leads — sorting by fit.`)}catch(b){B(b)}finally{oe(!1)}},children:["AI score",i.size>0?` (${i.size})`:` all (${h.length})`,a?" · capped 50":` · ${l} cr`]})}):e.jsx(V,{label:`AI lead scoring isn't on your ${g} plan. Upgrade to unlock.`,multiline:!0,maw:280,withArrow:!0,children:e.jsx(z,{variant:"light",color:"dark",leftSection:e.jsx(ge,{size:14}),onClick:()=>Pe({reason:"AI lead scoring requires a paid plan.",code:"plan-gate"}),children:"AI score — upgrade"})})})(),e.jsx(z,{variant:"default",leftSection:e.jsx(Ke,{size:14}),onClick:()=>ns(i.size>0?h.filter(s=>i.has(s.handle)):h,u,m),children:i.size>0?`CSV (${i.size})`:"CSV (all)"}),e.jsxs(z,{leftSection:e.jsx(Xe,{size:14}),disabled:i.size===0,onClick:()=>D(!0),children:["Add to list (",i.size,")"]})]})]}),e.jsx(Ue.Autosize,{mah:520,children:e.jsxs(o,{highlightOnHover:!0,stickyHeader:!0,children:[e.jsx(o.Thead,{children:e.jsxs(o.Tr,{children:[e.jsx(o.Th,{w:36,children:e.jsx(fe,{checked:i.size>0&&i.size===h.length,indeterminate:i.size>0&&i.size<h.length,onChange:$e})}),e.jsx(o.Th,{children:"User"}),e.jsx(o.Th,{children:"Bio"}),e.jsx(o.Th,{ta:"right",style:{cursor:"pointer"},onClick:()=>ce(s=>!s),title:W?"Sorted by AI fit — click for original order":"Click to sort by AI fit score",children:e.jsxs(d,{gap:4,justify:"flex-end",wrap:"nowrap",children:["AI fit",W&&e.jsx(Ye,{size:12})]})}),e.jsx(o.Th,{ta:"right",children:"Followers"}),e.jsx(o.Th,{})]})}),e.jsx(o.Tbody,{children:(W?[...h].sort((s,a)=>(a.aiFitScore||0)-(s.aiFitScore||0)):h).map(s=>e.jsxs(o.Tr,{children:[e.jsx(o.Td,{children:e.jsx(fe,{checked:i.has(s.handle),onChange:()=>Ae(s.handle)})}),e.jsx(o.Td,{children:e.jsxs(d,{gap:"xs",wrap:"nowrap",children:[e.jsx(Be,{src:s.avatar,radius:"xl",size:"sm",children:(s.name||s.handle||"?").slice(0,1).toUpperCase()}),e.jsxs(A,{gap:0,children:[e.jsxs(d,{gap:4,children:[e.jsx(f,{fw:600,size:"sm",children:s.name||s.handle}),s.verified&&e.jsx(me,{variant:"light",size:"xs",children:"verified"})]}),e.jsxs(f,{size:"xs",c:"dimmed",children:["@",s.handle]})]})]})}),e.jsx(o.Td,{style:{maxWidth:360},children:e.jsx(f,{size:"xs",c:"dimmed",lineClamp:2,children:s.bio||"—"})}),e.jsx(o.Td,{ta:"right",children:typeof s.aiFitScore=="number"?e.jsx(V,{label:s.aiFitReason||"",disabled:!s.aiFitReason,multiline:!0,maw:400,children:e.jsx(me,{size:"sm",variant:"light",color:s.aiFitScore>=80?"green":s.aiFitScore>=50?"yellow":"gray",children:s.aiFitScore})}):e.jsx(f,{size:"xs",c:"dimmed",children:"—"})}),e.jsx(o.Td,{ta:"right",children:e.jsx(f,{size:"xs",children:s.followers.toLocaleString()})}),e.jsx(o.Td,{children:e.jsx(Oe,{href:`https://x.com/${s.handle}`,target:"_blank",rel:"noreferrer",size:"xs",children:e.jsx(Qe,{size:12})})})]},s.handle))})]})})]}),ze&&e.jsx(is,{handles:Array.from(i),lists:((pe=ke.data)==null?void 0:pe.lists)||[],onClose:()=>D(!1),onSaved:()=>{r.invalidateQueries({queryKey:["lists"]}),D(!1),N(new Set),G("Added to list.")}})]})}function ts(r,n){const g=(n||"").trim();return r==="keyword"?g?`Searching X for "${g}"…`:"Searching X…":r==="followers"?g?`Pulling followers of @${g.replace(/^@/,"")}…`:"Pulling followers…":r==="retweeters"?"Pulling retweeters…":"Scraping…"}function as(r){if(!r)return"starting…";const n=(r.status||"").toLowerCase(),g=n==="started"||n==="ready"?"queued":n==="running"?"running":n==="succeeded"?"wrapping up":n,T=r.itemCount>0?`${r.itemCount} tweets so far`:"waiting for first batch";return`${g} · ${r.runtimeSec||0}s · ${T}`}function rs(r){if(r==null)return"";const n=String(r).replace(/"/g,'""');return/[",\n\r]/.test(n)?`"${n}"`:n}function ns(r,n,g){const u=[["handle","name","bio","followers","following","tweets","verified","location","created_at","profile_url"].join(",")];for(const c of r)u.push([c.handle,c.name,c.bio,c.followers,c.following,c.tweets,c.verified?"true":"false",c.location,c.createdAt,`https://x.com/${c.handle}`].map(rs).join(","));const E=new Blob([u.join(`
7`)],{type:"text/csv;charset=utf-8"}),m=URL.createObjectURL(E),w=document.createElement("a");
7w.href=m;const p=(g||n||"leads").toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"").slice(0,40)||"leads",I=new Date().toISOString().slice(0,10);w.download=`xlift-${n}-${p}-${I}.csv`,document.body.appendChild(w),w.click(),w.remove(),URL.revokeObjectURL(m)}function is({handles:r,lists:n,onClose:g,onSaved:T}){var R;const[u,E]=t.useState(n.length?"existing":"new"),[m,w]=t.useState(((R=n[0])==null?void 0:R.id)||null),[p,I]=t.useState(""),c=_e({mutationFn:async()=>{let x=m;if(u==="new"){if(!p.trim())throw new Error("Name the new list");x=(await $.createList({name:p.trim()})).id}if(!x)throw new Error("Pick a list");return await $.addHandles(x,{handles:r.map(M=>({handle:M}))}),x},onSuccess:T,onError:x=>B(x)});return e.jsx(Je,{opened:!0,onClose:g,title:`Add ${r.length} ${r.length===1?"lead":"leads"} to list`,children:e.jsxs(A,{children:[e.jsx(je,{value:u,onChange:E,data:[{value:"existing",label:"Existing list",disabled:!n.length},{value:"new",label:"New list"}]}),u==="existing"?e.jsx(we,{label:"Pick a list",value:m,onChange:w,data:n.map(x=>({value:x.id,label:x.name}))}):e.jsx(ee,{label:"New list name",placeholder:"e.g. Shopify founders Apr 2026",value:p,onChange:x=>I(x.currentTarget.value)}),e.jsxs(d,{justify:"flex-end",children:[e.jsx(z,{variant:"subtle",onClick:g,children:"Cancel"}),e.jsx(z,{leftSection:e.jsx(Ge,{size:14}),loading:c.isPending,onClick:()=>c.mutate(),children:"Add"})]})]})})}export{vs as default};

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.