@antontranelis/money-printer 1.0.28 → 1.0.29

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,11 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=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 Ne={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},b=bt.create()(xt.persist(e=>({...Ne,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}),setLanguage: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(Ne)}),{name:"money-generator-storage",partialize:e=>({personalInfo:e.personalInfo,voucherConfig:e.voucherConfig,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?"},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?"},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 K(e){return kt[e]}function Se(e,t,n){if(n&&n.trim())return n;const r=K(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=b(a=>a.voucherConfig.language),t=b(a=>a.personalInfo),n=b(a=>a.setPersonalInfo),r=K(e);return o.jsxs("div",{className:"space-y-4",children:[o.jsxs("div",{className:"form-control",children:[o.jsx("label",{className:"label",children:o.jsx("span",{className:"label-text font-medium",children:r.form.personalInfo.name})}),o.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})})]}),o.jsxs("div",{className:"form-control",children:[o.jsx("label",{className:"label",children:o.jsx("span",{className:"label-text font-medium",children:r.form.personalInfo.email})}),o.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})})]}),o.jsxs("div",{className:"form-control",children:[o.jsx("label",{className:"label",children:o.jsx("span",{className:"label-text font-medium",children:r.form.personalInfo.phone})}),o.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,De=null;function Te(e,t){return $||($=document.createElement("canvas"),De=$.getContext("2d",{willReadFrequently:!0})),($.width!==e||$.height!==t)&&($.width=e,$.height=t),De}function de(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 i=re.keys().next().value;i&&re.delete(i)}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 de(e),r=Math.max(n.width,n.height);if(r<=t)return e;const a=t/r,i=Math.round(n.width*a),s=Math.round(n.height*a),c=document.createElement("canvas"),d=c.getContext("2d");if(!d)throw new Error("Failed to get canvas context");return c.width=i,c.height=s,d.drawImage(n,0,0,i,s),c.toDataURL("image/jpeg",.9)}async function ye(e,t,n,r=0){const[a,i]=await Promise.all([de(e),de(t)]),s=Te(a.width,a.height);if(s.clearRect(0,0,a.width,a.height),n>0){const c=r*20;s.save(),s.globalAlpha=n,c>0&&(s.filter=`blur(${c}px)`),s.drawImage(i,0,0,a.width,a.height),s.restore()}return s.drawImage(a,0,0),$.toDataURL("image/png")}async function Ye(e,t=.5,n=40){const r=await de(e),a=Te(r.width,r.height);a.clearRect(0,0,r.width,r.height),a.drawImage(r,0,0);const i=a.getImageData(0,0,r.width,r.height),s=i.data,c=new Uint32Array(s.buffer),d=1+t*.8,u=1-t,y=n%360/360;for(let x=0;x<c.length;x++){const g=c[x],h=g&255,v=g>>8&255,m=g>>16&255,T=g>>24&255;if(T===0)continue;let k=(((77*h+150*v+29*m>>8)/255-.5)*d+.5)*255;k<0?k=0:k>255&&(k=255);const I=k/255,R=.12,[S,U,N]=_e(y,R,I),j=h*u+S*t|0,D=v*u+U*t|0,E=m*u+N*t|0;c[x]=T<<24|E<<16|D<<8|j}return a.putImageData(i,0,0),$.toDataURL("image/png")}function Tt(e,t,n){e/=255,t/=255,n/=255;const r=Math.max(e,t,n),a=Math.min(e,t,n),i=(r+a)/2;let s=0,c=0;if(r!==a){const d=r-a;switch(c=i>.5?d/(2-r-a):d/(r+a),r){case e:s=((t-n)/d+(t<n?6:0))/6;break;case t:s=((n-e)/d+2)/6;break;case n:s=((e-t)/d+4)/6;break}}return[s,c,i]}function _e(e,t,n){if(t===0){const s=Math.round(n*255);return[s,s,s]}const r=(s,c,d)=>(d<0&&(d+=1),d>1&&(d-=1),d<1/6?s+(c-s)*6*d:d<1/2?c:d<2/3?s+(c-s)*(2/3-d)*6:s),a=n<.5?n*(1+t):n+t-n*t,i=2*n-a;return[Math.round(r(i,a,e+1/3)*255),Math.round(r(i,a,e)*255),Math.round(r(i,a,e-1/3)*255)]}async function We(e,t){if(t>=155&&t<=165)return e;const n=await de(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),i=a.data,s=new Uint32Array(i.buffer),c=t%360/360,d=60/360,u=260/360,y=1e5,x=s.length;for(let g=0;g<x;g+=y){const h=Math.min(g+y,x);for(let v=g;v<h;v++){const m=s[v],T=m&255,H=m>>8&255,k=m>>16&255,I=m>>24&255;if(I===0)continue;const[R,S,U]=Tt(T,H,k);if(S<.06||R<d||R>u)continue;const N=c,[j,D,E]=_e(N,S,U);s[v]=I<<24|E<<16|D<<8|j}h<x&&await new Promise(v=>setTimeout(v,0))}return r.putImageData(a,0,0),$.toDataURL("image/png")}const Rt="https://api.stability.ai/v1/generation",jt="https://api.stability.ai/v2beta/stable-image/edit/remove-background",Xe="stability_api_key";let se=null;function Et(e){se=e}function Bt(){return se}function Ht(){return se!==null}const Lt={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"},Me=[{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 Nt(e,t){const n=e/t;let r=Me[0],a=1/0;for(const i of Me){const s=i.width/i.height,c=Math.abs(n-s);c<a&&(a=c,r=i)}return r}function Dt(e){return new Promise((t,n)=>{const r=new Image;r.onload=()=>{const a=Nt(r.width,r.height),i=document.createElement("canvas");i.width=a.width,i.height=a.height;const s=i.getContext("2d");if(!s){n(new Error("Failed to get canvas context"));return}const c=r.width/r.height,d=a.width/a.height;let u=0,y=0,x=r.width,g=r.height;c>d?(x=r.height*d,u=(r.width-x)/2):(g=r.width/d,y=(r.height-g)/2),s.drawImage(r,u,y,x,g,0,0,a.width,a.height),t(i.toDataURL("image/png"))},r.onerror=()=>n(new Error("Failed to load image")),r.src=e})}function $e(e){var s;const t=e.split(","),n=((s=t[0].match(/:(.*?);/))==null?void 0:s[1])||"image/png",r=atob(t[1]),a=r.length,i=new Uint8Array(a);for(let c=0;c<a;c++)i[c]=r.charCodeAt(c);return new Blob([i],{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(Xe):null}function Oe(e){localStorage.setItem(Xe,e)}function Pe(){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,i=await Dt(n),s=$e(i),c=new FormData;c.append("init_image",s,"portrait.png"),c.append("init_image_mode","IMAGE_STRENGTH"),c.append("image_strength",String(1-a)),c.append("text_prompts[0][text]",Lt[r]),c.append("text_prompts[0][weight]","1"),c.append("cfg_scale","7"),c.append("samples","1"),c.append("steps","30");const u=await fetch(`${Rt}/stable-diffusion-xl-1024-v1-0/image-to-image`,{method:"POST",headers:{Authorization:`Bearer ${t}`,Accept:"application/json"},body:c});if(!u.ok){const x=await u.text();throw console.error("Stability AI error:",x),u.status===401?new Error("Invalid API key"):u.status===402?new Error("Insufficient credits"):u.status===429?new Error("Rate limit exceeded. Please try again later."):new Error(`API error: ${u.status}`)}const y=await u.json();if(!y.artifacts||y.artifacts.length===0)throw new Error("No image generated");return`data:image/png;base64,${y.artifacts[0].base64}`}async function Fe(e){if(se){const s=await fetch(se,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({imageDataUrl:e})});if(!s.ok){const d=await s.json().catch(()=>({}));throw new Error(d.error||`API error: ${s.status}`)}return(await s.json()).imageDataUrl}const t=pe();if(!t)throw new Error("No Stability AI API key configured");const n=$e(e),r=new FormData;r.append("image",n,"image.png"),r.append("output_format","png");const a=await fetch(jt,{method:"POST",headers:{Authorization:`Bearer ${t}`,Accept:"image/*"},body:r});if(!a.ok){const s=await a.text();throw console.error("Stability AI remove background error:",s),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 i=await a.blob();return new Promise((s,c)=>{const d=new FileReader;d.onload=()=>s(d.result),d.onerror=()=>c(new Error("Failed to read result")),d.readAsDataURL(i)})}function At(){const[e,t]=p.useState(!1),[n,r]=p.useState(!1),[a,i]=p.useState(null),[s,c]=p.useState(()=>Pe());p.useEffect(()=>{c(Pe())},[]);const d=p.useCallback(()=>i(null),[]),u=p.useCallback(g=>{Oe(g),c(!0),i(null)},[]),y=p.useCallback(async(g,h=.5,v=40)=>{t(!0),i(null);try{return await Ye(g,h,v)}catch(m){const T=m instanceof Error?m.message:"Enhancement failed";throw i(T),m}finally{t(!1)}},[]),x=p.useCallback(async g=>{r(!0),i(null);try{return await Fe(g)}catch(h){const v=h instanceof Error?h.message:"Background removal failed";throw i(v),h}finally{r(!1)}},[]);return{enhance:y,removeBg:x,isEnhancing:e,isRemovingBg:n,error:a,hasKey:s,setApiKey:u,clearError:d}}function qe({isOpen:e,onClose:t,onSubmit:n}){const r=b(u=>u.voucherConfig.language),[a,i]=p.useState("");if(!e)return null;const s=u=>{u.preventDefault(),a.trim()&&(n(a.trim()),i(""),t())},d={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 o.jsxs("dialog",{className:"modal modal-open",children:[o.jsxs("div",{className:"modal-box",children:[o.jsx("h3",{className:"font-bold text-lg",children:d.title}),o.jsx("p",{className:"py-4 text-sm opacity-80",children:d.description}),o.jsxs("form",{onSubmit:s,children:[o.jsxs("div",{className:"form-control",children:[o.jsx("input",{type:"password",placeholder:d.placeholder,className:"input input-bordered w-full",value:a,onChange:u=>i(u.target.value),autoFocus:!0}),o.jsx("label",{className:"label",children:o.jsx("span",{className:"label-text-alt",children:d.hint})})]}),o.jsxs("div",{className:"modal-action",children:[o.jsx("button",{type:"button",className:"btn btn-ghost",onClick:t,children:d.cancel}),o.jsx("button",{type:"submit",className:"btn btn-primary",disabled:!a.trim(),children:d.submit})]})]})]}),o.jsx("form",{method:"dialog",className:"modal-backdrop",children:o.jsx("button",{onClick:t,children:"close"})})]})}function Ut(){const e=b(l=>l.voucherConfig.language),t=b(l=>l.portrait),n=b(l=>l.setPortrait),r=b(l=>l.setPortraitZoom),a=b(l=>l.setPortraitPan),i=b(l=>l.setPortraitRawImage),s=b(l=>l.setPortraitBgRemoved),c=b(l=>l.setPortraitBgOpacity),d=b(l=>l.setPortraitBgBlur),u=b(l=>l.setPortraitEngravingIntensity),{enhance:y,removeBg:x,isEnhancing:g,isRemovingBg:h,error:v,hasKey:m,setApiKey:T}=At(),H=K(e),k=p.useRef(null),I=p.useRef(null),[R,S]=p.useState(!1),[U,N]=p.useState(!1),[j,D]=p.useState(!1),E=p.useRef(null),L=p.useRef(null),M=p.useRef(null),B=t.rawImage,J=t.bgRemovedImage,z=t.bgRemoved,W=t.bgOpacity,O=t.bgBlur,Q=t.engravingIntensity;p.useEffect(()=>{t.original&&!t.rawImage&&i(t.original)},[t.original,t.rawImage,i]),p.useEffect(()=>()=>{L.current&&clearTimeout(L.current),M.current&&clearTimeout(M.current)},[]);const ee=b(l=>l.voucherConfig.templateHue),ue=p.useRef(ee),f=p.useCallback(async l=>{if(!l.type.startsWith("image/"))return;const w=new FileReader;w.onload=async C=>{var Y;const P=(Y=C.target)==null?void 0:Y.result,X=await St(P);i(X),n(X),s(!1,null),u(0)},w.readAsDataURL(l)},[n,i,s,u]),A=p.useCallback(l=>{l.preventDefault(),S(!1);const w=l.dataTransfer.files[0];w&&f(w)},[f]),F=p.useCallback(l=>{l.preventDefault(),S(!0)},[]),te=p.useCallback(l=>{l.preventDefault(),S(!1)},[]),le=()=>{var l;(l=k.current)==null||l.click()},ce=l=>{var C;const w=(C=l.target.files)==null?void 0:C[0];w&&f(w)},q=p.useCallback(async(l,w,C)=>{try{return await y(l,w,C)}catch(P){return console.error("Enhancement failed:",P),l}},[y]),ne=p.useCallback(async l=>{try{const w=await x(l);return s(!0,w),w}catch(w){return console.error("Background removal failed:",w),l}},[x,s]),G=p.useCallback(async()=>{const l=b.getState(),w=l.portrait,C=l.voucherConfig.templateHue;if(!w.rawImage)return;let P;w.bgRemoved&&w.bgRemovedImage?P=await ye(w.bgRemovedImage,w.rawImage,w.bgOpacity,w.bgBlur):P=w.rawImage,w.engravingIntensity>0&&(P=await q(P,w.engravingIntensity,C)),n(P)},[q,n]);p.useEffect(()=>{if(ue.current===ee)return;ue.current=ee;const l=b.getState().portrait;l.engravingIntensity>0&&l.rawImage&&(L.current&&clearTimeout(L.current),L.current=setTimeout(G,150))},[ee,G]);const be=async()=>{if(!B)return;if(!z&&!m){N(!0);return}if(!z){const w=await ne(B),C=b.getState(),P=C.portrait,X=C.voucherConfig.templateHue;let Y=await ye(w,B,P.bgOpacity,P.bgBlur);P.engravingIntensity>0&&(Y=await q(Y,P.engravingIntensity,X)),n(Y)}else{s(!1,null);const w=b.getState(),C=w.portrait.engravingIntensity,P=w.voucherConfig.templateHue;if(C>0){const X=await q(B,C,P);n(X)}else n(B)}},xe=l=>{u(l),L.current&&clearTimeout(L.current),B&&(L.current=setTimeout(G,150))},he=async l=>{if(T(l),!B)return;const w=await ne(B),C=b.getState(),P=C.portrait,X=C.voucherConfig.templateHue;let Y=await ye(w,B,P.bgOpacity,P.bgBlur);P.engravingIntensity>0&&(Y=await q(Y,P.engravingIntensity,X)),n(Y)},me=l=>{c(l),M.current&&clearTimeout(M.current),!(!B||!J)&&(M.current=setTimeout(G,150))},it=l=>{d(l),M.current&&clearTimeout(M.current),!(!B||!J)&&(M.current=setTimeout(G,150))},st=()=>{n(null),i(null),s(!1,null),c(0),d(0),u(0),Ct()},He=(l,w)=>{t.zoom<=1||(D(!0),E.current={x:l,y:w,panX:t.panX,panY:t.panY})},Le=(l,w)=>{if(!j||!E.current||!I.current)return;const C=I.current.getBoundingClientRect(),P=2/Math.max(C.width,C.height),X=(l-E.current.x)*P,Y=(w-E.current.y)*P,pt=Math.max(-1,Math.min(1,E.current.panX+X)),ft=Math.max(-1,Math.min(1,E.current.panY+Y));a(pt,ft)},we=()=>{D(!1),E.current=null},lt=l=>{l.preventDefault(),He(l.clientX,l.clientY)},ct=l=>{Le(l.clientX,l.clientY)},dt=()=>{we()},ut=()=>{we()},ht=l=>{l.touches.length===1&&He(l.touches[0].clientX,l.touches[0].clientY)},mt=l=>{l.touches.length===1&&Le(l.touches[0].clientX,l.touches[0].clientY)},gt=()=>{we()};return o.jsxs("div",{className:"space-y-4",children:[t.original?o.jsxs("div",{className:"flex flex-col items-center space-y-4",children:[o.jsxs("div",{className:"relative",children:[o.jsx("div",{ref:I,className:`w-32 h-32 rounded-full overflow-hidden border-4 border-currency-gold shadow-lg ${t.zoom>1?"cursor-grab":""} ${j?"cursor-grabbing":""}`,onMouseDown:lt,onMouseMove:ct,onMouseUp:dt,onMouseLeave:ut,onTouchStart:ht,onTouchMove:mt,onTouchEnd:gt,children:o.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})}),o.jsx("button",{className:"btn btn-circle btn-xs btn-error absolute -top-1 -right-1",onClick:st,children:o.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-4 w-4",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:o.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M6 18L18 6M6 6l12 12"})})})]}),o.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-4 w-full",children:[o.jsxs("div",{className:"form-control w-full",children:[o.jsxs("label",{className:"label",children:[o.jsx("span",{className:"label-text",children:H.form.portrait.zoom}),o.jsxs("span",{className:"label-text-alt",children:[Math.round(t.zoom*100),"%"]})]}),o.jsx("input",{type:"range",min:"0.5",max:"2",step:"0.05",value:t.zoom,onChange:l=>{const w=parseFloat(l.target.value);r(w),w<=1&&(t.panX!==0||t.panY!==0)&&a(0,0)},className:"range range-primary range-sm"})]}),o.jsxs("div",{className:"form-control w-full",children:[o.jsxs("label",{className:"label",children:[o.jsxs("span",{className:"label-text flex items-center gap-2",children:[e==="de"?"Farbanpassung":"Color adjustment",g&&o.jsx("span",{className:"loading loading-spinner loading-xs"})]}),o.jsxs("span",{className:"label-text-alt",children:[Math.round(Q*100),"%"]})]}),o.jsx("input",{type:"range",min:"0",max:"1",step:"0.05",value:Q,onChange:l=>xe(parseFloat(l.target.value)),className:"range range-secondary range-sm",disabled:g||!B})]})]}),z?o.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-4 w-full",children:[o.jsxs("div",{className:"form-control w-full",children:[o.jsxs("label",{className:"label",children:[o.jsx("span",{className:"label-text",children:e==="de"?"Hintergrund":"Background"}),o.jsxs("span",{className:"label-text-alt",children:[Math.round(W*100),"%"]})]}),o.jsx("input",{type:"range",min:"0",max:"1",step:"0.05",value:W,onChange:l=>me(parseFloat(l.target.value)),className:"range range-primary range-sm"})]}),o.jsxs("div",{className:"form-control w-full",children:[o.jsxs("label",{className:"label",children:[o.jsx("span",{className:"label-text",children:e==="de"?"Unschärfe":"Blur"}),o.jsxs("span",{className:"label-text-alt",children:[Math.round(O*100),"%"]})]}),o.jsx("input",{type:"range",min:"0",max:"1",step:"0.05",value:O,onChange:l=>it(parseFloat(l.target.value)),className:"range range-primary range-sm"})]})]}):o.jsx("div",{className:"form-control",children:o.jsxs("label",{className:"label cursor-pointer justify-start gap-3",children:[o.jsx("input",{type:"checkbox",className:`toggle toggle-primary ${h?"opacity-50":""}`,checked:z,onChange:be,disabled:h||!B}),o.jsxs("span",{className:"label-text flex items-center gap-2",children:[h?o.jsxs(o.Fragment,{children:[o.jsx("span",{className:"loading loading-spinner loading-xs"}),e==="de"?"Hintergrund wird entfernt...":"Removing background..."]}):e==="de"?"Hintergrund entfernen":"Remove background",!m&&o.jsx("span",{className:"badge badge-sm badge-outline",children:"API"})]})]})}),v&&o.jsxs("div",{className:"alert alert-warning text-sm py-2",children:[o.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:o.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"})}),o.jsx("span",{children:v})]})]}):o.jsxs("div",{className:`border-2 border-dashed rounded-lg p-8 text-center cursor-pointer transition-colors ${h?"border-primary bg-primary/10 pointer-events-none":R?"border-primary bg-primary/10":"border-base-300 hover:border-primary hover:bg-base-200"}`,onDrop:A,onDragOver:F,onDragLeave:te,onClick:le,children:[o.jsx("input",{ref:k,type:"file",accept:"image/*",className:"hidden",onChange:ce}),h?o.jsxs("div",{className:"flex flex-col items-center gap-2",children:[o.jsx("span",{className:"loading loading-spinner loading-lg text-primary"}),o.jsx("p",{className:"font-medium",children:e==="de"?"Hintergrund wird entfernt...":"Removing background..."})]}):o.jsxs("div",{className:"flex flex-col items-center gap-2",children:[o.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:o.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"})}),o.jsx("p",{className:"font-medium",children:H.form.portrait.upload}),o.jsx("p",{className:"text-sm text-base-content/60",children:H.form.portrait.dragDrop})]})]}),o.jsx(qe,{isOpen:U,onClose:()=>N(!1),onSubmit:he})]})}function zt(){const e=b(a=>a.voucherConfig.language),t=b(a=>a.voucherConfig.templateHue),n=b(a=>a.setTemplateHue),r=K(e);return o.jsx("div",{className:"space-y-4",children:o.jsxs("div",{className:"form-control",children:[o.jsx("label",{className:"label",children:o.jsx("span",{className:"label-text font-medium",children:r.form.billColor.label})}),o.jsx("input",{type:"range",min:"0",max:"360",value:t,onChange:a=>n(Number(a.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,
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=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 Ne={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},b=bt.create()(xt.persist(e=>({...Ne,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}),setLanguage: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(Ne)}),{name:"money-generator-storage",partialize:e=>({personalInfo:e.personalInfo,voucherConfig:e.voucherConfig,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?"},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?"},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 K(e){return kt[e]}function Se(e,t,n){if(n&&n.trim())return n;const r=K(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=b(a=>a.voucherConfig.language),t=b(a=>a.personalInfo),n=b(a=>a.setPersonalInfo),r=K(e);return o.jsxs("div",{className:"space-y-4",children:[o.jsxs("div",{className:"form-control",children:[o.jsx("label",{className:"label",children:o.jsx("span",{className:"label-text font-medium",children:r.form.personalInfo.name})}),o.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})})]}),o.jsxs("div",{className:"form-control",children:[o.jsx("label",{className:"label",children:o.jsx("span",{className:"label-text font-medium",children:r.form.personalInfo.email})}),o.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})})]}),o.jsxs("div",{className:"form-control",children:[o.jsx("label",{className:"label",children:o.jsx("span",{className:"label-text font-medium",children:r.form.personalInfo.phone})}),o.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,De=null;function Te(e,t){return $||($=document.createElement("canvas"),De=$.getContext("2d",{willReadFrequently:!0})),($.width!==e||$.height!==t)&&($.width=e,$.height=t),De}function de(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 i=re.keys().next().value;i&&re.delete(i)}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 de(e),r=Math.max(n.width,n.height);if(r<=t)return e;const a=t/r,i=Math.round(n.width*a),s=Math.round(n.height*a),c=document.createElement("canvas"),d=c.getContext("2d");if(!d)throw new Error("Failed to get canvas context");return c.width=i,c.height=s,d.drawImage(n,0,0,i,s),c.toDataURL("image/jpeg",.9)}async function ye(e,t,n,r=0){const[a,i]=await Promise.all([de(e),de(t)]),s=Te(a.width,a.height);if(s.clearRect(0,0,a.width,a.height),n>0){const c=r*20;s.save(),s.globalAlpha=n,c>0&&(s.filter=`blur(${c}px)`),s.drawImage(i,0,0,a.width,a.height),s.restore()}return s.drawImage(a,0,0),$.toDataURL("image/png")}async function Ye(e,t=.5,n=40){const r=await de(e),a=Te(r.width,r.height);a.clearRect(0,0,r.width,r.height),a.drawImage(r,0,0);const i=a.getImageData(0,0,r.width,r.height),s=i.data,c=new Uint32Array(s.buffer),d=1+t*.8,u=1-t,y=n%360/360;for(let x=0;x<c.length;x++){const g=c[x],h=g&255,v=g>>8&255,m=g>>16&255,T=g>>24&255;if(T===0)continue;let k=(((77*h+150*v+29*m>>8)/255-.5)*d+.5)*255;k<0?k=0:k>255&&(k=255);const I=k/255,R=.12,[S,z,N]=_e(y,R,I),j=h*u+S*t|0,D=v*u+z*t|0,E=m*u+N*t|0;c[x]=T<<24|E<<16|D<<8|j}return a.putImageData(i,0,0),$.toDataURL("image/png")}function Tt(e,t,n){e/=255,t/=255,n/=255;const r=Math.max(e,t,n),a=Math.min(e,t,n),i=(r+a)/2;let s=0,c=0;if(r!==a){const d=r-a;switch(c=i>.5?d/(2-r-a):d/(r+a),r){case e:s=((t-n)/d+(t<n?6:0))/6;break;case t:s=((n-e)/d+2)/6;break;case n:s=((e-t)/d+4)/6;break}}return[s,c,i]}function _e(e,t,n){if(t===0){const s=Math.round(n*255);return[s,s,s]}const r=(s,c,d)=>(d<0&&(d+=1),d>1&&(d-=1),d<1/6?s+(c-s)*6*d:d<1/2?c:d<2/3?s+(c-s)*(2/3-d)*6:s),a=n<.5?n*(1+t):n+t-n*t,i=2*n-a;return[Math.round(r(i,a,e+1/3)*255),Math.round(r(i,a,e)*255),Math.round(r(i,a,e-1/3)*255)]}async function We(e,t){if(t>=155&&t<=165)return e;const n=await de(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),i=a.data,s=new Uint32Array(i.buffer),c=t%360/360,d=60/360,u=260/360,y=1e5,x=s.length;for(let g=0;g<x;g+=y){const h=Math.min(g+y,x);for(let v=g;v<h;v++){const m=s[v],T=m&255,H=m>>8&255,k=m>>16&255,I=m>>24&255;if(I===0)continue;const[R,S,z]=Tt(T,H,k);if(S<.06||R<d||R>u)continue;const N=c,[j,D,E]=_e(N,S,z);s[v]=I<<24|E<<16|D<<8|j}h<x&&await new Promise(v=>setTimeout(v,0))}return r.putImageData(a,0,0),$.toDataURL("image/png")}const Rt="https://api.stability.ai/v1/generation",jt="https://api.stability.ai/v2beta/stable-image/edit/remove-background",Xe="stability_api_key";let se=null;function Et(e){se=e}function Bt(){return se}function Ht(){return se!==null}const Lt={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"},Me=[{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 Nt(e,t){const n=e/t;let r=Me[0],a=1/0;for(const i of Me){const s=i.width/i.height,c=Math.abs(n-s);c<a&&(a=c,r=i)}return r}function Dt(e){return new Promise((t,n)=>{const r=new Image;r.onload=()=>{const a=Nt(r.width,r.height),i=document.createElement("canvas");i.width=a.width,i.height=a.height;const s=i.getContext("2d");if(!s){n(new Error("Failed to get canvas context"));return}const c=r.width/r.height,d=a.width/a.height;let u=0,y=0,x=r.width,g=r.height;c>d?(x=r.height*d,u=(r.width-x)/2):(g=r.width/d,y=(r.height-g)/2),s.drawImage(r,u,y,x,g,0,0,a.width,a.height),t(i.toDataURL("image/png"))},r.onerror=()=>n(new Error("Failed to load image")),r.src=e})}function $e(e){var s;const t=e.split(","),n=((s=t[0].match(/:(.*?);/))==null?void 0:s[1])||"image/png",r=atob(t[1]),a=r.length,i=new Uint8Array(a);for(let c=0;c<a;c++)i[c]=r.charCodeAt(c);return new Blob([i],{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(Xe):null}function Fe(e){localStorage.setItem(Xe,e)}function Pe(){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,i=await Dt(n),s=$e(i),c=new FormData;c.append("init_image",s,"portrait.png"),c.append("init_image_mode","IMAGE_STRENGTH"),c.append("image_strength",String(1-a)),c.append("text_prompts[0][text]",Lt[r]),c.append("text_prompts[0][weight]","1"),c.append("cfg_scale","7"),c.append("samples","1"),c.append("steps","30");const u=await fetch(`${Rt}/stable-diffusion-xl-1024-v1-0/image-to-image`,{method:"POST",headers:{Authorization:`Bearer ${t}`,Accept:"application/json"},body:c});if(!u.ok){const x=await u.text();throw console.error("Stability AI error:",x),u.status===401?new Error("Invalid API key"):u.status===402?new Error("Insufficient credits"):u.status===429?new Error("Rate limit exceeded. Please try again later."):new Error(`API error: ${u.status}`)}const y=await u.json();if(!y.artifacts||y.artifacts.length===0)throw new Error("No image generated");return`data:image/png;base64,${y.artifacts[0].base64}`}async function Oe(e){if(se){const s=await fetch(se,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({imageDataUrl:e})});if(!s.ok){const d=await s.json().catch(()=>({}));throw new Error(d.error||`API error: ${s.status}`)}return(await s.json()).imageDataUrl}const t=pe();if(!t)throw new Error("No Stability AI API key configured");const n=$e(e),r=new FormData;r.append("image",n,"image.png"),r.append("output_format","png");const a=await fetch(jt,{method:"POST",headers:{Authorization:`Bearer ${t}`,Accept:"image/*"},body:r});if(!a.ok){const s=await a.text();throw console.error("Stability AI remove background error:",s),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 i=await a.blob();return new Promise((s,c)=>{const d=new FileReader;d.onload=()=>s(d.result),d.onerror=()=>c(new Error("Failed to read result")),d.readAsDataURL(i)})}function At(){const[e,t]=p.useState(!1),[n,r]=p.useState(!1),[a,i]=p.useState(null),[s,c]=p.useState(()=>Pe());p.useEffect(()=>{c(Pe())},[]);const d=p.useCallback(()=>i(null),[]),u=p.useCallback(g=>{Fe(g),c(!0),i(null)},[]),y=p.useCallback(async(g,h=.5,v=40)=>{t(!0),i(null);try{return await Ye(g,h,v)}catch(m){const T=m instanceof Error?m.message:"Enhancement failed";throw i(T),m}finally{t(!1)}},[]),x=p.useCallback(async g=>{r(!0),i(null);try{return await Oe(g)}catch(h){const v=h instanceof Error?h.message:"Background removal failed";throw i(v),h}finally{r(!1)}},[]);return{enhance:y,removeBg:x,isEnhancing:e,isRemovingBg:n,error:a,hasKey:s,setApiKey:u,clearError:d}}function qe({isOpen:e,onClose:t,onSubmit:n}){const r=b(u=>u.voucherConfig.language),[a,i]=p.useState("");if(!e)return null;const s=u=>{u.preventDefault(),a.trim()&&(n(a.trim()),i(""),t())},d={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 o.jsxs("dialog",{className:"modal modal-open",children:[o.jsxs("div",{className:"modal-box",children:[o.jsx("h3",{className:"font-bold text-lg",children:d.title}),o.jsx("p",{className:"py-4 text-sm opacity-80",children:d.description}),o.jsxs("form",{onSubmit:s,children:[o.jsxs("div",{className:"form-control",children:[o.jsx("input",{type:"password",placeholder:d.placeholder,className:"input input-bordered w-full",value:a,onChange:u=>i(u.target.value),autoFocus:!0}),o.jsx("label",{className:"label",children:o.jsx("span",{className:"label-text-alt",children:d.hint})})]}),o.jsxs("div",{className:"modal-action",children:[o.jsx("button",{type:"button",className:"btn btn-ghost",onClick:t,children:d.cancel}),o.jsx("button",{type:"submit",className:"btn btn-primary",disabled:!a.trim(),children:d.submit})]})]})]}),o.jsx("form",{method:"dialog",className:"modal-backdrop",children:o.jsx("button",{onClick:t,children:"close"})})]})}function zt(){const e=b(l=>l.voucherConfig.language),t=b(l=>l.portrait),n=b(l=>l.setPortrait),r=b(l=>l.setPortraitZoom),a=b(l=>l.setPortraitPan),i=b(l=>l.setPortraitRawImage),s=b(l=>l.setPortraitBgRemoved),c=b(l=>l.setPortraitBgOpacity),d=b(l=>l.setPortraitBgBlur),u=b(l=>l.setPortraitEngravingIntensity),{enhance:y,removeBg:x,isEnhancing:g,isRemovingBg:h,error:v,hasKey:m,setApiKey:T}=At(),H=K(e),k=p.useRef(null),I=p.useRef(null),[R,S]=p.useState(!1),[z,N]=p.useState(!1),[j,D]=p.useState(!1),E=p.useRef(null),L=p.useRef(null),M=p.useRef(null),B=t.rawImage,J=t.bgRemovedImage,U=t.bgRemoved,W=t.bgOpacity,F=t.bgBlur,Q=t.engravingIntensity;p.useEffect(()=>{t.original&&!t.rawImage&&i(t.original)},[t.original,t.rawImage,i]),p.useEffect(()=>()=>{L.current&&clearTimeout(L.current),M.current&&clearTimeout(M.current)},[]);const ee=b(l=>l.voucherConfig.templateHue),ue=p.useRef(ee),f=p.useCallback(async l=>{if(!l.type.startsWith("image/"))return;const w=new FileReader;w.onload=async C=>{var Y;const P=(Y=C.target)==null?void 0:Y.result,X=await St(P);i(X),n(X),s(!1,null),u(0)},w.readAsDataURL(l)},[n,i,s,u]),A=p.useCallback(l=>{l.preventDefault(),S(!1);const w=l.dataTransfer.files[0];w&&f(w)},[f]),O=p.useCallback(l=>{l.preventDefault(),S(!0)},[]),te=p.useCallback(l=>{l.preventDefault(),S(!1)},[]),le=()=>{var l;(l=k.current)==null||l.click()},ce=l=>{var C;const w=(C=l.target.files)==null?void 0:C[0];w&&f(w)},q=p.useCallback(async(l,w,C)=>{try{return await y(l,w,C)}catch(P){return console.error("Enhancement failed:",P),l}},[y]),ne=p.useCallback(async l=>{try{const w=await x(l);return s(!0,w),w}catch(w){return console.error("Background removal failed:",w),l}},[x,s]),G=p.useCallback(async()=>{const l=b.getState(),w=l.portrait,C=l.voucherConfig.templateHue;if(!w.rawImage)return;let P;w.bgRemoved&&w.bgRemovedImage?P=await ye(w.bgRemovedImage,w.rawImage,w.bgOpacity,w.bgBlur):P=w.rawImage,w.engravingIntensity>0&&(P=await q(P,w.engravingIntensity,C)),n(P)},[q,n]);p.useEffect(()=>{if(ue.current===ee)return;ue.current=ee;const l=b.getState().portrait;l.engravingIntensity>0&&l.rawImage&&(L.current&&clearTimeout(L.current),L.current=setTimeout(G,150))},[ee,G]);const be=async()=>{if(!B)return;if(!U&&!m){N(!0);return}if(!U){const w=await ne(B),C=b.getState(),P=C.portrait,X=C.voucherConfig.templateHue;let Y=await ye(w,B,P.bgOpacity,P.bgBlur);P.engravingIntensity>0&&(Y=await q(Y,P.engravingIntensity,X)),n(Y)}else{s(!1,null);const w=b.getState(),C=w.portrait.engravingIntensity,P=w.voucherConfig.templateHue;if(C>0){const X=await q(B,C,P);n(X)}else n(B)}},xe=l=>{u(l),L.current&&clearTimeout(L.current),B&&(L.current=setTimeout(G,150))},he=async l=>{if(T(l),!B)return;const w=await ne(B),C=b.getState(),P=C.portrait,X=C.voucherConfig.templateHue;let Y=await ye(w,B,P.bgOpacity,P.bgBlur);P.engravingIntensity>0&&(Y=await q(Y,P.engravingIntensity,X)),n(Y)},me=l=>{c(l),M.current&&clearTimeout(M.current),!(!B||!J)&&(M.current=setTimeout(G,150))},it=l=>{d(l),M.current&&clearTimeout(M.current),!(!B||!J)&&(M.current=setTimeout(G,150))},st=()=>{n(null),i(null),s(!1,null),c(0),d(0),u(0),Ct()},He=(l,w)=>{t.zoom<=1||(D(!0),E.current={x:l,y:w,panX:t.panX,panY:t.panY})},Le=(l,w)=>{if(!j||!E.current||!I.current)return;const C=I.current.getBoundingClientRect(),P=2/Math.max(C.width,C.height),X=(l-E.current.x)*P,Y=(w-E.current.y)*P,pt=Math.max(-1,Math.min(1,E.current.panX+X)),ft=Math.max(-1,Math.min(1,E.current.panY+Y));a(pt,ft)},we=()=>{D(!1),E.current=null},lt=l=>{l.preventDefault(),He(l.clientX,l.clientY)},ct=l=>{Le(l.clientX,l.clientY)},dt=()=>{we()},ut=()=>{we()},ht=l=>{l.touches.length===1&&He(l.touches[0].clientX,l.touches[0].clientY)},mt=l=>{l.touches.length===1&&Le(l.touches[0].clientX,l.touches[0].clientY)},gt=()=>{we()};return o.jsxs("div",{className:"space-y-4",children:[t.original?o.jsxs("div",{className:"flex flex-col items-center space-y-4",children:[o.jsxs("div",{className:"relative",children:[o.jsx("div",{ref:I,className:`w-32 h-32 rounded-full overflow-hidden border-4 border-currency-gold shadow-lg ${t.zoom>1?"cursor-grab":""} ${j?"cursor-grabbing":""}`,onMouseDown:lt,onMouseMove:ct,onMouseUp:dt,onMouseLeave:ut,onTouchStart:ht,onTouchMove:mt,onTouchEnd:gt,children:o.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})}),o.jsx("button",{className:"btn btn-circle btn-xs btn-error absolute -top-1 -right-1",onClick:st,children:o.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-4 w-4",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:o.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M6 18L18 6M6 6l12 12"})})})]}),o.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-4 w-full",children:[o.jsxs("div",{className:"form-control w-full",children:[o.jsxs("label",{className:"label",children:[o.jsx("span",{className:"label-text",children:H.form.portrait.zoom}),o.jsxs("span",{className:"label-text-alt",children:[Math.round(t.zoom*100),"%"]})]}),o.jsx("input",{type:"range",min:"0.5",max:"2",step:"0.05",value:t.zoom,onChange:l=>{const w=parseFloat(l.target.value);r(w),w<=1&&(t.panX!==0||t.panY!==0)&&a(0,0)},className:"range range-primary range-sm"})]}),o.jsxs("div",{className:"form-control w-full",children:[o.jsxs("label",{className:"label",children:[o.jsxs("span",{className:"label-text flex items-center gap-2",children:[e==="de"?"Farbanpassung":"Color adjustment",g&&o.jsx("span",{className:"loading loading-spinner loading-xs"})]}),o.jsxs("span",{className:"label-text-alt",children:[Math.round(Q*100),"%"]})]}),o.jsx("input",{type:"range",min:"0",max:"1",step:"0.05",value:Q,onChange:l=>xe(parseFloat(l.target.value)),className:"range range-secondary range-sm",disabled:g||!B})]})]}),U?o.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-4 w-full",children:[o.jsxs("div",{className:"form-control w-full",children:[o.jsxs("label",{className:"label",children:[o.jsx("span",{className:"label-text",children:e==="de"?"Hintergrund":"Background"}),o.jsxs("span",{className:"label-text-alt",children:[Math.round(W*100),"%"]})]}),o.jsx("input",{type:"range",min:"0",max:"1",step:"0.05",value:W,onChange:l=>me(parseFloat(l.target.value)),className:"range range-primary range-sm"})]}),o.jsxs("div",{className:"form-control w-full",children:[o.jsxs("label",{className:"label",children:[o.jsx("span",{className:"label-text",children:e==="de"?"Unschärfe":"Blur"}),o.jsxs("span",{className:"label-text-alt",children:[Math.round(F*100),"%"]})]}),o.jsx("input",{type:"range",min:"0",max:"1",step:"0.05",value:F,onChange:l=>it(parseFloat(l.target.value)),className:"range range-primary range-sm"})]})]}):o.jsx("div",{className:"form-control",children:o.jsxs("label",{className:"label cursor-pointer justify-start gap-3",children:[o.jsx("input",{type:"checkbox",className:`toggle toggle-primary ${h?"opacity-50":""}`,checked:U,onChange:be,disabled:h||!B}),o.jsxs("span",{className:"label-text flex items-center gap-2",children:[h?o.jsxs(o.Fragment,{children:[o.jsx("span",{className:"loading loading-spinner loading-xs"}),e==="de"?"Hintergrund wird entfernt...":"Removing background..."]}):e==="de"?"Hintergrund entfernen":"Remove background",!m&&o.jsx("span",{className:"badge badge-sm badge-outline",children:"API"})]})]})}),v&&o.jsxs("div",{className:"alert alert-warning text-sm py-2",children:[o.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:o.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"})}),o.jsx("span",{children:v})]})]}):o.jsxs("div",{className:`border-2 border-dashed rounded-lg p-8 text-center cursor-pointer transition-colors ${h?"border-primary bg-primary/10 pointer-events-none":R?"border-primary bg-primary/10":"border-base-300 hover:border-primary hover:bg-base-200"}`,onDrop:A,onDragOver:O,onDragLeave:te,onClick:le,children:[o.jsx("input",{ref:k,type:"file",accept:"image/*",className:"hidden",onChange:ce}),h?o.jsxs("div",{className:"flex flex-col items-center gap-2",children:[o.jsx("span",{className:"loading loading-spinner loading-lg text-primary"}),o.jsx("p",{className:"font-medium",children:e==="de"?"Hintergrund wird entfernt...":"Removing background..."})]}):o.jsxs("div",{className:"flex flex-col items-center gap-2",children:[o.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:o.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"})}),o.jsx("p",{className:"font-medium",children:H.form.portrait.upload}),o.jsx("p",{className:"text-sm text-base-content/60",children:H.form.portrait.dragDrop})]})]}),o.jsx(qe,{isOpen:z,onClose:()=>N(!1),onSubmit:he})]})}function Ut(){const e=b(a=>a.voucherConfig.language),t=b(a=>a.voucherConfig.templateHue),n=b(a=>a.setTemplateHue),r=K(e);return o.jsx("div",{className:"space-y-4",children:o.jsxs("div",{className:"form-control",children:[o.jsx("label",{className:"label",children:o.jsx("span",{className:"label-text font-medium",children:r.form.billColor.label})}),o.jsx("input",{type:"range",min:"0",max:"360",value:t,onChange:a=>n(Number(a.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
2
  hsl(0, 70%, 50%),
3
3
  hsl(60, 70%, 50%),
4
4
  hsl(120, 70%, 50%),
5
5
  hsl(180, 70%, 50%),
6
6
  hsl(240, 70%, 50%),
7
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"&&"/"||"/",Re={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,lineY:950,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:144,maxWidth:1520,align:"center"},contactInfo:{x:1520,y:1680,fontSize:160,lineHeight:280,align:"center"},description:{x:4600,y:1680,fontSize:145,maxWidth:2e3,lineHeight:210,align:"center"},signature:{x:4600,y:2850,width:1200,height:240,lineY:2700,labelFontSize:64}}};function je(e){return e==="de"?Z:V}function Ke(e,t){return Re[e][t]}const Ce=.25;function Yt(e){const t=je(e),n=Ce,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});return{front:r(t.front),back:r(t.back)}}function _t(e,t){const n=Re[e][t];return{...n,width:Math.round(n.width*Ce),height:Math.round(n.height*Ce)}}const ve=new Map,ae=new Map;async function oe(e){return ve.has(e)?ve.get(e):new Promise((t,n)=>{const r=new Image;r.crossOrigin="anonymous",r.onload=()=>{ve.set(e,r),t(r)},r.onerror=n,r.src=e})}function Ee(e,t,n,r){e.drawImage(t,0,0,n,r)}async function Ge(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 i=await oe(e),s=document.createElement("canvas");s.width=n,s.height=r;const c=s.getContext("2d");if(!c)throw new Error("Failed to get canvas context");c.drawImage(i,0,0,n,r);const d=s.toDataURL("image/png"),u=await We(d,t);if(ae.size>20){const y=ae.keys().next().value;y&&ae.delete(y)}return ae.set(a,u),oe(u)}function Ve(e,t,n,r,a,i,s=1,c=0,d=0){e.save(),e.beginPath(),e.ellipse(n,r,a,i,0,0,Math.PI*2),e.closePath(),e.clip();const u=t.width/t.height,y=a/i,x=a*2,g=i*2;let h,v;u>y?(v=g,h=g*u):(h=x,v=x/u),h*=s,v*=s;const m=Math.max(0,(h-x)/2),T=Math.max(0,(v-g)/2),H=n-h/2+c*m,k=r-v/2+d*T;e.drawImage(t,H,k,h,v),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 Ze(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,i=n.lineHeight||n.fontSize*1.4,s=t.split(" "),c=[];let d="";for(const x of s){const g=d?`${d} ${x}`:x;e.measureText(g).width>a&&d?(c.push(d),d=x):d=g}d&&c.push(d);const u=c.length*i;let y=n.y-u/2;for(const x of c)e.fillText(x,n.x,y),y+=i;e.restore()}function Je(e,t,n,r,a,i="#2a3a2a"){e.save(),e.font=`${a.fontSize}px "Times New Roman", serif`,e.textAlign=a.align||"center",e.textBaseline="middle",e.fillStyle=i;const s=a.lineHeight||a.fontSize*1.8,c=[t,n,r].filter(Boolean),d=(c.length-1)*s;let u=a.y-d/2;for(const y of c)y&&(e.fillText(y,a.x,u),u+=s);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.lineY),e.lineTo(t.x+t.width/2,t.lineY),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.lineY+t.labelFontSize*.3),e.restore()}async function Qe(e,t,n,r,a,i,s,c=1,d=0,u=0,y=0){const x=e.getContext("2d");if(!x)return;const g=document.createElement("canvas");g.width=i,g.height=s;const h=g.getContext("2d");if(!h)return;h.clearRect(0,0,i,s);const v=await Ge(t,y,i,s);if(Ee(h,v,i,s),n)try{const m=await oe(n);Ve(h,m,a.portrait.x,a.portrait.y,a.portrait.radiusX,a.portrait.radiusY,c,d,u)}catch(m){console.error("Failed to load portrait:",m)}r&&Be(h,r,a.namePlate),e.width=i,e.height=s,x.drawImage(g,0,0)}async function et(e,t,n,r,a,i,s,c,d,u=0,y="de"){const x=e.getContext("2d");if(!x)return;const g=document.createElement("canvas");g.width=c,g.height=d;const h=g.getContext("2d");if(!h)return;h.clearRect(0,0,c,d);const v=await Ge(t,u,c,d);if(Ee(h,v,c,d),s.contactInfo&&(n||r||a)&&Je(h,n,r,a,s.contactInfo),s.description&&i&&Ze(h,i,s.description),n&&Be(h,n,s.namePlate),s.signature){const m=y==="de"?"Unterschrift":"Signature";Wt(h,s.signature,m)}e.width=c,e.height=d,x.drawImage(g,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=b(f=>f.voucherConfig.language),t=b(f=>f.voucherConfig.hours),n=b(f=>f.voucherConfig.description),r=b(f=>f.voucherConfig.templateHue),a=b(f=>f.personalInfo),i=b(f=>f.portrait),s=b(f=>f.currentSide),c=b(f=>f.flipSide),d=b(f=>f.setPortraitPan),u=Xt(r,150),y=K(e),x=p.useRef(null),g=p.useRef(null),h=p.useRef(null),[v,m]=p.useState(!1),[T,H]=p.useState(!1),k=p.useRef(null),I=_t(e,t),R=Yt(e),S=i.useEnhanced&&i.enhanced?i.enhanced:i.original,U=Se(e,t,n);p.useEffect(()=>{x.current&&Qe(x.current,I.front,S,a.name,R.front,I.width,I.height,i.zoom,i.panX,i.panY,u)},[I,S,a.name,R,i.zoom,i.panX,i.panY,u]),p.useEffect(()=>{g.current&&et(g.current,I.back,a.name,a.email,a.phone,U,R.back,I.width,I.height,u,e)},[I,a,U,R,u,e]);const N=()=>{m(!0),setTimeout(()=>{c(),m(!1)},150)},j=p.useCallback((f,A)=>{if(!h.current||s!=="front"||!i.original)return!1;const F=h.current.getBoundingClientRect(),te=F.width/I.width,le=F.height/I.height,ce=(f-F.left)/te,q=(A-F.top)/le,{x:ne,y:G,radiusX:be,radiusY:xe}=R.front.portrait,he=(ce-ne)/be,me=(q-G)/xe;return he*he+me*me<=1},[s,i.original,I.width,I.height,R.front.portrait]),D=p.useCallback((f,A)=>{i.zoom<=1||!j(f,A)||(H(!0),k.current={x:f,y:A,panX:i.panX,panY:i.panY})},[i.zoom,i.panX,i.panY,j]),E=p.useCallback((f,A)=>{if(!T||!k.current||!h.current)return;const F=h.current.getBoundingClientRect(),te=3/Math.max(F.width,F.height),le=(f-k.current.x)*te,ce=(A-k.current.y)*te,q=Math.max(-1,Math.min(1,k.current.panX+le)),ne=Math.max(-1,Math.min(1,k.current.panY+ce));d(q,ne)},[T,d]),L=p.useCallback(()=>{H(!1),k.current=null},[]),M=f=>{i.zoom>1&&j(f.clientX,f.clientY)&&(f.preventDefault(),D(f.clientX,f.clientY))},B=f=>{E(f.clientX,f.clientY)},J=()=>L(),z=()=>L(),W=f=>{if(f.touches.length===1){const A=f.touches[0];i.zoom>1&&j(A.clientX,A.clientY)&&D(A.clientX,A.clientY)}},O=f=>{f.touches.length===1&&E(f.touches[0].clientX,f.touches[0].clientY)},Q=()=>L(),ee=s==="front"&&i.original&&i.zoom>1,ue=I.width/I.height;return o.jsxs("div",{className:"space-y-4",children:[o.jsxs("div",{className:"flex justify-between items-center",children:[o.jsxs("div",{className:"tabs tabs-boxed bg-base-200",children:[o.jsx("button",{className:`tab ${s==="front"?"tab-active bg-primary text-primary-content font-semibold":""}`,onClick:()=>s!=="front"&&N(),children:y.preview.front}),o.jsx("button",{className:`tab ${s==="back"?"tab-active bg-primary text-primary-content font-semibold":""}`,onClick:()=>s!=="back"&&N(),children:y.preview.back})]}),o.jsxs("button",{className:"btn btn-ghost btn-sm",onClick:N,children:[o.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-5 w-5",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:o.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"})}),y.preview.flip]})]}),o.jsxs("div",{ref:h,className:`relative w-full overflow-hidden shadow-lg ${ee?T?"cursor-grabbing":"cursor-grab":""}`,style:{aspectRatio:ue},onMouseDown:M,onMouseMove:B,onMouseUp:J,onMouseLeave:z,onTouchStart:W,onTouchMove:O,onTouchEnd:Q,children:[o.jsx("canvas",{ref:x,className:`absolute inset-0 w-full h-full transition-all duration-300 ${s==="front"?v?"opacity-0 scale-95":"opacity-100 scale-100":"opacity-0 scale-95 pointer-events-none"}`}),o.jsx("canvas",{ref:g,className:`absolute inset-0 w-full h-full transition-all duration-300 ${s==="back"?v?"opacity-0 scale-95":"opacity-100 scale-100":"opacity-0 scale-95 pointer-events-none"}`})]})]})}function Ot(){const e=p.useRef(null),t=p.useRef(null);return{frontCanvasRef:e,backCanvasRef:t}}const Ft=`
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"&&"/"||"/",Re={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 je(e){return e==="de"?Z:V}function Ke(e,t){return Re[e][t]}const Ce=.25;function Yt(e){const t=je(e),n=Ce,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=Re[e][t];return{...n,width:Math.round(n.width*Ce),height:Math.round(n.height*Ce)}}const ve=new Map,ae=new Map;async function oe(e){return ve.has(e)?ve.get(e):new Promise((t,n)=>{const r=new Image;r.crossOrigin="anonymous",r.onload=()=>{ve.set(e,r),t(r)},r.onerror=n,r.src=e})}function Ee(e,t,n,r){e.drawImage(t,0,0,n,r)}async function Ge(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 i=await oe(e),s=document.createElement("canvas");s.width=n,s.height=r;const c=s.getContext("2d");if(!c)throw new Error("Failed to get canvas context");c.drawImage(i,0,0,n,r);const d=s.toDataURL("image/png"),u=await We(d,t);if(ae.size>20){const y=ae.keys().next().value;y&&ae.delete(y)}return ae.set(a,u),oe(u)}function Ve(e,t,n,r,a,i,s=1,c=0,d=0){e.save(),e.beginPath(),e.ellipse(n,r,a,i,0,0,Math.PI*2),e.closePath(),e.clip();const u=t.width/t.height,y=a/i,x=a*2,g=i*2;let h,v;u>y?(v=g,h=g*u):(h=x,v=x/u),h*=s,v*=s;const m=Math.max(0,(h-x)/2),T=Math.max(0,(v-g)/2),H=n-h/2+c*m,k=r-v/2+d*T;e.drawImage(t,H,k,h,v),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 Ze(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,i=n.lineHeight||n.fontSize*1.4,s=t.split(" "),c=[];let d="";for(const x of s){const g=d?`${d} ${x}`:x;e.measureText(g).width>a&&d?(c.push(d),d=x):d=g}d&&c.push(d);const u=c.length*i;let y=n.y-u/2;for(const x of c)e.fillText(x,n.x,y),y+=i;e.restore()}function Je(e,t,n,r,a,i="#2a3a2a"){e.save(),e.font=`${a.fontSize}px "Times New Roman", serif`,e.textAlign=a.align||"center",e.textBaseline="middle",e.fillStyle=i;const s=a.lineHeight||a.fontSize*1.8,c=[t,n,r].filter(Boolean),d=(c.length-1)*s;let u=a.y-d/2;for(const y of c)y&&(e.fillText(y,a.x,u),u+=s);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 Qe(e,t,n,r,a,i,s,c=1,d=0,u=0,y=0){const x=e.getContext("2d");if(!x)return;const g=document.createElement("canvas");g.width=i,g.height=s;const h=g.getContext("2d");if(!h)return;h.clearRect(0,0,i,s);const v=await Ge(t,y,i,s);if(Ee(h,v,i,s),n)try{const m=await oe(n);Ve(h,m,a.portrait.x,a.portrait.y,a.portrait.radiusX,a.portrait.radiusY,c,d,u)}catch(m){console.error("Failed to load portrait:",m)}r&&Be(h,r,a.namePlate),e.width=i,e.height=s,x.drawImage(g,0,0)}async function et(e,t,n,r,a,i,s,c,d,u=0,y="de"){const x=e.getContext("2d");if(!x)return;const g=document.createElement("canvas");g.width=c,g.height=d;const h=g.getContext("2d");if(!h)return;h.clearRect(0,0,c,d);const v=await Ge(t,u,c,d);if(Ee(h,v,c,d),s.contactInfo&&(n||r||a)&&Je(h,n,r,a,s.contactInfo),s.description&&i&&Ze(h,i,s.description),n&&Be(h,n,s.namePlate),s.signature){const m=y==="de"?"Unterschrift":"Signature";Wt(h,s.signature,m)}e.width=c,e.height=d,x.drawImage(g,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=b(f=>f.voucherConfig.language),t=b(f=>f.voucherConfig.hours),n=b(f=>f.voucherConfig.description),r=b(f=>f.voucherConfig.templateHue),a=b(f=>f.personalInfo),i=b(f=>f.portrait),s=b(f=>f.currentSide),c=b(f=>f.flipSide),d=b(f=>f.setPortraitPan),u=Xt(r,150),y=K(e),x=p.useRef(null),g=p.useRef(null),h=p.useRef(null),[v,m]=p.useState(!1),[T,H]=p.useState(!1),k=p.useRef(null),I=_t(e,t),R=Yt(e),S=i.useEnhanced&&i.enhanced?i.enhanced:i.original,z=Se(e,t,n);p.useEffect(()=>{x.current&&Qe(x.current,I.front,S,a.name,R.front,I.width,I.height,i.zoom,i.panX,i.panY,u)},[I,S,a.name,R,i.zoom,i.panX,i.panY,u]),p.useEffect(()=>{g.current&&et(g.current,I.back,a.name,a.email,a.phone,z,R.back,I.width,I.height,u,e)},[I,a,z,R,u,e]);const N=()=>{m(!0),setTimeout(()=>{c(),m(!1)},150)},j=p.useCallback((f,A)=>{if(!h.current||s!=="front"||!i.original)return!1;const O=h.current.getBoundingClientRect(),te=O.width/I.width,le=O.height/I.height,ce=(f-O.left)/te,q=(A-O.top)/le,{x:ne,y:G,radiusX:be,radiusY:xe}=R.front.portrait,he=(ce-ne)/be,me=(q-G)/xe;return he*he+me*me<=1},[s,i.original,I.width,I.height,R.front.portrait]),D=p.useCallback((f,A)=>{i.zoom<=1||!j(f,A)||(H(!0),k.current={x:f,y:A,panX:i.panX,panY:i.panY})},[i.zoom,i.panX,i.panY,j]),E=p.useCallback((f,A)=>{if(!T||!k.current||!h.current)return;const O=h.current.getBoundingClientRect(),te=3/Math.max(O.width,O.height),le=(f-k.current.x)*te,ce=(A-k.current.y)*te,q=Math.max(-1,Math.min(1,k.current.panX+le)),ne=Math.max(-1,Math.min(1,k.current.panY+ce));d(q,ne)},[T,d]),L=p.useCallback(()=>{H(!1),k.current=null},[]),M=f=>{i.zoom>1&&j(f.clientX,f.clientY)&&(f.preventDefault(),D(f.clientX,f.clientY))},B=f=>{E(f.clientX,f.clientY)},J=()=>L(),U=()=>L(),W=f=>{if(f.touches.length===1){const A=f.touches[0];i.zoom>1&&j(A.clientX,A.clientY)&&D(A.clientX,A.clientY)}},F=f=>{f.touches.length===1&&E(f.touches[0].clientX,f.touches[0].clientY)},Q=()=>L(),ee=s==="front"&&i.original&&i.zoom>1,ue=I.width/I.height;return o.jsxs("div",{className:"space-y-4",children:[o.jsxs("div",{className:"flex justify-between items-center",children:[o.jsxs("div",{className:"tabs tabs-boxed bg-base-200",children:[o.jsx("button",{className:`tab ${s==="front"?"tab-active bg-primary text-primary-content font-semibold":""}`,onClick:()=>s!=="front"&&N(),children:y.preview.front}),o.jsx("button",{className:`tab ${s==="back"?"tab-active bg-primary text-primary-content font-semibold":""}`,onClick:()=>s!=="back"&&N(),children:y.preview.back})]}),o.jsxs("button",{className:"btn btn-ghost btn-sm",onClick:N,children:[o.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-5 w-5",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:o.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"})}),y.preview.flip]})]}),o.jsxs("div",{ref:h,className:`relative w-full overflow-hidden shadow-lg ${ee?T?"cursor-grabbing":"cursor-grab":""}`,style:{aspectRatio:ue},onMouseDown:M,onMouseMove:B,onMouseUp:J,onMouseLeave:U,onTouchStart:W,onTouchMove:F,onTouchEnd:Q,children:[o.jsx("canvas",{ref:x,className:`absolute inset-0 w-full h-full transition-all duration-300 ${s==="front"?v?"opacity-0 scale-95":"opacity-100 scale-100":"opacity-0 scale-95 pointer-events-none"}`}),o.jsx("canvas",{ref:g,className:`absolute inset-0 w-full h-full transition-all duration-300 ${s==="back"?v?"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=`
9
9
  // RGB to HSL conversion
10
10
  function rgbToHsl(r, g, b) {
11
11
  r /= 255;
@@ -222,6 +222,7 @@ self.onmessage = async (e) => {
222
222
  email,
223
223
  phone,
224
224
  description,
225
+ language,
225
226
  } = e.data;
226
227
 
227
228
  try {
@@ -337,12 +338,12 @@ self.onmessage = async (e) => {
337
338
  const sig = layout.back.signature;
338
339
  const signatureLabel = language === 'de' ? 'Unterschrift' : 'Signature';
339
340
 
340
- // Draw signature line
341
+ // Draw signature line at (x, y)
341
342
  backCtx.strokeStyle = '#2a3a2a';
342
343
  backCtx.lineWidth = Math.max(2, sig.labelFontSize / 16);
343
344
  backCtx.beginPath();
344
- backCtx.moveTo(sig.x - sig.width / 2, sig.lineY);
345
- backCtx.lineTo(sig.x + sig.width / 2, sig.lineY);
345
+ backCtx.moveTo(sig.x - sig.width / 2, sig.y);
346
+ backCtx.lineTo(sig.x + sig.width / 2, sig.y);
346
347
  backCtx.stroke();
347
348
 
348
349
  // Draw label below line
@@ -350,7 +351,7 @@ self.onmessage = async (e) => {
350
351
  backCtx.textAlign = 'center';
351
352
  backCtx.textBaseline = 'top';
352
353
  backCtx.fillStyle = '#2a3a2a';
353
- backCtx.fillText(signatureLabel, sig.x, sig.lineY + sig.labelFontSize * 0.3);
354
+ backCtx.fillText(signatureLabel, sig.x, sig.y + sig.labelFontSize * 0.3);
354
355
  }
355
356
 
356
357
  // Convert canvases to blobs and then to ArrayBuffer for transfer
@@ -379,4 +380,4 @@ self.onmessage = async (e) => {
379
380
  });
380
381
  }
381
382
  };
382
- `;let ke=null,Ae=null;function qt(){if(!ke){const e=new Blob([Ft],{type:"application/javascript"});Ae=URL.createObjectURL(e),ke=new Worker(Ae,{type:"module"})}return ke}async function Ie(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 tt(e){const{frontTemplateSrc:t,backTemplateSrc:n,templateWidth:r,templateHeight:a,layout:i,portrait:s,portraitZoom:c=1,portraitPanX:d=0,portraitPanY:u=0,templateHue:y=160,name:x,email:g,phone:h,description:v,language:m="de"}=e,[T,H]=await Promise.all([Ie(t),Ie(n)]);let k=null;return s&&(k=await Ie(s)),new Promise((I,R)=>{const S=qt(),U=j=>{if(S.removeEventListener("message",U),S.removeEventListener("error",N),URL.revokeObjectURL(T),URL.revokeObjectURL(H),k&&URL.revokeObjectURL(k),j.data.type==="success")try{const{frontImageData:D,backImageData:E,width:L,height:M}=j.data;if(!D||!E||!L||!M){R(new Error("Invalid response from worker"));return}const B=Ue(D,"image/jpeg"),J=Ue(E,"image/jpeg"),z=L/96*25.4,W=M/96*25.4,O=new wt.jsPDF({orientation:z>W?"landscape":"portrait",unit:"mm",format:[z,W]});O.addImage(B,"JPEG",0,0,z,W),O.addPage([z,W]),O.addImage(J,"JPEG",0,0,z,W);const Q=O.output("blob");I(Q)}catch(D){R(D)}else R(new Error(j.data.error))},N=j=>{S.removeEventListener("message",U),S.removeEventListener("error",N),URL.revokeObjectURL(T),URL.revokeObjectURL(H),k&&URL.revokeObjectURL(k),R(new Error(j.message))};S.addEventListener("message",U),S.addEventListener("error",N),S.postMessage({type:"generate",frontTemplateUrl:T,backTemplateUrl:H,portraitUrl:k,templateWidth:r,templateHeight:a,templateHue:y,portraitZoom:c,portraitPanX:d,portraitPanY:u,layout:{front:{portrait:i.front.portrait,namePlate:i.front.namePlate},back:{namePlate:i.back.namePlate,contactInfo:i.back.contactInfo,description:i.back.description,signature:i.back.signature}},name:x,email:g,phone:h,description:v,language:m})})}function nt(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 at(e){const t=await tt(e);nt(t,e.filename)}function Kt(){const e=b(m=>m.voucherConfig.language),t=b(m=>m.voucherConfig.hours),n=b(m=>m.voucherConfig.description),r=b(m=>m.voucherConfig.templateHue),a=b(m=>m.personalInfo),i=b(m=>m.portrait),s=b(m=>m.isExporting),c=b(m=>m.setIsExporting),d=K(e),u=Ke(e,t),y=je(e),x=i.useEnhanced&&i.enhanced?i.enhanced:i.original,g=Se(e,t,n),h=a.name.trim().length>0&&a.email.trim().length>0&&a.phone.trim().length>0&&i.original!==null,v=async()=>{if(!(!h||s)){c(!0);try{const m=`zeitgutschein-${t}h-${a.name.replace(/\s+/g,"-").toLowerCase()}.pdf`;await at({frontTemplateSrc:u.front,backTemplateSrc:u.back,templateWidth:u.width,templateHeight:u.height,layout:y,portrait:x,portraitZoom:i.zoom,portraitPanX:i.panX,portraitPanY:i.panY,templateHue:r,name:a.name,email:a.email,phone:a.phone,description:g,filename:m,language:e})}catch(m){console.error("PDF export failed:",m)}finally{c(!1)}}};return o.jsxs("button",{className:`btn btn-primary flex-1 ${h?"":"btn-disabled"}`,onClick:v,disabled:!h,"aria-busy":s,children:[s?o.jsx("span",{className:"loading loading-spinner loading-sm"}):o.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-5 w-5",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:o.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 rt(){const e=b(r=>r.voucherConfig.language),t=b(r=>r.setLanguage),n=r=>{t(r)};return o.jsxs("div",{className:"join",children:[o.jsx("button",{className:`join-item btn btn-sm ${e==="de"?"btn-active btn-primary":"btn-ghost"}`,onClick:()=>n("de"),children:"DE"}),o.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=b(n=>n.voucherConfig.language),t=K(e);return o.jsxs("div",{className:"navbar bg-currency-green text-currency-cream shadow-lg",children:[o.jsx("div",{className:"navbar-start",children:o.jsx("a",{className:"btn btn-ghost text-xl font-currency font-bold",children:t.header.title})}),o.jsx("div",{className:"navbar-center hidden sm:flex",children:o.jsx("span",{className:"text-sm opacity-80",children:t.header.subtitle})}),o.jsx("div",{className:"navbar-end",children:o.jsx(rt,{})})]})}const ge="/",Vt={id:"time-voucher-classic-de",name:"Zeitgutschein Classic",type:"time-voucher",category:"classic",images:{front:`${ge}templates/front_hdpi_de.jpg`,back:`${ge}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:`${ge}templates/front_ldpi_en.png`,back:`${ge}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"]},ze=[Vt,Zt],ot={async listTemplates(e){let t=[...ze];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=ze.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=ot;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=qe;exports.BillPreview=$t;exports.ExportButton=Kt;exports.Header=Gt;exports.LAYOUT_HDPI=Z;exports.LAYOUT_LDPI=V;exports.LanguageToggle=rt;exports.PersonalInfoForm=It;exports.PortraitUpload=Ut;exports.TEMPLATES=Re;exports.VoucherConfig=zt;exports.applyEngravingEffect=Ye;exports.applyHueShift=We;exports.downloadBlob=nt;exports.drawContactInfo=Je;exports.drawMultilineText=Ze;exports.drawOvalPortrait=Ve;exports.drawTemplate=Ee;exports.drawText=Be;exports.enhancePortrait=Mt;exports.exportBillAsPDF=at;exports.formatDescription=Se;exports.generateBillPDF=tt;exports.getApiKey=pe;exports.getDefaultTemplateId=Jt;exports.getLayout=je;exports.getRemoveBackgroundEndpoint=Bt;exports.getTemplate=Ke;exports.getTemplateById=nn;exports.getTemplateProvider=en;exports.hasApiKey=Pe;exports.hasCustomEndpoint=Ht;exports.listTemplates=tn;exports.loadImage=oe;exports.removeBackground=Fe;exports.renderBackSide=et;exports.renderFrontSide=Qe;exports.setApiKey=Oe;exports.setRemoveBackgroundEndpoint=Et;exports.setTemplateProvider=Qt;exports.staticTemplateProvider=ot;exports.t=K;exports.useBillCanvasRefs=Ot;exports.useBillStore=b;
383
+ `;let ke=null,Ae=null;function qt(){if(!ke){const e=new Blob([Ot],{type:"application/javascript"});Ae=URL.createObjectURL(e),ke=new Worker(Ae,{type:"module"})}return ke}async function Ie(e){const n=await(await fetch(e)).blob();return URL.createObjectURL(n)}function ze(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 tt(e){const{frontTemplateSrc:t,backTemplateSrc:n,templateWidth:r,templateHeight:a,layout:i,portrait:s,portraitZoom:c=1,portraitPanX:d=0,portraitPanY:u=0,templateHue:y=160,name:x,email:g,phone:h,description:v,language:m="de"}=e,[T,H]=await Promise.all([Ie(t),Ie(n)]);let k=null;return s&&(k=await Ie(s)),new Promise((I,R)=>{const S=qt(),z=j=>{if(S.removeEventListener("message",z),S.removeEventListener("error",N),URL.revokeObjectURL(T),URL.revokeObjectURL(H),k&&URL.revokeObjectURL(k),j.data.type==="success")try{const{frontImageData:D,backImageData:E,width:L,height:M}=j.data;if(!D||!E||!L||!M){R(new Error("Invalid response from worker"));return}const B=ze(D,"image/jpeg"),J=ze(E,"image/jpeg"),U=L/96*25.4,W=M/96*25.4,F=new wt.jsPDF({orientation:U>W?"landscape":"portrait",unit:"mm",format:[U,W]});F.addImage(B,"JPEG",0,0,U,W),F.addPage([U,W]),F.addImage(J,"JPEG",0,0,U,W);const Q=F.output("blob");I(Q)}catch(D){R(D)}else R(new Error(j.data.error))},N=j=>{S.removeEventListener("message",z),S.removeEventListener("error",N),URL.revokeObjectURL(T),URL.revokeObjectURL(H),k&&URL.revokeObjectURL(k),R(new Error(j.message))};S.addEventListener("message",z),S.addEventListener("error",N),S.postMessage({type:"generate",frontTemplateUrl:T,backTemplateUrl:H,portraitUrl:k,templateWidth:r,templateHeight:a,templateHue:y,portraitZoom:c,portraitPanX:d,portraitPanY:u,layout:{front:{portrait:i.front.portrait,namePlate:i.front.namePlate},back:{namePlate:i.back.namePlate,contactInfo:i.back.contactInfo,description:i.back.description,signature:i.back.signature}},name:x,email:g,phone:h,description:v,language:m})})}function nt(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 at(e){const t=await tt(e);nt(t,e.filename)}function Kt(){const e=b(m=>m.voucherConfig.language),t=b(m=>m.voucherConfig.hours),n=b(m=>m.voucherConfig.description),r=b(m=>m.voucherConfig.templateHue),a=b(m=>m.personalInfo),i=b(m=>m.portrait),s=b(m=>m.isExporting),c=b(m=>m.setIsExporting),d=K(e),u=Ke(e,t),y=je(e),x=i.useEnhanced&&i.enhanced?i.enhanced:i.original,g=Se(e,t,n),h=a.name.trim().length>0&&a.email.trim().length>0&&a.phone.trim().length>0&&i.original!==null,v=async()=>{if(!(!h||s)){c(!0);try{const m=`zeitgutschein-${t}h-${a.name.replace(/\s+/g,"-").toLowerCase()}.pdf`;await at({frontTemplateSrc:u.front,backTemplateSrc:u.back,templateWidth:u.width,templateHeight:u.height,layout:y,portrait:x,portraitZoom:i.zoom,portraitPanX:i.panX,portraitPanY:i.panY,templateHue:r,name:a.name,email:a.email,phone:a.phone,description:g,filename:m,language:e})}catch(m){console.error("PDF export failed:",m)}finally{c(!1)}}};return o.jsxs("button",{className:`btn btn-primary flex-1 ${h?"":"btn-disabled"}`,onClick:v,disabled:!h,"aria-busy":s,children:[s?o.jsx("span",{className:"loading loading-spinner loading-sm"}):o.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-5 w-5",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:o.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 rt(){const e=b(r=>r.voucherConfig.language),t=b(r=>r.setLanguage),n=r=>{t(r)};return o.jsxs("div",{className:"join",children:[o.jsx("button",{className:`join-item btn btn-sm ${e==="de"?"btn-active btn-primary":"btn-ghost"}`,onClick:()=>n("de"),children:"DE"}),o.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=b(n=>n.voucherConfig.language),t=K(e);return o.jsxs("div",{className:"navbar bg-currency-green text-currency-cream shadow-lg",children:[o.jsx("div",{className:"navbar-start",children:o.jsx("a",{className:"btn btn-ghost text-xl font-currency font-bold",children:t.header.title})}),o.jsx("div",{className:"navbar-center hidden sm:flex",children:o.jsx("span",{className:"text-sm opacity-80",children:t.header.subtitle})}),o.jsx("div",{className:"navbar-end",children:o.jsx(rt,{})})]})}const ge="/",Vt={id:"time-voucher-classic-de",name:"Zeitgutschein Classic",type:"time-voucher",category:"classic",images:{front:`${ge}templates/front_hdpi_de.jpg`,back:`${ge}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:`${ge}templates/front_ldpi_en.png`,back:`${ge}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"]},Ue=[Vt,Zt],ot={async listTemplates(e){let t=[...Ue];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=Ue.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=ot;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=qe;exports.BillPreview=$t;exports.ExportButton=Kt;exports.Header=Gt;exports.LAYOUT_HDPI=Z;exports.LAYOUT_LDPI=V;exports.LanguageToggle=rt;exports.PersonalInfoForm=It;exports.PortraitUpload=zt;exports.TEMPLATES=Re;exports.VoucherConfig=Ut;exports.applyEngravingEffect=Ye;exports.applyHueShift=We;exports.downloadBlob=nt;exports.drawContactInfo=Je;exports.drawMultilineText=Ze;exports.drawOvalPortrait=Ve;exports.drawTemplate=Ee;exports.drawText=Be;exports.enhancePortrait=Mt;exports.exportBillAsPDF=at;exports.formatDescription=Se;exports.generateBillPDF=tt;exports.getApiKey=pe;exports.getDefaultTemplateId=Jt;exports.getLayout=je;exports.getRemoveBackgroundEndpoint=Bt;exports.getTemplate=Ke;exports.getTemplateById=nn;exports.getTemplateProvider=en;exports.hasApiKey=Pe;exports.hasCustomEndpoint=Ht;exports.listTemplates=tn;exports.loadImage=oe;exports.removeBackground=Oe;exports.renderBackSide=et;exports.renderFrontSide=Qe;exports.setApiKey=Fe;exports.setRemoveBackgroundEndpoint=Et;exports.setTemplateProvider=Qt;exports.staticTemplateProvider=ot;exports.t=K;exports.useBillCanvasRefs=Ft;exports.useBillStore=b;
package/dist/index.d.ts CHANGED
@@ -262,7 +262,6 @@ export declare function setTemplateProvider(provider: TemplateProvider): void;
262
262
  export declare interface SignatureConfig extends CanvasPosition {
263
263
  width: number;
264
264
  height: number;
265
- lineY: number;
266
265
  labelFontSize: number;
267
266
  }
268
267
 
package/dist/index.js CHANGED
@@ -265,7 +265,7 @@ const Ne = {
265
265
  function Q(e) {
266
266
  return dt[e];
267
267
  }
268
- function Ye(e, t, n) {
268
+ function Ue(e, t, n) {
269
269
  if (n && n.trim())
270
270
  return n;
271
271
  const r = Q(e), a = t === 1 ? r.form.voucher.hourLabel : r.form.voucher.hoursLabel;
@@ -364,7 +364,7 @@ async function gt(e, t = 0.5, n = 40) {
364
364
  if (T === 0) continue;
365
365
  let k = (((77 * h + 150 * x + 29 * m >> 8) / 255 - 0.5) * c + 0.5) * 255;
366
366
  k < 0 ? k = 0 : k > 255 && (k = 255);
367
- const I = k / 255, E = 0.12, [S, U, M] = Ue(v, E, I), R = h * u + S * t | 0, A = x * u + U * t | 0, H = m * u + M * t | 0;
367
+ const I = k / 255, E = 0.12, [S, Y, M] = Ye(v, E, I), R = h * u + S * t | 0, A = x * u + Y * t | 0, H = m * u + M * t | 0;
368
368
  l[f] = T << 24 | H << 16 | A << 8 | R;
369
369
  }
370
370
  return a.putImageData(o, 0, 0), K.toDataURL("image/png");
@@ -389,7 +389,7 @@ function pt(e, t, n) {
389
389
  }
390
390
  return [i, l, o];
391
391
  }
392
- function Ue(e, t, n) {
392
+ function Ye(e, t, n) {
393
393
  if (t === 0) {
394
394
  const i = Math.round(n * 255);
395
395
  return [i, i, i];
@@ -412,9 +412,9 @@ async function ft(e, t) {
412
412
  for (let x = g; x < h; x++) {
413
413
  const m = i[x], T = m & 255, B = m >> 8 & 255, k = m >> 16 & 255, I = m >> 24 & 255;
414
414
  if (I === 0) continue;
415
- const [E, S, U] = pt(T, B, k);
415
+ const [E, S, Y] = pt(T, B, k);
416
416
  if (S < 0.06 || E < c || E > u) continue;
417
- const M = l, [R, A, H] = Ue(M, S, U);
417
+ const M = l, [R, A, H] = Ye(M, S, Y);
418
418
  i[x] = I << 24 | H << 16 | A << 8 | R;
419
419
  }
420
420
  h < f && await new Promise((x) => setTimeout(x, 0));
@@ -649,7 +649,7 @@ function Ct({ isOpen: e, onClose: t, onSubmit: n }) {
649
649
  ] });
650
650
  }
651
651
  function tn() {
652
- const e = w((s) => s.voucherConfig.language), t = w((s) => s.portrait), n = w((s) => s.setPortrait), r = w((s) => s.setPortraitZoom), a = w((s) => s.setPortraitPan), o = w((s) => s.setPortraitRawImage), i = w((s) => s.setPortraitBgRemoved), l = w((s) => s.setPortraitBgOpacity), c = w((s) => s.setPortraitBgBlur), u = w((s) => s.setPortraitEngravingIntensity), { enhance: v, removeBg: f, isEnhancing: g, isRemovingBg: h, error: x, hasKey: m, setApiKey: T } = Pt(), B = Q(e), k = $(null), I = $(null), [E, S] = O(!1), [U, M] = O(!1), [R, A] = O(!1), H = $(null), L = $(null), z = $(null), N = t.rawImage, ee = t.bgRemovedImage, _ = t.bgRemoved, F = t.bgOpacity, q = t.bgBlur, te = t.engravingIntensity;
652
+ const e = w((s) => s.voucherConfig.language), t = w((s) => s.portrait), n = w((s) => s.setPortrait), r = w((s) => s.setPortraitZoom), a = w((s) => s.setPortraitPan), o = w((s) => s.setPortraitRawImage), i = w((s) => s.setPortraitBgRemoved), l = w((s) => s.setPortraitBgOpacity), c = w((s) => s.setPortraitBgBlur), u = w((s) => s.setPortraitEngravingIntensity), { enhance: v, removeBg: f, isEnhancing: g, isRemovingBg: h, error: x, hasKey: m, setApiKey: T } = Pt(), B = Q(e), k = $(null), I = $(null), [E, S] = O(!1), [Y, M] = O(!1), [R, A] = O(!1), H = $(null), L = $(null), z = $(null), N = t.rawImage, ee = t.bgRemovedImage, _ = t.bgRemoved, F = t.bgOpacity, q = t.bgBlur, te = t.engravingIntensity;
653
653
  J(() => {
654
654
  t.original && !t.rawImage && o(t.original);
655
655
  }, [t.original, t.rawImage, o]), J(() => () => {
@@ -667,7 +667,7 @@ function tn() {
667
667
  }, y.readAsDataURL(s);
668
668
  },
669
669
  [n, o, i, u]
670
- ), Y = D(
670
+ ), U = D(
671
671
  (s) => {
672
672
  s.preventDefault(), S(!1);
673
673
  const y = s.dataTransfer.files[0];
@@ -953,7 +953,7 @@ function tn() {
953
953
  "div",
954
954
  {
955
955
  className: `border-2 border-dashed rounded-lg p-8 text-center cursor-pointer transition-colors ${h ? "border-primary bg-primary/10 pointer-events-none" : E ? "border-primary bg-primary/10" : "border-base-300 hover:border-primary hover:bg-base-200"}`,
956
- onDrop: Y,
956
+ onDrop: U,
957
957
  onDragOver: G,
958
958
  onDragLeave: ae,
959
959
  onClick: de,
@@ -1000,7 +1000,7 @@ function tn() {
1000
1000
  /* @__PURE__ */ d(
1001
1001
  Ct,
1002
1002
  {
1003
- isOpen: U,
1003
+ isOpen: Y,
1004
1004
  onClose: () => M(!1),
1005
1005
  onSubmit: pe
1006
1006
  }
@@ -1125,7 +1125,6 @@ const X = typeof import.meta < "u" && "/" || "/", Xe = {
1125
1125
  y: 920,
1126
1126
  width: 300,
1127
1127
  height: 60,
1128
- lineY: 950,
1129
1128
  labelFontSize: 16
1130
1129
  }
1131
1130
  }
@@ -1155,32 +1154,31 @@ const X = typeof import.meta < "u" && "/" || "/", Xe = {
1155
1154
  namePlate: {
1156
1155
  x: 3072,
1157
1156
  y: 2930,
1158
- fontSize: 144,
1157
+ fontSize: 145,
1159
1158
  maxWidth: 1520,
1160
1159
  align: "center"
1161
1160
  },
1162
1161
  contactInfo: {
1163
1162
  x: 1520,
1164
- y: 1680,
1163
+ y: 1580,
1165
1164
  fontSize: 160,
1166
1165
  lineHeight: 280,
1167
1166
  align: "center"
1168
1167
  },
1169
1168
  description: {
1170
1169
  x: 4600,
1171
- y: 1680,
1170
+ y: 1580,
1172
1171
  fontSize: 145,
1173
1172
  maxWidth: 2e3,
1174
1173
  lineHeight: 210,
1175
1174
  align: "center"
1176
1175
  },
1177
1176
  signature: {
1178
- x: 4600,
1179
- y: 2850,
1180
- width: 1200,
1177
+ x: 3080,
1178
+ y: 2450,
1179
+ width: 1600,
1181
1180
  height: 240,
1182
- lineY: 2700,
1183
- labelFontSize: 64
1181
+ labelFontSize: 145
1184
1182
  }
1185
1183
  }
1186
1184
  };
@@ -1222,6 +1220,13 @@ function Tt(e) {
1222
1220
  maxWidth: a.description.maxWidth ? a.description.maxWidth * n : void 0,
1223
1221
  lineHeight: a.description.lineHeight ? a.description.lineHeight * n : void 0,
1224
1222
  align: a.description.align
1223
+ } : void 0,
1224
+ signature: a.signature ? {
1225
+ x: a.signature.x * n,
1226
+ y: a.signature.y * n,
1227
+ width: a.signature.width * n,
1228
+ height: a.signature.height * n,
1229
+ labelFontSize: a.signature.labelFontSize * n
1225
1230
  } : void 0
1226
1231
  });
