@antontranelis/money-printer 1.0.19 → 1.0.21
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 +354 -1
- package/dist/index.js +903 -546
- package/package.json +1 -1
- package/dist/assets/pdfWorker-DjqCcfZq.js +0 -1
package/dist/index.cjs
CHANGED
|
@@ -1 +1,354 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("react/jsx-runtime"),ht=require("zustand"),pt=require("zustand/middleware"),m=require("react"),mt=require("jspdf");var F=typeof document<"u"?document.currentScript:null;const Le={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},w=ht.create()(pt.persist(e=>({...Le,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(Le)}),{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}})})),gt={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"}},ft={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"}},bt={de:gt,en:ft};function V(e){return bt[e]}function Ee(e,t,n){if(n&&n.trim())return n;const r=V(e),a=t===1?r.form.voucher.hourLabel:r.form.voucher.hoursLabel;return r.bill.descriptionText.replace("{hours}",t.toString()).replace("{hourLabel}",a)}function wt(){const e=w(a=>a.voucherConfig.language),t=w(a=>a.personalInfo),n=w(a=>a.setPersonalInfo),r=V(e);return i.jsxs("div",{className:"space-y-4",children:[i.jsxs("div",{className:"form-control",children:[i.jsx("label",{className:"label",children:i.jsx("span",{className:"label-text font-medium",children:r.form.personalInfo.name})}),i.jsx("input",{type:"text",placeholder:r.form.personalInfo.namePlaceholder,className:"input input-bordered w-full",value:t.name,onChange:a=>n({name:a.target.value})})]}),i.jsxs("div",{className:"form-control",children:[i.jsx("label",{className:"label",children:i.jsx("span",{className:"label-text font-medium",children:r.form.personalInfo.email})}),i.jsx("input",{type:"email",placeholder:r.form.personalInfo.emailPlaceholder,className:"input input-bordered w-full",value:t.email,onChange:a=>n({email:a.target.value})})]}),i.jsxs("div",{className:"form-control",children:[i.jsx("label",{className:"label",children:i.jsx("span",{className:"label-text font-medium",children:r.form.personalInfo.phone})}),i.jsx("input",{type:"tel",placeholder:r.form.personalInfo.phonePlaceholder,className:"input input-bordered w-full",value:t.phone,onChange:a=>n({phone:a.target.value})})]})]})}const vt=1024,Q=new Map;let z=null,Me=null;function je(e,t){return z||(z=document.createElement("canvas"),Me=z.getContext("2d",{willReadFrequently:!0})),(z.width!==e||z.height!==t)&&(z.width=e,z.height=t),Me}function re(e){const t=Q.get(e);return t?Promise.resolve(t):new Promise((n,r)=>{const a=new Image;a.onload=()=>{if(Q.size>10){const o=Q.keys().next().value;o&&Q.delete(o)}Q.set(e,a),n(a)},a.onerror=()=>r(new Error("Failed to load image")),a.src=e})}function yt(){Q.clear()}async function xt(e,t=vt){const n=await re(e),r=Math.max(n.width,n.height);if(r<=t)return e;const a=t/r,o=Math.round(n.width*a),s=Math.round(n.height*a),d=document.createElement("canvas"),c=d.getContext("2d");if(!c)throw new Error("Failed to get canvas context");return d.width=o,d.height=s,c.drawImage(n,0,0,o,s),d.toDataURL("image/jpeg",.9)}async function ye(e,t,n,r=0){const[a,o]=await Promise.all([re(e),re(t)]),s=je(a.width,a.height);if(s.clearRect(0,0,a.width,a.height),n>0){const d=r*20;s.save(),s.globalAlpha=n,d>0&&(s.filter=`blur(${d}px)`),s.drawImage(o,0,0,a.width,a.height),s.restore()}return s.drawImage(a,0,0),z.toDataURL("image/png")}async function Ue(e,t=.5){const n=await re(e),r=je(n.width,n.height);r.drawImage(n,0,0);const a=r.getImageData(0,0,n.width,n.height),o=a.data,s=new Uint32Array(o.buffer),d=1+t*.8,c=1-t;for(let u=0;u<s.length;u++){const h=s[u],p=h&255,v=h>>8&255,g=h>>16&255,x=h>>24&255;if(x===0)continue;let j=(((77*p+150*v+29*g>>8)/255-.5)*d+.5)*255;j<0?j=0:j>255&&(j=255);let S=j*.9+25,P=j*.78+15,I=j*.55+5;S>255&&(S=255),P>255&&(P=255),I>255&&(I=255);const C=p*c+S*t|0,R=v*c+P*t|0,B=g*c+I*t|0;s[u]=x<<24|B<<16|R<<8|C}return r.putImageData(a,0,0),z.toDataURL("image/png")}function It(e,t,n){e/=255,t/=255,n/=255;const r=Math.max(e,t,n),a=Math.min(e,t,n),o=(r+a)/2;let s=0,d=0;if(r!==a){const c=r-a;switch(d=o>.5?c/(2-r-a):c/(r+a),r){case e:s=((t-n)/c+(t<n?6:0))/6;break;case t:s=((n-e)/c+2)/6;break;case n:s=((e-t)/c+4)/6;break}}return[s,d,o]}function Pt(e,t,n){if(t===0){const s=Math.round(n*255);return[s,s,s]}const r=(s,d,c)=>(c<0&&(c+=1),c>1&&(c-=1),c<1/6?s+(d-s)*6*c:c<1/2?d:c<2/3?s+(d-s)*(2/3-c)*6:s),a=n<.5?n*(1+t):n+t-n*t,o=2*n-a;return[Math.round(r(o,a,e+1/3)*255),Math.round(r(o,a,e)*255),Math.round(r(o,a,e-1/3)*255)]}async function He(e,t){if(t>=155&&t<=165)return e;const n=await re(e),r=je(n.width,n.height);r.drawImage(n,0,0);const a=r.getImageData(0,0,n.width,n.height),o=a.data,s=new Uint32Array(o.buffer),d=t%360/360,c=60/360,u=260/360,h=1e5,p=s.length;for(let v=0;v<p;v+=h){const g=Math.min(v+h,p);for(let x=v;x<g;x++){const f=s[x],j=f&255,S=f>>8&255,P=f>>16&255,I=f>>24&255;if(I===0)continue;const[C,R,B]=It(j,S,P);if(R<.06||C<c||C>u)continue;const _=d,[M,H,N]=Pt(_,R,B);s[x]=I<<24|N<<16|H<<8|M}g<p&&await new Promise(x=>setTimeout(x,0))}return r.putImageData(a,0,0),z.toDataURL("image/png")}const kt="https://api.stability.ai/v1/generation",Et="https://api.stability.ai/v2beta/stable-image/edit/remove-background",ze="stability_api_key";let te=null;function jt(e){te=e}function St(){return te}function Ct(){return te!==null}const Rt={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"},De=[{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 Tt(e,t){const n=e/t;let r=De[0],a=1/0;for(const o of De){const s=o.width/o.height,d=Math.abs(n-s);d<a&&(a=d,r=o)}return r}function Nt(e){return new Promise((t,n)=>{const r=new Image;r.onload=()=>{const a=Tt(r.width,r.height),o=document.createElement("canvas");o.width=a.width,o.height=a.height;const s=o.getContext("2d");if(!s){n(new Error("Failed to get canvas context"));return}const d=r.width/r.height,c=a.width/a.height;let u=0,h=0,p=r.width,v=r.height;d>c?(p=r.height*c,u=(r.width-p)/2):(v=r.width/c,h=(r.height-v)/2),s.drawImage(r,u,h,p,v,0,0,a.width,a.height),t(o.toDataURL("image/png"))},r.onerror=()=>n(new Error("Failed to load image")),r.src=e})}function Ye(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,o=new Uint8Array(a);for(let d=0;d<a;d++)o[d]=r.charCodeAt(d);return new Blob([o],{type:n})}function pe(){var t;const e=typeof{url:typeof document>"u"?require("url").pathToFileURL(__filename).href:F&&F.tagName.toUpperCase()==="SCRIPT"&&F.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(ze):null}function $e(e){localStorage.setItem(ze,e)}function Pe(){return te?!0:pe()!==null}async function Bt(e){const t=pe();if(!t)throw new Error("No Stability AI API key configured");const{imageDataUrl:n,style:r,strength:a=.35}=e,o=await Nt(n),s=Ye(o),d=new FormData;d.append("init_image",s,"portrait.png"),d.append("init_image_mode","IMAGE_STRENGTH"),d.append("image_strength",String(1-a)),d.append("text_prompts[0][text]",Rt[r]),d.append("text_prompts[0][weight]","1"),d.append("cfg_scale","7"),d.append("samples","1"),d.append("steps","30");const u=await fetch(`${kt}/stable-diffusion-xl-1024-v1-0/image-to-image`,{method:"POST",headers:{Authorization:`Bearer ${t}`,Accept:"application/json"},body:d});if(!u.ok){const p=await u.text();throw console.error("Stability AI error:",p),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 h=await u.json();if(!h.artifacts||h.artifacts.length===0)throw new Error("No image generated");return`data:image/png;base64,${h.artifacts[0].base64}`}async function Xe(e){if(te){const s=await fetch(te,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({imageDataUrl:e})});if(!s.ok){const c=await s.json().catch(()=>({}));throw new Error(c.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=Ye(e),r=new FormData;r.append("image",n,"image.png"),r.append("output_format","png");const a=await fetch(Et,{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 o=await a.blob();return new Promise((s,d)=>{const c=new FileReader;c.onload=()=>s(c.result),c.onerror=()=>d(new Error("Failed to read result")),c.readAsDataURL(o)})}function Lt(){const[e,t]=m.useState(!1),[n,r]=m.useState(!1),[a,o]=m.useState(null),[s,d]=m.useState(()=>Pe());m.useEffect(()=>{d(Pe())},[]);const c=m.useCallback(()=>o(null),[]),u=m.useCallback(v=>{$e(v),d(!0),o(null)},[]),h=m.useCallback(async(v,g=.5)=>{t(!0),o(null);try{return await Ue(v,g)}catch(x){const f=x instanceof Error?x.message:"Enhancement failed";throw o(f),x}finally{t(!1)}},[]),p=m.useCallback(async v=>{r(!0),o(null);try{return await Xe(v)}catch(g){const x=g instanceof Error?g.message:"Background removal failed";throw o(x),g}finally{r(!1)}},[]);return{enhance:h,removeBg:p,isEnhancing:e,isRemovingBg:n,error:a,hasKey:s,setApiKey:u,clearError:c}}function Fe({isOpen:e,onClose:t,onSubmit:n}){const r=w(u=>u.voucherConfig.language),[a,o]=m.useState("");if(!e)return null;const s=u=>{u.preventDefault(),a.trim()&&(n(a.trim()),o(""),t())},c={de:{title:"Stability AI API Key",description:"Um die AI-Bildverbesserung zu nutzen, benötigst du einen Stability AI API Key. Du kannst ihn auf platform.stability.ai erhalten.",placeholder:"sk-...",submit:"Speichern",cancel:"Abbrechen",hint:"Der Key wird lokal in deinem Browser gespeichert."},en:{title:"Stability AI API Key",description:"To use AI image enhancement, you need a Stability AI API key. You can get one at platform.stability.ai.",placeholder:"sk-...",submit:"Save",cancel:"Cancel",hint:"The key is stored locally in your browser."}}[r];return i.jsxs("dialog",{className:"modal modal-open",children:[i.jsxs("div",{className:"modal-box",children:[i.jsx("h3",{className:"font-bold text-lg",children:c.title}),i.jsx("p",{className:"py-4 text-sm opacity-80",children:c.description}),i.jsxs("form",{onSubmit:s,children:[i.jsxs("div",{className:"form-control",children:[i.jsx("input",{type:"password",placeholder:c.placeholder,className:"input input-bordered w-full",value:a,onChange:u=>o(u.target.value),autoFocus:!0}),i.jsx("label",{className:"label",children:i.jsx("span",{className:"label-text-alt",children:c.hint})})]}),i.jsxs("div",{className:"modal-action",children:[i.jsx("button",{type:"button",className:"btn btn-ghost",onClick:t,children:c.cancel}),i.jsx("button",{type:"submit",className:"btn btn-primary",disabled:!a.trim(),children:c.submit})]})]})]}),i.jsx("form",{method:"dialog",className:"modal-backdrop",children:i.jsx("button",{onClick:t,children:"close"})})]})}function Mt(){const e=w(l=>l.voucherConfig.language),t=w(l=>l.portrait),n=w(l=>l.setPortrait),r=w(l=>l.setPortraitZoom),a=w(l=>l.setPortraitPan),o=w(l=>l.setPortraitRawImage),s=w(l=>l.setPortraitBgRemoved),d=w(l=>l.setPortraitBgOpacity),c=w(l=>l.setPortraitBgBlur),u=w(l=>l.setPortraitEngravingIntensity),{enhance:h,removeBg:p,isEnhancing:v,isRemovingBg:g,error:x,hasKey:f,setApiKey:j}=Lt(),S=V(e),P=m.useRef(null),I=m.useRef(null),[C,R]=m.useState(!1),[B,_]=m.useState(!1),[M,H]=m.useState(!1),N=m.useRef(null),U=m.useRef(null),T=m.useRef(null),k=t.rawImage,Y=t.bgRemovedImage,O=t.bgRemoved,oe=t.bgOpacity,ie=t.bgBlur,se=t.engravingIntensity;m.useEffect(()=>{t.original&&!t.rawImage&&o(t.original)},[t.original,t.rawImage,o]),m.useEffect(()=>()=>{U.current&&clearTimeout(U.current),T.current&&clearTimeout(T.current)},[]);const ne=m.useCallback(async l=>{if(!l.type.startsWith("image/"))return;const y=new FileReader;y.onload=async E=>{var ue;const D=(ue=E.target)==null?void 0:ue.result,de=await xt(D);o(de),n(de),s(!1,null),u(0)},y.readAsDataURL(l)},[n,o,s,u]),ge=m.useCallback(l=>{l.preventDefault(),R(!1);const y=l.dataTransfer.files[0];y&&ne(y)},[ne]),b=m.useCallback(l=>{l.preventDefault(),R(!0)},[]),L=m.useCallback(l=>{l.preventDefault(),R(!1)},[]),$=()=>{var l;(l=P.current)==null||l.click()},Z=l=>{var E;const y=(E=l.target.files)==null?void 0:E[0];y&&ne(y)},X=m.useCallback(async(l,y)=>{try{return await h(l,y)}catch(E){return console.error("Enhancement failed:",E),l}},[h]),G=m.useCallback(async l=>{try{const y=await p(l);return s(!0,y),y}catch(y){return console.error("Background removal failed:",y),l}},[p,s]),W=m.useCallback(async()=>{const l=w.getState().portrait;if(!l.rawImage)return;let y;l.bgRemoved&&l.bgRemovedImage?y=await ye(l.bgRemovedImage,l.rawImage,l.bgOpacity,l.bgBlur):y=l.rawImage,l.engravingIntensity>0&&(y=await X(y,l.engravingIntensity)),n(y)},[X,n]),ae=async()=>{if(!k)return;if(!O&&!f){_(!0);return}if(!O){const y=await G(k),E=w.getState().portrait;let D=await ye(y,k,E.bgOpacity,E.bgBlur);E.engravingIntensity>0&&(D=await X(D,E.engravingIntensity)),n(D)}else{s(!1,null);const y=w.getState().portrait.engravingIntensity;if(y>0){const E=await X(k,y);n(E)}else n(k)}},fe=l=>{u(l),U.current&&clearTimeout(U.current),k&&(U.current=setTimeout(W,150))},be=async l=>{if(j(l),!k)return;const y=await G(k),E=w.getState().portrait;let D=await ye(y,k,E.bgOpacity,E.bgBlur);E.engravingIntensity>0&&(D=await X(D,E.engravingIntensity)),n(D)},we=l=>{d(l),T.current&&clearTimeout(T.current),!(!k||!Y)&&(T.current=setTimeout(W,150))},le=l=>{c(l),T.current&&clearTimeout(T.current),!(!k||!Y)&&(T.current=setTimeout(W,150))},ce=()=>{n(null),o(null),s(!1,null),d(0),c(0),u(0),yt()},Ne=(l,y)=>{t.zoom<=1||(H(!0),N.current={x:l,y,panX:t.panX,panY:t.panY})},Be=(l,y)=>{if(!M||!N.current||!I.current)return;const E=I.current.getBoundingClientRect(),D=2/Math.max(E.width,E.height),de=(l-N.current.x)*D,ue=(y-N.current.y)*D,dt=Math.max(-1,Math.min(1,N.current.panX+de)),ut=Math.max(-1,Math.min(1,N.current.panY+ue));a(dt,ut)},ve=()=>{H(!1),N.current=null},at=l=>{l.preventDefault(),Ne(l.clientX,l.clientY)},rt=l=>{Be(l.clientX,l.clientY)},ot=()=>{ve()},it=()=>{ve()},st=l=>{l.touches.length===1&&Ne(l.touches[0].clientX,l.touches[0].clientY)},lt=l=>{l.touches.length===1&&Be(l.touches[0].clientX,l.touches[0].clientY)},ct=()=>{ve()};return i.jsxs("div",{className:"space-y-4",children:[t.original?i.jsxs("div",{className:"flex flex-col items-center space-y-4",children:[i.jsxs("div",{className:"relative",children:[i.jsx("div",{ref:I,className:`w-32 h-32 rounded-full overflow-hidden border-4 border-currency-gold shadow-lg ${t.zoom>1?"cursor-grab":""} ${M?"cursor-grabbing":""}`,onMouseDown:at,onMouseMove:rt,onMouseUp:ot,onMouseLeave:it,onTouchStart:st,onTouchMove:lt,onTouchEnd:ct,children:i.jsx("img",{src:t.original||"",alt:"Portrait",className:"w-full h-full object-cover pointer-events-none select-none",style:{transform:`scale(${t.zoom}) translate(${t.panX*50*(t.zoom-1)}%, ${t.panY*50*(t.zoom-1)}%)`},draggable:!1})}),i.jsx("button",{className:"btn btn-circle btn-xs btn-error absolute -top-1 -right-1",onClick:ce,children:i.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-4 w-4",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:i.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M6 18L18 6M6 6l12 12"})})})]}),i.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-4 w-full",children:[i.jsxs("div",{className:"form-control w-full",children:[i.jsxs("label",{className:"label",children:[i.jsx("span",{className:"label-text",children:S.form.portrait.zoom}),i.jsxs("span",{className:"label-text-alt",children:[Math.round(t.zoom*100),"%"]})]}),i.jsx("input",{type:"range",min:"0.5",max:"2",step:"0.05",value:t.zoom,onChange:l=>{const y=parseFloat(l.target.value);r(y),y<=1&&(t.panX!==0||t.panY!==0)&&a(0,0)},className:"range range-primary range-sm"})]}),i.jsxs("div",{className:"form-control w-full",children:[i.jsxs("label",{className:"label",children:[i.jsxs("span",{className:"label-text flex items-center gap-2",children:[e==="de"?"Sepia-Effekt":"Sepia effect",v&&i.jsx("span",{className:"loading loading-spinner loading-xs"})]}),i.jsxs("span",{className:"label-text-alt",children:[Math.round(se*100),"%"]})]}),i.jsx("input",{type:"range",min:"0",max:"1",step:"0.05",value:se,onChange:l=>fe(parseFloat(l.target.value)),className:"range range-secondary range-sm",disabled:v||!k})]})]}),O?i.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-4 w-full",children:[i.jsxs("div",{className:"form-control w-full",children:[i.jsxs("label",{className:"label",children:[i.jsx("span",{className:"label-text",children:e==="de"?"Hintergrund":"Background"}),i.jsxs("span",{className:"label-text-alt",children:[Math.round(oe*100),"%"]})]}),i.jsx("input",{type:"range",min:"0",max:"1",step:"0.05",value:oe,onChange:l=>we(parseFloat(l.target.value)),className:"range range-primary range-sm"})]}),i.jsxs("div",{className:"form-control w-full",children:[i.jsxs("label",{className:"label",children:[i.jsx("span",{className:"label-text",children:e==="de"?"Unschärfe":"Blur"}),i.jsxs("span",{className:"label-text-alt",children:[Math.round(ie*100),"%"]})]}),i.jsx("input",{type:"range",min:"0",max:"1",step:"0.05",value:ie,onChange:l=>le(parseFloat(l.target.value)),className:"range range-primary range-sm"})]})]}):i.jsx("div",{className:"form-control",children:i.jsxs("label",{className:"label cursor-pointer justify-start gap-3",children:[i.jsx("input",{type:"checkbox",className:`toggle toggle-primary ${g?"opacity-50":""}`,checked:O,onChange:ae,disabled:g||!k}),i.jsxs("span",{className:"label-text flex items-center gap-2",children:[g?i.jsxs(i.Fragment,{children:[i.jsx("span",{className:"loading loading-spinner loading-xs"}),e==="de"?"Hintergrund wird entfernt...":"Removing background..."]}):e==="de"?"Hintergrund entfernen":"Remove background",!f&&i.jsx("span",{className:"badge badge-sm badge-outline",children:"API"})]})]})}),x&&i.jsxs("div",{className:"alert alert-warning text-sm py-2",children:[i.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"stroke-current shrink-0 h-5 w-5",fill:"none",viewBox:"0 0 24 24",children:i.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:"2",d:"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"})}),i.jsx("span",{children:x})]})]}):i.jsxs("div",{className:`border-2 border-dashed rounded-lg p-8 text-center cursor-pointer transition-colors ${g?"border-primary bg-primary/10 pointer-events-none":C?"border-primary bg-primary/10":"border-base-300 hover:border-primary hover:bg-base-200"}`,onDrop:ge,onDragOver:b,onDragLeave:L,onClick:$,children:[i.jsx("input",{ref:P,type:"file",accept:"image/*",className:"hidden",onChange:Z}),g?i.jsxs("div",{className:"flex flex-col items-center gap-2",children:[i.jsx("span",{className:"loading loading-spinner loading-lg text-primary"}),i.jsx("p",{className:"font-medium",children:e==="de"?"Hintergrund wird entfernt...":"Removing background..."})]}):i.jsxs("div",{className:"flex flex-col items-center gap-2",children:[i.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-12 w-12 text-base-content/50",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:i.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"})}),i.jsx("p",{className:"font-medium",children:S.form.portrait.upload}),i.jsx("p",{className:"text-sm text-base-content/60",children:S.form.portrait.dragDrop})]})]}),i.jsx(Fe,{isOpen:B,onClose:()=>_(!1),onSubmit:be})]})}function Dt(){return null}const A=typeof{url:typeof document>"u"?require("url").pathToFileURL(__filename).href:F&&F.tagName.toUpperCase()==="SCRIPT"&&F.src||new URL("index.cjs",document.baseURI).href}<"u"&&"/"||"/",Se={en:{1:{front:`${A}templates/front_ldpi_en.png`,back:`${A}templates/back_ldpi_en.png`,width:1536,height:1024},5:{front:`${A}templates/front_ldpi_en.png`,back:`${A}templates/back_ldpi_en.png`,width:1536,height:1024},10:{front:`${A}templates/front_ldpi_en.png`,back:`${A}templates/back_ldpi_en.png`,width:1536,height:1024}},de:{1:{front:`${A}templates/front_hdpi_de.webp`,back:`${A}templates/back_hdpi_de.webp`,width:6144,height:3200},5:{front:`${A}templates/front_hdpi_de.webp`,back:`${A}templates/back_hdpi_de.webp`,width:6144,height:3200},10:{front:`${A}templates/front_hdpi_de.webp`,back:`${A}templates/back_hdpi_de.webp`,width:6144,height:3200}}},K={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"}}},q={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"}}};function Ce(e){return e==="de"?q:K}function Oe(e,t){return Se[e][t]}const ke=.25;function At(e){const t=Ce(e),n=ke,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=Se[e][t];return{...n,width:Math.round(n.width*ke),height:Math.round(n.height*ke)}}const xe=new Map,J=new Map;async function ee(e){return xe.has(e)?xe.get(e):new Promise((t,n)=>{const r=new Image;r.crossOrigin="anonymous",r.onload=()=>{xe.set(e,r),t(r)},r.onerror=n,r.src=e})}function Re(e,t,n,r){e.drawImage(t,0,0,n,r)}async function We(e,t,n,r){if(t>=155&&t<=165)return ee(e);const a=`${e}:${t}:${n}x${r}`;if(J.has(a))return ee(J.get(a));const o=await ee(e),s=document.createElement("canvas");s.width=n,s.height=r;const d=s.getContext("2d");if(!d)throw new Error("Failed to get canvas context");d.drawImage(o,0,0,n,r);const c=s.toDataURL("image/png"),u=await He(c,t);if(J.size>20){const h=J.keys().next().value;h&&J.delete(h)}return J.set(a,u),ee(u)}function Ke(e,t,n,r,a,o,s=1,d=0,c=0){e.save(),e.beginPath(),e.ellipse(n,r,a,o,0,0,Math.PI*2),e.closePath(),e.clip();const u=t.width/t.height,h=a/o,p=a*2,v=o*2;let g,x;u>h?(x=v,g=v*u):(g=p,x=p/u),g*=s,x*=s;const f=Math.max(0,(g-p)/2),j=Math.max(0,(x-v)/2),S=n-g/2+d*f,P=r-x/2+c*j;e.drawImage(t,S,P,g,x),e.restore()}function Te(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 qe(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,o=n.lineHeight||n.fontSize*1.4,s=t.split(" "),d=[];let c="";for(const p of s){const v=c?`${c} ${p}`:p;e.measureText(v).width>a&&c?(d.push(c),c=p):c=v}c&&d.push(c);const u=d.length*o;let h=n.y-u/2;for(const p of d)e.fillText(p,n.x,h),h+=o;e.restore()}function Ve(e,t,n,r,a,o="#2a3a2a"){e.save(),e.font=`${a.fontSize}px "Times New Roman", serif`,e.textAlign=a.align||"center",e.textBaseline="middle",e.fillStyle=o;const s=a.lineHeight||a.fontSize*1.8,d=[t,n,r].filter(Boolean),c=(d.length-1)*s;let u=a.y-c/2;for(const h of d)h&&(e.fillText(h,a.x,u),u+=s);e.restore()}async function Ze(e,t,n,r,a,o,s,d=1,c=0,u=0,h=0){const p=e.getContext("2d");if(!p)return;e.width=o,e.height=s,p.clearRect(0,0,o,s);const v=await We(t,h,o,s);if(Re(p,v,o,s),n)try{const g=await ee(n);Ke(p,g,a.portrait.x,a.portrait.y,a.portrait.radiusX,a.portrait.radiusY,d,c,u)}catch(g){console.error("Failed to load portrait:",g)}r&&Te(p,r,a.namePlate)}async function Ge(e,t,n,r,a,o,s,d,c,u=0){const h=e.getContext("2d");if(!h)return;e.width=d,e.height=c,h.clearRect(0,0,d,c);const p=await We(t,u,d,c);Re(h,p,d,c),s.contactInfo&&(n||r||a)&&Ve(h,n,r,a,s.contactInfo),s.description&&o&&qe(h,o,s.description),n&&Te(h,n,s.namePlate)}function Ut(e,t){const[n,r]=m.useState(e);return m.useEffect(()=>{const a=setTimeout(()=>r(e),t);return()=>clearTimeout(a)},[e,t]),n}function Ht(){const e=w(b=>b.voucherConfig.language),t=w(b=>b.voucherConfig.hours),n=w(b=>b.voucherConfig.description),r=w(b=>b.voucherConfig.templateHue),a=w(b=>b.personalInfo),o=w(b=>b.portrait),s=w(b=>b.currentSide),d=w(b=>b.flipSide),c=w(b=>b.setPortraitPan),u=Ut(r,150),h=V(e),p=m.useRef(null),v=m.useRef(null),g=m.useRef(null),[x,f]=m.useState(!1),[j,S]=m.useState(!1),P=m.useRef(null),I=_t(e,t),C=At(e),R=o.useEnhanced&&o.enhanced?o.enhanced:o.original,B=Ee(e,t,n);m.useEffect(()=>{p.current&&Ze(p.current,I.front,R,a.name,C.front,I.width,I.height,o.zoom,o.panX,o.panY,u)},[I,R,a.name,C,o.zoom,o.panX,o.panY,u]),m.useEffect(()=>{v.current&&Ge(v.current,I.back,a.name,a.email,a.phone,B,C.back,I.width,I.height,u)},[I,a,B,C,u]);const _=()=>{f(!0),setTimeout(()=>{d(),f(!1)},150)},M=m.useCallback((b,L)=>{if(!g.current||s!=="front"||!o.original)return!1;const $=g.current.getBoundingClientRect(),Z=$.width/I.width,X=$.height/I.height,G=(b-$.left)/Z,W=(L-$.top)/X,{x:ae,y:fe,radiusX:be,radiusY:we}=C.front.portrait,le=(G-ae)/be,ce=(W-fe)/we;return le*le+ce*ce<=1},[s,o.original,I.width,I.height,C.front.portrait]),H=m.useCallback((b,L)=>{o.zoom<=1||!M(b,L)||(S(!0),P.current={x:b,y:L,panX:o.panX,panY:o.panY})},[o.zoom,o.panX,o.panY,M]),N=m.useCallback((b,L)=>{if(!j||!P.current||!g.current)return;const $=g.current.getBoundingClientRect(),Z=3/Math.max($.width,$.height),X=(b-P.current.x)*Z,G=(L-P.current.y)*Z,W=Math.max(-1,Math.min(1,P.current.panX+X)),ae=Math.max(-1,Math.min(1,P.current.panY+G));c(W,ae)},[j,c]),U=m.useCallback(()=>{S(!1),P.current=null},[]),T=b=>{o.zoom>1&&M(b.clientX,b.clientY)&&(b.preventDefault(),H(b.clientX,b.clientY))},k=b=>{N(b.clientX,b.clientY)},Y=()=>U(),O=()=>U(),oe=b=>{if(b.touches.length===1){const L=b.touches[0];o.zoom>1&&M(L.clientX,L.clientY)&&H(L.clientX,L.clientY)}},ie=b=>{b.touches.length===1&&N(b.touches[0].clientX,b.touches[0].clientY)},se=()=>U(),ne=s==="front"&&o.original&&o.zoom>1,ge=I.width/I.height;return i.jsxs("div",{className:"space-y-4",children:[i.jsxs("div",{className:"flex justify-between items-center",children:[i.jsxs("div",{className:"tabs tabs-boxed bg-base-200",children:[i.jsx("button",{className:`tab ${s==="front"?"tab-active bg-primary text-primary-content font-semibold":""}`,onClick:()=>s!=="front"&&_(),children:h.preview.front}),i.jsx("button",{className:`tab ${s==="back"?"tab-active bg-primary text-primary-content font-semibold":""}`,onClick:()=>s!=="back"&&_(),children:h.preview.back})]}),i.jsxs("button",{className:"btn btn-ghost btn-sm",onClick:_,children:[i.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-5 w-5",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:i.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"})}),h.preview.flip]})]}),i.jsxs("div",{ref:g,className:`relative w-full overflow-hidden shadow-lg ${ne?j?"cursor-grabbing":"cursor-grab":""}`,style:{aspectRatio:ge},onMouseDown:T,onMouseMove:k,onMouseUp:Y,onMouseLeave:O,onTouchStart:oe,onTouchMove:ie,onTouchEnd:se,children:[i.jsx("canvas",{ref:p,className:`absolute inset-0 w-full h-full transition-all duration-300 ${s==="front"?x?"opacity-0 scale-95":"opacity-100 scale-100":"opacity-0 scale-95 pointer-events-none"}`}),i.jsx("canvas",{ref:v,className:`absolute inset-0 w-full h-full transition-all duration-300 ${s==="back"?x?"opacity-0 scale-95":"opacity-100 scale-100":"opacity-0 scale-95 pointer-events-none"}`})]})]})}function zt(){const e=m.useRef(null),t=m.useRef(null);return{frontCanvasRef:e,backCanvasRef:t}}let Ie=null;function Yt(){return Ie||(Ie=new Worker(new URL("/assets/pdfWorker-DjqCcfZq.js",typeof document>"u"?require("url").pathToFileURL(__filename).href:F&&F.tagName.toUpperCase()==="SCRIPT"&&F.src||new URL("index.cjs",document.baseURI).href),{type:"module"})),Ie}async function $t(e){const n=await(await fetch(e)).blob();return URL.createObjectURL(n)}function Ae(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 Je(e){const{frontTemplateSrc:t,backTemplateSrc:n,templateWidth:r,templateHeight:a,layout:o,portrait:s,portraitZoom:d=1,portraitPanX:c=0,portraitPanY:u=0,templateHue:h=160,name:p,email:v,phone:g,description:x}=e;let f=null;return s&&(f=await $t(s)),new Promise((j,S)=>{const P=Yt(),I=R=>{if(P.removeEventListener("message",I),P.removeEventListener("error",C),f&&URL.revokeObjectURL(f),R.data.type==="success")try{const{frontImageData:B,backImageData:_,width:M,height:H}=R.data;if(!B||!_||!M||!H){S(new Error("Invalid response from worker"));return}const N=Ae(B,"image/jpeg"),U=Ae(_,"image/jpeg"),T=M/96*25.4,k=H/96*25.4,Y=new mt.jsPDF({orientation:T>k?"landscape":"portrait",unit:"mm",format:[T,k]});Y.addImage(N,"JPEG",0,0,T,k),Y.addPage([T,k]),Y.addImage(U,"JPEG",0,0,T,k);const O=Y.output("blob");j(O)}catch(B){S(B)}else S(new Error(R.data.error))},C=R=>{P.removeEventListener("message",I),P.removeEventListener("error",C),f&&URL.revokeObjectURL(f),S(new Error(R.message))};P.addEventListener("message",I),P.addEventListener("error",C),P.postMessage({type:"generate",frontTemplateUrl:t,backTemplateUrl:n,portraitUrl:f,templateWidth:r,templateHeight:a,templateHue:h,portraitZoom:d,portraitPanX:c,portraitPanY:u,layout:{front:{portrait:o.front.portrait,namePlate:o.front.namePlate},back:{namePlate:o.back.namePlate,contactInfo:o.back.contactInfo,description:o.back.description}},name:p,email:v,phone:g,description:x})})}function Qe(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 et(e){const t=await Je(e);Qe(t,e.filename)}function Xt(){const e=w(f=>f.voucherConfig.language),t=w(f=>f.voucherConfig.hours),n=w(f=>f.voucherConfig.description),r=w(f=>f.voucherConfig.templateHue),a=w(f=>f.personalInfo),o=w(f=>f.portrait),s=w(f=>f.isExporting),d=w(f=>f.setIsExporting),c=V(e),u=Oe(e,t),h=Ce(e),p=o.useEnhanced&&o.enhanced?o.enhanced:o.original,v=Ee(e,t,n),g=a.name.trim().length>0&&a.email.trim().length>0&&a.phone.trim().length>0&&o.original!==null,x=async()=>{if(!(!g||s)){d(!0);try{const f=`zeitgutschein-${t}h-${a.name.replace(/\s+/g,"-").toLowerCase()}.pdf`;await et({frontTemplateSrc:u.front,backTemplateSrc:u.back,templateWidth:u.width,templateHeight:u.height,layout:h,portrait:p,portraitZoom:o.zoom,portraitPanX:o.panX,portraitPanY:o.panY,templateHue:r,name:a.name,email:a.email,phone:a.phone,description:v,filename:f})}catch(f){console.error("PDF export failed:",f)}finally{d(!1)}}};return i.jsxs("button",{className:`btn btn-primary flex-1 ${g?"":"btn-disabled"}`,onClick:x,disabled:!g,"aria-busy":s,children:[s?i.jsx("span",{className:"loading loading-spinner loading-sm"}):i.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-5 w-5",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:i.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"})}),c.export.button]})}function tt(){const e=w(r=>r.voucherConfig.language),t=w(r=>r.setLanguage),n=r=>{t(r)};return i.jsxs("div",{className:"join",children:[i.jsx("button",{className:`join-item btn btn-sm ${e==="de"?"btn-active btn-primary":"btn-ghost"}`,onClick:()=>n("de"),children:"DE"}),i.jsx("button",{className:`join-item btn btn-sm ${e==="en"?"btn-active btn-primary":"btn-ghost"}`,onClick:()=>n("en"),children:"EN"})]})}function Ft(){const e=w(n=>n.voucherConfig.language),t=V(e);return i.jsxs("div",{className:"navbar bg-currency-green text-currency-cream shadow-lg",children:[i.jsx("div",{className:"navbar-start",children:i.jsx("a",{className:"btn btn-ghost text-xl font-currency font-bold",children:t.header.title})}),i.jsx("div",{className:"navbar-center hidden sm:flex",children:i.jsx("span",{className:"text-sm opacity-80",children:t.header.subtitle})}),i.jsx("div",{className:"navbar-end",children:i.jsx(tt,{})})]})}const he="/",Ot={id:"time-voucher-classic-de",name:"Zeitgutschein Classic",type:"time-voucher",category:"classic",images:{front:`${he}templates/front_hdpi_de.jpg`,back:`${he}templates/back_hdpi_de.jpg`,width:6144,height:4096},fields:[{id:"name",type:"text",label:{de:"Name",en:"Name"},required:!0,validation:{minLength:1,maxLength:50}},{id:"hours",type:"select",label:{de:"Stunden",en:"Hours"},required:!0,options:["1","5","10"]},{id:"portrait",type:"image",label:{de:"Portrait",en:"Portrait"},required:!1},{id:"email",type:"text",label:{de:"E-Mail",en:"Email"},required:!1},{id:"phone",type:"text",label:{de:"Telefon",en:"Phone"},required:!1},{id:"description",type:"textarea",label:{de:"Beschreibung",en:"Description"},required:!1,validation:{maxLength:200}}],layout:{front:{portrait:q.front.portrait,name:q.front.namePlate},back:{name:q.back.namePlate,contactInfo:q.back.contactInfo,description:q.back.description}},languages:["de"]},Wt={id:"time-voucher-classic-en",name:"Time Voucher Classic",type:"time-voucher",category:"classic",images:{front:`${he}templates/front_ldpi_en.png`,back:`${he}templates/back_ldpi_en.png`,width:1536,height:1024},fields:[{id:"name",type:"text",label:{de:"Name",en:"Name"},required:!0,validation:{minLength:1,maxLength:50}},{id:"hours",type:"select",label:{de:"Stunden",en:"Hours"},required:!0,options:["1","5","10"]},{id:"portrait",type:"image",label:{de:"Portrait",en:"Portrait"},required:!1},{id:"email",type:"text",label:{de:"E-Mail",en:"Email"},required:!1},{id:"phone",type:"text",label:{de:"Telefon",en:"Phone"},required:!1},{id:"description",type:"textarea",label:{de:"Beschreibung",en:"Description"},required:!1,validation:{maxLength:200}}],layout:{front:{portrait:K.front.portrait,name:K.front.namePlate},back:{name:K.back.namePlate,contactInfo:K.back.contactInfo,description:K.back.description}},languages:["en"]},_e=[Ot,Wt],nt={async listTemplates(e){let t=[..._e];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=_e.find(n=>n.id===e);if(!t)throw new Error(`Template not found: ${e}`);return t}};function Kt(e){return e==="de"?"time-voucher-classic-de":"time-voucher-classic-en"}let me=nt;function qt(e){me=e}function Vt(){return me}async function Zt(e){return me.listTemplates(e)}async function Gt(e){return me.getTemplate(e)}exports.ApiKeyModal=Fe;exports.BillPreview=Ht;exports.ExportButton=Xt;exports.Header=Ft;exports.LAYOUT_HDPI=q;exports.LAYOUT_LDPI=K;exports.LanguageToggle=tt;exports.PersonalInfoForm=wt;exports.PortraitUpload=Mt;exports.TEMPLATES=Se;exports.VoucherConfig=Dt;exports.applyEngravingEffect=Ue;exports.applyHueShift=He;exports.downloadBlob=Qe;exports.drawContactInfo=Ve;exports.drawMultilineText=qe;exports.drawOvalPortrait=Ke;exports.drawTemplate=Re;exports.drawText=Te;exports.enhancePortrait=Bt;exports.exportBillAsPDF=et;exports.formatDescription=Ee;exports.generateBillPDF=Je;exports.getApiKey=pe;exports.getDefaultTemplateId=Kt;exports.getLayout=Ce;exports.getRemoveBackgroundEndpoint=St;exports.getTemplate=Oe;exports.getTemplateById=Gt;exports.getTemplateProvider=Vt;exports.hasApiKey=Pe;exports.hasCustomEndpoint=Ct;exports.listTemplates=Zt;exports.loadImage=ee;exports.removeBackground=Xe;exports.renderBackSide=Ge;exports.renderFrontSide=Ze;exports.setApiKey=$e;exports.setRemoveBackgroundEndpoint=jt;exports.setTemplateProvider=qt;exports.staticTemplateProvider=nt;exports.t=V;exports.useBillCanvasRefs=zt;exports.useBillStore=w;
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("react/jsx-runtime"),mt=require("zustand"),gt=require("zustand/middleware"),m=require("react"),ft=require("jspdf");var ne=typeof document<"u"?document.currentScript:null;const De={personalInfo:{name:"",email:"",phone:""},voucherConfig:{hours:1,description:"",language:"de",templateHue:160},portrait:{original:null,enhanced:null,useEnhanced:!1,zoom:1,panX:0,panY:0,rawImage:null,bgRemovedImage:null,bgRemoved:!1,bgOpacity:0,bgBlur:0,engravingIntensity:0},currentSide:"front",isEnhancing:!1,isExporting:!1},x=mt.create()(gt.persist(e=>({...De,setPersonalInfo:t=>e(n=>({personalInfo:{...n.personalInfo,...t}})),setVoucherConfig:t=>e(n=>({voucherConfig:{...n.voucherConfig,...t}})),setPortrait:(t,n=null)=>e(r=>({portrait:{...r.portrait,original:t,enhanced:n,useEnhanced:!1,zoom:r.portrait.original&&t?r.portrait.zoom:1,panX:r.portrait.original&&t?r.portrait.panX:0,panY:r.portrait.original&&t?r.portrait.panY:0}})),setEnhancedPortrait:t=>e(n=>({portrait:{...n.portrait,enhanced:t,useEnhanced:t!==null}})),toggleUseEnhanced:()=>e(t=>({portrait:{...t.portrait,useEnhanced:t.portrait.enhanced?!t.portrait.useEnhanced:!1}})),setPortraitZoom:t=>e(n=>({portrait:{...n.portrait,zoom:t}})),setPortraitPan:(t,n)=>e(r=>({portrait:{...r.portrait,panX:t,panY:n}})),setPortraitRawImage:t=>e(n=>({portrait:{...n.portrait,rawImage:t}})),setPortraitBgRemoved:(t,n)=>e(r=>({portrait:{...r.portrait,bgRemoved:t,bgRemovedImage:n!==void 0?n:r.portrait.bgRemovedImage}})),setPortraitBgOpacity:t=>e(n=>({portrait:{...n.portrait,bgOpacity:t}})),setPortraitBgBlur:t=>e(n=>({portrait:{...n.portrait,bgBlur:t}})),setPortraitEngravingIntensity:t=>e(n=>({portrait:{...n.portrait,engravingIntensity:t}})),setCurrentSide:t=>e({currentSide:t}),flipSide:()=>e(t=>({currentSide:t.currentSide==="front"?"back":"front"})),setIsEnhancing:t=>e({isEnhancing:t}),setIsExporting:t=>e({isExporting:t}),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(De)}),{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}})})),bt={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"}},xt={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"}},wt={de:bt,en:xt};function G(e){return wt[e]}function Se(e,t,n){if(n&&n.trim())return n;const r=G(e),a=t===1?r.form.voucher.hourLabel:r.form.voucher.hoursLabel;return r.bill.descriptionText.replace("{hours}",t.toString()).replace("{hourLabel}",a)}function yt(){const e=x(a=>a.voucherConfig.language),t=x(a=>a.personalInfo),n=x(a=>a.setPersonalInfo),r=G(e);return i.jsxs("div",{className:"space-y-4",children:[i.jsxs("div",{className:"form-control",children:[i.jsx("label",{className:"label",children:i.jsx("span",{className:"label-text font-medium",children:r.form.personalInfo.name})}),i.jsx("input",{type:"text",placeholder:r.form.personalInfo.namePlaceholder,className:"input input-bordered w-full",value:t.name,onChange:a=>n({name:a.target.value})})]}),i.jsxs("div",{className:"form-control",children:[i.jsx("label",{className:"label",children:i.jsx("span",{className:"label-text font-medium",children:r.form.personalInfo.email})}),i.jsx("input",{type:"email",placeholder:r.form.personalInfo.emailPlaceholder,className:"input input-bordered w-full",value:t.email,onChange:a=>n({email:a.target.value})})]}),i.jsxs("div",{className:"form-control",children:[i.jsx("label",{className:"label",children:i.jsx("span",{className:"label-text font-medium",children:r.form.personalInfo.phone})}),i.jsx("input",{type:"tel",placeholder:r.form.personalInfo.phonePlaceholder,className:"input input-bordered w-full",value:t.phone,onChange:a=>n({phone:a.target.value})})]})]})}const vt=1024,ee=new Map;let W=null,He=null;function Te(e,t){return W||(W=document.createElement("canvas"),He=W.getContext("2d",{willReadFrequently:!0})),(W.width!==e||W.height!==t)&&(W.width=e,W.height=t),He}function ie(e){const t=ee.get(e);return t?Promise.resolve(t):new Promise((n,r)=>{const a=new Image;a.onload=()=>{if(ee.size>10){const o=ee.keys().next().value;o&&ee.delete(o)}ee.set(e,a),n(a)},a.onerror=()=>r(new Error("Failed to load image")),a.src=e})}function It(){ee.clear()}async function kt(e,t=vt){const n=await ie(e),r=Math.max(n.width,n.height);if(r<=t)return e;const a=t/r,o=Math.round(n.width*a),s=Math.round(n.height*a),d=document.createElement("canvas"),c=d.getContext("2d");if(!c)throw new Error("Failed to get canvas context");return d.width=o,d.height=s,c.drawImage(n,0,0,o,s),d.toDataURL("image/jpeg",.9)}async function ye(e,t,n,r=0){const[a,o]=await Promise.all([ie(e),ie(t)]),s=Te(a.width,a.height);if(s.clearRect(0,0,a.width,a.height),n>0){const d=r*20;s.save(),s.globalAlpha=n,d>0&&(s.filter=`blur(${d}px)`),s.drawImage(o,0,0,a.width,a.height),s.restore()}return s.drawImage(a,0,0),W.toDataURL("image/png")}async function _e(e,t=.5){const n=await ie(e),r=Te(n.width,n.height);r.drawImage(n,0,0);const a=r.getImageData(0,0,n.width,n.height),o=a.data,s=new Uint32Array(o.buffer),d=1+t*.8,c=1-t;for(let u=0;u<s.length;u++){const p=s[u],h=p&255,w=p>>8&255,g=p>>16&255,v=p>>24&255;if(v===0)continue;let k=(((77*h+150*w+29*g>>8)/255-.5)*d+.5)*255;k<0?k=0:k>255&&(k=255);let P=k*.9+25,T=k*.78+15,I=k*.55+5;P>255&&(P=255),T>255&&(T=255),I>255&&(I=255);const C=h*c+P*t|0,E=w*c+T*t|0,D=g*c+I*t|0;s[u]=v<<24|D<<16|E<<8|C}return r.putImageData(a,0,0),W.toDataURL("image/png")}function Pt(e,t,n){e/=255,t/=255,n/=255;const r=Math.max(e,t,n),a=Math.min(e,t,n),o=(r+a)/2;let s=0,d=0;if(r!==a){const c=r-a;switch(d=o>.5?c/(2-r-a):c/(r+a),r){case e:s=((t-n)/c+(t<n?6:0))/6;break;case t:s=((n-e)/c+2)/6;break;case n:s=((e-t)/c+4)/6;break}}return[s,d,o]}function Ct(e,t,n){if(t===0){const s=Math.round(n*255);return[s,s,s]}const r=(s,d,c)=>(c<0&&(c+=1),c>1&&(c-=1),c<1/6?s+(d-s)*6*c:c<1/2?d:c<2/3?s+(d-s)*(2/3-c)*6:s),a=n<.5?n*(1+t):n+t-n*t,o=2*n-a;return[Math.round(r(o,a,e+1/3)*255),Math.round(r(o,a,e)*255),Math.round(r(o,a,e-1/3)*255)]}async function ze(e,t){if(t>=155&&t<=165)return e;const n=await ie(e),r=Te(n.width,n.height);r.drawImage(n,0,0);const a=r.getImageData(0,0,n.width,n.height),o=a.data,s=new Uint32Array(o.buffer),d=t%360/360,c=60/360,u=260/360,p=1e5,h=s.length;for(let w=0;w<h;w+=p){const g=Math.min(w+p,h);for(let v=w;v<g;v++){const b=s[v],k=b&255,P=b>>8&255,T=b>>16&255,I=b>>24&255;if(I===0)continue;const[C,E,D]=Pt(k,P,T);if(E<.06||C<c||C>u)continue;const B=d,[L,_,j]=Ct(B,E,D);s[v]=I<<24|j<<16|_<<8|L}g<h&&await new Promise(v=>setTimeout(v,0))}return r.putImageData(a,0,0),W.toDataURL("image/png")}const St="https://api.stability.ai/v1/generation",Tt="https://api.stability.ai/v2beta/stable-image/edit/remove-background",We="stability_api_key";let ae=null;function Rt(e){ae=e}function Et(){return ae}function jt(){return ae!==null}const Bt={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 Lt(e,t){const n=e/t;let r=Me[0],a=1/0;for(const o of Me){const s=o.width/o.height,d=Math.abs(n-s);d<a&&(a=d,r=o)}return r}function Nt(e){return new Promise((t,n)=>{const r=new Image;r.onload=()=>{const a=Lt(r.width,r.height),o=document.createElement("canvas");o.width=a.width,o.height=a.height;const s=o.getContext("2d");if(!s){n(new Error("Failed to get canvas context"));return}const d=r.width/r.height,c=a.width/a.height;let u=0,p=0,h=r.width,w=r.height;d>c?(h=r.height*c,u=(r.width-h)/2):(w=r.width/c,p=(r.height-w)/2),s.drawImage(r,u,p,h,w,0,0,a.width,a.height),t(o.toDataURL("image/png"))},r.onerror=()=>n(new Error("Failed to load image")),r.src=e})}function Xe(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,o=new Uint8Array(a);for(let d=0;d<a;d++)o[d]=r.charCodeAt(d);return new Blob([o],{type:n})}function he(){var t;const e=typeof{url:typeof document>"u"?require("url").pathToFileURL(__filename).href:ne&&ne.tagName.toUpperCase()==="SCRIPT"&&ne.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(We):null}function $e(e){localStorage.setItem(We,e)}function Pe(){return ae?!0:he()!==null}async function Dt(e){const t=he();if(!t)throw new Error("No Stability AI API key configured");const{imageDataUrl:n,style:r,strength:a=.35}=e,o=await Nt(n),s=Xe(o),d=new FormData;d.append("init_image",s,"portrait.png"),d.append("init_image_mode","IMAGE_STRENGTH"),d.append("image_strength",String(1-a)),d.append("text_prompts[0][text]",Bt[r]),d.append("text_prompts[0][weight]","1"),d.append("cfg_scale","7"),d.append("samples","1"),d.append("steps","30");const u=await fetch(`${St}/stable-diffusion-xl-1024-v1-0/image-to-image`,{method:"POST",headers:{Authorization:`Bearer ${t}`,Accept:"application/json"},body:d});if(!u.ok){const h=await u.text();throw console.error("Stability AI error:",h),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 p=await u.json();if(!p.artifacts||p.artifacts.length===0)throw new Error("No image generated");return`data:image/png;base64,${p.artifacts[0].base64}`}async function Oe(e){if(ae){const s=await fetch(ae,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({imageDataUrl:e})});if(!s.ok){const c=await s.json().catch(()=>({}));throw new Error(c.error||`API error: ${s.status}`)}return(await s.json()).imageDataUrl}const t=he();if(!t)throw new Error("No Stability AI API key configured");const n=Xe(e),r=new FormData;r.append("image",n,"image.png"),r.append("output_format","png");const a=await fetch(Tt,{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 o=await a.blob();return new Promise((s,d)=>{const c=new FileReader;c.onload=()=>s(c.result),c.onerror=()=>d(new Error("Failed to read result")),c.readAsDataURL(o)})}function Ht(){const[e,t]=m.useState(!1),[n,r]=m.useState(!1),[a,o]=m.useState(null),[s,d]=m.useState(()=>Pe());m.useEffect(()=>{d(Pe())},[]);const c=m.useCallback(()=>o(null),[]),u=m.useCallback(w=>{$e(w),d(!0),o(null)},[]),p=m.useCallback(async(w,g=.5)=>{t(!0),o(null);try{return await _e(w,g)}catch(v){const b=v instanceof Error?v.message:"Enhancement failed";throw o(b),v}finally{t(!1)}},[]),h=m.useCallback(async w=>{r(!0),o(null);try{return await Oe(w)}catch(g){const v=g instanceof Error?g.message:"Background removal failed";throw o(v),g}finally{r(!1)}},[]);return{enhance:p,removeBg:h,isEnhancing:e,isRemovingBg:n,error:a,hasKey:s,setApiKey:u,clearError:c}}function Fe({isOpen:e,onClose:t,onSubmit:n}){const r=x(u=>u.voucherConfig.language),[a,o]=m.useState("");if(!e)return null;const s=u=>{u.preventDefault(),a.trim()&&(n(a.trim()),o(""),t())},c={de:{title:"Stability AI API Key",description:"Um die AI-Bildverbesserung zu nutzen, benötigst du einen Stability AI API Key. Du kannst ihn auf platform.stability.ai erhalten.",placeholder:"sk-...",submit:"Speichern",cancel:"Abbrechen",hint:"Der Key wird lokal in deinem Browser gespeichert."},en:{title:"Stability AI API Key",description:"To use AI image enhancement, you need a Stability AI API key. You can get one at platform.stability.ai.",placeholder:"sk-...",submit:"Save",cancel:"Cancel",hint:"The key is stored locally in your browser."}}[r];return i.jsxs("dialog",{className:"modal modal-open",children:[i.jsxs("div",{className:"modal-box",children:[i.jsx("h3",{className:"font-bold text-lg",children:c.title}),i.jsx("p",{className:"py-4 text-sm opacity-80",children:c.description}),i.jsxs("form",{onSubmit:s,children:[i.jsxs("div",{className:"form-control",children:[i.jsx("input",{type:"password",placeholder:c.placeholder,className:"input input-bordered w-full",value:a,onChange:u=>o(u.target.value),autoFocus:!0}),i.jsx("label",{className:"label",children:i.jsx("span",{className:"label-text-alt",children:c.hint})})]}),i.jsxs("div",{className:"modal-action",children:[i.jsx("button",{type:"button",className:"btn btn-ghost",onClick:t,children:c.cancel}),i.jsx("button",{type:"submit",className:"btn btn-primary",disabled:!a.trim(),children:c.submit})]})]})]}),i.jsx("form",{method:"dialog",className:"modal-backdrop",children:i.jsx("button",{onClick:t,children:"close"})})]})}function Mt(){const e=x(l=>l.voucherConfig.language),t=x(l=>l.portrait),n=x(l=>l.setPortrait),r=x(l=>l.setPortraitZoom),a=x(l=>l.setPortraitPan),o=x(l=>l.setPortraitRawImage),s=x(l=>l.setPortraitBgRemoved),d=x(l=>l.setPortraitBgOpacity),c=x(l=>l.setPortraitBgBlur),u=x(l=>l.setPortraitEngravingIntensity),{enhance:p,removeBg:h,isEnhancing:w,isRemovingBg:g,error:v,hasKey:b,setApiKey:k}=Ht(),P=G(e),T=m.useRef(null),I=m.useRef(null),[C,E]=m.useState(!1),[D,B]=m.useState(!1),[L,_]=m.useState(!1),j=m.useRef(null),H=m.useRef(null),M=m.useRef(null),R=t.rawImage,z=t.bgRemovedImage,A=t.bgRemoved,X=t.bgOpacity,V=t.bgBlur,se=t.engravingIntensity;m.useEffect(()=>{t.original&&!t.rawImage&&o(t.original)},[t.original,t.rawImage,o]),m.useEffect(()=>()=>{H.current&&clearTimeout(H.current),M.current&&clearTimeout(M.current)},[]);const re=m.useCallback(async l=>{if(!l.type.startsWith("image/"))return;const y=new FileReader;y.onload=async S=>{var ue;const U=(ue=S.target)==null?void 0:ue.result,de=await kt(U);o(de),n(de),s(!1,null),u(0)},y.readAsDataURL(l)},[n,o,s,u]),ge=m.useCallback(l=>{l.preventDefault(),E(!1);const y=l.dataTransfer.files[0];y&&re(y)},[re]),f=m.useCallback(l=>{l.preventDefault(),E(!0)},[]),N=m.useCallback(l=>{l.preventDefault(),E(!1)},[]),$=()=>{var l;(l=T.current)==null||l.click()},Z=l=>{var S;const y=(S=l.target.files)==null?void 0:S[0];y&&re(y)},O=m.useCallback(async(l,y)=>{try{return await p(l,y)}catch(S){return console.error("Enhancement failed:",S),l}},[p]),J=m.useCallback(async l=>{try{const y=await h(l);return s(!0,y),y}catch(y){return console.error("Background removal failed:",y),l}},[h,s]),F=m.useCallback(async()=>{const l=x.getState().portrait;if(!l.rawImage)return;let y;l.bgRemoved&&l.bgRemovedImage?y=await ye(l.bgRemovedImage,l.rawImage,l.bgOpacity,l.bgBlur):y=l.rawImage,l.engravingIntensity>0&&(y=await O(y,l.engravingIntensity)),n(y)},[O,n]),oe=async()=>{if(!R)return;if(!A&&!b){B(!0);return}if(!A){const y=await J(R),S=x.getState().portrait;let U=await ye(y,R,S.bgOpacity,S.bgBlur);S.engravingIntensity>0&&(U=await O(U,S.engravingIntensity)),n(U)}else{s(!1,null);const y=x.getState().portrait.engravingIntensity;if(y>0){const S=await O(R,y);n(S)}else n(R)}},fe=l=>{u(l),H.current&&clearTimeout(H.current),R&&(H.current=setTimeout(F,150))},be=async l=>{if(k(l),!R)return;const y=await J(R),S=x.getState().portrait;let U=await ye(y,R,S.bgOpacity,S.bgBlur);S.engravingIntensity>0&&(U=await O(U,S.engravingIntensity)),n(U)},xe=l=>{d(l),M.current&&clearTimeout(M.current),!(!R||!z)&&(M.current=setTimeout(F,150))},le=l=>{c(l),M.current&&clearTimeout(M.current),!(!R||!z)&&(M.current=setTimeout(F,150))},ce=()=>{n(null),o(null),s(!1,null),d(0),c(0),u(0),It()},Le=(l,y)=>{t.zoom<=1||(_(!0),j.current={x:l,y,panX:t.panX,panY:t.panY})},Ne=(l,y)=>{if(!L||!j.current||!I.current)return;const S=I.current.getBoundingClientRect(),U=2/Math.max(S.width,S.height),de=(l-j.current.x)*U,ue=(y-j.current.y)*U,pt=Math.max(-1,Math.min(1,j.current.panX+de)),ht=Math.max(-1,Math.min(1,j.current.panY+ue));a(pt,ht)},we=()=>{_(!1),j.current=null},ot=l=>{l.preventDefault(),Le(l.clientX,l.clientY)},it=l=>{Ne(l.clientX,l.clientY)},st=()=>{we()},lt=()=>{we()},ct=l=>{l.touches.length===1&&Le(l.touches[0].clientX,l.touches[0].clientY)},dt=l=>{l.touches.length===1&&Ne(l.touches[0].clientX,l.touches[0].clientY)},ut=()=>{we()};return i.jsxs("div",{className:"space-y-4",children:[t.original?i.jsxs("div",{className:"flex flex-col items-center space-y-4",children:[i.jsxs("div",{className:"relative",children:[i.jsx("div",{ref:I,className:`w-32 h-32 rounded-full overflow-hidden border-4 border-currency-gold shadow-lg ${t.zoom>1?"cursor-grab":""} ${L?"cursor-grabbing":""}`,onMouseDown:ot,onMouseMove:it,onMouseUp:st,onMouseLeave:lt,onTouchStart:ct,onTouchMove:dt,onTouchEnd:ut,children:i.jsx("img",{src:t.original||"",alt:"Portrait",className:"w-full h-full object-cover pointer-events-none select-none",style:{transform:`scale(${t.zoom}) translate(${t.panX*50*(t.zoom-1)}%, ${t.panY*50*(t.zoom-1)}%)`},draggable:!1})}),i.jsx("button",{className:"btn btn-circle btn-xs btn-error absolute -top-1 -right-1",onClick:ce,children:i.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-4 w-4",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:i.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M6 18L18 6M6 6l12 12"})})})]}),i.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-4 w-full",children:[i.jsxs("div",{className:"form-control w-full",children:[i.jsxs("label",{className:"label",children:[i.jsx("span",{className:"label-text",children:P.form.portrait.zoom}),i.jsxs("span",{className:"label-text-alt",children:[Math.round(t.zoom*100),"%"]})]}),i.jsx("input",{type:"range",min:"0.5",max:"2",step:"0.05",value:t.zoom,onChange:l=>{const y=parseFloat(l.target.value);r(y),y<=1&&(t.panX!==0||t.panY!==0)&&a(0,0)},className:"range range-primary range-sm"})]}),i.jsxs("div",{className:"form-control w-full",children:[i.jsxs("label",{className:"label",children:[i.jsxs("span",{className:"label-text flex items-center gap-2",children:[e==="de"?"Sepia-Effekt":"Sepia effect",w&&i.jsx("span",{className:"loading loading-spinner loading-xs"})]}),i.jsxs("span",{className:"label-text-alt",children:[Math.round(se*100),"%"]})]}),i.jsx("input",{type:"range",min:"0",max:"1",step:"0.05",value:se,onChange:l=>fe(parseFloat(l.target.value)),className:"range range-secondary range-sm",disabled:w||!R})]})]}),A?i.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-4 w-full",children:[i.jsxs("div",{className:"form-control w-full",children:[i.jsxs("label",{className:"label",children:[i.jsx("span",{className:"label-text",children:e==="de"?"Hintergrund":"Background"}),i.jsxs("span",{className:"label-text-alt",children:[Math.round(X*100),"%"]})]}),i.jsx("input",{type:"range",min:"0",max:"1",step:"0.05",value:X,onChange:l=>xe(parseFloat(l.target.value)),className:"range range-primary range-sm"})]}),i.jsxs("div",{className:"form-control w-full",children:[i.jsxs("label",{className:"label",children:[i.jsx("span",{className:"label-text",children:e==="de"?"Unschärfe":"Blur"}),i.jsxs("span",{className:"label-text-alt",children:[Math.round(V*100),"%"]})]}),i.jsx("input",{type:"range",min:"0",max:"1",step:"0.05",value:V,onChange:l=>le(parseFloat(l.target.value)),className:"range range-primary range-sm"})]})]}):i.jsx("div",{className:"form-control",children:i.jsxs("label",{className:"label cursor-pointer justify-start gap-3",children:[i.jsx("input",{type:"checkbox",className:`toggle toggle-primary ${g?"opacity-50":""}`,checked:A,onChange:oe,disabled:g||!R}),i.jsxs("span",{className:"label-text flex items-center gap-2",children:[g?i.jsxs(i.Fragment,{children:[i.jsx("span",{className:"loading loading-spinner loading-xs"}),e==="de"?"Hintergrund wird entfernt...":"Removing background..."]}):e==="de"?"Hintergrund entfernen":"Remove background",!b&&i.jsx("span",{className:"badge badge-sm badge-outline",children:"API"})]})]})}),v&&i.jsxs("div",{className:"alert alert-warning text-sm py-2",children:[i.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"stroke-current shrink-0 h-5 w-5",fill:"none",viewBox:"0 0 24 24",children:i.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:"2",d:"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"})}),i.jsx("span",{children:v})]})]}):i.jsxs("div",{className:`border-2 border-dashed rounded-lg p-8 text-center cursor-pointer transition-colors ${g?"border-primary bg-primary/10 pointer-events-none":C?"border-primary bg-primary/10":"border-base-300 hover:border-primary hover:bg-base-200"}`,onDrop:ge,onDragOver:f,onDragLeave:N,onClick:$,children:[i.jsx("input",{ref:T,type:"file",accept:"image/*",className:"hidden",onChange:Z}),g?i.jsxs("div",{className:"flex flex-col items-center gap-2",children:[i.jsx("span",{className:"loading loading-spinner loading-lg text-primary"}),i.jsx("p",{className:"font-medium",children:e==="de"?"Hintergrund wird entfernt...":"Removing background..."})]}):i.jsxs("div",{className:"flex flex-col items-center gap-2",children:[i.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-12 w-12 text-base-content/50",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:i.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"})}),i.jsx("p",{className:"font-medium",children:P.form.portrait.upload}),i.jsx("p",{className:"text-sm text-base-content/60",children:P.form.portrait.dragDrop})]})]}),i.jsx(Fe,{isOpen:D,onClose:()=>B(!1),onSubmit:be})]})}function At(){return null}const Y=typeof{url:typeof document>"u"?require("url").pathToFileURL(__filename).href:ne&&ne.tagName.toUpperCase()==="SCRIPT"&&ne.src||new URL("index.cjs",document.baseURI).href}<"u"&&"/"||"/",Re={en:{1:{front:`${Y}templates/front_ldpi_en.png`,back:`${Y}templates/back_ldpi_en.png`,width:1536,height:1024},5:{front:`${Y}templates/front_ldpi_en.png`,back:`${Y}templates/back_ldpi_en.png`,width:1536,height:1024},10:{front:`${Y}templates/front_ldpi_en.png`,back:`${Y}templates/back_ldpi_en.png`,width:1536,height:1024}},de:{1:{front:`${Y}templates/front_hdpi_de.webp`,back:`${Y}templates/back_hdpi_de.webp`,width:6144,height:3200},5:{front:`${Y}templates/front_hdpi_de.webp`,back:`${Y}templates/back_hdpi_de.webp`,width:6144,height:3200},10:{front:`${Y}templates/front_hdpi_de.webp`,back:`${Y}templates/back_hdpi_de.webp`,width:6144,height:3200}}},q={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"}}},K={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"}}};function Ee(e){return e==="de"?K:q}function qe(e,t){return Re[e][t]}const Ce=.25;function Ut(e){const t=Ee(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 Yt(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,Q=new Map;async function te(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 je(e,t,n,r){e.drawImage(t,0,0,n,r)}async function Ke(e,t,n,r){if(t>=155&&t<=165)return te(e);const a=`${e}:${t}:${n}x${r}`;if(Q.has(a))return te(Q.get(a));const o=await te(e),s=document.createElement("canvas");s.width=n,s.height=r;const d=s.getContext("2d");if(!d)throw new Error("Failed to get canvas context");d.drawImage(o,0,0,n,r);const c=s.toDataURL("image/png"),u=await ze(c,t);if(Q.size>20){const p=Q.keys().next().value;p&&Q.delete(p)}return Q.set(a,u),te(u)}function Ge(e,t,n,r,a,o,s=1,d=0,c=0){e.save(),e.beginPath(),e.ellipse(n,r,a,o,0,0,Math.PI*2),e.closePath(),e.clip();const u=t.width/t.height,p=a/o,h=a*2,w=o*2;let g,v;u>p?(v=w,g=w*u):(g=h,v=h/u),g*=s,v*=s;const b=Math.max(0,(g-h)/2),k=Math.max(0,(v-w)/2),P=n-g/2+d*b,T=r-v/2+c*k;e.drawImage(t,P,T,g,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 Ve(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,o=n.lineHeight||n.fontSize*1.4,s=t.split(" "),d=[];let c="";for(const h of s){const w=c?`${c} ${h}`:h;e.measureText(w).width>a&&c?(d.push(c),c=h):c=w}c&&d.push(c);const u=d.length*o;let p=n.y-u/2;for(const h of d)e.fillText(h,n.x,p),p+=o;e.restore()}function Ze(e,t,n,r,a,o="#2a3a2a"){e.save(),e.font=`${a.fontSize}px "Times New Roman", serif`,e.textAlign=a.align||"center",e.textBaseline="middle",e.fillStyle=o;const s=a.lineHeight||a.fontSize*1.8,d=[t,n,r].filter(Boolean),c=(d.length-1)*s;let u=a.y-c/2;for(const p of d)p&&(e.fillText(p,a.x,u),u+=s);e.restore()}async function Je(e,t,n,r,a,o,s,d=1,c=0,u=0,p=0){const h=e.getContext("2d");if(!h)return;e.width=o,e.height=s,h.clearRect(0,0,o,s);const w=await Ke(t,p,o,s);if(je(h,w,o,s),n)try{const g=await te(n);Ge(h,g,a.portrait.x,a.portrait.y,a.portrait.radiusX,a.portrait.radiusY,d,c,u)}catch(g){console.error("Failed to load portrait:",g)}r&&Be(h,r,a.namePlate)}async function Qe(e,t,n,r,a,o,s,d,c,u=0){const p=e.getContext("2d");if(!p)return;e.width=d,e.height=c,p.clearRect(0,0,d,c);const h=await Ke(t,u,d,c);je(p,h,d,c),s.contactInfo&&(n||r||a)&&Ze(p,n,r,a,s.contactInfo),s.description&&o&&Ve(p,o,s.description),n&&Be(p,n,s.namePlate)}function _t(e,t){const[n,r]=m.useState(e);return m.useEffect(()=>{const a=setTimeout(()=>r(e),t);return()=>clearTimeout(a)},[e,t]),n}function zt(){const e=x(f=>f.voucherConfig.language),t=x(f=>f.voucherConfig.hours),n=x(f=>f.voucherConfig.description),r=x(f=>f.voucherConfig.templateHue),a=x(f=>f.personalInfo),o=x(f=>f.portrait),s=x(f=>f.currentSide),d=x(f=>f.flipSide),c=x(f=>f.setPortraitPan),u=_t(r,150),p=G(e),h=m.useRef(null),w=m.useRef(null),g=m.useRef(null),[v,b]=m.useState(!1),[k,P]=m.useState(!1),T=m.useRef(null),I=Yt(e,t),C=Ut(e),E=o.useEnhanced&&o.enhanced?o.enhanced:o.original,D=Se(e,t,n);m.useEffect(()=>{h.current&&Je(h.current,I.front,E,a.name,C.front,I.width,I.height,o.zoom,o.panX,o.panY,u)},[I,E,a.name,C,o.zoom,o.panX,o.panY,u]),m.useEffect(()=>{w.current&&Qe(w.current,I.back,a.name,a.email,a.phone,D,C.back,I.width,I.height,u)},[I,a,D,C,u]);const B=()=>{b(!0),setTimeout(()=>{d(),b(!1)},150)},L=m.useCallback((f,N)=>{if(!g.current||s!=="front"||!o.original)return!1;const $=g.current.getBoundingClientRect(),Z=$.width/I.width,O=$.height/I.height,J=(f-$.left)/Z,F=(N-$.top)/O,{x:oe,y:fe,radiusX:be,radiusY:xe}=C.front.portrait,le=(J-oe)/be,ce=(F-fe)/xe;return le*le+ce*ce<=1},[s,o.original,I.width,I.height,C.front.portrait]),_=m.useCallback((f,N)=>{o.zoom<=1||!L(f,N)||(P(!0),T.current={x:f,y:N,panX:o.panX,panY:o.panY})},[o.zoom,o.panX,o.panY,L]),j=m.useCallback((f,N)=>{if(!k||!T.current||!g.current)return;const $=g.current.getBoundingClientRect(),Z=3/Math.max($.width,$.height),O=(f-T.current.x)*Z,J=(N-T.current.y)*Z,F=Math.max(-1,Math.min(1,T.current.panX+O)),oe=Math.max(-1,Math.min(1,T.current.panY+J));c(F,oe)},[k,c]),H=m.useCallback(()=>{P(!1),T.current=null},[]),M=f=>{o.zoom>1&&L(f.clientX,f.clientY)&&(f.preventDefault(),_(f.clientX,f.clientY))},R=f=>{j(f.clientX,f.clientY)},z=()=>H(),A=()=>H(),X=f=>{if(f.touches.length===1){const N=f.touches[0];o.zoom>1&&L(N.clientX,N.clientY)&&_(N.clientX,N.clientY)}},V=f=>{f.touches.length===1&&j(f.touches[0].clientX,f.touches[0].clientY)},se=()=>H(),re=s==="front"&&o.original&&o.zoom>1,ge=I.width/I.height;return i.jsxs("div",{className:"space-y-4",children:[i.jsxs("div",{className:"flex justify-between items-center",children:[i.jsxs("div",{className:"tabs tabs-boxed bg-base-200",children:[i.jsx("button",{className:`tab ${s==="front"?"tab-active bg-primary text-primary-content font-semibold":""}`,onClick:()=>s!=="front"&&B(),children:p.preview.front}),i.jsx("button",{className:`tab ${s==="back"?"tab-active bg-primary text-primary-content font-semibold":""}`,onClick:()=>s!=="back"&&B(),children:p.preview.back})]}),i.jsxs("button",{className:"btn btn-ghost btn-sm",onClick:B,children:[i.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-5 w-5",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:i.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"})}),p.preview.flip]})]}),i.jsxs("div",{ref:g,className:`relative w-full overflow-hidden shadow-lg ${re?k?"cursor-grabbing":"cursor-grab":""}`,style:{aspectRatio:ge},onMouseDown:M,onMouseMove:R,onMouseUp:z,onMouseLeave:A,onTouchStart:X,onTouchMove:V,onTouchEnd:se,children:[i.jsx("canvas",{ref:h,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"}`}),i.jsx("canvas",{ref:w,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 Wt(){const e=m.useRef(null),t=m.useRef(null);return{frontCanvasRef:e,backCanvasRef:t}}const Xt=`
|
|
2
|
+
// RGB to HSL conversion
|
|
3
|
+
function rgbToHsl(r, g, b) {
|
|
4
|
+
r /= 255;
|
|
5
|
+
g /= 255;
|
|
6
|
+
b /= 255;
|
|
7
|
+
|
|
8
|
+
const max = Math.max(r, g, b);
|
|
9
|
+
const min = Math.min(r, g, b);
|
|
10
|
+
const l = (max + min) / 2;
|
|
11
|
+
let h = 0;
|
|
12
|
+
let s = 0;
|
|
13
|
+
|
|
14
|
+
if (max !== min) {
|
|
15
|
+
const d = max - min;
|
|
16
|
+
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
|
17
|
+
|
|
18
|
+
switch (max) {
|
|
19
|
+
case r:
|
|
20
|
+
h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
|
|
21
|
+
break;
|
|
22
|
+
case g:
|
|
23
|
+
h = ((b - r) / d + 2) / 6;
|
|
24
|
+
break;
|
|
25
|
+
case b:
|
|
26
|
+
h = ((r - g) / d + 4) / 6;
|
|
27
|
+
break;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return [h, s, l];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// HSL to RGB conversion
|
|
35
|
+
function hslToRgb(h, s, l) {
|
|
36
|
+
if (s === 0) {
|
|
37
|
+
const gray = Math.round(l * 255);
|
|
38
|
+
return [gray, gray, gray];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const hue2rgb = (p, q, t) => {
|
|
42
|
+
if (t < 0) t += 1;
|
|
43
|
+
if (t > 1) t -= 1;
|
|
44
|
+
if (t < 1 / 6) return p + (q - p) * 6 * t;
|
|
45
|
+
if (t < 1 / 2) return q;
|
|
46
|
+
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
|
|
47
|
+
return p;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
|
51
|
+
const p = 2 * l - q;
|
|
52
|
+
|
|
53
|
+
return [
|
|
54
|
+
Math.round(hue2rgb(p, q, h + 1 / 3) * 255),
|
|
55
|
+
Math.round(hue2rgb(p, q, h) * 255),
|
|
56
|
+
Math.round(hue2rgb(p, q, h - 1 / 3) * 255),
|
|
57
|
+
];
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Apply hue shift to ImageData
|
|
61
|
+
function applyHueShiftToImageData(imageData, targetHue) {
|
|
62
|
+
if (targetHue >= 155 && targetHue <= 165) return;
|
|
63
|
+
|
|
64
|
+
const pixels = new Uint32Array(imageData.data.buffer);
|
|
65
|
+
const targetH = (targetHue % 360) / 360;
|
|
66
|
+
const coolHueMin = 60 / 360;
|
|
67
|
+
const coolHueMax = 260 / 360;
|
|
68
|
+
|
|
69
|
+
for (let i = 0; i < pixels.length; i++) {
|
|
70
|
+
const pixel = pixels[i];
|
|
71
|
+
const r = pixel & 0xff;
|
|
72
|
+
const g = (pixel >> 8) & 0xff;
|
|
73
|
+
const b = (pixel >> 16) & 0xff;
|
|
74
|
+
const a = (pixel >> 24) & 0xff;
|
|
75
|
+
|
|
76
|
+
if (a === 0) continue;
|
|
77
|
+
|
|
78
|
+
const [h, s, l] = rgbToHsl(r, g, b);
|
|
79
|
+
if (s < 0.06) continue;
|
|
80
|
+
if (h < coolHueMin || h > coolHueMax) continue;
|
|
81
|
+
|
|
82
|
+
const [newR, newG, newB] = hslToRgb(targetH, s, l);
|
|
83
|
+
pixels[i] = (a << 24) | (newB << 16) | (newG << 8) | newR;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Load image from blob URL in worker
|
|
88
|
+
async function loadImageBitmap(url) {
|
|
89
|
+
const response = await fetch(url);
|
|
90
|
+
const blob = await response.blob();
|
|
91
|
+
return createImageBitmap(blob);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Draw oval portrait with clipping
|
|
95
|
+
function drawOvalPortrait(ctx, portrait, centerX, centerY, radiusX, radiusY, zoom, panX, panY) {
|
|
96
|
+
ctx.save();
|
|
97
|
+
ctx.beginPath();
|
|
98
|
+
ctx.ellipse(centerX, centerY, radiusX, radiusY, 0, 0, Math.PI * 2);
|
|
99
|
+
ctx.closePath();
|
|
100
|
+
ctx.clip();
|
|
101
|
+
|
|
102
|
+
const imgAspect = portrait.width / portrait.height;
|
|
103
|
+
const ellipseAspect = radiusX / radiusY;
|
|
104
|
+
const ellipseWidth = radiusX * 2;
|
|
105
|
+
const ellipseHeight = radiusY * 2;
|
|
106
|
+
|
|
107
|
+
let drawWidth, drawHeight;
|
|
108
|
+
|
|
109
|
+
if (imgAspect > ellipseAspect) {
|
|
110
|
+
drawHeight = ellipseHeight;
|
|
111
|
+
drawWidth = ellipseHeight * imgAspect;
|
|
112
|
+
} else {
|
|
113
|
+
drawWidth = ellipseWidth;
|
|
114
|
+
drawHeight = ellipseWidth / imgAspect;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
drawWidth *= zoom;
|
|
118
|
+
drawHeight *= zoom;
|
|
119
|
+
|
|
120
|
+
const maxPanX = Math.max(0, (drawWidth - ellipseWidth) / 2);
|
|
121
|
+
const maxPanY = Math.max(0, (drawHeight - ellipseHeight) / 2);
|
|
122
|
+
|
|
123
|
+
const drawX = centerX - drawWidth / 2 + panX * maxPanX;
|
|
124
|
+
const drawY = centerY - drawHeight / 2 + panY * maxPanY;
|
|
125
|
+
|
|
126
|
+
ctx.drawImage(portrait, drawX, drawY, drawWidth, drawHeight);
|
|
127
|
+
ctx.restore();
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Draw text
|
|
131
|
+
function drawText(ctx, text, x, y, fontSize, align, maxWidth) {
|
|
132
|
+
ctx.save();
|
|
133
|
+
ctx.font = fontSize + 'px "Times New Roman", serif';
|
|
134
|
+
ctx.textAlign = align || 'center';
|
|
135
|
+
ctx.textBaseline = 'middle';
|
|
136
|
+
ctx.fillStyle = '#2a3a2a';
|
|
137
|
+
|
|
138
|
+
if (maxWidth) {
|
|
139
|
+
ctx.fillText(text, x, y, maxWidth);
|
|
140
|
+
} else {
|
|
141
|
+
ctx.fillText(text, x, y);
|
|
142
|
+
}
|
|
143
|
+
ctx.restore();
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Draw multiline text
|
|
147
|
+
function drawMultilineText(ctx, text, x, y, fontSize, maxWidth, lineHeight, align) {
|
|
148
|
+
ctx.save();
|
|
149
|
+
ctx.font = fontSize + 'px "Times New Roman", serif';
|
|
150
|
+
ctx.textAlign = align || 'center';
|
|
151
|
+
ctx.textBaseline = 'top';
|
|
152
|
+
ctx.fillStyle = '#2a3a2a';
|
|
153
|
+
|
|
154
|
+
const words = text.split(' ');
|
|
155
|
+
const lines = [];
|
|
156
|
+
let currentLine = '';
|
|
157
|
+
|
|
158
|
+
for (const word of words) {
|
|
159
|
+
const testLine = currentLine ? currentLine + ' ' + word : word;
|
|
160
|
+
const metrics = ctx.measureText(testLine);
|
|
161
|
+
|
|
162
|
+
if (metrics.width > maxWidth && currentLine) {
|
|
163
|
+
lines.push(currentLine);
|
|
164
|
+
currentLine = word;
|
|
165
|
+
} else {
|
|
166
|
+
currentLine = testLine;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
if (currentLine) lines.push(currentLine);
|
|
170
|
+
|
|
171
|
+
const totalHeight = lines.length * lineHeight;
|
|
172
|
+
let startY = y - totalHeight / 2;
|
|
173
|
+
|
|
174
|
+
for (const line of lines) {
|
|
175
|
+
ctx.fillText(line, x, startY);
|
|
176
|
+
startY += lineHeight;
|
|
177
|
+
}
|
|
178
|
+
ctx.restore();
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Draw contact info
|
|
182
|
+
function drawContactInfo(ctx, name, email, phone, x, y, fontSize, lineHeight, align) {
|
|
183
|
+
ctx.save();
|
|
184
|
+
ctx.font = fontSize + 'px "Times New Roman", serif';
|
|
185
|
+
ctx.textAlign = align || 'center';
|
|
186
|
+
ctx.textBaseline = 'middle';
|
|
187
|
+
ctx.fillStyle = '#2a3a2a';
|
|
188
|
+
|
|
189
|
+
const lines = [name, email, phone].filter(Boolean);
|
|
190
|
+
const totalHeight = (lines.length - 1) * lineHeight;
|
|
191
|
+
let currentY = y - totalHeight / 2;
|
|
192
|
+
|
|
193
|
+
for (const line of lines) {
|
|
194
|
+
if (line) {
|
|
195
|
+
ctx.fillText(line, x, currentY);
|
|
196
|
+
currentY += lineHeight;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
ctx.restore();
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
self.onmessage = async (e) => {
|
|
203
|
+
const {
|
|
204
|
+
frontTemplateUrl,
|
|
205
|
+
backTemplateUrl,
|
|
206
|
+
portraitUrl,
|
|
207
|
+
templateWidth,
|
|
208
|
+
templateHeight,
|
|
209
|
+
templateHue,
|
|
210
|
+
portraitZoom,
|
|
211
|
+
portraitPanX,
|
|
212
|
+
portraitPanY,
|
|
213
|
+
layout,
|
|
214
|
+
name,
|
|
215
|
+
email,
|
|
216
|
+
phone,
|
|
217
|
+
description,
|
|
218
|
+
} = e.data;
|
|
219
|
+
|
|
220
|
+
try {
|
|
221
|
+
// Load images
|
|
222
|
+
const [frontTemplate, backTemplate] = await Promise.all([
|
|
223
|
+
loadImageBitmap(frontTemplateUrl),
|
|
224
|
+
loadImageBitmap(backTemplateUrl),
|
|
225
|
+
]);
|
|
226
|
+
|
|
227
|
+
let portrait = null;
|
|
228
|
+
if (portraitUrl) {
|
|
229
|
+
portrait = await loadImageBitmap(portraitUrl);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Create offscreen canvases
|
|
233
|
+
const frontCanvas = new OffscreenCanvas(templateWidth, templateHeight);
|
|
234
|
+
const backCanvas = new OffscreenCanvas(templateWidth, templateHeight);
|
|
235
|
+
const frontCtx = frontCanvas.getContext('2d');
|
|
236
|
+
const backCtx = backCanvas.getContext('2d');
|
|
237
|
+
|
|
238
|
+
// Render front side
|
|
239
|
+
frontCtx.drawImage(frontTemplate, 0, 0, templateWidth, templateHeight);
|
|
240
|
+
|
|
241
|
+
// Apply hue shift to front
|
|
242
|
+
if (templateHue < 155 || templateHue > 165) {
|
|
243
|
+
const frontImageData = frontCtx.getImageData(0, 0, templateWidth, templateHeight);
|
|
244
|
+
applyHueShiftToImageData(frontImageData, templateHue);
|
|
245
|
+
frontCtx.putImageData(frontImageData, 0, 0);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Draw portrait
|
|
249
|
+
if (portrait) {
|
|
250
|
+
drawOvalPortrait(
|
|
251
|
+
frontCtx,
|
|
252
|
+
portrait,
|
|
253
|
+
layout.front.portrait.x,
|
|
254
|
+
layout.front.portrait.y,
|
|
255
|
+
layout.front.portrait.radiusX,
|
|
256
|
+
layout.front.portrait.radiusY,
|
|
257
|
+
portraitZoom,
|
|
258
|
+
portraitPanX,
|
|
259
|
+
portraitPanY
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// Draw name on front
|
|
264
|
+
if (name) {
|
|
265
|
+
drawText(
|
|
266
|
+
frontCtx,
|
|
267
|
+
name,
|
|
268
|
+
layout.front.namePlate.x,
|
|
269
|
+
layout.front.namePlate.y,
|
|
270
|
+
layout.front.namePlate.fontSize,
|
|
271
|
+
layout.front.namePlate.align || 'center',
|
|
272
|
+
layout.front.namePlate.maxWidth
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// Render back side
|
|
277
|
+
backCtx.drawImage(backTemplate, 0, 0, templateWidth, templateHeight);
|
|
278
|
+
|
|
279
|
+
// Apply hue shift to back
|
|
280
|
+
if (templateHue < 155 || templateHue > 165) {
|
|
281
|
+
const backImageData = backCtx.getImageData(0, 0, templateWidth, templateHeight);
|
|
282
|
+
applyHueShiftToImageData(backImageData, templateHue);
|
|
283
|
+
backCtx.putImageData(backImageData, 0, 0);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// Draw contact info
|
|
287
|
+
if (layout.back.contactInfo && (name || email || phone)) {
|
|
288
|
+
drawContactInfo(
|
|
289
|
+
backCtx,
|
|
290
|
+
name,
|
|
291
|
+
email,
|
|
292
|
+
phone,
|
|
293
|
+
layout.back.contactInfo.x,
|
|
294
|
+
layout.back.contactInfo.y,
|
|
295
|
+
layout.back.contactInfo.fontSize,
|
|
296
|
+
layout.back.contactInfo.lineHeight || layout.back.contactInfo.fontSize * 1.8,
|
|
297
|
+
layout.back.contactInfo.align || 'center'
|
|
298
|
+
);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// Draw description
|
|
302
|
+
if (layout.back.description && description) {
|
|
303
|
+
drawMultilineText(
|
|
304
|
+
backCtx,
|
|
305
|
+
description,
|
|
306
|
+
layout.back.description.x,
|
|
307
|
+
layout.back.description.y,
|
|
308
|
+
layout.back.description.fontSize,
|
|
309
|
+
layout.back.description.maxWidth || 400,
|
|
310
|
+
layout.back.description.lineHeight || layout.back.description.fontSize * 1.4,
|
|
311
|
+
layout.back.description.align || 'center'
|
|
312
|
+
);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// Draw name on back
|
|
316
|
+
if (name) {
|
|
317
|
+
drawText(
|
|
318
|
+
backCtx,
|
|
319
|
+
name,
|
|
320
|
+
layout.back.namePlate.x,
|
|
321
|
+
layout.back.namePlate.y,
|
|
322
|
+
layout.back.namePlate.fontSize,
|
|
323
|
+
layout.back.namePlate.align || 'center',
|
|
324
|
+
layout.back.namePlate.maxWidth
|
|
325
|
+
);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// Convert canvases to blobs and then to ArrayBuffer for transfer
|
|
329
|
+
const [frontBlob, backBlob] = await Promise.all([
|
|
330
|
+
frontCanvas.convertToBlob({ type: 'image/jpeg', quality: 0.95 }),
|
|
331
|
+
backCanvas.convertToBlob({ type: 'image/jpeg', quality: 0.95 }),
|
|
332
|
+
]);
|
|
333
|
+
|
|
334
|
+
const [frontBuffer, backBuffer] = await Promise.all([
|
|
335
|
+
frontBlob.arrayBuffer(),
|
|
336
|
+
backBlob.arrayBuffer(),
|
|
337
|
+
]);
|
|
338
|
+
|
|
339
|
+
// Transfer buffers back to main thread (zero-copy)
|
|
340
|
+
self.postMessage({
|
|
341
|
+
type: 'success',
|
|
342
|
+
frontImageData: frontBuffer,
|
|
343
|
+
backImageData: backBuffer,
|
|
344
|
+
width: templateWidth,
|
|
345
|
+
height: templateHeight,
|
|
346
|
+
}, [frontBuffer, backBuffer]);
|
|
347
|
+
} catch (error) {
|
|
348
|
+
self.postMessage({
|
|
349
|
+
type: 'error',
|
|
350
|
+
error: String(error),
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
};
|
|
354
|
+
`;let Ie=null,Ae=null;function $t(){if(!Ie){const e=new Blob([Xt],{type:"application/javascript"});Ae=URL.createObjectURL(e),Ie=new Worker(Ae,{type:"module"})}return Ie}async function ke(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 et(e){const{frontTemplateSrc:t,backTemplateSrc:n,templateWidth:r,templateHeight:a,layout:o,portrait:s,portraitZoom:d=1,portraitPanX:c=0,portraitPanY:u=0,templateHue:p=160,name:h,email:w,phone:g,description:v}=e,[b,k]=await Promise.all([ke(t),ke(n)]);let P=null;return s&&(P=await ke(s)),new Promise((T,I)=>{const C=$t(),E=B=>{if(C.removeEventListener("message",E),C.removeEventListener("error",D),URL.revokeObjectURL(b),URL.revokeObjectURL(k),P&&URL.revokeObjectURL(P),B.data.type==="success")try{const{frontImageData:L,backImageData:_,width:j,height:H}=B.data;if(!L||!_||!j||!H){I(new Error("Invalid response from worker"));return}const M=Ue(L,"image/jpeg"),R=Ue(_,"image/jpeg"),z=j/96*25.4,A=H/96*25.4,X=new ft.jsPDF({orientation:z>A?"landscape":"portrait",unit:"mm",format:[z,A]});X.addImage(M,"JPEG",0,0,z,A),X.addPage([z,A]),X.addImage(R,"JPEG",0,0,z,A);const V=X.output("blob");T(V)}catch(L){I(L)}else I(new Error(B.data.error))},D=B=>{C.removeEventListener("message",E),C.removeEventListener("error",D),URL.revokeObjectURL(b),URL.revokeObjectURL(k),P&&URL.revokeObjectURL(P),I(new Error(B.message))};C.addEventListener("message",E),C.addEventListener("error",D),C.postMessage({type:"generate",frontTemplateUrl:b,backTemplateUrl:k,portraitUrl:P,templateWidth:r,templateHeight:a,templateHue:p,portraitZoom:d,portraitPanX:c,portraitPanY:u,layout:{front:{portrait:o.front.portrait,namePlate:o.front.namePlate},back:{namePlate:o.back.namePlate,contactInfo:o.back.contactInfo,description:o.back.description}},name:h,email:w,phone:g,description:v})})}function tt(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 nt(e){const t=await et(e);tt(t,e.filename)}function Ot(){const e=x(b=>b.voucherConfig.language),t=x(b=>b.voucherConfig.hours),n=x(b=>b.voucherConfig.description),r=x(b=>b.voucherConfig.templateHue),a=x(b=>b.personalInfo),o=x(b=>b.portrait),s=x(b=>b.isExporting),d=x(b=>b.setIsExporting),c=G(e),u=qe(e,t),p=Ee(e),h=o.useEnhanced&&o.enhanced?o.enhanced:o.original,w=Se(e,t,n),g=a.name.trim().length>0&&a.email.trim().length>0&&a.phone.trim().length>0&&o.original!==null,v=async()=>{if(!(!g||s)){d(!0);try{const b=`zeitgutschein-${t}h-${a.name.replace(/\s+/g,"-").toLowerCase()}.pdf`;await nt({frontTemplateSrc:u.front,backTemplateSrc:u.back,templateWidth:u.width,templateHeight:u.height,layout:p,portrait:h,portraitZoom:o.zoom,portraitPanX:o.panX,portraitPanY:o.panY,templateHue:r,name:a.name,email:a.email,phone:a.phone,description:w,filename:b})}catch(b){console.error("PDF export failed:",b)}finally{d(!1)}}};return i.jsxs("button",{className:`btn btn-primary flex-1 ${g?"":"btn-disabled"}`,onClick:v,disabled:!g,"aria-busy":s,children:[s?i.jsx("span",{className:"loading loading-spinner loading-sm"}):i.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-5 w-5",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:i.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"})}),c.export.button]})}function at(){const e=x(r=>r.voucherConfig.language),t=x(r=>r.setLanguage),n=r=>{t(r)};return i.jsxs("div",{className:"join",children:[i.jsx("button",{className:`join-item btn btn-sm ${e==="de"?"btn-active btn-primary":"btn-ghost"}`,onClick:()=>n("de"),children:"DE"}),i.jsx("button",{className:`join-item btn btn-sm ${e==="en"?"btn-active btn-primary":"btn-ghost"}`,onClick:()=>n("en"),children:"EN"})]})}function Ft(){const e=x(n=>n.voucherConfig.language),t=G(e);return i.jsxs("div",{className:"navbar bg-currency-green text-currency-cream shadow-lg",children:[i.jsx("div",{className:"navbar-start",children:i.jsx("a",{className:"btn btn-ghost text-xl font-currency font-bold",children:t.header.title})}),i.jsx("div",{className:"navbar-center hidden sm:flex",children:i.jsx("span",{className:"text-sm opacity-80",children:t.header.subtitle})}),i.jsx("div",{className:"navbar-end",children:i.jsx(at,{})})]})}const pe="/",qt={id:"time-voucher-classic-de",name:"Zeitgutschein Classic",type:"time-voucher",category:"classic",images:{front:`${pe}templates/front_hdpi_de.jpg`,back:`${pe}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:K.front.portrait,name:K.front.namePlate},back:{name:K.back.namePlate,contactInfo:K.back.contactInfo,description:K.back.description}},languages:["de"]},Kt={id:"time-voucher-classic-en",name:"Time Voucher Classic",type:"time-voucher",category:"classic",images:{front:`${pe}templates/front_ldpi_en.png`,back:`${pe}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:q.front.portrait,name:q.front.namePlate},back:{name:q.back.namePlate,contactInfo:q.back.contactInfo,description:q.back.description}},languages:["en"]},Ye=[qt,Kt],rt={async listTemplates(e){let t=[...Ye];return e!=null&&e.type&&(t=t.filter(n=>n.type===e.type)),e!=null&&e.category&&(t=t.filter(n=>n.category===e.category)),e!=null&&e.language&&(t=t.filter(n=>n.languages.includes(e.language))),t},async getTemplate(e){const t=Ye.find(n=>n.id===e);if(!t)throw new Error(`Template not found: ${e}`);return t}};function Gt(e){return e==="de"?"time-voucher-classic-de":"time-voucher-classic-en"}let me=rt;function Vt(e){me=e}function Zt(){return me}async function Jt(e){return me.listTemplates(e)}async function Qt(e){return me.getTemplate(e)}exports.ApiKeyModal=Fe;exports.BillPreview=zt;exports.ExportButton=Ot;exports.Header=Ft;exports.LAYOUT_HDPI=K;exports.LAYOUT_LDPI=q;exports.LanguageToggle=at;exports.PersonalInfoForm=yt;exports.PortraitUpload=Mt;exports.TEMPLATES=Re;exports.VoucherConfig=At;exports.applyEngravingEffect=_e;exports.applyHueShift=ze;exports.downloadBlob=tt;exports.drawContactInfo=Ze;exports.drawMultilineText=Ve;exports.drawOvalPortrait=Ge;exports.drawTemplate=je;exports.drawText=Be;exports.enhancePortrait=Dt;exports.exportBillAsPDF=nt;exports.formatDescription=Se;exports.generateBillPDF=et;exports.getApiKey=he;exports.getDefaultTemplateId=Gt;exports.getLayout=Ee;exports.getRemoveBackgroundEndpoint=Et;exports.getTemplate=qe;exports.getTemplateById=Qt;exports.getTemplateProvider=Zt;exports.hasApiKey=Pe;exports.hasCustomEndpoint=jt;exports.listTemplates=Jt;exports.loadImage=te;exports.removeBackground=Oe;exports.renderBackSide=Qe;exports.renderFrontSide=Je;exports.setApiKey=$e;exports.setRemoveBackgroundEndpoint=Rt;exports.setTemplateProvider=Vt;exports.staticTemplateProvider=rt;exports.t=G;exports.useBillCanvasRefs=Wt;exports.useBillStore=x;
|