@antontranelis/money-printer 1.0.32 → 1.0.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1,11 +1,4 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("react/jsx-runtime"),bt=require("zustand"),xt=require("zustand/middleware"),p=require("react"),wt=require("jspdf");var ie=typeof document<"u"?document.currentScript:null;const De={personalInfo:{name:"",email:"",phone:""},voucherConfig:{hours:1,description:"",language:"de",templateHue:160},portrait:{original:null,enhanced:null,useEnhanced:!1,zoom:1,panX:0,panY:0,rawImage:null,bgRemovedImage:null,bgRemoved:!1,bgOpacity:0,bgBlur:0,engravingIntensity:0},currentSide:"front",isEnhancing:!1,isExporting:!1,appLanguage:"de"},g=bt.create()(xt.persist(e=>({...De,setPersonalInfo:t=>e(n=>({personalInfo:{...n.personalInfo,...t}})),setVoucherConfig:t=>e(n=>({voucherConfig:{...n.voucherConfig,...t}})),setPortrait:(t,n=null)=>e(r=>({portrait:{...r.portrait,original:t,enhanced:n,useEnhanced:!1,zoom:r.portrait.original&&t?r.portrait.zoom:1,panX:r.portrait.original&&t?r.portrait.panX:0,panY:r.portrait.original&&t?r.portrait.panY:0}})),setEnhancedPortrait:t=>e(n=>({portrait:{...n.portrait,enhanced:t,useEnhanced:t!==null}})),toggleUseEnhanced:()=>e(t=>({portrait:{...t.portrait,useEnhanced:t.portrait.enhanced?!t.portrait.useEnhanced:!1}})),setPortraitZoom:t=>e(n=>({portrait:{...n.portrait,zoom:t}})),setPortraitPan:(t,n)=>e(r=>({portrait:{...r.portrait,panX:t,panY:n}})),setPortraitRawImage:t=>e(n=>({portrait:{...n.portrait,rawImage:t}})),setPortraitBgRemoved:(t,n)=>e(r=>({portrait:{...r.portrait,bgRemoved:t,bgRemovedImage:n!==void 0?n:r.portrait.bgRemovedImage}})),setPortraitBgOpacity:t=>e(n=>({portrait:{...n.portrait,bgOpacity:t}})),setPortraitBgBlur:t=>e(n=>({portrait:{...n.portrait,bgBlur:t}})),setPortraitEngravingIntensity:t=>e(n=>({portrait:{...n.portrait,engravingIntensity:t}})),setCurrentSide:t=>e({currentSide:t}),flipSide:()=>e(t=>({currentSide:t.currentSide==="front"?"back":"front"})),setIsEnhancing:t=>e({isEnhancing:t}),setIsExporting:t=>e({isExporting:t}),setAppLanguage:t=>e({appLanguage:t}),setBillLanguage:t=>e(n=>({voucherConfig:{...n.voucherConfig,language:t}})),setHours:t=>e(n=>({voucherConfig:{...n.voucherConfig,hours:t}})),setTemplateHue:t=>e(n=>({voucherConfig:{...n.voucherConfig,templateHue:t}})),reset:()=>e(De)}),{name:"money-generator-storage",partialize:e=>({personalInfo:e.personalInfo,voucherConfig:e.voucherConfig,appLanguage:e.appLanguage,portrait:{original:null,enhanced:null,useEnhanced:e.portrait.useEnhanced,zoom:e.portrait.zoom,panX:e.portrait.panX,panY:e.portrait.panY,rawImage:null,bgRemovedImage:null,bgRemoved:!1,bgOpacity:0,bgBlur:0,engravingIntensity:e.portrait.engravingIntensity}})})),yt={header:{title:"Money Generator",subtitle:"Erstelle deinen persönlichen Zeitgutschein"},form:{personalInfo:{title:"Persönliche Daten",name:"Name",namePlaceholder:"Dein Name",email:"E-Mail",emailPlaceholder:"deine@email.de",phone:"Telefon",phonePlaceholder:"+49 123 456789"},portrait:{title:"Portrait",upload:"Bild hochladen",dragDrop:"oder hierher ziehen",enhance:"Mit AI verbessern",enhancing:"Wird verbessert...",useOriginal:"Original verwenden",useEnhanced:"Verbessertes verwenden",zoom:"Zoom"},voucher:{title:"Gutschein",hours:"Stunden",hourLabel:"Stunde",hoursLabel:"Stunden",description:"Beschreibung",descriptionPlaceholder:"Was kann mit diesem Gutschein eingelöst werden?",billLanguage:"Schein-Sprache",billLanguageGerman:"Deutsch",billLanguageEnglish:"Englisch"},billColor:{title:"Scheinfarbe",label:"Farbton"}},preview:{front:"Vorderseite",back:"Rückseite",flip:"Umdrehen"},export:{button:"Als PDF herunterladen",exporting:"PDF wird erstellt...",success:"Download gestartet!"},bill:{descriptionText:"Für diesen Schein erhältst du {hours} {hourLabel} meiner Zeit oder ein gleichwertiges Dankeschön"}},vt={header:{title:"Money Generator",subtitle:"Create your personal time voucher"},form:{personalInfo:{title:"Personal Information",name:"Name",namePlaceholder:"Your name",email:"Email",emailPlaceholder:"your@email.com",phone:"Phone",phonePlaceholder:"+1 234 567890"},portrait:{title:"Portrait",upload:"Upload image",dragDrop:"or drag and drop",enhance:"Enhance with AI",enhancing:"Enhancing...",useOriginal:"Use original",useEnhanced:"Use enhanced",zoom:"Zoom"},voucher:{title:"Voucher",hours:"Hours",hourLabel:"hour",hoursLabel:"hours",description:"Description",descriptionPlaceholder:"What can be redeemed with this voucher?",billLanguage:"Bill Language",billLanguageGerman:"German",billLanguageEnglish:"English"},billColor:{title:"Bill Color",label:"Hue"}},preview:{front:"Front",back:"Back",flip:"Flip"},export:{button:"Download as PDF",exporting:"Creating PDF...",success:"Download started!"},bill:{descriptionText:"This voucher entitles you to {hours} {hourLabel} of my time or an equivalent thank you"}},kt={de:yt,en:vt};function G(e){return kt[e]}function je(e,t,n){if(n&&n.trim())return n;const r=G(e),a=t===1?r.form.voucher.hourLabel:r.form.voucher.hoursLabel;return r.bill.descriptionText.replace("{hours}",t.toString()).replace("{hourLabel}",a)}function It(){const e=g(a=>a.appLanguage),t=g(a=>a.personalInfo),n=g(a=>a.setPersonalInfo),r=G(e);return i.jsxs("div",{className:"space-y-4",children:[i.jsxs("div",{className:"form-control",children:[i.jsx("label",{className:"label",children:i.jsx("span",{className:"label-text font-medium",children:r.form.personalInfo.name})}),i.jsx("input",{type:"text",placeholder:r.form.personalInfo.namePlaceholder,className:"input input-bordered w-full",value:t.name,onChange:a=>n({name:a.target.value})})]}),i.jsxs("div",{className:"form-control",children:[i.jsx("label",{className:"label",children:i.jsx("span",{className:"label-text font-medium",children:r.form.personalInfo.email})}),i.jsx("input",{type:"email",placeholder:r.form.personalInfo.emailPlaceholder,className:"input input-bordered w-full",value:t.email,onChange:a=>n({email:a.target.value})})]}),i.jsxs("div",{className:"form-control",children:[i.jsx("label",{className:"label",children:i.jsx("span",{className:"label-text font-medium",children:r.form.personalInfo.phone})}),i.jsx("input",{type:"tel",placeholder:r.form.personalInfo.phonePlaceholder,className:"input input-bordered w-full",value:t.phone,onChange:a=>n({phone:a.target.value})})]})]})}const Pt=1024,re=new Map;let $=null,Me=null;function Te(e,t){return $||($=document.createElement("canvas"),Me=$.getContext("2d",{willReadFrequently:!0})),($.width!==e||$.height!==t)&&($.width=e,$.height=t),Me}function ue(e){const t=re.get(e);return t?Promise.resolve(t):new Promise((n,r)=>{const a=new Image;a.onload=()=>{if(re.size>10){const s=re.keys().next().value;s&&re.delete(s)}re.set(e,a),n(a)},a.onerror=()=>r(new Error("Failed to load image")),a.src=e})}function Ct(){re.clear()}async function St(e,t=Pt){const n=await ue(e),r=Math.max(n.width,n.height);if(r<=t)return e;const a=t/r,s=Math.round(n.width*a),o=Math.round(n.height*a),l=document.createElement("canvas"),u=l.getContext("2d");if(!u)throw new Error("Failed to get canvas context");return l.width=s,l.height=o,u.drawImage(n,0,0,s,o),l.toDataURL("image/jpeg",.9)}async function ve(e,t,n,r=0){const[a,s]=await Promise.all([ue(e),ue(t)]),o=Te(a.width,a.height);if(o.clearRect(0,0,a.width,a.height),n>0){const l=r*20;o.save(),o.globalAlpha=n,l>0&&(o.filter=`blur(${l}px)`),o.drawImage(s,0,0,a.width,a.height),o.restore()}return o.drawImage(a,0,0),$.toDataURL("image/png")}async function _e(e,t=.5,n=40){const r=await ue(e),a=Te(r.width,r.height);a.clearRect(0,0,r.width,r.height),a.drawImage(r,0,0);const s=a.getImageData(0,0,r.width,r.height),o=s.data,l=new Uint32Array(o.buffer),u=1+t*.8,d=1-t,b=n%360/360;for(let x=0;x<l.length;x++){const h=l[x],m=h&255,y=h>>8&255,k=h>>16&255,v=h>>24&255;if(v===0)continue;let S=(((77*m+150*y+29*k>>8)/255-.5)*u+.5)*255;S<0?S=0:S>255&&(S=255);const T=S/255,I=.12,[C,z,M]=We(b,I,T),B=m*d+C*t|0,N=y*d+z*t|0,L=k*d+M*t|0;l[x]=v<<24|L<<16|N<<8|B}return a.putImageData(s,0,0),$.toDataURL("image/png")}function jt(e,t,n){e/=255,t/=255,n/=255;const r=Math.max(e,t,n),a=Math.min(e,t,n),s=(r+a)/2;let o=0,l=0;if(r!==a){const u=r-a;switch(l=s>.5?u/(2-r-a):u/(r+a),r){case e:o=((t-n)/u+(t<n?6:0))/6;break;case t:o=((n-e)/u+2)/6;break;case n:o=((e-t)/u+4)/6;break}}return[o,l,s]}function We(e,t,n){if(t===0){const o=Math.round(n*255);return[o,o,o]}const r=(o,l,u)=>(u<0&&(u+=1),u>1&&(u-=1),u<1/6?o+(l-o)*6*u:u<1/2?l:u<2/3?o+(l-o)*(2/3-u)*6:o),a=n<.5?n*(1+t):n+t-n*t,s=2*n-a;return[Math.round(r(s,a,e+1/3)*255),Math.round(r(s,a,e)*255),Math.round(r(s,a,e-1/3)*255)]}async function Xe(e,t){if(t>=155&&t<=165)return e;const n=await ue(e),r=Te(n.width,n.height);r.clearRect(0,0,n.width,n.height),r.drawImage(n,0,0);const a=r.getImageData(0,0,n.width,n.height),s=a.data,o=new Uint32Array(s.buffer),l=t%360/360,u=60/360,d=260/360,b=1e5,x=o.length;for(let h=0;h<x;h+=b){const m=Math.min(h+b,x);for(let y=h;y<m;y++){const k=o[y],v=k&255,R=k>>8&255,S=k>>16&255,T=k>>24&255;if(T===0)continue;const[I,C,z]=jt(v,R,S);if(C<.06||I<u||I>d)continue;const M=l,[B,N,L]=We(M,C,z);o[y]=T<<24|L<<16|N<<8|B}m<x&&await new Promise(y=>setTimeout(y,0))}return r.putImageData(a,0,0),$.toDataURL("image/png")}const Tt="https://api.stability.ai/v1/generation",Lt="https://api.stability.ai/v2beta/stable-image/edit/remove-background",$e="stability_api_key";let se=null;function Et(e){se=e}function Rt(){return se}function Bt(){return se!==null}const Nt={vintage:"portrait in the style of vintage currency engraving, fine line work, crosshatching, sepia tones, detailed stippling, classic bank note portrait style",engraved:"portrait as detailed intaglio engraving, currency bill style, fine parallel lines, high contrast, official government portrait",currency:"portrait rendered as US dollar bill engraving, official currency portrait style, green tint, fine line engraving technique"},Ae=[{width:1024,height:1024},{width:1152,height:896},{width:1216,height:832},{width:1344,height:768},{width:1536,height:640},{width:640,height:1536},{width:768,height:1344},{width:832,height:1216},{width:896,height:1152}];function Ht(e,t){const n=e/t;let r=Ae[0],a=1/0;for(const s of Ae){const o=s.width/s.height,l=Math.abs(n-o);l<a&&(a=l,r=s)}return r}function Dt(e){return new Promise((t,n)=>{const r=new Image;r.onload=()=>{const a=Ht(r.width,r.height),s=document.createElement("canvas");s.width=a.width,s.height=a.height;const o=s.getContext("2d");if(!o){n(new Error("Failed to get canvas context"));return}const l=r.width/r.height,u=a.width/a.height;let d=0,b=0,x=r.width,h=r.height;l>u?(x=r.height*u,d=(r.width-x)/2):(h=r.width/u,b=(r.height-h)/2),o.drawImage(r,d,b,x,h,0,0,a.width,a.height),t(s.toDataURL("image/png"))},r.onerror=()=>n(new Error("Failed to load image")),r.src=e})}function Fe(e){var o;const t=e.split(","),n=((o=t[0].match(/:(.*?);/))==null?void 0:o[1])||"image/png",r=atob(t[1]),a=r.length,s=new Uint8Array(a);for(let l=0;l<a;l++)s[l]=r.charCodeAt(l);return new Blob([s],{type:n})}function pe(){var t;const e=typeof{url:typeof document>"u"?require("url").pathToFileURL(__filename).href:ie&&ie.tagName.toUpperCase()==="SCRIPT"&&ie.src||new URL("index.cjs",document.baseURI).href}<"u"&&"sk-7mEKklrqaltdtgbX0VoZbkA8E1cl939Spn75jSIYRvp1BW0b"||typeof process<"u"&&((t=process.env)==null?void 0:t.NEXT_PUBLIC_STABILITY_API_KEY);return e&&e!=="your-api-key-here"?e:typeof localStorage<"u"?localStorage.getItem($e):null}function Oe(e){localStorage.setItem($e,e)}function Ce(){return se?!0:pe()!==null}async function Mt(e){const t=pe();if(!t)throw new Error("No Stability AI API key configured");const{imageDataUrl:n,style:r,strength:a=.35}=e,s=await Dt(n),o=Fe(s),l=new FormData;l.append("init_image",o,"portrait.png"),l.append("init_image_mode","IMAGE_STRENGTH"),l.append("image_strength",String(1-a)),l.append("text_prompts[0][text]",Nt[r]),l.append("text_prompts[0][weight]","1"),l.append("cfg_scale","7"),l.append("samples","1"),l.append("steps","30");const d=await fetch(`${Tt}/stable-diffusion-xl-1024-v1-0/image-to-image`,{method:"POST",headers:{Authorization:`Bearer ${t}`,Accept:"application/json"},body:l});if(!d.ok){const x=await d.text();throw console.error("Stability AI error:",x),d.status===401?new Error("Invalid API key"):d.status===402?new Error("Insufficient credits"):d.status===429?new Error("Rate limit exceeded. Please try again later."):new Error(`API error: ${d.status}`)}const b=await d.json();if(!b.artifacts||b.artifacts.length===0)throw new Error("No image generated");return`data:image/png;base64,${b.artifacts[0].base64}`}async function qe(e){if(se){const o=await fetch(se,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({imageDataUrl:e})});if(!o.ok){const u=await o.json().catch(()=>({}));throw new Error(u.error||`API error: ${o.status}`)}return(await o.json()).imageDataUrl}const t=pe();if(!t)throw new Error("No Stability AI API key configured");const n=Fe(e),r=new FormData;r.append("image",n,"image.png"),r.append("output_format","png");const a=await fetch(Lt,{method:"POST",headers:{Authorization:`Bearer ${t}`,Accept:"image/*"},body:r});if(!a.ok){const o=await a.text();throw console.error("Stability AI remove background error:",o),a.status===401?new Error("Invalid API key"):a.status===402?new Error("Insufficient credits"):a.status===429?new Error("Rate limit exceeded. Please try again later."):new Error(`API error: ${a.status}`)}const s=await a.blob();return new Promise((o,l)=>{const u=new FileReader;u.onload=()=>o(u.result),u.onerror=()=>l(new Error("Failed to read result")),u.readAsDataURL(s)})}function At(){const[e,t]=p.useState(!1),[n,r]=p.useState(!1),[a,s]=p.useState(null),[o,l]=p.useState(()=>Ce());p.useEffect(()=>{l(Ce())},[]);const u=p.useCallback(()=>s(null),[]),d=p.useCallback(h=>{Oe(h),l(!0),s(null)},[]),b=p.useCallback(async(h,m=.5,y=40)=>{t(!0),s(null);try{return await _e(h,m,y)}catch(k){const v=k instanceof Error?k.message:"Enhancement failed";throw s(v),k}finally{t(!1)}},[]),x=p.useCallback(async h=>{r(!0),s(null);try{return await qe(h)}catch(m){const y=m instanceof Error?m.message:"Background removal failed";throw s(y),m}finally{r(!1)}},[]);return{enhance:b,removeBg:x,isEnhancing:e,isRemovingBg:n,error:a,hasKey:o,setApiKey:d,clearError:u}}function Ke({isOpen:e,onClose:t,onSubmit:n}){const r=g(d=>d.appLanguage),[a,s]=p.useState("");if(!e)return null;const o=d=>{d.preventDefault(),a.trim()&&(n(a.trim()),s(""),t())},u={de:{title:"Stability AI API Key",description:"Um die AI-Bildverbesserung zu nutzen, benötigst du einen Stability AI API Key. Du kannst ihn auf platform.stability.ai erhalten.",placeholder:"sk-...",submit:"Speichern",cancel:"Abbrechen",hint:"Der Key wird lokal in deinem Browser gespeichert."},en:{title:"Stability AI API Key",description:"To use AI image enhancement, you need a Stability AI API key. You can get one at platform.stability.ai.",placeholder:"sk-...",submit:"Save",cancel:"Cancel",hint:"The key is stored locally in your browser."}}[r];return i.jsxs("dialog",{className:"modal modal-open",children:[i.jsxs("div",{className:"modal-box",children:[i.jsx("h3",{className:"font-bold text-lg",children:u.title}),i.jsx("p",{className:"py-4 text-sm opacity-80",children:u.description}),i.jsxs("form",{onSubmit:o,children:[i.jsxs("div",{className:"form-control",children:[i.jsx("input",{type:"password",placeholder:u.placeholder,className:"input input-bordered w-full",value:a,onChange:d=>s(d.target.value),autoFocus:!0}),i.jsx("label",{className:"label",children:i.jsx("span",{className:"label-text-alt",children:u.hint})})]}),i.jsxs("div",{className:"modal-action",children:[i.jsx("button",{type:"button",className:"btn btn-ghost",onClick:t,children:u.cancel}),i.jsx("button",{type:"submit",className:"btn btn-primary",disabled:!a.trim(),children:u.submit})]})]})]}),i.jsx("form",{method:"dialog",className:"modal-backdrop",children:i.jsx("button",{onClick:t,children:"close"})})]})}function zt(){const e=g(c=>c.appLanguage),t=g(c=>c.portrait),n=g(c=>c.setPortrait),r=g(c=>c.setPortraitZoom),a=g(c=>c.setPortraitPan),s=g(c=>c.setPortraitRawImage),o=g(c=>c.setPortraitBgRemoved),l=g(c=>c.setPortraitBgOpacity),u=g(c=>c.setPortraitBgBlur),d=g(c=>c.setPortraitEngravingIntensity),{enhance:b,removeBg:x,isEnhancing:h,isRemovingBg:m,error:y,hasKey:k,setApiKey:v}=At(),R=G(e),S=p.useRef(null),T=p.useRef(null),[I,C]=p.useState(!1),[z,M]=p.useState(!1),[B,N]=p.useState(!1),L=p.useRef(null),D=p.useRef(null),H=p.useRef(null),E=t.rawImage,J=t.bgRemovedImage,U=t.bgRemoved,W=t.bgOpacity,F=t.bgBlur,Q=t.engravingIntensity;p.useEffect(()=>{t.original&&!t.rawImage&&s(t.original)},[t.original,t.rawImage,s]),p.useEffect(()=>()=>{D.current&&clearTimeout(D.current),H.current&&clearTimeout(H.current)},[]);const ee=g(c=>c.voucherConfig.templateHue),de=p.useRef(ee),le=p.useCallback(async c=>{if(!c.type.startsWith("image/"))return;const w=new FileReader;w.onload=async j=>{var Y;const P=(Y=j.target)==null?void 0:Y.result,X=await St(P);s(X),n(X),o(!1,null),d(0)},w.readAsDataURL(c)},[n,s,o,d]),f=p.useCallback(c=>{c.preventDefault(),C(!1);const w=c.dataTransfer.files[0];w&&le(w)},[le]),A=p.useCallback(c=>{c.preventDefault(),C(!0)},[]),O=p.useCallback(c=>{c.preventDefault(),C(!1)},[]),te=()=>{var c;(c=S.current)==null||c.click()},ce=c=>{var j;const w=(j=c.target.files)==null?void 0:j[0];w&&le(w)},q=p.useCallback(async(c,w,j)=>{try{return await b(c,w,j)}catch(P){return console.error("Enhancement failed:",P),c}},[b]),ne=p.useCallback(async c=>{try{const w=await x(c);return o(!0,w),w}catch(w){return console.error("Background removal failed:",w),c}},[x,o]),K=p.useCallback(async()=>{const c=g.getState(),w=c.portrait,j=c.voucherConfig.templateHue;if(!w.rawImage)return;let P;w.bgRemoved&&w.bgRemovedImage?P=await ve(w.bgRemovedImage,w.rawImage,w.bgOpacity,w.bgBlur):P=w.rawImage,w.engravingIntensity>0&&(P=await q(P,w.engravingIntensity,j)),n(P)},[q,n]);p.useEffect(()=>{if(de.current===ee)return;de.current=ee;const c=g.getState().portrait;c.engravingIntensity>0&&c.rawImage&&(D.current&&clearTimeout(D.current),D.current=setTimeout(K,150))},[ee,K]);const be=async()=>{if(!E)return;if(!U&&!k){M(!0);return}if(!U){const w=await ne(E),j=g.getState(),P=j.portrait,X=j.voucherConfig.templateHue;let Y=await ve(w,E,P.bgOpacity,P.bgBlur);P.engravingIntensity>0&&(Y=await q(Y,P.engravingIntensity,X)),n(Y)}else{o(!1,null);const w=g.getState(),j=w.portrait.engravingIntensity,P=w.voucherConfig.templateHue;if(j>0){const X=await q(E,j,P);n(X)}else n(E)}},xe=c=>{d(c),D.current&&clearTimeout(D.current),E&&(D.current=setTimeout(K,150))},we=async c=>{if(v(c),!E)return;const w=await ne(E),j=g.getState(),P=j.portrait,X=j.voucherConfig.templateHue;let Y=await ve(w,E,P.bgOpacity,P.bgBlur);P.engravingIntensity>0&&(Y=await q(Y,P.engravingIntensity,X)),n(Y)},ge=c=>{l(c),H.current&&clearTimeout(H.current),!(!E||!J)&&(H.current=setTimeout(K,150))},me=c=>{u(c),H.current&&clearTimeout(H.current),!(!E||!J)&&(H.current=setTimeout(K,150))},st=()=>{n(null),s(null),o(!1,null),l(0),u(0),d(0),Ct()},Ne=(c,w)=>{t.zoom<=1||(N(!0),L.current={x:c,y:w,panX:t.panX,panY:t.panY})},He=(c,w)=>{if(!B||!L.current||!T.current)return;const j=T.current.getBoundingClientRect(),P=2/Math.max(j.width,j.height),X=(c-L.current.x)*P,Y=(w-L.current.y)*P,pt=Math.max(-1,Math.min(1,L.current.panX+X)),ft=Math.max(-1,Math.min(1,L.current.panY+Y));a(pt,ft)},ye=()=>{N(!1),L.current=null},lt=c=>{c.preventDefault(),Ne(c.clientX,c.clientY)},ct=c=>{He(c.clientX,c.clientY)},ut=()=>{ye()},dt=()=>{ye()},gt=c=>{c.touches.length===1&&Ne(c.touches[0].clientX,c.touches[0].clientY)},mt=c=>{c.touches.length===1&&He(c.touches[0].clientX,c.touches[0].clientY)},ht=()=>{ye()};return i.jsxs("div",{className:"space-y-4",children:[t.original?i.jsxs("div",{className:"flex flex-col items-center space-y-4",children:[i.jsxs("div",{className:"relative",children:[i.jsx("div",{ref:T,className:`w-32 h-32 rounded-full overflow-hidden border-4 border-currency-gold shadow-lg ${t.zoom>1?"cursor-grab":""} ${B?"cursor-grabbing":""}`,onMouseDown:lt,onMouseMove:ct,onMouseUp:ut,onMouseLeave:dt,onTouchStart:gt,onTouchMove:mt,onTouchEnd:ht,children:i.jsx("img",{src:t.original||"",alt:"Portrait",className:"w-full h-full object-cover pointer-events-none select-none",style:{transform:`scale(${t.zoom}) translate(${t.panX*50*(t.zoom-1)}%, ${t.panY*50*(t.zoom-1)}%)`},draggable:!1})}),i.jsx("button",{className:"btn btn-circle btn-xs btn-error absolute -top-1 -right-1",onClick:st,children:i.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-4 w-4",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:i.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M6 18L18 6M6 6l12 12"})})})]}),i.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-4 w-full",children:[i.jsxs("div",{className:"form-control w-full",children:[i.jsxs("label",{className:"label",children:[i.jsx("span",{className:"label-text",children:R.form.portrait.zoom}),i.jsxs("span",{className:"label-text-alt",children:[Math.round(t.zoom*100),"%"]})]}),i.jsx("input",{type:"range",min:"0.5",max:"2",step:"0.05",value:t.zoom,onChange:c=>{const w=parseFloat(c.target.value);r(w),w<=1&&(t.panX!==0||t.panY!==0)&&a(0,0)},className:"range range-primary range-sm"})]}),i.jsxs("div",{className:"form-control w-full",children:[i.jsxs("label",{className:"label",children:[i.jsxs("span",{className:"label-text flex items-center gap-2",children:[e==="de"?"Farbanpassung":"Color adjustment",h&&i.jsx("span",{className:"loading loading-spinner loading-xs"})]}),i.jsxs("span",{className:"label-text-alt",children:[Math.round(Q*100),"%"]})]}),i.jsx("input",{type:"range",min:"0",max:"1",step:"0.05",value:Q,onChange:c=>xe(parseFloat(c.target.value)),className:"range range-secondary range-sm",disabled:h||!E})]})]}),U?i.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-4 w-full",children:[i.jsxs("div",{className:"form-control w-full",children:[i.jsxs("label",{className:"label",children:[i.jsx("span",{className:"label-text",children:e==="de"?"Hintergrund":"Background"}),i.jsxs("span",{className:"label-text-alt",children:[Math.round(W*100),"%"]})]}),i.jsx("input",{type:"range",min:"0",max:"1",step:"0.05",value:W,onChange:c=>ge(parseFloat(c.target.value)),className:"range range-primary range-sm"})]}),i.jsxs("div",{className:"form-control w-full",children:[i.jsxs("label",{className:"label",children:[i.jsx("span",{className:"label-text",children:e==="de"?"Unschärfe":"Blur"}),i.jsxs("span",{className:"label-text-alt",children:[Math.round(F*100),"%"]})]}),i.jsx("input",{type:"range",min:"0",max:"1",step:"0.05",value:F,onChange:c=>me(parseFloat(c.target.value)),className:"range range-primary range-sm"})]})]}):i.jsx("div",{className:"form-control",children:i.jsxs("label",{className:"label cursor-pointer justify-start gap-3",children:[i.jsx("input",{type:"checkbox",className:`toggle toggle-primary ${m?"opacity-50":""}`,checked:U,onChange:be,disabled:m||!E}),i.jsxs("span",{className:"label-text flex items-center gap-2",children:[m?i.jsxs(i.Fragment,{children:[i.jsx("span",{className:"loading loading-spinner loading-xs"}),e==="de"?"Hintergrund wird entfernt...":"Removing background..."]}):e==="de"?"Hintergrund entfernen":"Remove background",!k&&i.jsx("span",{className:"badge badge-sm badge-outline",children:"API"})]})]})}),y&&i.jsxs("div",{className:"alert alert-warning text-sm py-2",children:[i.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"stroke-current shrink-0 h-5 w-5",fill:"none",viewBox:"0 0 24 24",children:i.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:"2",d:"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"})}),i.jsx("span",{children:y})]})]}):i.jsxs("div",{className:`border-2 border-dashed rounded-lg p-8 text-center cursor-pointer transition-colors ${m?"border-primary bg-primary/10 pointer-events-none":I?"border-primary bg-primary/10":"border-base-300 hover:border-primary hover:bg-base-200"}`,onDrop:f,onDragOver:A,onDragLeave:O,onClick:te,children:[i.jsx("input",{ref:S,type:"file",accept:"image/*",className:"hidden",onChange:ce}),m?i.jsxs("div",{className:"flex flex-col items-center gap-2",children:[i.jsx("span",{className:"loading loading-spinner loading-lg text-primary"}),i.jsx("p",{className:"font-medium",children:e==="de"?"Hintergrund wird entfernt...":"Removing background..."})]}):i.jsxs("div",{className:"flex flex-col items-center gap-2",children:[i.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-12 w-12 text-base-content/50",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:i.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"})}),i.jsx("p",{className:"font-medium",children:R.form.portrait.upload}),i.jsx("p",{className:"text-sm text-base-content/60",children:R.form.portrait.dragDrop})]})]}),i.jsx(Ke,{isOpen:z,onClose:()=>M(!1),onSubmit:we})]})}function Ut(){const e=g(d=>d.appLanguage),t=g(d=>d.voucherConfig.language),n=g(d=>d.voucherConfig.hours),r=g(d=>d.voucherConfig.templateHue),a=g(d=>d.setBillLanguage),s=g(d=>d.setHours),o=g(d=>d.setTemplateHue),l=G(e),u=[1,5,10];return i.jsxs("div",{className:"space-y-4",children:[i.jsx("div",{className:"form-control",children:i.jsxs("div",{className:"flex items-center justify-between",children:[i.jsx("span",{className:"label-text font-medium",children:l.form.voucher.billLanguage}),i.jsxs("div",{className:"join border border-base-300 rounded-lg",children:[i.jsx("button",{className:`join-item btn btn-sm ${t==="de"?"btn-active btn-primary":"btn-ghost"}`,onClick:()=>a("de"),children:l.form.voucher.billLanguageGerman}),i.jsx("button",{className:`join-item btn btn-sm ${t==="en"?"btn-active btn-primary":"btn-ghost"}`,onClick:()=>a("en"),children:l.form.voucher.billLanguageEnglish})]})]})}),i.jsx("div",{className:"form-control",children:i.jsxs("div",{className:"flex items-center justify-between",children:[i.jsx("span",{className:"label-text font-medium",children:l.form.voucher.hours}),i.jsx("div",{className:"join border border-base-300 rounded-lg",children:u.map(d=>i.jsxs("button",{className:`join-item btn btn-sm ${n===d?"btn-active btn-primary":"btn-ghost"}`,onClick:()=>s(d),children:[d," ",d===1?l.form.voucher.hourLabel:l.form.voucher.hoursLabel]},d))})]})}),i.jsxs("div",{className:"form-control",children:[i.jsx("label",{className:"label",children:i.jsx("span",{className:"label-text font-medium",children:l.form.billColor.label})}),i.jsx("input",{type:"range",min:"0",max:"360",value:r,onChange:d=>o(Number(d.target.value)),className:"w-full h-3 rounded-lg appearance-none cursor-pointer [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:w-5 [&::-webkit-slider-thumb]:h-5 [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:bg-white [&::-webkit-slider-thumb]:shadow-md [&::-webkit-slider-thumb]:border-2 [&::-webkit-slider-thumb]:border-gray-300 [&::-moz-range-thumb]:w-5 [&::-moz-range-thumb]:h-5 [&::-moz-range-thumb]:rounded-full [&::-moz-range-thumb]:bg-white [&::-moz-range-thumb]:shadow-md [&::-moz-range-thumb]:border-2 [&::-moz-range-thumb]:border-gray-300",style:{background:`linear-gradient(to right,
2
- hsl(0, 70%, 50%),
3
- hsl(60, 70%, 50%),
4
- hsl(120, 70%, 50%),
5
- hsl(180, 70%, 50%),
6
- hsl(240, 70%, 50%),
7
- hsl(300, 70%, 50%),
8
- hsl(360, 70%, 50%))`}})]})]})}const _=typeof{url:typeof document>"u"?require("url").pathToFileURL(__filename).href:ie&&ie.tagName.toUpperCase()==="SCRIPT"&&ie.src||new URL("index.cjs",document.baseURI).href}<"u"&&"/"||"/",Le={en:{1:{front:`${_}templates/front_ldpi_en.png`,back:`${_}templates/back_ldpi_en.png`,width:1536,height:1024},5:{front:`${_}templates/front_ldpi_en.png`,back:`${_}templates/back_ldpi_en.png`,width:1536,height:1024},10:{front:`${_}templates/front_ldpi_en.png`,back:`${_}templates/back_ldpi_en.png`,width:1536,height:1024}},de:{1:{front:`${_}templates/front_hdpi_de.webp`,back:`${_}templates/back_hdpi_de.webp`,width:6144,height:3200},5:{front:`${_}templates/front_hdpi_de.webp`,back:`${_}templates/back_hdpi_de.webp`,width:6144,height:3200},10:{front:`${_}templates/front_hdpi_de.webp`,back:`${_}templates/back_hdpi_de.webp`,width:6144,height:3200}}},V={front:{portrait:{x:768,y:490,radiusX:236,radiusY:258},namePlate:{x:768,y:848,fontSize:36,maxWidth:380,align:"center"}},back:{portrait:{x:0,y:0,radiusX:0,radiusY:0},namePlate:{x:768,y:832,fontSize:36,maxWidth:380,align:"center"},contactInfo:{x:380,y:500,fontSize:38,lineHeight:55,align:"center"},description:{x:1150,y:500,fontSize:38,maxWidth:480,lineHeight:42,align:"center"},signature:{x:768,y:920,width:300,height:60,labelFontSize:16}}},Z={front:{portrait:{x:3074,y:1530,radiusX:942,radiusY:1020},namePlate:{x:3072,y:2950,fontSize:144,maxWidth:1520,align:"center"}},back:{portrait:{x:0,y:0,radiusX:0,radiusY:0},namePlate:{x:3072,y:2930,fontSize:145,maxWidth:1520,align:"center"},contactInfo:{x:1520,y:1580,fontSize:160,lineHeight:280,align:"center"},description:{x:4600,y:1580,fontSize:145,maxWidth:2e3,lineHeight:210,align:"center"},signature:{x:3080,y:2450,width:1600,height:240,labelFontSize:145}}};function Ee(e){return e==="de"?Z:V}function Ge(e,t){return Le[e][t]}const Se=.25;function Yt(e){const t=Ee(e),n=Se,r=a=>({portrait:{x:a.portrait.x*n,y:a.portrait.y*n,radiusX:a.portrait.radiusX*n,radiusY:a.portrait.radiusY*n},namePlate:{x:a.namePlate.x*n,y:a.namePlate.y*n,fontSize:a.namePlate.fontSize*n,maxWidth:a.namePlate.maxWidth?a.namePlate.maxWidth*n:void 0,lineHeight:a.namePlate.lineHeight?a.namePlate.lineHeight*n:void 0,align:a.namePlate.align},contactInfo:a.contactInfo?{x:a.contactInfo.x*n,y:a.contactInfo.y*n,fontSize:a.contactInfo.fontSize*n,maxWidth:a.contactInfo.maxWidth?a.contactInfo.maxWidth*n:void 0,lineHeight:a.contactInfo.lineHeight?a.contactInfo.lineHeight*n:void 0,align:a.contactInfo.align}:void 0,description:a.description?{x:a.description.x*n,y:a.description.y*n,fontSize:a.description.fontSize*n,maxWidth:a.description.maxWidth?a.description.maxWidth*n:void 0,lineHeight:a.description.lineHeight?a.description.lineHeight*n:void 0,align:a.description.align}:void 0,signature:a.signature?{x:a.signature.x*n,y:a.signature.y*n,width:a.signature.width*n,height:a.signature.height*n,labelFontSize:a.signature.labelFontSize*n}:void 0});return{front:r(t.front),back:r(t.back)}}function _t(e,t){const n=Le[e][t];return{...n,width:Math.round(n.width*Se),height:Math.round(n.height*Se)}}const ke=new Map,ae=new Map;async function oe(e){return ke.has(e)?ke.get(e):new Promise((t,n)=>{const r=new Image;r.crossOrigin="anonymous",r.onload=()=>{ke.set(e,r),t(r)},r.onerror=n,r.src=e})}function Re(e,t,n,r){e.drawImage(t,0,0,n,r)}async function Ve(e,t,n,r){if(t>=155&&t<=165)return oe(e);const a=`${e}:${t}:${n}x${r}`;if(ae.has(a))return oe(ae.get(a));const s=await oe(e),o=document.createElement("canvas");o.width=n,o.height=r;const l=o.getContext("2d");if(!l)throw new Error("Failed to get canvas context");l.drawImage(s,0,0,n,r);const u=o.toDataURL("image/png"),d=await Xe(u,t);if(ae.size>20){const b=ae.keys().next().value;b&&ae.delete(b)}return ae.set(a,d),oe(d)}function Ze(e,t,n,r,a,s,o=1,l=0,u=0){e.save(),e.beginPath(),e.ellipse(n,r,a,s,0,0,Math.PI*2),e.closePath(),e.clip();const d=t.width/t.height,b=a/s,x=a*2,h=s*2;let m,y;d>b?(y=h,m=h*d):(m=x,y=x/d),m*=o,y*=o;const k=Math.max(0,(m-x)/2),v=Math.max(0,(y-h)/2),R=n-m/2+l*k,S=r-y/2+u*v;e.drawImage(t,R,S,m,y),e.restore()}function Be(e,t,n,r="#2a3a2a"){e.save(),e.font=`${n.fontSize}px "Times New Roman", serif`,e.textAlign=n.align||"center",e.textBaseline="middle",e.fillStyle=r,n.maxWidth?e.fillText(t,n.x,n.y,n.maxWidth):e.fillText(t,n.x,n.y),e.restore()}function Je(e,t,n,r="#2a3a2a"){e.save(),e.font=`${n.fontSize}px "Times New Roman", serif`,e.textAlign=n.align||"center",e.textBaseline="top",e.fillStyle=r;const a=n.maxWidth||400,s=n.lineHeight||n.fontSize*1.4,o=t.split(" "),l=[];let u="";for(const x of o){const h=u?`${u} ${x}`:x;e.measureText(h).width>a&&u?(l.push(u),u=x):u=h}u&&l.push(u);const d=l.length*s;let b=n.y-d/2;for(const x of l)e.fillText(x,n.x,b),b+=s;e.restore()}function Qe(e,t,n,r,a,s="#2a3a2a"){e.save(),e.font=`${a.fontSize}px "Times New Roman", serif`,e.textAlign=a.align||"center",e.textBaseline="middle",e.fillStyle=s;const o=a.lineHeight||a.fontSize*1.8,l=[t,n,r].filter(Boolean),u=(l.length-1)*o;let d=a.y-u/2;for(const b of l)b&&(e.fillText(b,a.x,d),d+=o);e.restore()}function Wt(e,t,n,r="#2a3a2a"){e.save(),e.strokeStyle=r,e.lineWidth=Math.max(2,t.labelFontSize/16),e.beginPath(),e.moveTo(t.x-t.width/2,t.y),e.lineTo(t.x+t.width/2,t.y),e.stroke(),e.font=`${t.labelFontSize}px "Times New Roman", serif`,e.textAlign="center",e.textBaseline="top",e.fillStyle=r,e.fillText(n,t.x,t.y+t.labelFontSize*.3),e.restore()}async function et(e,t,n,r,a,s,o,l=1,u=0,d=0,b=0){const x=e.getContext("2d");if(!x)return;const h=document.createElement("canvas");h.width=s,h.height=o;const m=h.getContext("2d");if(!m)return;m.clearRect(0,0,s,o);const y=await Ve(t,b,s,o);if(Re(m,y,s,o),n)try{const k=await oe(n);Ze(m,k,a.portrait.x,a.portrait.y,a.portrait.radiusX,a.portrait.radiusY,l,u,d)}catch(k){console.error("Failed to load portrait:",k)}r&&Be(m,r,a.namePlate),e.width=s,e.height=o,x.drawImage(h,0,0)}async function tt(e,t,n,r,a,s,o,l,u,d=0,b="de"){const x=e.getContext("2d");if(!x)return;const h=document.createElement("canvas");h.width=l,h.height=u;const m=h.getContext("2d");if(!m)return;m.clearRect(0,0,l,u);const y=await Ve(t,d,l,u);if(Re(m,y,l,u),o.contactInfo&&(n||r||a)&&Qe(m,n,r,a,o.contactInfo),o.description&&s&&Je(m,s,o.description),n&&Be(m,n,o.namePlate),o.signature){const k=b==="de"?"Unterschrift":"Signature";Wt(m,o.signature,k)}e.width=l,e.height=u,x.drawImage(h,0,0)}function Xt(e,t){const[n,r]=p.useState(e);return p.useEffect(()=>{const a=setTimeout(()=>r(e),t);return()=>clearTimeout(a)},[e,t]),n}function $t(){const e=g(f=>f.appLanguage),t=g(f=>f.voucherConfig.language),n=g(f=>f.voucherConfig.hours),r=g(f=>f.voucherConfig.description),a=g(f=>f.voucherConfig.templateHue),s=g(f=>f.personalInfo),o=g(f=>f.portrait),l=g(f=>f.currentSide),u=g(f=>f.flipSide),d=g(f=>f.setPortraitPan),b=Xt(a,150),x=G(e),h=p.useRef(null),m=p.useRef(null),y=p.useRef(null),[k,v]=p.useState(!1),[R,S]=p.useState(!1),T=p.useRef(null),I=_t(t,n),C=Yt(t),z=o.useEnhanced&&o.enhanced?o.enhanced:o.original,M=je(t,n,r);p.useEffect(()=>{h.current&&et(h.current,I.front,z,s.name,C.front,I.width,I.height,o.zoom,o.panX,o.panY,b)},[I,z,s.name,C,o.zoom,o.panX,o.panY,b]),p.useEffect(()=>{m.current&&tt(m.current,I.back,s.name,s.email,s.phone,M,C.back,I.width,I.height,b,t)},[I,s,M,C,b,t]);const B=()=>{v(!0),setTimeout(()=>{u(),v(!1)},150)},N=p.useCallback((f,A)=>{if(!y.current||l!=="front"||!o.original)return!1;const O=y.current.getBoundingClientRect(),te=O.width/I.width,ce=O.height/I.height,q=(f-O.left)/te,ne=(A-O.top)/ce,{x:K,y:be,radiusX:xe,radiusY:we}=C.front.portrait,ge=(q-K)/xe,me=(ne-be)/we;return ge*ge+me*me<=1},[l,o.original,I.width,I.height,C.front.portrait]),L=p.useCallback((f,A)=>{o.zoom<=1||!N(f,A)||(S(!0),T.current={x:f,y:A,panX:o.panX,panY:o.panY})},[o.zoom,o.panX,o.panY,N]),D=p.useCallback((f,A)=>{if(!R||!T.current||!y.current)return;const O=y.current.getBoundingClientRect(),te=3/Math.max(O.width,O.height),ce=(f-T.current.x)*te,q=(A-T.current.y)*te,ne=Math.max(-1,Math.min(1,T.current.panX+ce)),K=Math.max(-1,Math.min(1,T.current.panY+q));d(ne,K)},[R,d]),H=p.useCallback(()=>{S(!1),T.current=null},[]),E=f=>{o.zoom>1&&N(f.clientX,f.clientY)&&(f.preventDefault(),L(f.clientX,f.clientY))},J=f=>{D(f.clientX,f.clientY)},U=()=>H(),W=()=>H(),F=f=>{if(f.touches.length===1){const A=f.touches[0];o.zoom>1&&N(A.clientX,A.clientY)&&L(A.clientX,A.clientY)}},Q=f=>{f.touches.length===1&&D(f.touches[0].clientX,f.touches[0].clientY)},ee=()=>H(),de=l==="front"&&o.original&&o.zoom>1,le=I.width/I.height;return i.jsxs("div",{className:"space-y-4",children:[i.jsxs("div",{className:"flex justify-between items-center",children:[i.jsxs("div",{className:"tabs tabs-boxed bg-base-200",children:[i.jsx("button",{className:`tab ${l==="front"?"tab-active bg-primary text-primary-content font-semibold":""}`,onClick:()=>l!=="front"&&B(),children:x.preview.front}),i.jsx("button",{className:`tab ${l==="back"?"tab-active bg-primary text-primary-content font-semibold":""}`,onClick:()=>l!=="back"&&B(),children:x.preview.back})]}),i.jsxs("button",{className:"btn btn-ghost btn-sm",onClick:B,children:[i.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-5 w-5",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:i.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"})}),x.preview.flip]})]}),i.jsxs("div",{ref:y,className:`relative w-full overflow-hidden shadow-lg ${de?R?"cursor-grabbing":"cursor-grab":""}`,style:{aspectRatio:le},onMouseDown:E,onMouseMove:J,onMouseUp:U,onMouseLeave:W,onTouchStart:F,onTouchMove:Q,onTouchEnd:ee,children:[i.jsx("canvas",{ref:h,className:`absolute inset-0 w-full h-full transition-all duration-300 ${l==="front"?k?"opacity-0 scale-95":"opacity-100 scale-100":"opacity-0 scale-95 pointer-events-none"}`}),i.jsx("canvas",{ref:m,className:`absolute inset-0 w-full h-full transition-all duration-300 ${l==="back"?k?"opacity-0 scale-95":"opacity-100 scale-100":"opacity-0 scale-95 pointer-events-none"}`})]})]})}function Ft(){const e=p.useRef(null),t=p.useRef(null);return{frontCanvasRef:e,backCanvasRef:t}}const Ot=`
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const s=require("react/jsx-runtime"),zt=require("zustand"),Ft=require("zustand/middleware"),b=require("react"),Wt=require("jspdf");var me=typeof document<"u"?document.currentScript:null;function Ot(){return(typeof navigator<"u"?navigator.language:"de").toLowerCase().startsWith("de")?"de":"en"}const ge=Ot(),at={personalInfo:{name:"",email:"",phone:""},voucherConfig:{hours:1,description:"",language:ge,templateHue:29},portrait:{original:null,enhanced:null,useEnhanced:!1,zoom:1,panX:0,panY:0,rawImage:null,bgRemovedImage:null,bgRemoved:!1,bgOpacity:0,bgBlur:0,engravingIntensity:0},currentSide:"front",isEnhancing:!1,isExporting:!1,appLanguage:ge},x=zt.create()(Ft.persist(e=>({...at,setPersonalInfo:t=>e(n=>({personalInfo:{...n.personalInfo,...t}})),setVoucherConfig:t=>e(n=>({voucherConfig:{...n.voucherConfig,...t}})),setPortrait:(t,n=null)=>e(a=>({portrait:{...a.portrait,original:t,enhanced:n,useEnhanced:!1,zoom:a.portrait.original&&t?a.portrait.zoom:1,panX:a.portrait.original&&t?a.portrait.panX:0,panY:a.portrait.original&&t?a.portrait.panY:0}})),setEnhancedPortrait:t=>e(n=>({portrait:{...n.portrait,enhanced:t,useEnhanced:t!==null}})),toggleUseEnhanced:()=>e(t=>({portrait:{...t.portrait,useEnhanced:t.portrait.enhanced?!t.portrait.useEnhanced:!1}})),setPortraitZoom:t=>e(n=>({portrait:{...n.portrait,zoom:t}})),setPortraitPan:(t,n)=>e(a=>({portrait:{...a.portrait,panX:t,panY:n}})),setPortraitRawImage:t=>e(n=>({portrait:{...n.portrait,rawImage:t}})),setPortraitBgRemoved:(t,n)=>e(a=>({portrait:{...a.portrait,bgRemoved:t,bgRemovedImage:n!==void 0?n:a.portrait.bgRemovedImage}})),setPortraitBgOpacity:t=>e(n=>({portrait:{...n.portrait,bgOpacity:t}})),setPortraitBgBlur:t=>e(n=>({portrait:{...n.portrait,bgBlur:t}})),setPortraitEngravingIntensity:t=>e(n=>({portrait:{...n.portrait,engravingIntensity:t}})),setCurrentSide:t=>e({currentSide:t}),flipSide:()=>e(t=>({currentSide:t.currentSide==="front"?"back":"front"})),setIsEnhancing:t=>e({isEnhancing:t}),setIsExporting:t=>e({isExporting:t}),setAppLanguage:t=>e({appLanguage:t}),setBillLanguage:t=>e(n=>({voucherConfig:{...n.voucherConfig,language:t}})),setHours:t=>e(n=>({voucherConfig:{...n.voucherConfig,hours:t}})),setTemplateHue:t=>e(n=>({voucherConfig:{...n.voucherConfig,templateHue:t}})),reset:()=>e(at)}),{name:"money-generator-storage",migrate:e=>{const t=e;return t!=null&&t.voucherConfig&&(t.voucherConfig.templateHue=29,t.voucherConfig.hours=1,t.voucherConfig.language=ge),t&&(t.appLanguage=ge),t},version:1,partialize:e=>({personalInfo:e.personalInfo,voucherConfig:{...e.voucherConfig,hours:1,language:ge,templateHue:29},appLanguage:ge,portrait:{original:null,enhanced:null,useEnhanced:e.portrait.useEnhanced,zoom:e.portrait.zoom,panX:e.portrait.panX,panY:e.portrait.panY,rawImage:null,bgRemovedImage:null,bgRemoved:!1,bgOpacity:0,bgBlur:0,engravingIntensity:e.portrait.engravingIntensity},currentSide:"front",isEnhancing:!1,isExporting:!1})})),_t={header:{title:"Money Generator",subtitle:"Erstelle deinen persönlichen Zeitgutschein"},form:{personalInfo:{title:"Persönliche Daten",name:"Name",namePlaceholder:"Dein Name",email:"E-Mail",emailPlaceholder:"deine@email.de",phone:"Telefon",phonePlaceholder:"+49 123 456789"},portrait:{title:"Portrait",upload:"Bild hochladen",dragDrop:"oder hierher ziehen",enhance:"Mit AI verbessern",enhancing:"Wird verbessert...",useOriginal:"Original verwenden",useEnhanced:"Verbessertes verwenden",zoom:"Zoom"},voucher:{title:"Gutschein",hours:"Stunden",hourLabel:"Stunde",hoursLabel:"Stunden",description:"Beschreibung",descriptionPlaceholder:"Was kann mit diesem Gutschein eingelöst werden?",billLanguage:"Schein-Sprache",billLanguageGerman:"Deutsch",billLanguageEnglish:"Englisch"},billColor:{title:"Scheinfarbe",label:"Farbton"}},preview:{front:"Vorderseite",back:"Rückseite",flip:"Umdrehen"},export:{button:"Als PDF herunterladen",exporting:"PDF wird erstellt...",success:"Download gestartet!"},bill:{descriptionText:"Für diesen Schein erhältst du {hours} {hourLabel} meiner Zeit oder ein gleichwertiges Dankeschön"}},$t={header:{title:"Money Generator",subtitle:"Create your personal time voucher"},form:{personalInfo:{title:"Personal Information",name:"Name",namePlaceholder:"Your name",email:"Email",emailPlaceholder:"your@email.com",phone:"Phone",phonePlaceholder:"+1 234 567890"},portrait:{title:"Portrait",upload:"Upload image",dragDrop:"or drag and drop",enhance:"Enhance with AI",enhancing:"Enhancing...",useOriginal:"Use original",useEnhanced:"Use enhanced",zoom:"Zoom"},voucher:{title:"Voucher",hours:"Hours",hourLabel:"hour",hoursLabel:"hours",description:"Description",descriptionPlaceholder:"What can be redeemed with this voucher?",billLanguage:"Bill Language",billLanguageGerman:"German",billLanguageEnglish:"English"},billColor:{title:"Bill Color",label:"Hue"}},preview:{front:"Front",back:"Back",flip:"Flip"},export:{button:"Download as PDF",exporting:"Creating PDF...",success:"Download started!"},bill:{descriptionText:"This voucher entitles you to {hours} {hourLabel} of my time or an equivalent thank you"}},Xt={de:_t,en:$t};function J(e){return Xt[e]}function Ve(e,t,n){if(n&&n.trim())return n;const a=J(e),r=t===1?a.form.voucher.hourLabel:a.form.voucher.hoursLabel;return a.bill.descriptionText.replace("{hours}",t.toString()).replace("{hourLabel}",r)}function Kt(){const e=x(r=>r.appLanguage),t=x(r=>r.personalInfo),n=x(r=>r.setPersonalInfo),a=J(e);return s.jsxs("div",{className:"space-y-4",children:[s.jsxs("div",{className:"form-control",children:[s.jsx("label",{className:"label",children:s.jsx("span",{className:"label-text font-medium",children:a.form.personalInfo.name})}),s.jsx("input",{type:"text",placeholder:a.form.personalInfo.namePlaceholder,className:"input input-bordered w-full",value:t.name,onChange:r=>n({name:r.target.value})})]}),s.jsxs("div",{className:"form-control",children:[s.jsx("label",{className:"label",children:s.jsx("span",{className:"label-text font-medium",children:a.form.personalInfo.email})}),s.jsx("input",{type:"email",placeholder:a.form.personalInfo.emailPlaceholder,className:"input input-bordered w-full",value:t.email,onChange:r=>n({email:r.target.value})})]}),s.jsxs("div",{className:"form-control",children:[s.jsx("label",{className:"label",children:s.jsx("span",{className:"label-text font-medium",children:a.form.personalInfo.phone})}),s.jsx("input",{type:"tel",placeholder:a.form.personalInfo.phonePlaceholder,className:"input input-bordered w-full",value:t.phone,onChange:r=>n({phone:r.target.value})})]})]})}const qt=1024,ce=new Map;let K=null,rt=null;function Ze(e,t){return K||(K=document.createElement("canvas"),rt=K.getContext("2d",{willReadFrequently:!0})),(K.width!==e||K.height!==t)&&(K.width=e,K.height=t),rt}function Ie(e){const t=ce.get(e);return t?Promise.resolve(t):new Promise((n,a)=>{const r=new Image;r.onload=()=>{if(ce.size>10){const l=ce.keys().next().value;l&&ce.delete(l)}ce.set(e,r),n(r)},r.onerror=()=>a(new Error("Failed to load image")),r.src=e})}function Gt(){ce.clear()}async function Vt(e,t=qt){const n=await Ie(e),a=Math.max(n.width,n.height);if(a<=t)return e;const r=t/a,l=Math.round(n.width*r),o=Math.round(n.height*r),i=document.createElement("canvas"),c=i.getContext("2d");if(!c)throw new Error("Failed to get canvas context");return i.width=l,i.height=o,c.drawImage(n,0,0,l,o),i.toDataURL("image/jpeg",.9)}async function ze(e,t,n,a=0){const[r,l]=await Promise.all([Ie(e),Ie(t)]),o=Ze(r.width,r.height);if(o.clearRect(0,0,r.width,r.height),n>0){const i=a*20;o.save(),o.globalAlpha=n,i>0&&(o.filter=`blur(${i}px)`),o.drawImage(l,0,0,r.width,r.height),o.restore()}return o.drawImage(r,0,0),K.toDataURL("image/png")}async function dt(e,t=.5,n=40){const a=await Ie(e),r=Ze(a.width,a.height);r.clearRect(0,0,a.width,a.height),r.drawImage(a,0,0);const l=r.getImageData(0,0,a.width,a.height),o=l.data,i=new Uint32Array(o.buffer),c=1+t*.8,d=1-t,g=n%360/360;for(let f=0;f<i.length;f++){const h=i[f],p=h&255,y=h>>8&255,k=h>>16&255,m=h>>24&255;if(m===0)continue;let P=(((77*p+150*y+29*k>>8)/255-.5)*c+.5)*255;P<0?P=0:P>255&&(P=255);const S=P/255,T=.12,[C,j,U]=gt(g,T,S),N=p*d+C*t|0,_=y*d+j*t|0,H=k*d+U*t|0;i[f]=m<<24|H<<16|_<<8|N}return r.putImageData(l,0,0),K.toDataURL("image/png")}function Zt(e,t,n){e/=255,t/=255,n/=255;const a=Math.max(e,t,n),r=Math.min(e,t,n),l=(a+r)/2;let o=0,i=0;if(a!==r){const c=a-r;switch(i=l>.5?c/(2-a-r):c/(a+r),a){case e:o=((t-n)/c+(t<n?6:0))/6;break;case t:o=((n-e)/c+2)/6;break;case n:o=((e-t)/c+4)/6;break}}return[o,i,l]}function gt(e,t,n){if(t===0){const o=Math.round(n*255);return[o,o,o]}const a=(o,i,c)=>(c<0&&(c+=1),c>1&&(c-=1),c<1/6?o+(i-o)*6*c:c<1/2?i:c<2/3?o+(i-o)*(2/3-c)*6:o),r=n<.5?n*(1+t):n+t-n*t,l=2*n-r;return[Math.round(a(l,r,e+1/3)*255),Math.round(a(l,r,e)*255),Math.round(a(l,r,e-1/3)*255)]}const Jt=29,Qt=5;async function mt(e,t){if(Math.abs(t-Jt)<=Qt)return e;const n=await Ie(e),a=Ze(n.width,n.height);a.clearRect(0,0,n.width,n.height),a.drawImage(n,0,0);const r=a.getImageData(0,0,n.width,n.height),l=r.data,o=new Uint32Array(l.buffer),i=t%360/360,c=20/360,d=45/360,g=o.length;for(let f=0;f<g;f++){const h=o[f],p=h&255,y=h>>8&255,k=h>>16&255,m=h>>24&255;if(m===0)continue;const[I,P,S]=Zt(p,y,k);if(P<.08||I<c||I>d)continue;const T=i,C=Math.min(P,.05),[j,U,N]=gt(T,C,S);o[f]=m<<24|N<<16|U<<8|j}return a.putImageData(r,0,0),K.toDataURL("image/png")}const Fe={},en="https://api.stability.ai/v1/generation",tn="https://api.stability.ai/v2beta/stable-image/edit/remove-background",ht="stability_api_key";let pe=null;function nn(e){pe=e}function an(){return pe}function rn(){return pe!==null}const on={vintage:"portrait in the style of vintage currency engraving, fine line work, crosshatching, sepia tones, detailed stippling, classic bank note portrait style",engraved:"portrait as detailed intaglio engraving, currency bill style, fine parallel lines, high contrast, official government portrait",currency:"portrait rendered as US dollar bill engraving, official currency portrait style, green tint, fine line engraving technique"},ot=[{width:1024,height:1024},{width:1152,height:896},{width:1216,height:832},{width:1344,height:768},{width:1536,height:640},{width:640,height:1536},{width:768,height:1344},{width:832,height:1216},{width:896,height:1152}];function sn(e,t){const n=e/t;let a=ot[0],r=1/0;for(const l of ot){const o=l.width/l.height,i=Math.abs(n-o);i<r&&(r=i,a=l)}return a}function ln(e){return new Promise((t,n)=>{const a=new Image;a.onload=()=>{const r=sn(a.width,a.height),l=document.createElement("canvas");l.width=r.width,l.height=r.height;const o=l.getContext("2d");if(!o){n(new Error("Failed to get canvas context"));return}const i=a.width/a.height,c=r.width/r.height;let d=0,g=0,f=a.width,h=a.height;i>c?(f=a.height*c,d=(a.width-f)/2):(h=a.width/c,g=(a.height-h)/2),o.drawImage(a,d,g,f,h,0,0,r.width,r.height),t(l.toDataURL("image/png"))},a.onerror=()=>n(new Error("Failed to load image")),a.src=e})}function pt(e){var o;const t=e.split(","),n=((o=t[0].match(/:(.*?);/))==null?void 0:o[1])||"image/png",a=atob(t[1]),r=a.length,l=new Uint8Array(r);for(let i=0;i<r;i++)l[i]=a.charCodeAt(i);return new Blob([l],{type:n})}function Ee(){var t;const e=typeof{url:typeof document>"u"?require("url").pathToFileURL(__filename).href:me&&me.tagName.toUpperCase()==="SCRIPT"&&me.src||new URL("index.cjs",document.baseURI).href}<"u"&&(Fe==null?void 0:Fe.VITE_STABILITY_API_KEY)||typeof process<"u"&&((t=process.env)==null?void 0:t.NEXT_PUBLIC_STABILITY_API_KEY);return e&&e!=="your-api-key-here"?e:typeof localStorage<"u"?localStorage.getItem(ht):null}function ft(e){localStorage.setItem(ht,e)}function $e(){return pe?!0:Ee()!==null}async function cn(e){const t=Ee();if(!t)throw new Error("No Stability AI API key configured");const{imageDataUrl:n,style:a,strength:r=.35}=e,l=await ln(n),o=pt(l),i=new FormData;i.append("init_image",o,"portrait.png"),i.append("init_image_mode","IMAGE_STRENGTH"),i.append("image_strength",String(1-r)),i.append("text_prompts[0][text]",on[a]),i.append("text_prompts[0][weight]","1"),i.append("cfg_scale","7"),i.append("samples","1"),i.append("steps","30");const d=await fetch(`${en}/stable-diffusion-xl-1024-v1-0/image-to-image`,{method:"POST",headers:{Authorization:`Bearer ${t}`,Accept:"application/json"},body:i});if(!d.ok){const f=await d.text();throw console.error("Stability AI error:",f),d.status===401?new Error("Invalid API key"):d.status===402?new Error("Insufficient credits"):d.status===429?new Error("Rate limit exceeded. Please try again later."):new Error(`API error: ${d.status}`)}const g=await d.json();if(!g.artifacts||g.artifacts.length===0)throw new Error("No image generated");return`data:image/png;base64,${g.artifacts[0].base64}`}async function bt(e){if(pe){const o=await fetch(pe,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({imageDataUrl:e})});if(!o.ok){const c=await o.json().catch(()=>({}));throw new Error(c.error||`API error: ${o.status}`)}return(await o.json()).imageDataUrl}const t=Ee();if(!t)throw new Error("No Stability AI API key configured");const n=pt(e),a=new FormData;a.append("image",n,"image.png"),a.append("output_format","png");const r=await fetch(tn,{method:"POST",headers:{Authorization:`Bearer ${t}`,Accept:"image/*"},body:a});if(!r.ok){const o=await r.text();throw console.error("Stability AI remove background error:",o),r.status===401?new Error("Invalid API key"):r.status===402?new Error("Insufficient credits"):r.status===429?new Error("Rate limit exceeded. Please try again later."):new Error(`API error: ${r.status}`)}const l=await r.blob();return new Promise((o,i)=>{const c=new FileReader;c.onload=()=>o(c.result),c.onerror=()=>i(new Error("Failed to read result")),c.readAsDataURL(l)})}function un(){const[e,t]=b.useState(!1),[n,a]=b.useState(!1),[r,l]=b.useState(null),[o,i]=b.useState(()=>$e());b.useEffect(()=>{i($e())},[]);const c=b.useCallback(()=>l(null),[]),d=b.useCallback(h=>{ft(h),i(!0),l(null)},[]),g=b.useCallback(async(h,p=.5,y=40)=>{t(!0),l(null);try{return await dt(h,p,y)}catch(k){const m=k instanceof Error?k.message:"Enhancement failed";throw l(m),k}finally{t(!1)}},[]),f=b.useCallback(async h=>{a(!0),l(null);try{return await bt(h)}catch(p){const y=p instanceof Error?p.message:"Background removal failed";throw l(y),p}finally{a(!1)}},[]);return{enhance:g,removeBg:f,isEnhancing:e,isRemovingBg:n,error:r,hasKey:o,setApiKey:d,clearError:c}}function xt({isOpen:e,onClose:t,onSubmit:n}){const a=x(d=>d.appLanguage),[r,l]=b.useState("");if(!e)return null;const o=d=>{d.preventDefault(),r.trim()&&(n(r.trim()),l(""),t())},c={de:{title:"Stability AI API Key",description:"Um die AI-Bildverbesserung zu nutzen, benötigst du einen Stability AI API Key. Du kannst ihn auf platform.stability.ai erhalten.",placeholder:"sk-...",submit:"Speichern",cancel:"Abbrechen",hint:"Der Key wird lokal in deinem Browser gespeichert."},en:{title:"Stability AI API Key",description:"To use AI image enhancement, you need a Stability AI API key. You can get one at platform.stability.ai.",placeholder:"sk-...",submit:"Save",cancel:"Cancel",hint:"The key is stored locally in your browser."}}[a];return s.jsxs("dialog",{className:"modal modal-open",children:[s.jsxs("div",{className:"modal-box",children:[s.jsx("h3",{className:"font-bold text-lg",children:c.title}),s.jsx("p",{className:"py-4 text-sm opacity-80",children:c.description}),s.jsxs("form",{onSubmit:o,children:[s.jsxs("div",{className:"form-control",children:[s.jsx("input",{type:"password",placeholder:c.placeholder,className:"input input-bordered w-full",value:r,onChange:d=>l(d.target.value),autoFocus:!0}),s.jsx("label",{className:"label",children:s.jsx("span",{className:"label-text-alt",children:c.hint})})]}),s.jsxs("div",{className:"modal-action",children:[s.jsx("button",{type:"button",className:"btn btn-ghost",onClick:t,children:c.cancel}),s.jsx("button",{type:"submit",className:"btn btn-primary",disabled:!r.trim(),children:c.submit})]})]})]}),s.jsx("form",{method:"dialog",className:"modal-backdrop",children:s.jsx("button",{onClick:t,children:"close"})})]})}function dn(){const e=x(u=>u.appLanguage),t=x(u=>u.portrait),n=x(u=>u.setPortrait),a=x(u=>u.setPortraitZoom),r=x(u=>u.setPortraitPan),l=x(u=>u.setPortraitRawImage),o=x(u=>u.setPortraitBgRemoved),i=x(u=>u.setPortraitBgOpacity),c=x(u=>u.setPortraitBgBlur),d=x(u=>u.setPortraitEngravingIntensity),{enhance:g,removeBg:f,isEnhancing:h,isRemovingBg:p,error:y,hasKey:k,setApiKey:m}=un(),I=J(e),P=b.useRef(null),S=b.useRef(null),[T,C]=b.useState(!1),[j,U]=b.useState(!1),[N,_]=b.useState(!1),H=b.useRef(null),Y=b.useRef(null),D=b.useRef(null),B=t.rawImage,V=t.bgRemovedImage,z=t.bgRemoved,F=t.bgOpacity,q=t.bgBlur,Z=t.engravingIntensity;b.useEffect(()=>{t.original&&!t.rawImage&&l(t.original)},[t.original,t.rawImage,l]),b.useEffect(()=>()=>{Y.current&&clearTimeout(Y.current),D.current&&clearTimeout(D.current)},[]);const oe=x(u=>u.voucherConfig.templateHue),fe=b.useRef(oe),ie=b.useCallback(async u=>{if(!u.type.startsWith("image/"))return;const v=new FileReader;v.onload=async E=>{var W;const L=(W=E.target)==null?void 0:W.result,X=await Vt(L);l(X),n(X),o(!1,null),d(0)},v.readAsDataURL(u)},[n,l,o,d]),be=b.useCallback(u=>{u.preventDefault(),C(!1);const v=u.dataTransfer.files[0];v&&ie(v)},[ie]),se=b.useCallback(u=>{u.preventDefault(),C(!0)},[]),Pe=b.useCallback(u=>{u.preventDefault(),C(!1)},[]),Te=()=>{var u;(u=P.current)==null||u.click()},xe=u=>{var E;const v=(E=u.target.files)==null?void 0:E[0];v&&ie(v)},Q=b.useCallback(async(u,v,E)=>{try{return await g(u,v,E)}catch(L){return console.error("Enhancement failed:",L),u}},[g]),Ce=b.useCallback(async u=>{try{const v=await f(u);return o(!0,v),v}catch(v){return console.error("Background removal failed:",v),u}},[f,o]),ee=b.useCallback(async()=>{const u=x.getState(),v=u.portrait,E=u.voucherConfig.templateHue;if(!v.rawImage)return;let L;v.bgRemoved&&v.bgRemovedImage?L=await ze(v.bgRemovedImage,v.rawImage,v.bgOpacity,v.bgBlur):L=v.rawImage,v.engravingIntensity>0&&(L=await Q(L,v.engravingIntensity,E)),n(L)},[Q,n]);b.useEffect(()=>{if(fe.current===oe)return;fe.current=oe;const u=x.getState().portrait;u.engravingIntensity>0&&u.rawImage&&(Y.current&&clearTimeout(Y.current),Y.current=setTimeout(ee,150))},[oe,ee]);const je=async()=>{if(!B)return;if(!z&&!k){U(!0);return}if(!z){const v=await Ce(B),E=x.getState(),L=E.portrait,X=E.voucherConfig.templateHue;let W=await ze(v,B,L.bgOpacity,L.bgBlur);L.engravingIntensity>0&&(W=await Q(W,L.engravingIntensity,X)),n(W)}else{o(!1,null);const v=x.getState(),E=v.portrait.engravingIntensity,L=v.voucherConfig.templateHue;if(E>0){const X=await Q(B,E,L);n(X)}else n(B)}},Ne=u=>{d(u),Y.current&&clearTimeout(Y.current),B&&(Y.current=setTimeout(ee,150))},He=async u=>{if(m(u),!B)return;const v=await Ce(B),E=x.getState(),L=E.portrait,X=E.voucherConfig.templateHue;let W=await ze(v,B,L.bgOpacity,L.bgBlur);L.engravingIntensity>0&&(W=await Q(W,L.engravingIntensity,X)),n(W)},Me=u=>{i(u),D.current&&clearTimeout(D.current),!(!B||!V)&&(D.current=setTimeout(ee,150))},De=u=>{c(u),D.current&&clearTimeout(D.current),!(!B||!V)&&(D.current=setTimeout(ee,150))},Ae=()=>{n(null),l(null),o(!1,null),i(0),c(0),d(0),Gt()},w=(u,v)=>{t.zoom<=1||(_(!0),H.current={x:u,y:v,panX:t.panX,panY:t.panY})},M=(u,v)=>{if(!N||!H.current||!S.current)return;const E=S.current.getBoundingClientRect(),L=2/Math.max(E.width,E.height),X=(u-H.current.x)*L,W=(v-H.current.y)*L,Ut=Math.max(-1,Math.min(1,H.current.panX+X)),Yt=Math.max(-1,Math.min(1,H.current.panY+W));r(Ut,Yt)},A=()=>{_(!1),H.current=null},$=u=>{u.preventDefault(),w(u.clientX,u.clientY)},we=u=>{M(u.clientX,u.clientY)},ye=()=>{A()},ve=()=>{A()},ke=u=>{u.touches.length===1&&w(u.touches[0].clientX,u.touches[0].clientY)},Ue=u=>{u.touches.length===1&&M(u.touches[0].clientX,u.touches[0].clientY)},Ye=()=>{A()};return s.jsxs("div",{className:"space-y-4",children:[t.original?s.jsxs("div",{className:"flex flex-col items-center space-y-4",children:[s.jsxs("div",{className:"relative",children:[s.jsx("div",{ref:S,className:`w-32 h-32 rounded-full overflow-hidden border-4 border-currency-gold shadow-lg ${t.zoom>1?"cursor-grab":""} ${N?"cursor-grabbing":""}`,onMouseDown:$,onMouseMove:we,onMouseUp:ye,onMouseLeave:ve,onTouchStart:ke,onTouchMove:Ue,onTouchEnd:Ye,children:s.jsx("img",{src:t.original||"",alt:"Portrait",className:"w-full h-full object-cover pointer-events-none select-none",style:{transform:`scale(${t.zoom}) translate(${t.panX*50*(t.zoom-1)}%, ${t.panY*50*(t.zoom-1)}%)`},draggable:!1})}),s.jsx("button",{className:"btn btn-circle btn-xs btn-error absolute -top-1 -right-1",onClick:Ae,children:s.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-4 w-4",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:s.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M6 18L18 6M6 6l12 12"})})})]}),s.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-4 w-full",children:[s.jsxs("div",{className:"form-control w-full",children:[s.jsxs("label",{className:"label",children:[s.jsx("span",{className:"label-text",children:I.form.portrait.zoom}),s.jsxs("span",{className:"label-text-alt",children:[Math.round(t.zoom*100),"%"]})]}),s.jsx("input",{type:"range",min:"0.5",max:"2",step:"0.05",value:t.zoom,onChange:u=>{const v=parseFloat(u.target.value);a(v),v<=1&&(t.panX!==0||t.panY!==0)&&r(0,0)},className:"range range-primary range-sm"})]}),s.jsxs("div",{className:"form-control w-full",children:[s.jsxs("label",{className:"label",children:[s.jsxs("span",{className:"label-text flex items-center gap-2",children:[e==="de"?"Farbanpassung":"Color adjustment",h&&s.jsx("span",{className:"loading loading-spinner loading-xs"})]}),s.jsxs("span",{className:"label-text-alt",children:[Math.round(Z*100),"%"]})]}),s.jsx("input",{type:"range",min:"0",max:"1",step:"0.05",value:Z,onChange:u=>Ne(parseFloat(u.target.value)),className:"range range-secondary range-sm",disabled:h||!B})]})]}),z?s.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-4 w-full",children:[s.jsxs("div",{className:"form-control w-full",children:[s.jsxs("label",{className:"label",children:[s.jsx("span",{className:"label-text",children:e==="de"?"Hintergrund":"Background"}),s.jsxs("span",{className:"label-text-alt",children:[Math.round(F*100),"%"]})]}),s.jsx("input",{type:"range",min:"0",max:"1",step:"0.05",value:F,onChange:u=>Me(parseFloat(u.target.value)),className:"range range-primary range-sm"})]}),s.jsxs("div",{className:"form-control w-full",children:[s.jsxs("label",{className:"label",children:[s.jsx("span",{className:"label-text",children:e==="de"?"Unschärfe":"Blur"}),s.jsxs("span",{className:"label-text-alt",children:[Math.round(q*100),"%"]})]}),s.jsx("input",{type:"range",min:"0",max:"1",step:"0.05",value:q,onChange:u=>De(parseFloat(u.target.value)),className:"range range-primary range-sm"})]})]}):s.jsx("div",{className:"form-control",children:s.jsxs("label",{className:"label cursor-pointer justify-start gap-3",children:[s.jsx("input",{type:"checkbox",className:`toggle toggle-primary ${p?"opacity-50":""}`,checked:z,onChange:je,disabled:p||!B}),s.jsxs("span",{className:"label-text flex items-center gap-2",children:[p?s.jsxs(s.Fragment,{children:[s.jsx("span",{className:"loading loading-spinner loading-xs"}),e==="de"?"Hintergrund wird entfernt...":"Removing background..."]}):e==="de"?"Hintergrund entfernen":"Remove background",!k&&s.jsx("span",{className:"badge badge-sm badge-outline",children:"API"})]})]})}),y&&s.jsxs("div",{className:"alert alert-warning text-sm py-2",children:[s.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"stroke-current shrink-0 h-5 w-5",fill:"none",viewBox:"0 0 24 24",children:s.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:"2",d:"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"})}),s.jsx("span",{children:y})]})]}):s.jsxs("div",{className:`border-2 border-dashed rounded-lg p-8 text-center cursor-pointer transition-colors ${p?"border-primary bg-primary/10 pointer-events-none":T?"border-primary bg-primary/10":"border-base-300 hover:border-primary hover:bg-base-200"}`,onDrop:be,onDragOver:se,onDragLeave:Pe,onClick:Te,children:[s.jsx("input",{ref:P,type:"file",accept:"image/*",className:"hidden",onChange:xe}),p?s.jsxs("div",{className:"flex flex-col items-center gap-2",children:[s.jsx("span",{className:"loading loading-spinner loading-lg text-primary"}),s.jsx("p",{className:"font-medium",children:e==="de"?"Hintergrund wird entfernt...":"Removing background..."})]}):s.jsxs("div",{className:"flex flex-col items-center gap-2",children:[s.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-12 w-12 text-base-content/50",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:s.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"})}),s.jsx("p",{className:"font-medium",children:I.form.portrait.upload}),s.jsx("p",{className:"text-sm text-base-content/60",children:I.form.portrait.dragDrop})]})]}),s.jsx(xt,{isOpen:j,onClose:()=>U(!1),onSubmit:He})]})}function gn(){const e=x(i=>i.appLanguage),t=x(i=>i.voucherConfig.language),n=x(i=>i.voucherConfig.hours);x(i=>i.voucherConfig.templateHue);const a=x(i=>i.setBillLanguage),r=x(i=>i.setHours);x(i=>i.setTemplateHue);const l=J(e),o=[1,5,10];return s.jsxs("div",{className:"space-y-4",children:[s.jsx("div",{className:"form-control",children:s.jsxs("div",{className:"flex items-center justify-between",children:[s.jsx("span",{className:"label-text font-medium",children:l.form.voucher.billLanguage}),s.jsxs("div",{className:"join border border-base-300 rounded-lg",children:[s.jsx("button",{className:`join-item btn btn-sm ${t==="de"?"btn-active btn-primary":"btn-ghost"}`,onClick:()=>a("de"),children:l.form.voucher.billLanguageGerman}),s.jsx("button",{className:`join-item btn btn-sm ${t==="en"?"btn-active btn-primary":"btn-ghost"}`,onClick:()=>a("en"),children:l.form.voucher.billLanguageEnglish})]})]})}),s.jsx("div",{className:"form-control",children:s.jsxs("div",{className:"flex items-center justify-between",children:[s.jsx("span",{className:"label-text font-medium",children:l.form.voucher.hours}),s.jsx("div",{className:"join border border-base-300 rounded-lg",children:o.map(i=>s.jsxs("button",{className:`join-item btn btn-sm ${n===i?"btn-active btn-primary":"btn-ghost"}`,onClick:()=>r(i),children:[i," ",i===1?l.form.voucher.hourLabel:l.form.voucher.hoursLabel]},i))})]})}),!1]})}const We=new Map,le=new Map;async function R(e){return We.has(e)?We.get(e):new Promise((t,n)=>{const a=new Image;a.crossOrigin="anonymous",a.onload=()=>{We.set(e,a),t(a)},a.onerror=n,a.src=e})}function ne(e,t,n,a){e.drawImage(t,0,0,n,a)}async function wt(e,t,n,a){if(t>=155&&t<=165)return R(e);const r=`${e}:${t}:${n}x${a}`;if(le.has(r))return R(le.get(r));const l=await R(e),o=document.createElement("canvas");o.width=n,o.height=a;const i=o.getContext("2d");if(!i)throw new Error("Failed to get canvas context");i.drawImage(l,0,0,n,a);const c=o.toDataURL("image/png"),d=await mt(c,t);if(le.size>20){const g=le.keys().next().value;g&&le.delete(g)}return le.set(r,d),R(d)}function yt(e,t,n,a,r,l,o=1,i=0,c=0){e.save(),e.beginPath(),e.ellipse(n,a,r,l,0,0,Math.PI*2),e.closePath(),e.clip();const d=t.width/t.height,g=r/l,f=r*2,h=l*2;let p,y;d>g?(y=h,p=h*d):(p=f,y=f/d),p*=o,y*=o;const k=Math.max(0,(p-f)/2),m=Math.max(0,(y-h)/2),I=n-p/2+i*k,P=a-y/2+c*m;e.drawImage(t,I,P,p,y),e.restore()}function Je(e,t,n,a="#2a3a2a"){e.save(),e.font=`${n.fontSize}px "Times New Roman", serif`,e.textAlign=n.align||"center",e.textBaseline="middle",e.fillStyle=a,n.maxWidth?e.fillText(t,n.x,n.y,n.maxWidth):e.fillText(t,n.x,n.y),e.restore()}function vt(e,t,n,a="#2a3a2a"){e.save(),e.font=`${n.fontSize}px "Times New Roman", serif`,e.textAlign=n.align||"center",e.textBaseline="top",e.fillStyle=a;const r=n.maxWidth||400,l=n.lineHeight||n.fontSize*1.4,o=t.split(" "),i=[];let c="";for(const f of o){const h=c?`${c} ${f}`:f;e.measureText(h).width>r&&c?(i.push(c),c=f):c=h}c&&i.push(c);const d=i.length*l;let g=n.y-d/2;for(const f of i)e.fillText(f,n.x,g),g+=l;e.restore()}function kt(e,t,n,a,r,l="#2a3a2a"){e.save(),e.font=`${r.fontSize}px "Times New Roman", serif`,e.textAlign=r.align||"center",e.textBaseline="middle",e.fillStyle=l;const o=r.lineHeight||r.fontSize*1.8,i=[t,n,a].filter(Boolean),c=(i.length-1)*o;let d=r.y-c/2;for(const g of i)g&&(e.fillText(g,r.x,d),d+=o);e.restore()}function mn(e,t,n,a="#2a3a2a"){e.save(),e.strokeStyle=a,e.lineWidth=Math.max(2,t.labelFontSize/16),e.beginPath(),e.moveTo(t.x-t.width/2,t.y),e.lineTo(t.x+t.width/2,t.y),e.stroke(),e.font=`${t.labelFontSize}px "Times New Roman", serif`,e.textAlign="center",e.textBaseline="top",e.fillStyle=a,e.fillText(n,t.x,t.y+t.labelFontSize*.3),e.restore()}async function It(e,t,n,a,r,l,o,i,c,d=1,g=0,f=0,h=0,p=1,y="de"){const k=e.getContext("2d");if(!k)return;const m=document.createElement("canvas");m.width=i,m.height=c;const I=m.getContext("2d");if(!I)return;I.clearRect(0,0,i,c);const P=await wt(t,h,i,c);ne(I,P,i,c);const S=await R(n);if(ne(I,S,i,c),r)try{const j=await R(r);yt(I,j,o.portrait.x,o.portrait.y,o.portrait.radiusX,o.portrait.radiusY,d,g,f)}catch(j){console.error("Failed to load portrait:",j)}const T=await R(a);ne(I,T,i,c);const C=i/3633;Rt(I,p,y,C),l&&Je(I,l,o.namePlate),e.width=i,e.height=c,k.drawImage(m,0,0)}async function Pt(e,t,n,a,r,l,o,i,c,d,g,f=0,h=1,p="de"){const y=e.getContext("2d");if(!y)return;const k=document.createElement("canvas");k.width=d,k.height=g;const m=k.getContext("2d");if(!m)return;m.clearRect(0,0,d,g);const I=await wt(t,f,d,g);ne(m,I,d,g);const P=await R(n);ne(m,P,d,g);const S=await R(a);ne(m,S,d,g);const T=d/3633;if(Rt(m,h,p,T),c.contactInfo&&(r||l||o)&&kt(m,r,l,o,c.contactInfo),c.description&&i&&vt(m,i,c.description),r&&Je(m,r,c.namePlate),c.signature){const C=p==="de"?"Unterschrift":"Signature";mn(m,c.signature,C)}e.width=d,e.height=g,y.drawImage(k,0,0)}const he=typeof{url:typeof document>"u"?require("url").pathToFileURL(__filename).href:me&&me.tagName.toUpperCase()==="SCRIPT"&&me.src||new URL("index.cjs",document.baseURI).href}<"u"&&"/"||"/",G={background:`${he}templates/background.webp`,frontFrame:`${he}templates/front_frame.webp`,backFrame:`${he}templates/back_frame.webp`},Qe={1:`${he}templates/1.png`,5:`${he}templates/5.png`,10:`${he}templates/10.png`},Tt={de:{banner:{1:"EINE STUNDE",5:"FÜNF STUNDEN",10:"ZEHN STUNDEN"}},en:{banner:{1:"ONE HOUR",5:"FIVE HOURS",10:"TEN HOURS"}}},ae=3633,re=1920,Ct=.5,Lt=320,St=335,O={badges:{topLeft:{x:286,y:235},topRight:{x:3340,y:230},bottomLeft:{x:282,y:1665},bottomRight:{x:3345,y:1665}},banner:{centerX:1816,centerY:3820,radius:3610,fontSize:103,color:"#2a3a2a"}},Le=new Map,te=new Map,Xe=new Map,Ke=new Map,qe=new Map;function Et(e,t,n,a,r,l,o){e.save(),e.font=`900 ${l}px "Times New Roman", Georgia, serif`,e.fillStyle=o,e.textAlign="center",e.textBaseline="middle";const c=e.measureText(t).width/r,d=-Math.PI/2-c/2,g=t.split(""),f=[];for(const p of g)f.push(e.measureText(p).width);let h=d;for(let p=0;p<g.length;p++){const y=g[p],k=f[p],m=h+k/2/r,I=n+r*Math.cos(m),P=a+r*Math.sin(m);e.save(),e.translate(I,P),e.rotate(m+Math.PI/2),e.fillText(y,0,0),e.restore(),h+=k/r}e.restore()}let et={badges:{1:null,5:null,10:null}};function hn(e,t){const n=Math.round(ae*e),a=Math.round(re*e),r=document.createElement("canvas");r.width=n,r.height=a;const l=r.getContext("2d");if(!l)throw new Error("Failed to get canvas context");l.drawImage(t,0,0,n,a);const o=e<1?.8:.95;return r.toDataURL("image/jpeg",o)}function pn(e,t){const n=Math.round(ae*e),a=Math.round(re*e),r=document.createElement("canvas");r.width=n,r.height=a;const l=r.getContext("2d");if(!l)throw new Error("Failed to get canvas context");const o=Lt*e,i=St*e,c=O.badges,d=(g,f)=>{const h=f/2,p=g.x*e-h,y=g.y*e-h;l.drawImage(t,p,y,f,f)};return d(c.topLeft,o),d(c.topRight,o),d(c.bottomLeft,i),d(c.bottomRight,i),r.toDataURL("image/png")}function Rt(e,t,n,a=1){const r=Tt[n].banner[t];Et(e,r,O.banner.centerX*a,O.banner.centerY*a,O.banner.radius*a,O.banner.fontSize*a,O.banner.color)}function Bt(e,t,n,a,r,l,o){const i=Math.round(ae*a),c=Math.round(re*a),d=document.createElement("canvas");d.width=i,d.height=c;const g=d.getContext("2d");if(!g)throw new Error("Failed to get canvas context");g.drawImage(r,0,0,i,c);{const h=Lt*a,p=St*a,y=O.badges,k=(m,I)=>{const P=I/2,S=m.x*a-P,T=m.y*a-P;g.drawImage(o,S,T,I,I)};k(y.topLeft,h),k(y.topRight,h),k(y.bottomLeft,p),k(y.bottomRight,p)}if(g.drawImage(l,0,0,i,c),n==="front"){const h=Tt[t].banner[e];Et(g,h,O.banner.centerX*a,O.banner.centerY*a,O.banner.radius*a,O.banner.fontSize*a,O.banner.color)}const f=a<1?.8:.95;return d.toDataURL("image/jpeg",f)}async function jt(e,t,n){const a=`${e}-${t}-${n}`;if(Le.has(a))return Le.get(a);const r=await R(G.background),l=n==="front"?await R(G.frontFrame):await R(G.backFrame),o=et.badges[e]||await R(Qe[e]),i=Bt(e,t,n,Ct,r,l,o);return Le.set(a,i),i}async function it(e,t,n){const a=`${e}-${t}-${n}`;if(te.has(a))return te.get(a);const r=await R(G.background),l=n==="front"?await R(G.frontFrame):await R(G.backFrame),o=et.badges[e]||await R(Qe[e]),i=Bt(e,t,n,1,r,l,o);if(te.size>4){const c=te.keys().next().value;c&&te.delete(c)}return te.set(a,i),i}function fn(){return{width:ae,height:re}}function bn(){Le.clear(),te.clear(),Xe.clear(),Ke.clear(),qe.clear()}async function st(e,t,n="front",a=Ct){const r=`bg-${a}`;let l=Xe.get(r);if(!l){const g=await R(G.background);l=hn(a,g),Xe.set(r,l)}const o=`badges-${e}-${a}`;let i=Ke.get(o);if(!i){const g=et.badges[e]||await R(Qe[e]);i=pn(a,g),Ke.set(o,i)}const c=`${n}-${a}`;let d=qe.get(c);if(!d){const g=n==="front"?await R(G.frontFrame):await R(G.backFrame),f=Math.round(ae*a),h=Math.round(re*a),p=document.createElement("canvas");p.width=f,p.height=h;const y=p.getContext("2d");if(!y)throw new Error("Failed to get canvas context");y.drawImage(g,0,0,f,h),d=p.toDataURL("image/png"),qe.set(c,d)}return{background:l,badges:i,frame:d}}async function xn(){const e=[1,5,10],t=["de","en"],n=["front","back"],a=[];for(const r of e)for(const l of t)for(const o of n)a.push(jt(r,l,o));await Promise.all(a)}function tt(e,t){return{front:"",back:"",width:ae,height:re}}const Re={front:{portrait:{x:1810,y:918,radiusX:570,radiusY:605},namePlate:{x:1816,y:1765,fontSize:85,maxWidth:898,align:"center"}},back:{portrait:{x:0,y:0,radiusX:0,radiusY:0},namePlate:{x:1816,y:1770,fontSize:85,maxWidth:898,align:"center"},contactInfo:{x:898,y:939,fontSize:93,lineHeight:165,align:"center"},description:{x:2721,y:939,fontSize:85,maxWidth:1177,lineHeight:124,align:"center"},signature:{x:1820,y:1445,width:950,height:145,labelFontSize:85}}},ue=Re,de=Re;function nt(e){return Re}const Ge=.75;function wn(e){const t=nt(),n=Ge,a=r=>({portrait:{x:r.portrait.x*n,y:r.portrait.y*n,radiusX:r.portrait.radiusX*n,radiusY:r.portrait.radiusY*n},namePlate:{x:r.namePlate.x*n,y:r.namePlate.y*n,fontSize:r.namePlate.fontSize*n,maxWidth:r.namePlate.maxWidth?r.namePlate.maxWidth*n:void 0,lineHeight:r.namePlate.lineHeight?r.namePlate.lineHeight*n:void 0,align:r.namePlate.align},contactInfo:r.contactInfo?{x:r.contactInfo.x*n,y:r.contactInfo.y*n,fontSize:r.contactInfo.fontSize*n,maxWidth:r.contactInfo.maxWidth?r.contactInfo.maxWidth*n:void 0,lineHeight:r.contactInfo.lineHeight?r.contactInfo.lineHeight*n:void 0,align:r.contactInfo.align}:void 0,description:r.description?{x:r.description.x*n,y:r.description.y*n,fontSize:r.description.fontSize*n,maxWidth:r.description.maxWidth?r.description.maxWidth*n:void 0,lineHeight:r.description.lineHeight?r.description.lineHeight*n:void 0,align:r.description.align}:void 0,signature:r.signature?{x:r.signature.x*n,y:r.signature.y*n,width:r.signature.width*n,height:r.signature.height*n,labelFontSize:r.signature.labelFontSize*n}:void 0});return{front:a(t.front),back:a(t.back)}}function yn(e,t){const n=tt();return{...n,width:Math.round(n.width*Ge),height:Math.round(n.height*Ge)}}function vn(e,t){const[n,a]=b.useState(e);return b.useEffect(()=>{const r=setTimeout(()=>a(e),t);return()=>clearTimeout(r)},[e,t]),n}function kn(){const e=x(w=>w.appLanguage),t=x(w=>w.voucherConfig.language),n=x(w=>w.voucherConfig.hours),a=x(w=>w.voucherConfig.description),r=x(w=>w.voucherConfig.templateHue),l=x(w=>w.personalInfo),o=x(w=>w.portrait),i=x(w=>w.currentSide),c=x(w=>w.flipSide),d=x(w=>w.setPortraitPan),g=vn(r,150),f=J(e),h=b.useRef(null),p=b.useRef(null),y=b.useRef(null),[k,m]=b.useState(!1),[I,P]=b.useState(!1),S=b.useRef(null),T=yn(),C=wn(),j=o.useEnhanced&&o.enhanced?o.enhanced:o.original,U=Ve(t,n,a),[N,_]=b.useState(""),[H,Y]=b.useState(""),[D,B]=b.useState(""),[V,z]=b.useState(""),[F,q]=b.useState(""),[Z,oe]=b.useState(""),[fe,ie]=b.useState(!0);b.useEffect(()=>{let w=!0;ie(!0);async function M(){const[A,$]=await Promise.all([st(n,t,"front"),st(n,t,"back")]);w&&(_(A.background),Y(A.badges),B(A.frame),z($.background),q($.badges),oe($.frame),ie(!1))}return M(),()=>{w=!1}},[n,t]),b.useEffect(()=>{!h.current||!N||!H||!D||It(h.current,N,H,D,j,l.name,C.front,T.width,T.height,o.zoom,o.panX,o.panY,g,n,t)},[T,N,H,D,j,l.name,C,o.zoom,o.panX,o.panY,g,n,t]),b.useEffect(()=>{!p.current||!V||!F||!Z||Pt(p.current,V,F,Z,l.name,l.email,l.phone,U,C.back,T.width,T.height,g,n,t)},[T,V,F,Z,l,U,C,g,n,t]);const be=()=>{m(!k),c()},se=b.useCallback((w,M)=>{if(!y.current||i!=="front"||!o.original)return!1;const A=y.current.getBoundingClientRect(),$=A.width/T.width,we=A.height/T.height,ye=(w-A.left)/$,ve=(M-A.top)/we,{x:ke,y:Ue,radiusX:Ye,radiusY:u}=C.front.portrait,v=(ye-ke)/Ye,E=(ve-Ue)/u;return v*v+E*E<=1},[i,o.original,T.width,T.height,C.front.portrait]),Pe=b.useCallback((w,M)=>{o.zoom<=1||!se(w,M)||(P(!0),S.current={x:w,y:M,panX:o.panX,panY:o.panY})},[o.zoom,o.panX,o.panY,se]),Te=b.useCallback((w,M)=>{if(!I||!S.current||!y.current)return;const A=y.current.getBoundingClientRect(),$=3/Math.max(A.width,A.height),we=(w-S.current.x)*$,ye=(M-S.current.y)*$,ve=Math.max(-1,Math.min(1,S.current.panX+we)),ke=Math.max(-1,Math.min(1,S.current.panY+ye));d(ve,ke)},[I,d]),xe=b.useCallback(()=>{P(!1),S.current=null},[]),Q=w=>{o.zoom>1&&se(w.clientX,w.clientY)&&(w.preventDefault(),Pe(w.clientX,w.clientY))},Ce=w=>{Te(w.clientX,w.clientY)},ee=()=>xe(),je=()=>xe(),Ne=w=>{if(w.touches.length===1){const M=w.touches[0];o.zoom>1&&se(M.clientX,M.clientY)&&Pe(M.clientX,M.clientY)}},He=w=>{w.touches.length===1&&Te(w.touches[0].clientX,w.touches[0].clientY)},Me=()=>xe(),De=i==="front"&&o.original&&o.zoom>1,Ae=T.width/T.height;return s.jsxs("div",{className:"space-y-4",children:[s.jsxs("div",{className:"flex justify-between items-center",children:[s.jsxs("div",{className:"tabs tabs-boxed bg-base-200",children:[s.jsx("button",{className:`tab ${i==="front"?"tab-active bg-primary text-primary-content font-semibold":""}`,onClick:()=>i!=="front"&&be(),children:f.preview.front}),s.jsx("button",{className:`tab ${i==="back"?"tab-active bg-primary text-primary-content font-semibold":""}`,onClick:()=>i!=="back"&&be(),children:f.preview.back})]}),s.jsxs("button",{className:"btn btn-ghost btn-sm",onClick:be,children:[s.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-5 w-5",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:s.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"})}),f.preview.flip]})]}),s.jsxs("div",{className:"relative w-full overflow-visible",style:{aspectRatio:Ae,perspective:"1500px"},children:[fe&&s.jsx("div",{className:"absolute inset-0 flex items-center justify-center bg-base-300 rounded-lg z-10",children:s.jsx("span",{className:"loading loading-spinner loading-lg text-primary"})}),s.jsxs("div",{ref:y,className:`relative w-full h-full shadow-lg ${De?I?"cursor-grabbing":"cursor-grab":""} ${fe?"opacity-0":"opacity-100"} transition-opacity duration-300`,style:{transformStyle:"preserve-3d",transition:"transform 0.6s ease-in-out, opacity 0.3s ease-in-out",transform:k?"rotateY(180deg)":"rotateY(0deg)"},onMouseDown:Q,onMouseMove:Ce,onMouseUp:ee,onMouseLeave:je,onTouchStart:Ne,onTouchMove:He,onTouchEnd:Me,children:[s.jsx("canvas",{ref:h,className:"absolute inset-0 w-full h-full",style:{backfaceVisibility:"hidden",WebkitBackfaceVisibility:"hidden"}}),s.jsx("canvas",{ref:p,className:"absolute inset-0 w-full h-full",style:{backfaceVisibility:"hidden",WebkitBackfaceVisibility:"hidden",transform:"rotateY(180deg)"}})]})]})]})}function In(){const e=b.useRef(null),t=b.useRef(null);return{frontCanvasRef:e,backCanvasRef:t}}const Pn=`
9
2
  // RGB to HSL conversion