1227
1232
  return {
@@ -1302,7 +1307,7 @@ function Nt(e, t, n, r, a, o = "#2a3a2a") {
1302
1307
  e.restore();
1303
1308
  }
1304
1309
  function Bt(e, t, n, r = "#2a3a2a") {
1305
- e.save(), e.strokeStyle = r, e.lineWidth = Math.max(2, t.labelFontSize / 16), e.beginPath(), e.moveTo(t.x - t.width / 2, t.lineY), e.lineTo(t.x + t.width / 2, t.lineY), 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.lineY + t.labelFontSize * 0.3), e.restore();
1310
+ 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 * 0.3), e.restore();
1306
1311
  }
1307
1312
  async function Lt(e, t, n, r, a, o, i, l = 1, c = 0, u = 0, v = 0) {
1308
1313
  const f = e.getContext("2d");
@@ -1355,7 +1360,7 @@ function Mt(e, t) {
1355
1360
  }, [e, t]), n;
1356
1361
  }
1357
1362
  function an() {
1358
- const e = w((p) => p.voucherConfig.language), t = w((p) => p.voucherConfig.hours), n = w((p) => p.voucherConfig.description), r = w((p) => p.voucherConfig.templateHue), a = w((p) => p.personalInfo), o = w((p) => p.portrait), i = w((p) => p.currentSide), l = w((p) => p.flipSide), c = w((p) => p.setPortraitPan), u = Mt(r, 150), v = Q(e), f = $(null), g = $(null), h = $(null), [x, m] = O(!1), [T, B] = O(!1), k = $(null), I = Et(e, t), E = Tt(e), S = o.useEnhanced && o.enhanced ? o.enhanced : o.original, U = Ye(e, t, n);
1363
+ const e = w((p) => p.voucherConfig.language), t = w((p) => p.voucherConfig.hours), n = w((p) => p.voucherConfig.description), r = w((p) => p.voucherConfig.templateHue), a = w((p) => p.personalInfo), o = w((p) => p.portrait), i = w((p) => p.currentSide), l = w((p) => p.flipSide), c = w((p) => p.setPortraitPan), u = Mt(r, 150), v = Q(e), f = $(null), g = $(null), h = $(null), [x, m] = O(!1), [T, B] = O(!1), k = $(null), I = Et(e, t), E = Tt(e), S = o.useEnhanced && o.enhanced ? o.enhanced : o.original, Y = Ue(e, t, n);
1359
1364
  J(() => {
1360
1365
  f.current && Lt(
1361
1366
  f.current,
@@ -1377,32 +1382,32 @@ function an() {
1377
1382
  a.name,
1378
1383
  a.email,
1379
1384
  a.phone,
1380
- U,
1385
+ Y,
1381
1386
  E.back,
1382
1387
  I.width,
1383
1388
  I.height,
1384
1389
  u,
1385
1390
  e
1386
1391
  );
1387
- }, [I, a, U, E, u, e]);
1392
+ }, [I, a, Y, E, u, e]);
1388
1393
  const M = () => {
1389
1394
  m(!0), setTimeout(() => {
1390
1395
  l(), m(!1);
1391
1396
  }, 150);
1392
- }, R = D((p, Y) => {
1397
+ }, R = D((p, U) => {
1393
1398
  if (!h.current || i !== "front" || !o.original) return !1;
1394
- const G = h.current.getBoundingClientRect(), ae = G.width / I.width, de = G.height / I.height, ue = (p - G.left) / ae, V = (Y - G.top) / de, { x: re, y: Z, radiusX: ye, radiusY: ve } = E.front.portrait, pe = (ue - re) / ye, fe = (V - Z) / ve;
1399
+ const G = h.current.getBoundingClientRect(), ae = G.width / I.width, de = G.height / I.height, ue = (p - G.left) / ae, V = (U - G.top) / de, { x: re, y: Z, radiusX: ye, radiusY: ve } = E.front.portrait, pe = (ue - re) / ye, fe = (V - Z) / ve;
1395
1400
  return pe * pe + fe * fe <= 1;
1396
- }, [i, o.original, I.width, I.height, E.front.portrait]), A = D((p, Y) => {
1397
- o.zoom <= 1 || !R(p, Y) || (B(!0), k.current = {
1401
+ }, [i, o.original, I.width, I.height, E.front.portrait]), A = D((p, U) => {
1402
+ o.zoom <= 1 || !R(p, U) || (B(!0), k.current = {
1398
1403
  x: p,
1399
- y: Y,
1404
+ y: U,
1400
1405
  panX: o.panX,
1401
1406
  panY: o.panY
1402
1407
  });
1403
- }, [o.zoom, o.panX, o.panY, R]), H = D((p, Y) => {
1408
+ }, [o.zoom, o.panX, o.panY, R]), H = D((p, U) => {
1404
1409
  if (!T || !k.current || !h.current) return;
1405
- const G = h.current.getBoundingClientRect(), ae = 3 / Math.max(G.width, G.height), de = (p - k.current.x) * ae, ue = (Y - k.current.y) * ae, V = Math.max(-1, Math.min(1, k.current.panX + de)), re = Math.max(-1, Math.min(1, k.current.panY + ue));
1410
+ const G = h.current.getBoundingClientRect(), ae = 3 / Math.max(G.width, G.height), de = (p - k.current.x) * ae, ue = (U - k.current.y) * ae, V = Math.max(-1, Math.min(1, k.current.panX + de)), re = Math.max(-1, Math.min(1, k.current.panY + ue));
1406
1411
  c(V, re);
1407
1412
  }, [T, c]), L = D(() => {
1408
1413
  B(!1), k.current = null;
@@ -1412,8 +1417,8 @@ function an() {
1412
1417
  H(p.clientX, p.clientY);
1413
1418
  }, ee = () => L(), _ = () => L(), F = (p) => {
1414
1419
  if (p.touches.length === 1) {
1415
- const Y = p.touches[0];
1416
- o.zoom > 1 && R(Y.clientX, Y.clientY) && A(Y.clientX, Y.clientY);
1420
+ const U = p.touches[0];
1421
+ o.zoom > 1 && R(U.clientX, U.clientY) && A(U.clientX, U.clientY);
1417
1422
  }
1418
1423
  }, q = (p) => {
1419
1424
  p.touches.length === 1 && H(p.touches[0].clientX, p.touches[0].clientY);
@@ -1715,6 +1720,7 @@ self.onmessage = async (e) => {
1715
1720
  email,
1716
1721
  phone,
1717
1722
  description,
1723
+ language,
1718
1724
  } = e.data;
1719
1725
 
1720
1726
  try {
@@ -1830,12 +1836,12 @@ self.onmessage = async (e) => {
1830
1836
  const sig = layout.back.signature;
1831
1837
  const signatureLabel = language === 'de' ? 'Unterschrift' : 'Signature';
1832
1838
 
1833
- // Draw signature line
1839
+ // Draw signature line at (x, y)
1834
1840
  backCtx.strokeStyle = '#2a3a2a';
1835
1841
  backCtx.lineWidth = Math.max(2, sig.labelFontSize / 16);
1836
1842
  backCtx.beginPath();
1837
- backCtx.moveTo(sig.x - sig.width / 2, sig.lineY);
1838
- backCtx.lineTo(sig.x + sig.width / 2, sig.lineY);
1843
+ backCtx.moveTo(sig.x - sig.width / 2, sig.y);
1844
+ backCtx.lineTo(sig.x + sig.width / 2, sig.y);
1839
1845
  backCtx.stroke();
1840
1846
 
1841
1847
  // Draw label below line
@@ -1843,7 +1849,7 @@ self.onmessage = async (e) => {
1843
1849
  backCtx.textAlign = 'center';
1844
1850
  backCtx.textBaseline = 'top';
1845
1851
  backCtx.fillStyle = '#2a3a2a';
1846
- backCtx.fillText(signatureLabel, sig.x, sig.lineY + sig.labelFontSize * 0.3);
1852
+ backCtx.fillText(signatureLabel, sig.x, sig.y + sig.labelFontSize * 0.3);
1847
1853
  }
1848
1854
 
1849
1855
  // Convert canvases to blobs and then to ArrayBuffer for transfer
@@ -1892,7 +1898,7 @@ function Ae(e, t) {
1892
1898
  r += String.fromCharCode(n[a]);
1893
1899
  return `data:${t};base64,${btoa(r)}`;
1894
1900
  }
1895
- async function Yt(e) {
1901
+ async function Ut(e) {
1896
1902
  const {
1897
1903
  frontTemplateSrc: t,
1898
1904
  backTemplateSrc: n,
@@ -1915,8 +1921,8 @@ async function Yt(e) {
1915
1921
  ]);
1916
1922
  let k = null;
1917
1923
  return i && (k = await Ce(i)), new Promise((I, E) => {
1918
- const S = zt(), U = (R) => {
1919
- if (S.removeEventListener("message", U), S.removeEventListener("error", M), URL.revokeObjectURL(T), URL.revokeObjectURL(B), k && URL.revokeObjectURL(k), R.data.type === "success")
1924
+ const S = zt(), Y = (R) => {
1925
+ if (S.removeEventListener("message", Y), S.removeEventListener("error", M), URL.revokeObjectURL(T), URL.revokeObjectURL(B), k && URL.revokeObjectURL(k), R.data.type === "success")
1920
1926
  try {
1921
1927
  const { frontImageData: A, backImageData: H, width: L, height: z } = R.data;
1922
1928
  if (!A || !H || !L || !z) {
@@ -1937,9 +1943,9 @@ async function Yt(e) {
1937
1943
  else
1938
1944
  E(new Error(R.data.error));
1939
1945
  }, M = (R) => {
1940
- S.removeEventListener("message", U), S.removeEventListener("error", M), URL.revokeObjectURL(T), URL.revokeObjectURL(B), k && URL.revokeObjectURL(k), E(new Error(R.message));
1946
+ S.removeEventListener("message", Y), S.removeEventListener("error", M), URL.revokeObjectURL(T), URL.revokeObjectURL(B), k && URL.revokeObjectURL(k), E(new Error(R.message));
1941
1947
  };
1942
- S.addEventListener("message", U), S.addEventListener("error", M), S.postMessage({
1948
+ S.addEventListener("message", Y), S.addEventListener("error", M), S.postMessage({
1943
1949
  type: "generate",
1944
1950
  frontTemplateUrl: T,
1945
1951
  backTemplateUrl: B,
@@ -1970,16 +1976,16 @@ async function Yt(e) {
1970
1976
  });
1971
1977
  });
1972
1978
  }
1973
- function Ut(e, t) {
1979
+ function Yt(e, t) {
1974
1980
  const n = URL.createObjectURL(e), r = document.createElement("a");
1975
1981
  r.href = n, r.download = t, document.body.appendChild(r), r.click(), document.body.removeChild(r), URL.revokeObjectURL(n);
1976
1982
  }
1977
1983
  async function _t(e) {
1978
- const t = await Yt(e);
1979
- Ut(t, e.filename);
1984
+ const t = await Ut(e);
1985
+ Yt(t, e.filename);
1980
1986
  }
1981
1987
  function on() {
1982
- const e = w((m) => m.voucherConfig.language), t = w((m) => m.voucherConfig.hours), n = w((m) => m.voucherConfig.description), r = w((m) => m.voucherConfig.templateHue), a = w((m) => m.personalInfo), o = w((m) => m.portrait), i = w((m) => m.isExporting), l = w((m) => m.setIsExporting), c = Q(e), u = St(e, t), v = $e(e), f = o.useEnhanced && o.enhanced ? o.enhanced : o.original, g = Ye(e, t, n), h = a.name.trim().length > 0 && a.email.trim().length > 0 && a.phone.trim().length > 0 && o.original !== null;
1988
+ const e = w((m) => m.voucherConfig.language), t = w((m) => m.voucherConfig.hours), n = w((m) => m.voucherConfig.description), r = w((m) => m.voucherConfig.templateHue), a = w((m) => m.personalInfo), o = w((m) => m.portrait), i = w((m) => m.isExporting), l = w((m) => m.setIsExporting), c = Q(e), u = St(e, t), v = $e(e), f = o.useEnhanced && o.enhanced ? o.enhanced : o.original, g = Ue(e, t, n), h = a.name.trim().length > 0 && a.email.trim().length > 0 && a.phone.trim().length > 0 && o.original !== null;
1983
1989
  return /* @__PURE__ */ b(
1984
1990
  "button",
1985
1991
  {
@@ -2245,7 +2251,7 @@ export {
2245
2251
  nn as VoucherConfig,
2246
2252
  gt as applyEngravingEffect,
2247
2253
  ft as applyHueShift,
2248
- Ut as downloadBlob,
2254
+ Yt as downloadBlob,
2249
2255
  Nt as drawContactInfo,
2250
2256
  Ht as drawMultilineText,
2251
2257
  Rt as drawOvalPortrait,
@@ -2253,8 +2259,8 @@ export {
2253
2259
  je as drawText,
2254
2260
  en as enhancePortrait,
2255
2261
  _t as exportBillAsPDF,
2256
- Ye as formatDescription,
2257
- Yt as generateBillPDF,
2262
+ Ue as formatDescription,
2263
+ Ut as generateBillPDF,
2258
2264
  Ee as getApiKey,
2259
2265
  ln as getDefaultTemplateId,
2260
2266
  $e as getLayout,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@antontranelis/money-printer",
3
- "version": "1.0.28",
3
+ "version": "1.0.29",
4
4
  "description": "Create personalized time vouchers that look like real currency. React components for voucher generation with PDF export.",
5
5
  "type": "module",
6
6
  "license": "MIT",