PageSourceSearch

https://lo.st/assets/StickerWizard-o4Iel2qT.js

js lo.st collected 2026-10-03 22:05:05 UTC 28,236 bytes, 1 lines download raw bytes

1import{l as E,e as Ut,r as l,h as z,j as e,x as D,a as Ft,o as Je,J as Ke,bo as Dt,X as ee,L as Ye,ay as Ze,ax as Se,ar as et,as as tt,at,au as rt,av as pe,V as Lt}from"./index-f--GfbGy.js";import{r as nt,S as $t,f as st,e as Wt,s as Ht,L as Ot}from"./export-CGDJNp5Y.js";import{b as ot,a as it}from"./utm-dof6oR25.js";import{m as Bt,i as Vt}from"./tagCode-DovrqfD5.js";import{A as lt}from"./arrow-left-CibCCW_O.js";import{W as Gt}from"./wand-sparkles-Cc9i3BGh.js";import{C as Xt}from"./circle-alert-Cm_KuaSA.js";import{R as ct}from"./rotate-ccw-Cc9dq3Gs.js";import{U as dt}from"./upload-B4rIEMqt.js";import{I as mt}from"./info-CGOxyNkp.js";import{M as Jt}from"./mouse-pointer-B2lN_HbT.js";import{D as Kt}from"./download-BJHNM_Au.js";import{A as Yt}from"./arrow-right-BM8FEdkT.js";import"./types-5nQI3Ypg.js";import"./BrandedQr-CLyiI_ri.js";import"./brandedQr-MYFiD4Ef.js";import"./browser-CjSdxGTc.js";const ut=200,Zt=.06,ea=.7,ta=.35,aa=2e5;async function ht(r,a={}){const o=typeof r=="string"?await sa(r):r;if(a.signal?.aborted)throw new DOMException("Aborted","AbortError");const s=o.naturalHeight/o.naturalWidth,x=ut,d=Math.max(1,Math.round(ut*s)),h=document.createElement("canvas");h.width=x,h.height=d;const n=h.getContext("2d",{willReadFrequently:!0});if(!n)return oe();n.drawImage(o,0,0,x,d);const k=n.getImageData(0,0,x,d).data,v=new Uint8ClampedArray(x*d);for(let q=0,N=0;q<k.length;q+=4,N++)v[N]=Math.round(.299*k[q]+.587*k[q+1]+.114*k[q+2]);return ra(v,x,d,a.signal)}function ra(r,a,o,s){const x=gt(r,a,o,n=>n>=235,s);if(s?.aborted)throw new DOMException("Aborted","AbortError");const d=gt(r,a,o,n=>n<=30,s),h=na(x,d);return h||oe()}function gt(r,a,o,s,x){const d=new Uint8Array(a*o),h=[];let n=null,k=0;const v=a*o,q=Math.floor(v*ea);for(let N=0;N<o;N++){if(x?.aborted)return null;for(let H=0;H<a;H++){const J=N*a+H;if(d[J]||!s(r[J]))continue;let K=0,g=H,te=H,ae=N,ie=N,b=!1;for(h.length=0,h.push(J),d[J]=1;h.length;){const f=h.pop(),Q=f%a,L=(f-Q)/a;if(K++,k++,Q<g&&(g=Q),Q>te&&(te=Q),L<ae&&(ae=L),L>ie&&(ie=L),K>q){b=!0;break}if(k>aa)return n?ft(n,a,o,s):null;if(Q>0){const m=f-1;!d[m]&&s(r[m])&&(d[m]=1,h.push(m))}if(Q<a-1){const m=f+1;!d[m]&&s(r[m])&&(d[m]=1,h.push(m))}if(L>0){const m=f-a;!d[m]&&s(r[m])&&(d[m]=1,h.push(m))}if(L<o-1){const m=f+a;!d[m]&&s(r[m])&&(d[m]=1,h.push(m))}}b||(!n||K>n.area)&&(n={x:g,y:ae,w:te-g+1,h:ie-ae+1,area:K})}}return n?ft(n,a,o,s):null}function ft(r,a,o,s){const x=a*o;if(r.area/x<Zt)return null;const d=r.w/Math.max(1,r.h);if(Math.abs(d-1)>ta)return null;const h=(r.x+r.w/2)/a*100,n=(r.y+r.h/2)/o*100,k=Math.min(a,o),v=Math.min(r.w,r.h)/k*100;return{cx:h,cy:n,sizePct:v,kind:s(255)?"white":"dark",_region:r}}function na(r,a){return!r&&!a?null:Re(r&&!a?r:a&&!r?a:r._region.area>=a._region.area?r:a)}function Re(r){return{cx:r.cx,cy:r.cy,sizePct:r.sizePct,kind:r.kind}}function oe(){return{cx:85,cy:85,sizePct:22,kind:"fallback"}}function sa(r){return new Promise((a,o)=>{const s=new Image;/^https?:/i.test(r)&&(s.crossOrigin="anonymous"),s.onload=()=>a(s),s.onerror=()=>o(new Error("Could not load image for placeholder detection")),s.src=r})}function oa(r,a){if(!r||!a)return 100;const o=r/a;return o>=1.7?100:o>=1.2?90:o>=.85&&o<=1.15?60:80}function G(r){try{E.functions.invoke("sticker-detection-log",{body:r}).catch(()=>{})}catch{}}const X=["upload","place","style","destination","mint"],ia=540;function Ra(){const r=Ut(),[a,o]=l.useState("upload"),[s,x]=l.useState([]),[d,h]=l.useState(""),[n,k]=l.useState(null),[v,q]=l.useState(null),[N,H]=l.useState(0),[J,K]=l.useState(0),[g,te]=l.useState(100),[ae,ie]=l.useState(!1),b=l.useMemo(()=>N>0?Math.round(J/N*g*10)/10:50,[N,J,g]),[f,Q]=l.useState(25),[L,m]=l.useState(50),[Ae,O]=l.useState(50),[C,T]=l.useState(null),[ue,M]=l.useState(!1),[he,I]=l.useState(!1),[Ee,S]=l.useState(null),[wt,R]=l.useState(null),Qe=l.useRef(null),ge=l.useRef(!1),[Y,Ie]=l.useState("square"),[B,qe]=l.useState("#0A0A0A"),[j,_t]=l.useState("none"),[V,bt]=l.useState(null),[we,Te]=l.useState(null),[re,vt]=l.useState("https://lo.st"),[Z,Ue]=l.useState("short"),[U,jt]=l.useState(""),[fe,kt]=l.useState(10),[Fe,De]=l.useState(!1),[_e,yt]=l.useState(null),[Le,Nt]=l.useState(33);l.useEffect(()=>{(async()=>{const{data:t}=await E.from("brands").select("id, name, organization_id").order("name").limit(200);x(t??[]),t?.[0]&&h(t[0].id)})()},[]),l.useEffect(()=>{if(!n){q(null),H(0),K(0),T(null),M(!1),I(!1),S(null),R(null);return}const t=URL.createObjectURL(n);q(t),M(!1),I(!1),S(null),R(null);let c=!1;const _=new AbortController;let u,p;const i=new Image;return i.onload=()=>
1{if(c)return;H(i.naturalWidth),K(i.naturalHeight),ae||te(oa(i.naturalWidth,i.naturalHeight)),T("detecting");const $=async()=>{const P=performance.now(),F={artwork_filename:n?.name??null,artwork_mime:n?.type??null,artwork_bytes:n?.size??null,image_w:i.naturalWidth,image_h:i.naturalHeight};try{const w=await ht(i,{signal:_.signal});if(c){G({...F,outcome:"aborted",abort_reason:"unmount",duration_ms:Math.round(performance.now()-P)});return}m(w.cx),O(w.cy),M(!1),I(!1);const W=Math.min(i.naturalWidth>0?g:100,i.naturalWidth>0?i.naturalHeight/i.naturalWidth*g:50);Q(Math.max(15,Math.round(w.sizePct/100*W))),T(w.kind),S(null),R(null),w.kind!=="fallback"?z.success("Found a QR slot in your artwork — nudge it if needed."):z.message("No clear QR slot found — drag the square or accept the current placement."),G({...F,outcome:w.kind==="white"?"detected_white":w.kind==="dark"?"detected_dark":"fallback",detection_kind:w.kind,duration_ms:Math.round(performance.now()-P),cx:w.cx,cy:w.cy,size_pct:w.sizePct})}catch(w){const W=Math.round(performance.now()-P);if(c||w?.name==="AbortError"){G({...F,outcome:"aborted",abort_reason:c?"unmount":"abort_signal",duration_ms:W});return}console.warn("[sticker-wizard] placeholder detection failed",{ms:W,w:i.naturalWidth,h:i.naturalHeight,error:w?.message});const se=oe();m(se.cx),O(se.cy),M(!1),I(!1),T("fallback"),S("QR slot detection hit an error. Manual placement is ready, so you can continue without restarting."),R("detect"),G({...F,outcome:"exception",failure_code:"detect_exception",error_message:w?.message??String(w),duration_ms:W})}finally{u!==void 0&&(window.clearTimeout(u),u=void 0)}};(P=>{const F=window.requestIdleCallback;typeof F=="function"?p=F(P,{timeout:200}):p=window.setTimeout(P,0)})(()=>{$()}),u=window.setTimeout(()=>{if(c)return;_.abort();const P=oe();m(P.cx),O(P.cy),M(!1),I(!1),T("fallback"),S("QR slot detection timed out. Manual placement is ready, so the wizard will not get stuck."),R("detect"),z.message("Couldn't auto-detect a slot — drag the QR where you want it."),G({artwork_filename:n?.name??null,artwork_mime:n?.type??null,artwork_bytes:n?.size??null,image_w:i.naturalWidth,image_h:i.naturalHeight,outcome:"timeout",abort_reason:"timeout_1500ms",duration_ms:1500})},1500)},i.onerror=()=>{c||(T("fallback"),M(!1),I(!1),S("Could not load this artwork preview. Try a PNG or JPG export, then place the QR manually."),R("generic"),G({artwork_filename:n?.name??null,artwork_mime:n?.type??null,artwork_bytes:n?.size??null,outcome:"load_error",failure_code:"image_load_failed"}))},i.src=t,()=>{if(c=!0,_.abort(),u!==void 0&&window.clearTimeout(u),p!==void 0){const $=window.cancelIdleCallback;typeof $=="function"?$(p):window.clearTimeout(p)}URL.revokeObjectURL(t)}},[n]),l.useEffect(()=>{if(!V){Te(null);return}ze(V).then(Te)},[V]);const be=Math.max(0,Math.min(g-f,L/100*g-f/2)),ve=Math.max(0,Math.min(b-f,Ae/100*b-f/2)),le=l.useMemo(()=>({id:"preview",owner_org_id:null,name:U||"New sticker",description:null,category:"general",status:"draft",width_mm:g,height_mm:b,bleed_mm:0,safe_area_mm:0,corner_radius_mm:2,orientation:g===b?"square":g>b?"landscape":"portrait",preview_url:null,background_color:"#ffffff",created_at:"",updated_at:""}),[U,g,b]),je=l.useMemo(()=>v?[{id:"preview-bg",template_id:"preview",kind:"background",storage_path:"",public_url:v,z_index:0,opacity:1,x_mm:null,y_mm:null,width_mm:null,height_mm:null,rotation_deg:0}]:[],[v]),ke={template_id:"preview",x_mm:be,y_mm:ve,width_mm:f,height_mm:f,rotation_deg:0,padding_mm:1,alignment:"center",quiet_zone_modules:4,error_correction:j==="none"?"M":"H",logo_overlay:j!=="none",module_style:Y,fg_color:B,logo_kind:j,logo_asset_path:null},Ct={left:`${be/Math.max(g,1)*100}%`,top:`${ve/Math.max(b,1)*100}%`,width:`${f/Math.max(g,1)*100}%`,height:`${f/Math.max(b,1)*100}%`},Mt=!!v&&C!=="detecting",ne=C==="white"||C==="dark",$e="PREVIEW2",ce=l.useMemo(()=>Z==="short"?ot($e):it({base_url:re||"https://lo.st",utm_source:"sticker",utm_medium:"qr",utm_campaign:Pe(U||"preview"),utm_content:null},$e),[Z,re,U]);l.useEffect(()=>{let t=!1;const c=xt(j,we);return nt({value:ce,moduleStyle:Y,fgColor:B,level:c?"H":"M",logo:c}).then(_=>{t||(yt(_.fragment),Nt(_.modules))}),()=>{t=!0}},[ce,Y,B,j,we]);const St=(t,c)=>{const _=Qe.current;if(!_)return;const u=_.getBoundingClientRect(),p=Math.max(0,Math.min(u.width,t-u.left)),i=Math.max(0,Math.min(u.height,c-u.top));m(p/u.width*100),O(i/u.height*100),I(!0),M(!0),S(null),R(null)},We=t=>{St(t.clientX,t.clientY)},ye=()=>{I(!0),M(!0),S(null),R(null)},Rt=()=>{const t=X.indexOf(a);t<X.length-1&&o(X[t+1])},Pt=()=>{const t=X.indexOf(a);t>0&&o(X[t-1])},He=async()=>
1{if(!v)return;T("detecting");const t=new AbortController,c=performance.now(),_={artwork_filename:n?.name??null,artwork_mime:n?.type??null,artwork_bytes:n?.size??null},u=window.setTimeout(()=>t.abort(),1500);try{const p=await ca(v),i=await ht(p,{signal:t.signal});m(i.cx),O(i.cy),M(!1),I(!1);const $=Math.min(g,b);Q(Math.max(15,Math.round(i.sizePct/100*$))),T(i.kind),S(null),R(null),i.kind==="fallback"&&z.message("No clear QR slot found — drag the square or accept the current placement."),G({..._,image_w:p.naturalWidth,image_h:p.naturalHeight,outcome:i.kind==="white"?"detected_white":i.kind==="dark"?"detected_dark":"fallback",detection_kind:i.kind,abort_reason:"re_detect",duration_ms:Math.round(performance.now()-c),cx:i.cx,cy:i.cy,size_pct:i.sizePct})}catch(p){const i=oe();m(i.cx),O(i.cy),M(!1),I(!1),T("fallback"),S("QR slot re-detection failed. Manual placement is ready, so you can continue."),R("detect"),z.error("Couldn't re-detect a slot — placed in the corner. Drag to move."),G({..._,outcome:p?.name==="AbortError"?"timeout":"exception",abort_reason:"re_detect",failure_code:p?.name==="AbortError"?"timeout_1500ms":"detect_exception",error_message:p?.message??null,duration_ms:Math.round(performance.now()-c)})}finally{window.clearTimeout(u)}},Oe=()=>{const t=oe();m(t.cx),O(t.cy),M(!1),I(!1),T("fallback"),S(null),R(null),z.message("Drag the square or accept the current placement.")},zt=()=>{M(!0),S(null),R(null),z.success("QR placement confirmed.")},At=async()=>{if(!(!n||!_e))try{const t=await ze(n),c=le,_=[{...je[0],public_url:t}],u=st({template:c,assets:_,slot:ke,qrSvg:_e,qrValue:ce});await Wt(u,c,`${Pe(U||"preview")}.jpg`)}catch(t){z.error(t.message)}},Et=async()=>{if(!U.trim()||!d||!n){z.error("Name, brand and artwork are required.");return}De(!0);try{const{data:t}=await E.auth.getUser(),c=t.user?.id??null,_=s.find(y=>y.id===d),u=await E.from("sticker_templates").insert({name:U.trim(),category:"general",status:"published",width_mm:g,height_mm:b,bleed_mm:0,safe_area_mm:0,corner_radius_mm:2,orientation:le.orientation,background_color:"#ffffff",created_by_user_id:c}).select("id").single();if(u.error)throw u.error;const p=u.data.id,i=`${c??"anon"}/${p}/${Date.now()}-${n.name.replace(/\s+/g,"_")}`,$=await E.storage.from("sticker-artwork").upload(i,n,{cacheControl:"3600"});if($.error)throw $.error;const{data:Be}=await E.storage.from("sticker-artwork").createSignedUrl(i,3600*24*365),P=await E.from("sticker_template_assets").insert({template_id:p,kind:"background",storage_path:i,public_url:Be?.signedUrl??null,z_index:0});if(P.error)throw P.error;let F=null;if(j==="custom"&&V){const y=`${c??"anon"}/${p}/logo-${Date.now()}-${V.name.replace(/\s+/g,"_")}`;(await E.storage.from("sticker-artwork").upload(y,V,{cacheControl:"3600"})).error||(F=y)}const w=await E.from("sticker_template_qr_slot").insert({template_id:p,x_mm:be,y_mm:ve,width_mm:f,height_mm:f,rotation_deg:0,padding_mm:1,alignment:"center",quiet_zone_modules:4,error_correction:j==="none"?"M":"H",logo_overlay:j!=="none",module_style:Y,fg_color:B,logo_kind:j,logo_asset_path:F});if(w.error)throw w.error;const W=Pe(U),se=await E.from("tag_campaigns").insert({name:U.trim(),slug:W,brand_id:d,owner_org_id:_?.organization_id??null,campaign_type:"qr_sticker",theme:"generic",status:"draft",created_by_user_id:c}).select("id").single();if(se.error)throw se.error;const Ne=se.data.id,Ve=await E.from("sticker_campaign_config").insert({tag_campaign_id:Ne,template_id:p,destination_url:re,utm_source:"sticker",utm_medium:"qr",utm_campaign:W,utm_content:null});if(Ve.error)throw Ve.error;const Ce=Bt(fe).map(y=>{if(!Vt(y))throw new Error(`Generated tag code "${y}" failed format validation`);const de=Z==="short"?ot(y):it({base_url:re,utm_source:"sticker",utm_medium:"qr",utm_campaign:W,utm_content:null},y);return{campaign_id:Ne,tag_code:y,qr_url:de,status:"created"}}),Me=await E.from("tags").insert(Ce);if(Me.error)throw(Me.error.message??"").includes("tags_tag_code_format_chk")?new Error("Tag code format rejected by the database — please report this."):Me.error;try{const y=await ze(n),de=Ce[0].qr_url,Ge=xt(j,we),It=await nt({value:de,moduleStyle:Y,fgColor:B,level:Ge?"H":"M",logo:Ge}),qt=st({template:le,assets:[{...je[0],public_url:y}],slot:ke,qrSvg:It.fragment,qrValue:de}),Tt=await Ht(qt,le),Xe=URL.createObjectURL(Tt),me=document.createElement("a");me.href=Xe,me.download=`${Ce[0].tag_code}.jpg`,document.body.appendChild(me),me.click(),document.body.removeChild(me),setTimeout(()=>URL.revokeObjectURL(Xe),1e3)}catch{}z.success(`Created campaign with ${fe} trackable stickers`),r(`/admin/sticker-campaigns/${Ne}`)}catch(t){const c=t?.message??"Failed";z.error(c.includes("row-level security")?"You don't have permission to create campaigns for this brand's organization.":c)}finally{De(!1)}},Qt=a==="upload"&&!!n||a==="place"&&f>=10&&(ue||he)||a==="style"||a==="destination"&&!!re.trim()||a==="mint";
1return e.jsxs("div",{className:"p-6 max-w-6xl mx-auto space-y-6",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(D,{asChild:!0,variant:"ghost",size:"sm",children:e.jsxs(Ft,{to:"/admin/sticker-campaigns",children:[e.jsx(lt,{className:"w-4 h-4 me-1"}),"Back"]})}),e.jsxs("h1",{className:"text-2xl font-semibold flex items-center gap-2",children:[e.jsx(Gt,{className:"w-5 h-5"})," Sticker wizard"]})]}),e.jsx("div",{className:"flex items-center gap-2 flex-wrap",children:X.map((t,c)=>{const _=t===a,u=X.indexOf(a)>c;return e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("div",{className:`w-7 h-7 grid place-items-center rounded-full text-xs font-medium ${u?"bg-emerald-500 text-white":_?"bg-emerald-100 text-emerald-700 ring-2 ring-emerald-500":"bg-muted text-muted-foreground"}`,children:u?e.jsx(Je,{className:"w-4 h-4"}):c+1}),e.jsx("div",{className:"text-sm",children:la(t)}),c<X.length-1&&e.jsx("div",{className:"w-8 h-px bg-border mx-1"})]},t)})}),e.jsxs("div",{className:"grid lg:grid-cols-[1fr,400px] gap-6",children:[e.jsx(Ke,{className:"p-6 flex flex-col items-center justify-center bg-muted/20 min-h-[480px] gap-3",children:v?e.jsxs(e.Fragment,{children:[e.jsxs("div",{ref:Qe,className:a==="place"?"relative cursor-crosshair select-none touch-none":"relative select-none",onPointerDown:t=>{a==="place"&&(t.preventDefault(),ge.current=!0,t.currentTarget.setPointerCapture(t.pointerId),We(t))},onPointerMove:t=>{a==="place"&&ge.current&&(t.preventDefault(),We(t))},onPointerUp:t=>{ge.current=!1,t.currentTarget.hasPointerCapture(t.pointerId)&&t.currentTarget.releasePointerCapture(t.pointerId)},onPointerCancel:()=>{ge.current=!1},children:[e.jsx($t,{template:le,assets:je,slot:ke,qrValue:a==="upload"?null:ce,qrSvgFragment:a==="upload"?null:_e,displayWidthPx:ia,showSlotOutline:a==="place"}),Mt&&e.jsx("div",{"aria-label":ne?"Detected QR slot":"QR slot placement",className:`absolute z-20 grid place-items-center rounded-md border-2 shadow-lg transition ${ne?"border-primary bg-primary/10 ring-4 ring-primary/20":"border-warning bg-warning-soft ring-4 ring-warning/20"} ${a==="place"?"cursor-grab active:cursor-grabbing pointer-events-auto":"pointer-events-none"}`,style:Ct,children:e.jsx("span",{className:`rounded px-2 py-1 text-[10px] font-semibold uppercase shadow-sm ${ne?"bg-primary text-primary-foreground":"bg-background text-foreground"}`,children:ne?"Detected QR slot":"QR slot"})})]}),e.jsxs("div",{className:"text-xs text-muted-foreground text-center",children:[g.toFixed(0)," × ",b.toFixed(0)," mm · QR ",f.toFixed(0)," mm",a==="place"&&" · click or drag on the preview to position the QR",a==="upload"&&ne&&" · detected slot shown"]})]}):e.jsxs("div",{className:"text-sm text-muted-foreground flex flex-col items-center gap-2",children:[e.jsx(Dt,{className:"w-10 h-10"}),"Upload your sticker artwork to begin."]})}),e.jsxs(Ke,{className:"p-5 space-y-4",children:[Ee&&e.jsxs("div",{className:"rounded-lg border border-destructive/30 bg-destructive/10 p-3 text-xs text-destructive flex flex-col gap-2",children:[e.jsxs("div",{className:"flex gap-2",children:[e.jsx(Xt,{className:"w-4 h-4 shrink-0"}),e.jsx("span",{children:Ee})]}),wt==="detect"&&n&&e.jsxs("div",{className:"flex gap-2 ps-6",children:[e.jsxs(D,{variant:"outline",size:"sm",className:"h-7 border-destructive/40 text-destructive hover:bg-destructive/15",onClick:He,disabled:C==="detecting",children:[e.jsx(ct,{className:"w-3.5 h-3.5 me-1"}),C==="detecting"?"Retrying…":"Try again"]}),e.jsx(D,{variant:"ghost",size:"sm",className:"h-7 text-destructive hover:bg-destructive/10",onClick:Oe,children:"Place manually"})]})]}),a==="upload"&&e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"font-medium",children:"1. Upload your sticker artwork"}),e.jsxs("label",{className:"block border-2 border-dashed rounded-lg p-6 text-center cursor-pointer hover:border-emerald-500",children:[e.jsx(dt,{className:"w-5 h-5 mx-auto mb-1 text-muted-foreground"}),e.jsx("div",{className:"text-sm",children:n?n.name:"Drop a PNG or JPG"}),e.jsx("input",{type:"file",accept:"image/png,image/jpeg",className:"hidden",onChange:t=>k(t.target.files?.[0]??null)})]}),e.jsx(A,{label:`Physical width (${g} mm)`,children:e.jsx(ee,{type:"number",min:20,max:600,value:g,onChange:t=>{ie(!0),te(Math.max(20,Math.min(600,Number(t.target.value)||0)))}})}),e.jsxs("p",{className:"text-[11px] text-muted-foreground",children:["Width is auto-picked from the artwork aspect (",b.toFixed(1)," mm tall). Override if you have a specific print size in mind."]}),C==="detecting"&&e.jsxs("div",{className:"text-[11px] text-muted-foreground flex items-center gap-1.5",children:[e.jsx(Ye,{className:"w-3 h-3 animate-spin"}
1),"Finding QR slot in your artwork…"]}),C==="fallback"&&e.jsxs("div",{className:"text-[11px] text-muted-foreground flex items-center gap-1.5",children:[e.jsx(mt,{className:"w-3 h-3"}),"No slot detected — you'll place the QR manually on the next step."]}),ne&&e.jsxs("div",{className:"text-[11px] text-muted-foreground flex items-center gap-1.5",children:[e.jsx(Ze,{className:"w-3 h-3"}),"Detected slot is highlighted on the artwork. Confirm or adjust it on the next step."]})]}),a==="place"&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"font-medium flex items-center gap-2",children:["2. Place the QR code",C==="detecting"&&e.jsxs(Se,{variant:"secondary",className:"gap-1",children:[e.jsx(Ye,{className:"w-3 h-3 animate-spin"}),"Finding QR slot…"]}),(C==="white"||C==="dark")&&e.jsxs(Se,{variant:"secondary",className:"gap-1",children:[e.jsx(Ze,{className:"w-3 h-3"}),"Auto-detected"]}),C==="fallback"&&e.jsxs(Se,{variant:"outline",className:"gap-1",children:[e.jsx(mt,{className:"w-3 h-3"}),"Drag to place"]})]}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Click or drag anywhere on the artwork to recenter the QR. Use the slider to resize."}),e.jsx(A,{label:`QR size (${f.toFixed(0)} mm)`,children:e.jsx("input",{type:"range",min:10,max:Math.floor(Math.min(g,b)*.9),value:f,onChange:t=>{Q(Number(t.target.value)),ye()},className:"w-full"})}),e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsx(A,{label:"Center X (%)",children:e.jsx(ee,{type:"number",min:0,max:100,value:Math.round(L),onChange:t=>{m(Math.max(0,Math.min(100,Number(t.target.value)||0))),ye()}})}),e.jsx(A,{label:"Center Y (%)",children:e.jsx(ee,{type:"number",min:0,max:100,value:Math.round(Ae),onChange:t=>{O(Math.max(0,Math.min(100,Number(t.target.value)||0))),ye()}})})]}),!ue&&!he&&e.jsx("div",{className:"rounded-lg border border-warning/30 bg-warning-soft p-3 text-xs text-warning",children:"Confirm the highlighted square, or drag it onto the right QR location before continuing."}),e.jsxs("div",{className:"grid grid-cols-2 gap-2",children:[e.jsxs(D,{variant:"ghost",size:"sm",onClick:He,disabled:C==="detecting",children:[e.jsx(ct,{className:"w-3.5 h-3.5 me-1"}),"Re-detect"]}),e.jsxs(D,{variant:"ghost",size:"sm",onClick:Oe,children:[e.jsx(Jt,{className:"w-3.5 h-3.5 me-1"}),"Place manually"]})]}),e.jsxs(D,{variant:ue||he?"outline":"default",size:"sm",onClick:zt,className:"w-full",children:[e.jsx(Je,{className:"w-3.5 h-3.5 me-1"}),ue||he?"Placement confirmed":"Confirm highlighted placement"]}),e.jsx(pt,{qrSizeMm:f,modules:Le,payloadMode:Z,hasLogo:j!=="none"})]}),a==="style"&&e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"font-medium",children:"3. QR design"}),e.jsx(A,{label:"Module style",children:e.jsxs("div",{className:"grid grid-cols-2 gap-2",children:[e.jsx(xe,{label:"Square",active:Y==="square",onClick:()=>Ie("square")}),e.jsx(xe,{label:"Dots",active:Y==="dots",onClick:()=>Ie("dots")})]})}),e.jsxs(A,{label:"Foreground color",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("input",{type:"color",value:B,onChange:t=>qe(t.target.value),className:"h-10 w-14 rounded border border-input bg-background cursor-pointer"}),e.jsx(ee,{value:B,onChange:t=>qe(t.target.value),className:"font-mono uppercase"})]}),!da(B)&&e.jsx("p",{className:"text-[11px] text-amber-600 mt-1",children:"⚠ Low contrast vs white — scanners may struggle. Use a darker color."})]}),e.jsx(A,{label:"Center logo",children:e.jsxs(et,{value:j,onValueChange:t=>_t(t),children:[e.jsx(tt,{children:e.jsx(at,{})}),e.jsxs(rt,{children:[e.jsx(pe,{value:"none",children:"None"}),e.jsx(pe,{value:"lost",children:"lo.st mark"}),e.jsx(pe,{value:"custom",children:"Custom upload"})]})]})}),j==="custom"&&e.jsxs("label",{className:"block border-2 border-dashed rounded-lg p-3 text-center cursor-pointer hover:border-emerald-500 text-xs",children:[e.jsx(dt,{className:"w-4 h-4 mx-auto mb-1 text-muted-foreground"}),V?V.name:"PNG or SVG, ≤ 200 KB",e.jsx("input",{type:"file",accept:"image/png,image/svg+xml",className:"hidden",onChange:t=>{const c=t.target.files?.[0];if(c&&c.size>2e5){z.error("Logo must be ≤ 200 KB");return}bt(c??null)}})]}),e.jsx("p",{className:"text-[11px] text-muted-foreground",children:"Adding a logo automatically bumps error-correction to H so the QR still scans."})]}),a==="destination"&&e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"font-medium",children:"4. Where should the QR send people?"}),e.jsxs(A,{label:"QR payload",children:[e.jsxs("div",{className:"grid grid-cols-2 gap-2",children:[e.jsx(xe,{label:"Short link · /s/code",active:Z==="short",onClick:()=>Ue("short")}),e.jsx(xe,{label:"Full URL + UTM",active:Z==="full",onClick:()=>Ue("full")})]}),e.jsxs("p",{className:"text-[11px] text-muted-foreground mt-1",children:["Short link encodes ",e.jsx("code",{children:"lo.st/s/<code>"})," (~24 chars) so the QR has fewer modules and scans from much further away. The /s/ page records the scan and forwards to your destination with full analytics."]})]}),e.jsx(A,{label:"Destination URL (may include query params)",children:e.jsx(ee,{value:re,onChange:t=>vt(t.target.value),placeholder:"https://lo.st/found?promo=summer"})}),e.jsxs("p",{className:"text-[11px] text-muted-foreground",children:["Each minted sticker appends ",e.jsx("code",{children:"utm_content=<tag_code>"})," so individual scans are trackable. Existing query parameters are preserved."]}),e.jsx(pt,{qrSizeMm:f,modules:Le,payloadMode:Z,hasLogo:j!=="none"}),e.jsxs("div",{className:"rounded bg-muted/40 p-2 text-[11px] break-all",children:["Preview QR encodes: ",e.jsx("code",{children:ce})]}),e.jsxs(D,{variant:"outline",size:"sm",onClick:At,className:"w-full",children:[e.jsx(Kt,{className:"w-4 h-4 me-1"}),"Download preview JPG"]})]}),a==="mint"&&e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"font-medium",children:"5. Name & mint"}),e.jsx(A,{label:"Campaign name",children:e.jsx(ee,{value:U,onChange:t=>jt(t.target.value),placeholder:"Airport Summer 2026"})}),e.jsx(A,{label:"Brand",children:e.jsxs(et,{value:d,onValueChange:h,children:[e.jsx(tt,{children:e.jsx(at,{placeholder:"Select brand"})}),e.jsx(rt,{children:s.map(t=>e.jsx(pe,{value:t.id,children:t.name},t.id))})]})}),e.jsx(A,{label:"How many stickers?",children:e.jsx(ee,{type:"number",min:1,max:500,value:fe,onChange:t=>kt(Math.max(1,Math.min(500,Number(t.target.value)||1)))})}),e.jsxs("p",{className:"text-[11px] text-muted-foreground",children:["Saves the template + campaign, mints ",fe," unique tags, and downloads a sample JPG of the first sticker. You can re-download per-sticker JPGs from the campaign detail page."]})]}),e.jsxs("div",{className:"flex justify-between pt-2",children:[e.jsxs(D,{variant:"ghost",onClick:Pt,disabled:a==="upload",children:[e.jsx(lt,{className:"w-4 h-4 me-1"}),"Back"]}),a!=="mint"?e.jsxs(D,{onClick:Rt,disabled:!Qt,children:["Next",e.jsx(Yt,{className:"w-4 h-4 ms-1"})]}):e.jsx(D,{onClick:Et,disabled:Fe,children:Fe?"Creating…":"Create campaign + JPG"})]})]})]})]})}function la(r){switch(r){case"upload":return"Artwork";case"place":return"Place QR";case"style":return"QR design";case"destination":return"Destination";case"mint":return"Mint"}}function A({label:r,children:a}){return e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(Lt,{className:"text-xs",children:r}),a]})}function xe({label:r,active:a,onClick:o}){return e.jsx("button",{type:"button",onClick:o,className:`rounded-lg border p-3 text-xs font-medium transition ${a?"border-emerald-500 ring-2 ring-emerald-500/40 bg-emerald-50":"border-input hover:border-emerald-300"}`,children:r})}function pt({qrSizeMm:r,modules:a,payloadMode:o,hasLogo:s}){if(!a)return null;const x=r/a,h=(x*10/100).toFixed(1),n=x>=1?{tone:"ok",label:"Scans cleanly"}:x>=.6?{tone:"warn",label:"Borderline"}:{tone:"bad",label:"Too dense"},k=n.tone==="ok"?"border-emerald-200 bg-emerald-50 text-emerald-800":n.tone==="warn"?"border-amber-200 bg-amber-50 text-amber-800":"border-rose-200 bg-rose-50 text-rose-800";return e.jsxs("div",{className:`rounded-lg border p-3 text-xs space-y-1 ${k}`,children:[e.jsxs("div",{className:"flex items-center justify-between font-medium",children:[e.jsxs("span",{children:[n.label,": scans up to ~",h," m"]}),e.jsxs("span",{className:"font-mono",children:[x.toFixed(2)," mm/module"]})]}),e.jsxs("div",{className:"text-[11px] opacity-80",children:["QR matrix: ",a," × ",a," modules ·"," ","payload: ",o==="short"?"short link":"full URL + UTM",s?" · logo forces EC=H":""]}),n.tone!=="ok"&&e.jsxs("div",{className:"text-[11px] opacity-90",children:["To improve: enlarge the QR, switch to ",e.jsx("strong",{children:"Short link"})," payload",s?", or remove the center logo":"","."]})]})}function Pe(r){return r.toLowerCase().trim().replace(/[^a-z0-9]+/g,"-").replace(/(^-|-$)/g,"").slice(0,60)||`wiz-${Date.now()}`}function ze(r){return new Promise((a,o)=>{const s=new FileReader;s.onload=()=>a(s.result),s.onerror=()=>o(new Error("Failed to read file")),s.readAsDataURL(r)})}function ca(r){return new Promise((a,o)=>{const s=new Image;s.crossOrigin="anonymous",s.onload=()=>a(s),s.onerror=()=>o(new Error("Could not load image")),s.src=r})}function xt(r,a){return r==="lost"?{svg:Ot}:r==="custom"&&a?{href:a}:null}function da(r){const a=r.replace("#","").match(/^([0-9a-f]{6})$/i);if(!a)return!0;const o=parseInt(a[1],16),s=o>>16&255,x=o>>8&255,d=o&255;return .299*s+.587*x+.114*d<150}export{Ra 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.