10
3
  function rgbToHsl(r, g, b) {
11
4
  r /= 255;
@@ -380,4 +373,4 @@ self.onmessage = async (e) => {
380
373
  });
381
374
  }
382
375
  };
383
- `;let Ie=null,ze=null;function qt(){if(!Ie){const e=new Blob([Ot],{type:"application/javascript"});ze=URL.createObjectURL(e),Ie=new Worker(ze,{type:"module"})}return Ie}async function Pe(e){const n=await(await fetch(e)).blob();return URL.createObjectURL(n)}function Ue(e,t){const n=new Uint8Array(e);let r="";for(let a=0;a<n.length;a++)r+=String.fromCharCode(n[a]);return`data:${t};base64,${btoa(r)}`}async function nt(e){const{frontTemplateSrc:t,backTemplateSrc:n,templateWidth:r,templateHeight:a,layout:s,portrait:o,portraitZoom:l=1,portraitPanX:u=0,portraitPanY:d=0,templateHue:b=160,name:x,email:h,phone:m,description:y,language:k="de"}=e,[v,R]=await Promise.all([Pe(t),Pe(n)]);let S=null;return o&&(S=await Pe(o)),new Promise((T,I)=>{const C=qt(),z=B=>{if(C.removeEventListener("message",z),C.removeEventListener("error",M),URL.revokeObjectURL(v),URL.revokeObjectURL(R),S&&URL.revokeObjectURL(S),B.data.type==="success")try{const{frontImageData:N,backImageData:L,width:D,height:H}=B.data;if(!N||!L||!D||!H){I(new Error("Invalid response from worker"));return}const E=Ue(N,"image/jpeg"),J=Ue(L,"image/jpeg"),U=D/96*25.4,W=H/96*25.4,F=new wt.jsPDF({orientation:U>W?"landscape":"portrait",unit:"mm",format:[U,W]});F.addImage(E,"JPEG",0,0,U,W),F.addPage([U,W]),F.addImage(J,"JPEG",0,0,U,W);const Q=F.output("blob");T(Q)}catch(N){I(N)}else I(new Error(B.data.error))},M=B=>{C.removeEventListener("message",z),C.removeEventListener("error",M),URL.revokeObjectURL(v),URL.revokeObjectURL(R),S&&URL.revokeObjectURL(S),I(new Error(B.message))};C.addEventListener("message",z),C.addEventListener("error",M),C.postMessage({type:"generate",frontTemplateUrl:v,backTemplateUrl:R,portraitUrl:S,templateWidth:r,templateHeight:a,templateHue:b,portraitZoom:l,portraitPanX:u,portraitPanY:d,layout:{front:{portrait:s.front.portrait,namePlate:s.front.namePlate},back:{namePlate:s.back.namePlate,contactInfo:s.back.contactInfo,description:s.back.description,signature:s.back.signature}},name:x,email:h,phone:m,description:y,language:k})})}function at(e,t){const n=URL.createObjectURL(e),r=document.createElement("a");r.href=n,r.download=t,document.body.appendChild(r),r.click(),document.body.removeChild(r),URL.revokeObjectURL(n)}async function rt(e){const t=await nt(e);at(t,e.filename)}function Kt(){const e=g(v=>v.appLanguage),t=g(v=>v.voucherConfig.language),n=g(v=>v.voucherConfig.hours),r=g(v=>v.voucherConfig.description),a=g(v=>v.voucherConfig.templateHue),s=g(v=>v.personalInfo),o=g(v=>v.portrait),l=g(v=>v.isExporting),u=g(v=>v.setIsExporting),d=G(e),b=Ge(t,n),x=Ee(t),h=o.useEnhanced&&o.enhanced?o.enhanced:o.original,m=je(t,n,r),y=s.name.trim().length>0&&s.email.trim().length>0&&s.phone.trim().length>0&&o.original!==null,k=async()=>{if(!(!y||l)){u(!0);try{const v=`zeitgutschein-${n}h-${s.name.replace(/\s+/g,"-").toLowerCase()}.pdf`;await rt({frontTemplateSrc:b.front,backTemplateSrc:b.back,templateWidth:b.width,templateHeight:b.height,layout:x,portrait:h,portraitZoom:o.zoom,portraitPanX:o.panX,portraitPanY:o.panY,templateHue:a,name:s.name,email:s.email,phone:s.phone,description:m,filename:v,language:t})}catch(v){console.error("PDF export failed:",v)}finally{u(!1)}}};return i.jsxs("button",{className:`btn btn-primary flex-1 ${y?"":"btn-disabled"}`,onClick:k,disabled:!y,"aria-busy":l,children:[l?i.jsx("span",{className:"loading loading-spinner loading-sm"}):i.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-5 w-5",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:i.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"})}),d.export.button]})}function ot(){const e=g(r=>r.appLanguage),t=g(r=>r.setAppLanguage),n=r=>{t(r)};return i.jsxs("div",{className:"join",children:[i.jsx("button",{className:`join-item btn btn-sm ${e==="de"?"btn-active btn-primary":"btn-ghost"}`,onClick:()=>n("de"),children:"DE"}),i.jsx("button",{className:`join-item btn btn-sm ${e==="en"?"btn-active btn-primary":"btn-ghost"}`,onClick:()=>n("en"),children:"EN"})]})}function Gt(){const e=g(n=>n.appLanguage),t=G(e);return i.jsxs("div",{className:"navbar bg-currency-green text-currency-cream shadow-lg",children:[i.jsx("div",{className:"navbar-start",children:i.jsx("a",{className:"btn btn-ghost text-xl font-currency font-bold",children:t.header.title})}),i.jsx("div",{className:"navbar-center hidden sm:flex",children:i.jsx("span",{className:"text-sm opacity-80",children:t.header.subtitle})}),i.jsx("div",{className:"navbar-end",children:i.jsx(ot,{})})]})}const he="/",Vt={id:"time-voucher-classic-de",name:"Zeitgutschein Classic",type:"time-voucher",category:"classic",images:{front:`${he}templates/front_hdpi_de.jpg`,back:`${he}templates/back_hdpi_de.jpg`,width:6144,height:4096},fields:[{id:"name",type:"text",label:{de:"Name",en:"Name"},required:!0,validation:{minLength:1,maxLength:50}},{id:"hours",type:"select",label:{de:"Stunden",en:"Hours"},required:!0,options:["1","5","10"]},{id:"portrait",type:"image",label:{de:"Portrait",en:"Portrait"},required:!1},{id:"email",type:"text",label:{de:"E-Mail",en:"Email"},required:!1},{id:"phone",type:"text",label:{de:"Telefon",en:"Phone"},required:!1},{id:"description",type:"textarea",label:{de:"Beschreibung",en:"Description"},required:!1,validation:{maxLength:200}}],layout:{front:{portrait:Z.front.portrait,name:Z.front.namePlate},back:{name:Z.back.namePlate,contactInfo:Z.back.contactInfo,description:Z.back.description}},languages:["de"]},Zt={id:"time-voucher-classic-en",name:"Time Voucher Classic",type:"time-voucher",category:"classic",images:{front:`${he}templates/front_ldpi_en.png`,back:`${he}templates/back_ldpi_en.png`,width:1536,height:1024},fields:[{id:"name",type:"text",label:{de:"Name",en:"Name"},required:!0,validation:{minLength:1,maxLength:50}},{id:"hours",type:"select",label:{de:"Stunden",en:"Hours"},required:!0,options:["1","5","10"]},{id:"portrait",type:"image",label:{de:"Portrait",en:"Portrait"},required:!1},{id:"email",type:"text",label:{de:"E-Mail",en:"Email"},required:!1},{id:"phone",type:"text",label:{de:"Telefon",en:"Phone"},required:!1},{id:"description",type:"textarea",label:{de:"Beschreibung",en:"Description"},required:!1,validation:{maxLength:200}}],layout:{front:{portrait:V.front.portrait,name:V.front.namePlate},back:{name:V.back.namePlate,contactInfo:V.back.contactInfo,description:V.back.description}},languages:["en"]},Ye=[Vt,Zt],it={async listTemplates(e){let t=[...Ye];return e!=null&&e.type&&(t=t.filter(n=>n.type===e.type)),e!=null&&e.category&&(t=t.filter(n=>n.category===e.category)),e!=null&&e.language&&(t=t.filter(n=>n.languages.includes(e.language))),t},async getTemplate(e){const t=Ye.find(n=>n.id===e);if(!t)throw new Error(`Template not found: ${e}`);return t}};function Jt(e){return e==="de"?"time-voucher-classic-de":"time-voucher-classic-en"}let fe=it;function Qt(e){fe=e}function en(){return fe}async function tn(e){return fe.listTemplates(e)}async function nn(e){return fe.getTemplate(e)}exports.ApiKeyModal=Ke;exports.BillPreview=$t;exports.ExportButton=Kt;exports.Header=Gt;exports.LAYOUT_HDPI=Z;exports.LAYOUT_LDPI=V;exports.LanguageToggle=ot;exports.PersonalInfoForm=It;exports.PortraitUpload=zt;exports.TEMPLATES=Le;exports.VoucherConfig=Ut;exports.applyEngravingEffect=_e;exports.applyHueShift=Xe;exports.downloadBlob=at;exports.drawContactInfo=Qe;exports.drawMultilineText=Je;exports.drawOvalPortrait=Ze;exports.drawTemplate=Re;exports.drawText=Be;exports.enhancePortrait=Mt;exports.exportBillAsPDF=rt;exports.formatDescription=je;exports.generateBillPDF=nt;exports.getApiKey=pe;exports.getDefaultTemplateId=Jt;exports.getLayout=Ee;exports.getRemoveBackgroundEndpoint=Rt;exports.getTemplate=Ge;exports.getTemplateById=nn;exports.getTemplateProvider=en;exports.hasApiKey=Ce;exports.hasCustomEndpoint=Bt;exports.listTemplates=tn;exports.loadImage=oe;exports.removeBackground=qe;exports.renderBackSide=tt;exports.renderFrontSide=et;exports.setApiKey=Oe;exports.setRemoveBackgroundEndpoint=Et;exports.setTemplateProvider=Qt;exports.staticTemplateProvider=it;exports.t=G;exports.useBillCanvasRefs=Ft;exports.useBillStore=g;
376
+ `;let Oe=null,lt=null;function Tn(){if(!Oe){const e=new Blob([Pn],{type:"application/javascript"});lt=URL.createObjectURL(e),Oe=new Worker(lt,{type:"module"})}return Oe}async function _e(e){const n=await(await fetch(e)).blob();return URL.createObjectURL(n)}function ct(e,t){const n=new Uint8Array(e);let a="";for(let r=0;r<n.length;r++)a+=String.fromCharCode(n[r]);return`data:${t};base64,${btoa(a)}`}async function Nt(e){const{frontTemplateSrc:t,backTemplateSrc:n,templateWidth:a,templateHeight:r,layout:l,portrait:o,portraitZoom:i=1,portraitPanX:c=0,portraitPanY:d=0,templateHue:g=160,name:f,email:h,phone:p,description:y,language:k="de"}=e,[m,I]=await Promise.all([_e(t),_e(n)]);let P=null;return o&&(P=await _e(o)),new Promise((S,T)=>{const C=Tn(),j=N=>{if(C.removeEventListener("message",j),C.removeEventListener("error",U),URL.revokeObjectURL(m),URL.revokeObjectURL(I),P&&URL.revokeObjectURL(P),N.data.type==="success")try{const{frontImageData:_,backImageData:H,width:Y,height:D}=N.data;if(!_||!H||!Y||!D){T(new Error("Invalid response from worker"));return}const B=ct(_,"image/jpeg"),V=ct(H,"image/jpeg"),z=Y/96*25.4,F=D/96*25.4,q=new Wt.jsPDF({orientation:z>F?"landscape":"portrait",unit:"mm",format:[z,F]});q.addImage(B,"JPEG",0,0,z,F),q.addPage([z,F]),q.addImage(V,"JPEG",0,0,z,F);const Z=q.output("blob");S(Z)}catch(_){T(_)}else T(new Error(N.data.error))},U=N=>{C.removeEventListener("message",j),C.removeEventListener("error",U),URL.revokeObjectURL(m),URL.revokeObjectURL(I),P&&URL.revokeObjectURL(P),T(new Error(N.message))};C.addEventListener("message",j),C.addEventListener("error",U),C.postMessage({type:"generate",frontTemplateUrl:m,backTemplateUrl:I,portraitUrl:P,templateWidth:a,templateHeight:r,templateHue:g,portraitZoom:i,portraitPanX:c,portraitPanY:d,layout:{front:{portrait:l.front.portrait,namePlate:l.front.namePlate},back:{namePlate:l.back.namePlate,contactInfo:l.back.contactInfo,description:l.back.description,signature:l.back.signature}},name:f,email:h,phone:p,description:y,language:k})})}function Ht(e,t){const n=URL.createObjectURL(e),a=document.createElement("a");a.href=n,a.download=t,document.body.appendChild(a),a.click(),document.body.removeChild(a),URL.revokeObjectURL(n)}async function Mt(e){const t=await Nt(e);Ht(t,e.filename)}function Cn(){const e=x(m=>m.appLanguage),t=x(m=>m.voucherConfig.language),n=x(m=>m.voucherConfig.hours),a=x(m=>m.voucherConfig.description),r=x(m=>m.voucherConfig.templateHue),l=x(m=>m.personalInfo),o=x(m=>m.portrait),i=x(m=>m.isExporting),c=x(m=>m.setIsExporting),d=J(e),g=tt(),f=nt(),h=o.useEnhanced&&o.enhanced?o.enhanced:o.original,p=Ve(t,n,a),y=l.name.trim().length>0&&l.email.trim().length>0&&l.phone.trim().length>0&&o.original!==null,k=async()=>{if(!(!y||i)){c(!0);try{const[m,I]=await Promise.all([it(n,t,"front"),it(n,t,"back")]),P=`zeitgutschein-${n}h-${l.name.replace(/\s+/g,"-").toLowerCase()}.pdf`;await Mt({frontTemplateSrc:m,backTemplateSrc:I,templateWidth:g.width,templateHeight:g.height,layout:f,portrait:h,portraitZoom:o.zoom,portraitPanX:o.panX,portraitPanY:o.panY,templateHue:r,name:l.name,email:l.email,phone:l.phone,description:p,filename:P,language:t})}catch(m){console.error("PDF export failed:",m)}finally{c(!1)}}};return s.jsxs("button",{className:`btn btn-primary flex-1 ${y?"":"btn-disabled"}`,onClick:k,disabled:!y,"aria-busy":i,children:[i?s.jsx("span",{className:"loading loading-spinner loading-sm"}):s.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-5 w-5",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:s.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"})}),d.export.button]})}function Dt(){const e=x(a=>a.appLanguage),t=x(a=>a.setAppLanguage),n=a=>{t(a)};return s.jsxs("div",{className:"join",children:[s.jsx("button",{className:`join-item btn btn-sm ${e==="de"?"btn-active btn-primary":"btn-ghost"}`,onClick:()=>n("de"),children:"DE"}),s.jsx("button",{className:`join-item btn btn-sm ${e==="en"?"btn-active btn-primary":"btn-ghost"}`,onClick:()=>n("en"),children:"EN"})]})}function Ln(){const e=x(n=>n.appLanguage),t=J(e);return s.jsxs("div",{className:"navbar bg-currency-green text-currency-cream shadow-lg",children:[s.jsx("div",{className:"navbar-start",children:s.jsx("a",{className:"btn btn-ghost text-xl font-currency font-bold",children:t.header.title})}),s.jsx("div",{className:"navbar-center hidden sm:flex",children:s.jsx("span",{className:"text-sm opacity-80",children:t.header.subtitle})}),s.jsx("div",{className:"navbar-end",children:s.jsx(Dt,{})})]})}const Se="/",Sn={id:"time-voucher-classic-de",name:"Zeitgutschein Classic",type:"time-voucher",category:"classic",images:{front:`${Se}templates/front_hdpi_de.jpg`,back:`${Se}templates/back_hdpi_de.jpg`,width:6144,height:4096},fields:[{id:"name",type:"text",label:{de:"Name",en:"Name"},required:!0,validation:{minLength:1,maxLength:50}},{id:"hours",type:"select",label:{de:"Stunden",en:"Hours"},required:!0,options:["1","5","10"]},{id:"portrait",type:"image",label:{de:"Portrait",en:"Portrait"},required:!1},{id:"email",type:"text",label:{de:"E-Mail",en:"Email"},required:!1},{id:"phone",type:"text",label:{de:"Telefon",en:"Phone"},required:!1},{id:"description",type:"textarea",label:{de:"Beschreibung",en:"Description"},required:!1,validation:{maxLength:200}}],layout:{front:{portrait:ue.front.portrait,name:ue.front.namePlate},back:{name:ue.back.namePlate,contactInfo:ue.back.contactInfo,description:ue.back.description}},languages:["de"]},En={id:"time-voucher-classic-en",name:"Time Voucher Classic",type:"time-voucher",category:"classic",images:{front:`${Se}templates/front_ldpi_en.png`,back:`${Se}templates/back_ldpi_en.png`,width:1536,height:1024},fields:[{id:"name",type:"text",label:{de:"Name",en:"Name"},required:!0,validation:{minLength:1,maxLength:50}},{id:"hours",type:"select",label:{de:"Stunden",en:"Hours"},required:!0,options:["1","5","10"]},{id:"portrait",type:"image",label:{de:"Portrait",en:"Portrait"},required:!1},{id:"email",type:"text",label:{de:"E-Mail",en:"Email"},required:!1},{id:"phone",type:"text",label:{de:"Telefon",en:"Phone"},required:!1},{id:"description",type:"textarea",label:{de:"Beschreibung",en:"Description"},required:!1,validation:{maxLength:200}}],layout:{front:{portrait:de.front.portrait,name:de.front.namePlate},back:{name:de.back.namePlate,contactInfo:de.back.contactInfo,description:de.back.description}},languages:["en"]},ut=[Sn,En],At={async listTemplates(e){let t=[...ut];return e!=null&&e.type&&(t=t.filter(n=>n.type===e.type)),e!=null&&e.category&&(t=t.filter(n=>n.category===e.category)),e!=null&&e.language&&(t=t.filter(n=>n.languages.includes(e.language))),t},async getTemplate(e){const t=ut.find(n=>n.id===e);if(!t)throw new Error(`Template not found: ${e}`);return t}};function Rn(e){return e==="de"?"time-voucher-classic-de":"time-voucher-classic-en"}let Be=At;function Bn(e){Be=e}function jn(){return Be}async function Nn(e){return Be.listTemplates(e)}async function Hn(e){return Be.getTemplate(e)}exports.ApiKeyModal=xt;exports.BillPreview=kn;exports.ExportButton=Cn;exports.Header=Ln;exports.LAYOUT_HDPI=ue;exports.LAYOUT_LDPI=de;exports.LanguageToggle=Dt;exports.PersonalInfoForm=Kt;exports.PortraitUpload=dn;exports.TEMPLATE_HEIGHT=re;exports.TEMPLATE_LAYOUT=Re;exports.TEMPLATE_WIDTH=ae;exports.VoucherConfig=gn;exports.applyEngravingEffect=dt;exports.applyHueShift=mt;exports.clearCompositorCache=bn;exports.composeTemplate=jt;exports.downloadBlob=Ht;exports.drawContactInfo=kt;exports.drawMultilineText=vt;exports.drawOvalPortrait=yt;exports.drawTemplate=ne;exports.drawText=Je;exports.enhancePortrait=cn;exports.exportBillAsPDF=Mt;exports.formatDescription=Ve;exports.generateBillPDF=Nt;exports.getApiKey=Ee;exports.getDefaultTemplateId=Rn;exports.getLayout=nt;exports.getRemoveBackgroundEndpoint=an;exports.getTemplate=tt;exports.getTemplateById=Hn;exports.getTemplateDimensions=fn;exports.getTemplateProvider=jn;exports.hasApiKey=$e;exports.hasCustomEndpoint=rn;exports.listTemplates=Nn;exports.loadImage=R;exports.preloadAllTemplates=xn;exports.removeBackground=bt;exports.renderBackSide=Pt;exports.renderFrontSide=It;exports.setApiKey=ft;exports.setRemoveBackgroundEndpoint=nn;exports.setTemplateProvider=Bn;exports.staticTemplateProvider=At;exports.t=J;exports.useBillCanvasRefs=In;exports.useBillStore=x;
package/dist/index.d.ts CHANGED
@@ -23,11 +23,11 @@ declare interface ApiKeyModalProps {
23
23
  export declare function applyEngravingEffect(imageDataUrl: string, intensity?: number, tintHue?: number): Promise<string>;
24
24
 
25
25
  /**
26
- * Replace cool colors (greens, cyans, blues) with target hue
27
- * Maps all cool colors to the target hue while preserving saturation and lightness
26
+ * Replace beige/warm colors with target hue
27
+ * Maps beige colors (background) to the target hue while preserving saturation and lightness
28
28
  * @param imageDataUrl - Base64 data URL of the image
29
- * @param targetHue - Target hue in degrees (0-360). 160 = original (no shift)
30
- * @returns Image with cool colors replaced by target hue
29
+ * @param targetHue - Target hue in degrees (0-360). ~29 = original beige (no shift)
30
+ * @returns Image with beige colors replaced by target hue
31
31
  */
32
32
  export declare function applyHueShift(imageDataUrl: string, targetHue: number): Promise<string>;
33
33
 
@@ -74,6 +74,20 @@ export declare interface CanvasPosition {
74
74
  y: number;
75
75
  }
76
76
 
77
+ /**
78
+ * Clear the compositor cache (useful when templates are updated)
79
+ */
80
+ export declare function clearCompositorCache(): void;
81
+
82
+ /**
83
+ * Compose a template for PREVIEW (smaller, faster)
84
+ * @param hours - The hour value (1, 5, or 10)
85
+ * @param language - The language ('de' or 'en')
86
+ * @param side - 'front' or 'back'
87
+ * @returns Data URL of the composited template at preview resolution
88
+ */
89
+ export declare function composeTemplate(hours: HourValue, language: Language, side: 'front' | 'back'): Promise<string>;
90
+
77
91
  export declare function downloadBlob(blob: Blob, filename: string): void;
78
92
 
79
93
  export declare function drawContactInfo(ctx: CanvasRenderingContext2D, name: string, email: string, phone: string, config: TextConfig, color?: string): void;
@@ -125,7 +139,7 @@ export declare function getApiKey(): string | null;
125
139
  */
126
140
  export declare function getDefaultTemplateId(language: 'de' | 'en'): string;
127
141
 
128
- export declare function getLayout(language: Language): {
142
+ export declare function getLayout(_language: Language): {
129
143
  front: TemplateLayout;
130
144
  back: TemplateLayout;
131
145
  };
@@ -135,13 +149,21 @@ export declare function getLayout(language: Language): {
135
149
  */
136
150
  export declare function getRemoveBackgroundEndpoint(): string | null;
137
151
 
138
- export declare function getTemplate(language: Language, hours: HourValue): TemplateConfig;
152
+ export declare function getTemplate(_language: Language, _hours: HourValue): TemplateConfig;
139
153
 
140
154
  /**
141
155
  * Get a specific template by ID
142
156
  */
143
157
  export declare function getTemplateById(templateId: string): Promise<Template>;
144
158
 
159
+ /**
160
+ * Get the template dimensions
161
+ */
162
+ export declare function getTemplateDimensions(): {
163
+ width: number;
164
+ height: number;
165
+ };
166
+
145
167
  /**
146
168
  * Get the current template provider
147
169
  */
@@ -235,11 +257,16 @@ export declare interface PortraitState {
235
257
 
236
258
  export declare function PortraitUpload(): JSX.Element;
237
259
 
260
+ /**
261
+ * Preload all template combinations for faster access
262
+ */
263
+ export declare function preloadAllTemplates(): Promise<void>;
264
+
238
265
  export declare function removeBackground(imageDataUrl: string): Promise<string>;
239
266
 
240
- export declare function renderBackSide(canvas: HTMLCanvasElement, templateSrc: string, name: string, email: string, phone: string, description: string, layout: TemplateLayout, width: number, height: number, templateHue?: number, language?: 'de' | 'en'): Promise<void>;
267
+ export declare function renderBackSide(canvas: HTMLCanvasElement, backgroundSrc: string, badgesSrc: string, frameSrc: string, name: string, email: string, phone: string, description: string, layout: TemplateLayout, width: number, height: number, templateHue?: number, hours?: HourValue, language?: Language): Promise<void>;
241
268
 
242
- export declare function renderFrontSide(canvas: HTMLCanvasElement, templateSrc: string, portraitSrc: string | null, name: string, layout: TemplateLayout, width: number, height: number, portraitZoom?: number, portraitPanX?: number, portraitPanY?: number, templateHue?: number): Promise<void>;
269
+ export declare function renderFrontSide(canvas: HTMLCanvasElement, backgroundSrc: string, badgesSrc: string, frameSrc: string, portraitSrc: string | null, name: string, layout: TemplateLayout, width: number, height: number, portraitZoom?: number, portraitPanX?: number, portraitPanY?: number, templateHue?: number, hours?: HourValue, language?: Language): Promise<void>;
243
270
 
244
271
  export declare function setApiKey(key: string): void;
245
272
 
@@ -303,6 +330,15 @@ export declare interface Template {
303
330
  };
304
331
  }
305
332
 
333
+ export declare const TEMPLATE_HEIGHT = 1920;
334
+
335
+ export declare const TEMPLATE_LAYOUT: {
336
+ front: TemplateLayout;
337
+ back: TemplateLayout;
338
+ };
339
+
340
+ export declare const TEMPLATE_WIDTH = 3633;
341
+
306
342
  export declare interface TemplateConfig {
307
343
  front: string;
308
344
  back: string;
@@ -334,8 +370,6 @@ export declare interface TemplateLayout {
334
370
  signature?: SignatureConfig;
335
371
  }
336
372
 
337
- declare type TemplateMap = Record<Language, Record<HourValue, TemplateConfig>>;
338
-
339
373
  /**
340
374
  * Provider interface for template sources
341
375
  * Implementations can load from static files, CMS, or other sources
@@ -355,8 +389,6 @@ export declare interface TemplateProvider {
355
389
  getTemplate(templateId: string): Promise<Template>;
356
390
  }
357
391
 
358
- export declare const TEMPLATES: TemplateMap;
359
-
360
392
  export declare interface TextConfig extends CanvasPosition {
361
393
  fontSize: number;
362
394
  maxWidth?: number;
@@ -429,49 +461,13 @@ export declare const useBillStore: UseBoundStore<Omit<StoreApi<BillState & BillA
429
461
  setState(partial: (BillState & BillActions) | Partial<BillState & BillActions> | ((state: BillState & BillActions) => (BillState & BillActions) | Partial<BillState & BillActions>), replace?: false | undefined): unknown;
430
462
  setState(state: (BillState & BillActions) | ((state: BillState & BillActions) => BillState & BillActions), replace: true): unknown;
431
463
  persist: {
432
- setOptions: (options: Partial<PersistOptions<BillState & BillActions, {
433
- personalInfo: PersonalInfo;
434
- voucherConfig: VoucherConfigType;
435
- appLanguage: Language;
436
- portrait: {
437
- original: null;
438
- enhanced: null;
439
- useEnhanced: boolean;
440
- zoom: number;
441
- panX: number;
442
- panY: number;
443
- rawImage: null;
444
- bgRemovedImage: null;
445
- bgRemoved: boolean;
446
- bgOpacity: number;
447
- bgBlur: number;
448
- engravingIntensity: number;
449
- };
450
- }, unknown>>) => void;
464
+ setOptions: (options: Partial<PersistOptions<BillState & BillActions, BillState, unknown>>) => void;
451
465
  clearStorage: () => void;
452
466
  rehydrate: () => Promise<void> | void;
453
467
  hasHydrated: () => boolean;
454
468
  onHydrate: (fn: (state: BillState & BillActions) => void) => () => void;
455
469
  onFinishHydration: (fn: (state: BillState & BillActions) => void) => () => void;
456
- getOptions: () => Partial<PersistOptions<BillState & BillActions, {
457
- personalInfo: PersonalInfo;
458
- voucherConfig: VoucherConfigType;
459
- appLanguage: Language;
460
- portrait: {
461
- original: null;
462
- enhanced: null;
463
- useEnhanced: boolean;
464
- zoom: number;
465
- panX: number;
466
- panY: number;
467
- rawImage: null;
468
- bgRemovedImage: null;
469
- bgRemoved: boolean;
470
- bgOpacity: number;
471
- bgBlur: number;
472
- engravingIntensity: number;
473
- };
474
- }, unknown>>;
470
+ getOptions: () => Partial<PersistOptions<BillState & BillActions, BillState, unknown>>;
475
471
  };
476
472
  }>;
477
473