diff --git a/dist/immac_style_mixer/StyleMixerPanel-BFSOQjMS.js b/dist/immac_style_mixer/StyleMixerPanel-CrHXHY0o.js similarity index 61% rename from dist/immac_style_mixer/StyleMixerPanel-BFSOQjMS.js rename to dist/immac_style_mixer/StyleMixerPanel-CrHXHY0o.js index b51a220..431a26c 100644 --- a/dist/immac_style_mixer/StyleMixerPanel-BFSOQjMS.js +++ b/dist/immac_style_mixer/StyleMixerPanel-CrHXHY0o.js @@ -1 +1 @@ -import{j as t}from"./main.js";import{r as a,b as B}from"./vendor-DPfS0z4g.js";const P={styles:[],mixes:[],current_mix_id:null},E="/immac_style_mixer/api/data";function $(){const[e,l]=a.useState(P),[s,o]=a.useState(!0),[c,y]=a.useState(null),h=a.useRef(null);a.useEffect(()=>{fetch(E).then(u=>{if(!u.ok)throw new Error(`HTTP ${u.status}`);return u.json()}).then(u=>l(u)).catch(u=>y(String(u))).finally(()=>o(!1))},[]);const m=a.useCallback(u=>{l(b=>{const v=typeof u=="function"?u(b):u;return h.current&&clearTimeout(h.current),h.current=setTimeout(()=>{fetch(E,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(v)}).catch(j=>console.error("[ImmacStyleMixer] Save failed",j))},400),v})},[]);return{data:e,loading:s,error:c,update:m}}async function U(e){const l=new FormData;l.append("image",e),l.append("subfolder","immac_style_mixer/styles"),l.append("type","input");const s=await fetch("/upload/image",{method:"POST",body:l});if(!s.ok)throw new Error(`Upload failed: HTTP ${s.status}`);return(await s.json()).name}function M(e){return`/view?filename=${encodeURIComponent(e)}&subfolder=immac_style_mixer%2Fstyles&type=input`}async function L(e){const l=new FormData;l.append("image",e),l.append("subfolder","immac_style_mixer/mixes"),l.append("type","input");const s=await fetch("/upload/image",{method:"POST",body:l});if(!s.ok)throw new Error(`Upload failed: HTTP ${s.status}`);return(await s.json()).name}function N(e){return`/view?filename=${encodeURIComponent(e)}&subfolder=immac_style_mixer%2Fmixes&type=input`}function O({src:e,alt:l,onClose:s}){return a.useEffect(()=>{function o(c){c.key==="Escape"&&s()}return window.addEventListener("keydown",o),()=>window.removeEventListener("keydown",o)},[s]),B.createPortal(t.jsxs("div",{onClick:s,style:{position:"fixed",inset:0,zIndex:99999,background:"rgba(0,0,0,0.85)",display:"flex",alignItems:"center",justifyContent:"center",cursor:"zoom-out"},children:[t.jsx("img",{src:e,alt:l??"",onClick:o=>o.stopPropagation(),style:{maxWidth:"90vw",maxHeight:"90vh",objectFit:"contain",borderRadius:8,boxShadow:"0 8px 40px rgba(0,0,0,0.7)",cursor:"default"}}),t.jsx("button",{onClick:s,title:"Close",style:{position:"fixed",top:16,right:20,background:"none",border:"none",color:"#fff",fontSize:28,cursor:"pointer",lineHeight:1,opacity:.8},children:"✕"})]}),document.body)}function V({mix:e,styles:l,isActive:s,onActivate:o,onUpdate:c,onDelete:y}){const[h,m]=a.useState(!1),[u,b]=a.useState(e.name),[v,j]=a.useState(!1),[f,w]=a.useState(!1),k=a.useRef(null);async function n(i){if(i.type.startsWith("image/")){j(!0);try{const x=await L(i);c({...e,image_filename:x})}catch(x){console.error("[ImmacStyleMixer] Mix image upload failed",x)}finally{j(!1)}}}function r(){m(!1),u.trim()!==e.name&&c({...e,name:u.trim()||e.name})}function p(i,x){const S=e.styles.map((_,A)=>A===i?{..._,...x}:_);c({...e,styles:S})}function C(i){c({...e,styles:e.styles.filter((x,S)=>S!==i)})}function d(i){e.styles.some(x=>x.style_id===i)||c({...e,styles:[...e.styles,{style_id:i,weight:1,enabled:!0}]})}const g=l.filter(i=>!e.styles.some(x=>x.style_id===i.id));return t.jsxs("div",{style:{border:`2px solid ${s?"var(--p-primary-color, #6c6)":"var(--p-surface-border, #444)"}`,borderRadius:8,padding:10,background:"var(--p-surface-section, #1e1e1e)",display:"flex",flexDirection:"column",gap:8,minWidth:240,maxWidth:340,flexShrink:0},children:[t.jsxs("div",{style:{display:"flex",alignItems:"center",gap:6},children:[t.jsx("input",{type:"radio",title:"Set as current mix",checked:s,onChange:o,style:{cursor:"pointer",flexShrink:0}}),h?t.jsx("input",{autoFocus:!0,value:u,onChange:i=>b(i.target.value),onBlur:r,onKeyDown:i=>{i.key==="Enter"&&r(),i.key==="Escape"&&m(!1)},style:z}):t.jsx("span",{title:"Double-click to rename",onDoubleClick:()=>{b(e.name),m(!0)},style:{fontWeight:600,flex:1,cursor:"text",fontSize:13},children:e.name}),t.jsx("button",{title:e.favorite?"Unfavorite":"Favorite",onClick:()=>c({...e,favorite:!e.favorite}),style:D,children:e.favorite?"★":"☆"}),t.jsx("button",{title:"Delete mix",onClick:y,style:{...D,color:"#e55"},children:"✕"})]}),t.jsxs("div",{style:{position:"relative",width:"100%",paddingBottom:"100%"},children:[t.jsx("div",{title:"Click or drop an image to set mix cover",onClick:()=>{var i;return(i=k.current)==null?void 0:i.click()},onDragOver:i=>i.preventDefault(),onDrop:i=>{i.preventDefault();const x=i.dataTransfer.files[0];x&&n(x)},style:{position:"absolute",inset:0,borderRadius:6,border:"1px dashed var(--p-surface-border, #555)",overflow:"hidden",cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center",background:"var(--p-surface-ground, #141414)",fontSize:11,color:"#888",flexShrink:0},children:v?"Uploading…":e.image_filename?t.jsx("img",{src:N(e.image_filename),alt:e.name,style:{width:"100%",height:"100%",objectFit:"cover"}}):"+ cover image"}),!v&&e.image_filename&&t.jsx("button",{title:"View full size",onClick:i=>{i.stopPropagation(),w(!0)},style:K,children:t.jsx("i",{className:"pi pi-search-plus"})})]}),f&&e.image_filename&&t.jsx(O,{src:N(e.image_filename),alt:e.name,onClose:()=>w(!1)}),t.jsx("input",{ref:k,type:"file",accept:"image/*",style:{display:"none"},onChange:i=>{var S;const x=(S=i.target.files)==null?void 0:S[0];x&&n(x),i.target.value=""}}),t.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:6,maxHeight:240,overflowY:"auto"},children:[e.styles.length===0&&t.jsx("div",{style:{fontSize:11,color:"#666"},children:"No styles added yet."}),e.styles.map((i,x)=>{const S=l.find(_=>_.id===i.style_id);return t.jsxs("div",{style:{display:"flex",alignItems:"center",gap:6},children:[t.jsx("button",{title:i.enabled?"Disable":"Enable",onClick:()=>p(x,{enabled:!i.enabled}),style:{...D,fontSize:11,padding:"2px 5px",border:"1px solid var(--p-surface-border, #555)",borderRadius:4,background:i.enabled?"var(--p-primary-color, #557755)":"transparent",color:i.enabled?"#fff":"#888",minWidth:32},children:i.enabled?"ON":"OFF"}),t.jsx("span",{style:{fontSize:12,flex:1,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:(S==null?void 0:S.name)??i.style_id}),t.jsx("input",{type:"number",min:0,max:2,step:.05,value:i.weight,onChange:_=>p(x,{weight:parseFloat(_.target.value)||0}),style:{...z,width:52,textAlign:"right"}}),t.jsx("button",{title:"Remove from mix",onClick:()=>C(x),style:{...D,color:"#e55",fontSize:13},children:"✕"})]},i.style_id)})]}),t.jsxs("select",{value:"",disabled:g.length===0,onChange:i=>{i.target.value&&d(i.target.value)},style:{...z,cursor:g.length===0?"not-allowed":"pointer",opacity:g.length===0?.45:1},title:g.length===0?"All library styles are already in this mix":"Add a style to this mix",children:[t.jsx("option",{value:"",children:g.length===0?"— all styles already added —":"+ add style…"}),g.map(i=>t.jsx("option",{value:i.id,children:i.name},i.id))]})]})}const D={background:"none",border:"none",cursor:"pointer",fontSize:16,padding:"0 2px",color:"inherit",lineHeight:1,flexShrink:0},K={position:"absolute",top:6,left:6,background:"rgba(255,255,255,0.92)",border:"none",borderRadius:6,cursor:"pointer",fontSize:13,padding:"3px 6px",lineHeight:1,color:"#222",boxShadow:"0 1px 4px rgba(0,0,0,0.25)"},z={background:"var(--p-surface-ground, #141414)",border:"1px solid var(--p-surface-border, #444)",borderRadius:4,color:"inherit",padding:"2px 4px",fontSize:12,boxSizing:"border-box"};function Y({style:e,onUpdate:l,onDelete:s}){const[o,c]=a.useState(!1),[y,h]=a.useState(!1),[m,u]=a.useState(e.name),[b,v]=a.useState(e.value),[j,f]=a.useState(!1),[w,k]=a.useState(!1),n=a.useRef(null);function r(){c(!1),m.trim()!==e.name&&l({...e,name:m.trim()||e.name})}function p(){h(!1),b!==e.value&&l({...e,value:b})}async function C(d){if(d.type.startsWith("image/")){f(!0);try{const g=await U(d);l({...e,image_filename:g})}catch(g){console.error("[ImmacStyleMixer] Image upload failed",g)}finally{f(!1)}}}return t.jsxs("div",{style:{border:"1px solid var(--p-surface-border, #444)",borderRadius:8,padding:8,width:180,flexShrink:0,background:"var(--p-surface-section, #1e1e1e)",display:"flex",flexDirection:"column",gap:6,position:"relative"},children:[t.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center"},children:[t.jsx("button",{title:e.favorite?"Unfavorite":"Favorite",onClick:()=>l({...e,favorite:!e.favorite}),style:F,children:e.favorite?"★":"☆"}),t.jsx("button",{title:"Delete style",onClick:s,style:{...F,color:"#e55"},children:"✕"})]}),t.jsxs("div",{style:{position:"relative",width:"100%",paddingBottom:"100%"},children:[t.jsx("div",{title:"Click or drop to upload image",onClick:()=>{var d;return(d=n.current)==null?void 0:d.click()},onDragOver:d=>d.preventDefault(),onDrop:d=>{d.preventDefault();const g=d.dataTransfer.files[0];g&&C(g)},style:{position:"absolute",inset:0,borderRadius:6,border:"1px dashed var(--p-surface-border, #555)",overflow:"hidden",cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center",background:"var(--p-surface-ground, #141414)",fontSize:11,color:"#888"},children:j?"Uploading…":e.image_filename?t.jsx("img",{src:M(e.image_filename),alt:e.name,style:{width:"100%",height:"100%",objectFit:"cover"}}):"+ image"}),!j&&e.image_filename&&t.jsx("button",{title:"View full size",onClick:d=>{d.stopPropagation(),k(!0)},style:G,children:t.jsx("i",{className:"pi pi-search-plus"})})]}),w&&e.image_filename&&t.jsx(O,{src:M(e.image_filename),alt:e.name,onClose:()=>k(!1)}),t.jsx("input",{ref:n,type:"file",accept:"image/*",style:{display:"none"},onChange:d=>{var i;const g=(i=d.target.files)==null?void 0:i[0];g&&C(g),d.target.value=""}}),o?t.jsx("input",{autoFocus:!0,value:m,onChange:d=>u(d.target.value),onBlur:r,onKeyDown:d=>{d.key==="Enter"&&r(),d.key==="Escape"&&c(!1)},style:T}):t.jsx("div",{title:"Click to rename",onDoubleClick:()=>{u(e.name),c(!0)},style:{fontWeight:600,fontSize:13,cursor:"text",wordBreak:"break-word"},children:e.name}),y?t.jsx("textarea",{autoFocus:!0,value:b,onChange:d=>v(d.target.value),onBlur:p,onKeyDown:d=>{d.key==="Escape"&&h(!1)},rows:3,style:{...T,resize:"vertical"}}):t.jsx("div",{title:"Click to edit prompt text",onDoubleClick:()=>{v(e.value),h(!0)},style:{fontSize:11,color:"#aaa",cursor:"text",wordBreak:"break-word",minHeight:32},children:e.value||t.jsx("span",{style:{color:"#555"},children:"double-click to add prompt…"})})]})}const F={background:"none",border:"none",cursor:"pointer",fontSize:16,padding:"0 2px",color:"inherit",lineHeight:1},G={position:"absolute",top:6,left:6,background:"rgba(255,255,255,0.92)",border:"none",borderRadius:6,cursor:"pointer",fontSize:13,padding:"3px 6px",lineHeight:1,color:"#222",boxShadow:"0 1px 4px rgba(0,0,0,0.25)"},T={width:"100%",boxSizing:"border-box",background:"var(--p-surface-ground, #141414)",border:"1px solid var(--p-primary-color, #6c6)",borderRadius:4,color:"inherit",padding:"2px 4px",fontSize:12};function J({styles:e,onUpdate:l,onDelete:s,onAdd:o}){const[c,y]=a.useState(""),[h,m]=a.useState(!1);function u(){const f=c.trim();f&&(o(f),y(""),m(!1))}const b=e.filter(f=>f.favorite),v=e.filter(f=>!f.favorite),j=[...b,...v];return t.jsx("div",{style:{display:"flex",flexDirection:"column",gap:10},children:t.jsxs("div",{style:{display:"flex",flexWrap:"wrap",gap:10},children:[j.map(f=>t.jsx(Y,{style:f,onUpdate:l,onDelete:()=>s(f.id)},f.id)),h?t.jsxs("div",{style:{border:"1px dashed var(--p-primary-color, #6c6)",borderRadius:8,padding:10,width:180,display:"flex",flexDirection:"column",gap:8,background:"var(--p-surface-section, #1e1e1e)",flexShrink:0},children:[t.jsx("input",{autoFocus:!0,placeholder:"Style name…",value:c,onChange:f=>y(f.target.value),onKeyDown:f=>{f.key==="Enter"&&u(),f.key==="Escape"&&m(!1)},style:q}),t.jsxs("div",{style:{display:"flex",gap:6},children:[t.jsx("button",{onClick:u,style:W,children:"Add"}),t.jsx("button",{onClick:()=>{m(!1),y("")},style:{...W,background:"transparent",color:"#aaa"},children:"Cancel"})]})]}):t.jsx("button",{title:"Add a new style",onClick:()=>m(!0),style:{width:180,aspectRatio:"unset",minHeight:80,border:"1px dashed var(--p-surface-border, #555)",borderRadius:8,background:"transparent",color:"#666",cursor:"pointer",fontSize:24,flexShrink:0},children:"+"})]})})}const q={width:"100%",boxSizing:"border-box",background:"var(--p-surface-ground, #141414)",border:"1px solid var(--p-primary-color, #6c6)",borderRadius:4,color:"inherit",padding:"4px 6px",fontSize:13},W={flex:1,background:"var(--p-primary-color, #557755)",border:"none",borderRadius:4,color:"#fff",cursor:"pointer",padding:"4px 8px",fontSize:12};function H(){return crypto.randomUUID()}function I({title:e,children:l,defaultOpen:s=!0}){const[o,c]=a.useState(s);return t.jsxs("div",{style:{display:"flex",flexDirection:"column",flex:o?"1 1 0":"0 0 auto",minHeight:0,borderBottom:"1px solid var(--p-surface-border, #333)"},children:[t.jsxs("button",{onClick:()=>c(y=>!y),style:{display:"flex",alignItems:"center",gap:6,background:"none",border:"none",cursor:"pointer",padding:"8px 0",width:"100%",textAlign:"left",color:"#888",flexShrink:0},children:[t.jsx("i",{className:`pi ${o?"pi-chevron-down":"pi-chevron-right"}`,style:{fontSize:10,flexShrink:0}}),t.jsx("span",{style:{fontWeight:700,fontSize:12,textTransform:"uppercase",letterSpacing:"0.08em"},children:e})]}),o&&t.jsx("div",{style:{flex:1,minHeight:0,overflowY:"auto",paddingBottom:8},children:l})]})}function Z(){const{data:e,loading:l,error:s,update:o}=$(),c=e.mixes.find(n=>n.id===e.current_mix_id)??null,y=a.useCallback(n=>{const r={id:H(),name:n,value:"",favorite:!1,image_filename:null};o(p=>({...p,styles:[...p.styles,r]}))},[o]),h=a.useCallback(n=>{o(r=>({...r,styles:r.styles.map(p=>p.id===n.id?n:p)}))},[o]),m=a.useCallback(n=>{o(r=>({...r,styles:r.styles.filter(p=>p.id!==n),mixes:r.mixes.map(p=>({...p,styles:p.styles.filter(C=>C.style_id!==n)}))}))},[o]),u=a.useCallback(()=>{const n={id:H(),name:`Mix ${e.mixes.length+1}`,favorite:!1,image_filename:null,styles:[]};o(r=>({...r,mixes:[...r.mixes,n]}))},[e.mixes.length,o]),b=a.useCallback(n=>{o(r=>({...r,mixes:r.mixes.map(p=>p.id===n.id?n:p)}))},[o]),v=a.useCallback(n=>{o(r=>({...r,mixes:r.mixes.filter(p=>p.id!==n),current_mix_id:r.current_mix_id===n?null:r.current_mix_id}))},[o]),j=a.useCallback(n=>{o(r=>({...r,current_mix_id:n}))},[o]);if(l)return t.jsx("div",{style:R,children:"Loading…"});if(s)return t.jsxs("div",{style:{...R,color:"#e55"},children:["Error: ",s]});const f=e.mixes.filter(n=>n.favorite),w=e.mixes.filter(n=>!n.favorite),k=[...f,...w];return t.jsxs("div",{style:R,children:[t.jsx(I,{title:"Current Mix",children:c?t.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:6},children:[t.jsx("div",{style:{fontWeight:600,fontSize:14},children:c.name}),t.jsxs("div",{style:{display:"flex",gap:8,flexWrap:"wrap"},children:[c.styles.length===0&&t.jsx("div",{style:{fontSize:12,color:"#666"},children:"No styles in this mix yet."}),c.styles.map(n=>{const r=e.styles.find(p=>p.id===n.style_id);return t.jsxs("div",{style:{border:`1px solid ${n.enabled?"var(--p-primary-color, #6c6)":"var(--p-surface-border, #444)"}`,borderRadius:6,padding:"6px 10px",background:"var(--p-surface-section, #1e1e1e)",opacity:n.enabled?1:.45,fontSize:12,display:"flex",flexDirection:"column",alignItems:"center",gap:4,minWidth:80},children:[t.jsx("span",{style:{fontWeight:600},children:(r==null?void 0:r.name)??"?"}),t.jsxs("span",{style:{color:"#aaa"},children:["×",n.weight.toFixed(2)]})]},n.style_id)})]})]}):t.jsx("div",{style:{fontSize:12,color:"#666"},children:"No mix active — select one from Mixes below."})}),t.jsx(I,{title:"Mixes",children:t.jsxs("div",{style:{display:"flex",gap:10,flexWrap:"wrap"},children:[k.map(n=>t.jsx(V,{mix:n,styles:e.styles,isActive:n.id===e.current_mix_id,onActivate:()=>j(n.id),onUpdate:b,onDelete:()=>v(n.id)},n.id)),t.jsx("button",{title:"Add a new mix",onClick:u,style:{minWidth:80,minHeight:60,border:"1px dashed var(--p-surface-border, #555)",borderRadius:8,background:"transparent",color:"#666",cursor:"pointer",fontSize:22,alignSelf:"flex-start"},children:"+"})]})}),t.jsx(I,{title:"Styles",children:t.jsx(J,{styles:e.styles,onUpdate:h,onDelete:m,onAdd:y})})]})}const R={position:"absolute",inset:0,padding:"0 12px",display:"flex",flexDirection:"column",overflow:"hidden",color:"var(--p-text-color, #eee)",fontSize:13,boxSizing:"border-box"};export{Z as default}; +import{j as t}from"./main.js";import{r as a,b as B}from"./vendor-DPfS0z4g.js";const P={styles:[],mixes:[],current_mix_id:null},E="/immac_style_mixer/api/data";function $(){const[e,l]=a.useState(P),[s,o]=a.useState(!0),[d,h]=a.useState(null),y=a.useRef(null);a.useEffect(()=>{fetch(E).then(u=>{if(!u.ok)throw new Error(`HTTP ${u.status}`);return u.json()}).then(u=>l(u)).catch(u=>h(String(u))).finally(()=>o(!1))},[]);const m=a.useCallback(u=>{l(b=>{const v=typeof u=="function"?u(b):u;return y.current&&clearTimeout(y.current),y.current=setTimeout(()=>{fetch(E,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(v)}).catch(j=>console.error("[ImmacStyleMixer] Save failed",j))},400),v})},[]);return{data:e,loading:s,error:d,update:m}}async function U(e){const l=new FormData;l.append("image",e),l.append("subfolder","immac_style_mixer/styles"),l.append("type","input");const s=await fetch("/upload/image",{method:"POST",body:l});if(!s.ok)throw new Error(`Upload failed: HTTP ${s.status}`);return(await s.json()).name}function M(e){return`/view?filename=${encodeURIComponent(e)}&subfolder=immac_style_mixer%2Fstyles&type=input`}async function L(e){const l=new FormData;l.append("image",e),l.append("subfolder","immac_style_mixer/mixes"),l.append("type","input");const s=await fetch("/upload/image",{method:"POST",body:l});if(!s.ok)throw new Error(`Upload failed: HTTP ${s.status}`);return(await s.json()).name}function N(e){return`/view?filename=${encodeURIComponent(e)}&subfolder=immac_style_mixer%2Fmixes&type=input`}function O({src:e,alt:l,onClose:s}){return a.useEffect(()=>{function o(d){d.key==="Escape"&&s()}return window.addEventListener("keydown",o),()=>window.removeEventListener("keydown",o)},[s]),B.createPortal(t.jsxs("div",{onClick:s,style:{position:"fixed",inset:0,zIndex:99999,background:"rgba(0,0,0,0.85)",display:"flex",alignItems:"center",justifyContent:"center",cursor:"zoom-out"},children:[t.jsx("img",{src:e,alt:l??"",onClick:o=>o.stopPropagation(),style:{maxWidth:"90vw",maxHeight:"90vh",objectFit:"contain",borderRadius:8,boxShadow:"0 8px 40px rgba(0,0,0,0.7)",cursor:"default"}}),t.jsx("button",{onClick:s,title:"Close",style:{position:"fixed",top:16,right:20,background:"none",border:"none",color:"#fff",fontSize:28,cursor:"pointer",lineHeight:1,opacity:.8},children:"✕"})]}),document.body)}function V({mix:e,styles:l,isActive:s,onActivate:o,onUpdate:d,onDelete:h}){const[y,m]=a.useState(!1),[u,b]=a.useState(e.name),[v,j]=a.useState(!1),[f,w]=a.useState(!1),k=a.useRef(null);async function n(i){if(i.type.startsWith("image/")){j(!0);try{const x=await L(i);d({...e,image_filename:x})}catch(x){console.error("[ImmacStyleMixer] Mix image upload failed",x)}finally{j(!1)}}}function r(){m(!1),u.trim()!==e.name&&d({...e,name:u.trim()||e.name})}function p(i,x){const S=e.styles.map((_,A)=>A===i?{..._,...x}:_);d({...e,styles:S})}function C(i){d({...e,styles:e.styles.filter((x,S)=>S!==i)})}function c(i){e.styles.some(x=>x.style_id===i)||d({...e,styles:[...e.styles,{style_id:i,weight:1,enabled:!0}]})}const g=l.filter(i=>!e.styles.some(x=>x.style_id===i.id));return t.jsxs("div",{style:{border:`2px solid ${s?"var(--p-primary-color, #6c6)":"var(--p-surface-border, #444)"}`,borderRadius:8,padding:10,background:"var(--p-surface-section, #1e1e1e)",display:"flex",flexDirection:"column",gap:8,minWidth:240,maxWidth:340,flexShrink:0},children:[t.jsxs("div",{style:{display:"flex",alignItems:"center",gap:6},children:[t.jsx("input",{type:"radio",title:"Set as current mix",checked:s,onChange:o,style:{cursor:"pointer",flexShrink:0}}),y?t.jsx("input",{autoFocus:!0,value:u,onChange:i=>b(i.target.value),onBlur:r,onKeyDown:i=>{i.key==="Enter"&&r(),i.key==="Escape"&&m(!1)},style:z}):t.jsx("span",{title:"Double-click to rename",onDoubleClick:()=>{b(e.name),m(!0)},style:{fontWeight:600,flex:1,cursor:"text",fontSize:13},children:e.name}),t.jsx("button",{title:e.favorite?"Unfavorite":"Favorite",onClick:()=>d({...e,favorite:!e.favorite}),style:D,children:e.favorite?"★":"☆"}),t.jsx("button",{title:"Delete mix",onClick:h,style:{...D,color:"#e55"},children:"✕"})]}),t.jsxs("div",{style:{position:"relative",width:"100%",paddingBottom:"100%"},children:[t.jsx("div",{title:"Click or drop an image to set mix cover",onClick:()=>{var i;return(i=k.current)==null?void 0:i.click()},onDragOver:i=>i.preventDefault(),onDrop:i=>{i.preventDefault();const x=i.dataTransfer.files[0];x&&n(x)},style:{position:"absolute",inset:0,borderRadius:6,border:"1px dashed var(--p-surface-border, #555)",overflow:"hidden",cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center",background:"var(--p-surface-ground, #141414)",fontSize:11,color:"#888",flexShrink:0},children:v?"Uploading…":e.image_filename?t.jsx("img",{src:N(e.image_filename),alt:e.name,style:{width:"100%",height:"100%",objectFit:"cover"}}):"+ cover image"}),!v&&e.image_filename&&t.jsx("button",{title:"View full size",onClick:i=>{i.stopPropagation(),w(!0)},style:K,children:t.jsx("i",{className:"pi pi-search-plus"})})]}),f&&e.image_filename&&t.jsx(O,{src:N(e.image_filename),alt:e.name,onClose:()=>w(!1)}),t.jsx("input",{ref:k,type:"file",accept:"image/*",style:{display:"none"},onChange:i=>{var S;const x=(S=i.target.files)==null?void 0:S[0];x&&n(x),i.target.value=""}}),t.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:6,maxHeight:240,overflowY:"auto"},children:[e.styles.length===0&&t.jsx("div",{style:{fontSize:11,color:"#666"},children:"No styles added yet."}),e.styles.map((i,x)=>{const S=l.find(_=>_.id===i.style_id);return t.jsxs("div",{style:{display:"flex",alignItems:"center",gap:6},children:[t.jsx("button",{title:i.enabled?"Disable":"Enable",onClick:()=>p(x,{enabled:!i.enabled}),style:{...D,fontSize:11,padding:"2px 5px",border:"1px solid var(--p-surface-border, #555)",borderRadius:4,background:i.enabled?"var(--p-primary-color, #557755)":"transparent",color:i.enabled?"#fff":"#888",minWidth:32},children:i.enabled?"ON":"OFF"}),t.jsx("span",{style:{fontSize:12,flex:1,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:(S==null?void 0:S.name)??i.style_id}),t.jsx("input",{type:"number",min:0,max:2,step:.05,value:i.weight,onChange:_=>p(x,{weight:parseFloat(_.target.value)||0}),style:{...z,width:52,textAlign:"right"}}),t.jsx("button",{title:"Remove from mix",onClick:()=>C(x),style:{...D,color:"#e55",fontSize:13},children:"✕"})]},i.style_id)})]}),t.jsxs("select",{value:"",disabled:g.length===0,onChange:i=>{i.target.value&&c(i.target.value)},style:{...z,cursor:g.length===0?"not-allowed":"pointer",opacity:g.length===0?.45:1},title:g.length===0?"All library styles are already in this mix":"Add a style to this mix",children:[t.jsx("option",{value:"",children:g.length===0?"— all styles already added —":"+ add style…"}),g.map(i=>t.jsx("option",{value:i.id,children:i.name},i.id))]})]})}const D={background:"none",border:"none",cursor:"pointer",fontSize:16,padding:"0 2px",color:"inherit",lineHeight:1,flexShrink:0},K={position:"absolute",top:6,left:6,background:"rgba(255,255,255,0.92)",border:"none",borderRadius:6,cursor:"pointer",fontSize:13,padding:"3px 6px",lineHeight:1,color:"#222",boxShadow:"0 1px 4px rgba(0,0,0,0.25)"},z={background:"var(--p-surface-ground, #141414)",border:"1px solid var(--p-surface-border, #444)",borderRadius:4,color:"inherit",padding:"2px 4px",fontSize:12,boxSizing:"border-box"};function Y({style:e,onUpdate:l,onDelete:s}){const[o,d]=a.useState(!1),[h,y]=a.useState(!1),[m,u]=a.useState(e.name),[b,v]=a.useState(e.value),[j,f]=a.useState(!1),[w,k]=a.useState(!1),n=a.useRef(null);function r(){d(!1),m.trim()!==e.name&&l({...e,name:m.trim()||e.name})}function p(){y(!1),b!==e.value&&l({...e,value:b})}async function C(c){if(c.type.startsWith("image/")){f(!0);try{const g=await U(c);l({...e,image_filename:g})}catch(g){console.error("[ImmacStyleMixer] Image upload failed",g)}finally{f(!1)}}}return t.jsxs("div",{style:{border:"1px solid var(--p-surface-border, #444)",borderRadius:8,padding:8,width:180,flexShrink:0,background:"var(--p-surface-section, #1e1e1e)",display:"flex",flexDirection:"column",gap:6,position:"relative"},children:[t.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center"},children:[t.jsx("button",{title:e.favorite?"Unfavorite":"Favorite",onClick:()=>l({...e,favorite:!e.favorite}),style:F,children:e.favorite?"★":"☆"}),t.jsx("button",{title:"Delete style",onClick:s,style:{...F,color:"#e55"},children:"✕"})]}),t.jsxs("div",{style:{position:"relative",width:"100%",paddingBottom:"100%"},children:[t.jsx("div",{title:"Click or drop to upload image",onClick:()=>{var c;return(c=n.current)==null?void 0:c.click()},onDragOver:c=>c.preventDefault(),onDrop:c=>{c.preventDefault();const g=c.dataTransfer.files[0];g&&C(g)},style:{position:"absolute",inset:0,borderRadius:6,border:"1px dashed var(--p-surface-border, #555)",overflow:"hidden",cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center",background:"var(--p-surface-ground, #141414)",fontSize:11,color:"#888"},children:j?"Uploading…":e.image_filename?t.jsx("img",{src:M(e.image_filename),alt:e.name,style:{width:"100%",height:"100%",objectFit:"cover"}}):"+ image"}),!j&&e.image_filename&&t.jsx("button",{title:"View full size",onClick:c=>{c.stopPropagation(),k(!0)},style:G,children:t.jsx("i",{className:"pi pi-search-plus"})})]}),w&&e.image_filename&&t.jsx(O,{src:M(e.image_filename),alt:e.name,onClose:()=>k(!1)}),t.jsx("input",{ref:n,type:"file",accept:"image/*",style:{display:"none"},onChange:c=>{var i;const g=(i=c.target.files)==null?void 0:i[0];g&&C(g),c.target.value=""}}),o?t.jsx("input",{autoFocus:!0,value:m,onChange:c=>u(c.target.value),onBlur:r,onKeyDown:c=>{c.key==="Enter"&&r(),c.key==="Escape"&&d(!1)},style:T}):t.jsx("div",{title:"Click to rename",onDoubleClick:()=>{u(e.name),d(!0)},style:{fontWeight:600,fontSize:13,cursor:"text",wordBreak:"break-word"},children:e.name}),h?t.jsx("textarea",{autoFocus:!0,value:b,onChange:c=>v(c.target.value),onBlur:p,onKeyDown:c=>{c.key==="Escape"&&y(!1)},rows:3,style:{...T,resize:"vertical"}}):t.jsx("div",{title:"Click to edit prompt text",onDoubleClick:()=>{v(e.value),y(!0)},style:{fontSize:11,color:"#aaa",cursor:"text",wordBreak:"break-word",minHeight:32},children:e.value||t.jsx("span",{style:{color:"#555"},children:"double-click to add prompt…"})})]})}const F={background:"none",border:"none",cursor:"pointer",fontSize:16,padding:"0 2px",color:"inherit",lineHeight:1},G={position:"absolute",top:6,left:6,background:"rgba(255,255,255,0.92)",border:"none",borderRadius:6,cursor:"pointer",fontSize:13,padding:"3px 6px",lineHeight:1,color:"#222",boxShadow:"0 1px 4px rgba(0,0,0,0.25)"},T={width:"100%",boxSizing:"border-box",background:"var(--p-surface-ground, #141414)",border:"1px solid var(--p-primary-color, #6c6)",borderRadius:4,color:"inherit",padding:"2px 4px",fontSize:12};function J({styles:e,onUpdate:l,onDelete:s,onAdd:o}){const[d,h]=a.useState(""),[y,m]=a.useState(!1);function u(){const f=d.trim();f&&(o(f),h(""),m(!1))}const b=e.filter(f=>f.favorite),v=e.filter(f=>!f.favorite),j=[...b,...v];return t.jsx("div",{style:{display:"flex",flexDirection:"column",gap:10},children:t.jsxs("div",{style:{display:"flex",flexWrap:"wrap",gap:10},children:[j.map(f=>t.jsx(Y,{style:f,onUpdate:l,onDelete:()=>s(f.id)},f.id)),y?t.jsxs("div",{style:{border:"1px dashed var(--p-primary-color, #6c6)",borderRadius:8,padding:10,width:180,display:"flex",flexDirection:"column",gap:8,background:"var(--p-surface-section, #1e1e1e)",flexShrink:0},children:[t.jsx("input",{autoFocus:!0,placeholder:"Style name…",value:d,onChange:f=>h(f.target.value),onKeyDown:f=>{f.key==="Enter"&&u(),f.key==="Escape"&&m(!1)},style:q}),t.jsxs("div",{style:{display:"flex",gap:6},children:[t.jsx("button",{onClick:u,style:W,children:"Add"}),t.jsx("button",{onClick:()=>{m(!1),h("")},style:{...W,background:"transparent",color:"#aaa"},children:"Cancel"})]})]}):t.jsx("button",{title:"Add a new style",onClick:()=>m(!0),style:{width:180,aspectRatio:"unset",minHeight:80,border:"1px dashed var(--p-surface-border, #555)",borderRadius:8,background:"transparent",color:"#666",cursor:"pointer",fontSize:24,flexShrink:0},children:"+"})]})})}const q={width:"100%",boxSizing:"border-box",background:"var(--p-surface-ground, #141414)",border:"1px solid var(--p-primary-color, #6c6)",borderRadius:4,color:"inherit",padding:"4px 6px",fontSize:13},W={flex:1,background:"var(--p-primary-color, #557755)",border:"none",borderRadius:4,color:"#fff",cursor:"pointer",padding:"4px 8px",fontSize:12};function H(){return crypto.randomUUID()}function I({title:e,children:l,defaultOpen:s=!0,grow:o=!0}){const[d,h]=a.useState(s);return t.jsxs("div",{style:{display:"flex",flexDirection:"column",flex:d&&o?"1 1 0":"0 0 auto",minHeight:0,borderBottom:"1px solid var(--p-surface-border, #333)"},children:[t.jsxs("button",{onClick:()=>h(y=>!y),style:{display:"flex",alignItems:"center",gap:6,background:"none",border:"none",cursor:"pointer",padding:"8px 0",width:"100%",textAlign:"left",color:"#888",flexShrink:0},children:[t.jsx("i",{className:`pi ${d?"pi-chevron-down":"pi-chevron-right"}`,style:{fontSize:10,flexShrink:0}}),t.jsx("span",{style:{fontWeight:700,fontSize:12,textTransform:"uppercase",letterSpacing:"0.08em"},children:e})]}),d&&t.jsx("div",{style:{flex:1,minHeight:0,overflowY:"auto",paddingBottom:8},children:l})]})}function Z(){const{data:e,loading:l,error:s,update:o}=$(),d=e.mixes.find(n=>n.id===e.current_mix_id)??null,h=a.useCallback(n=>{const r={id:H(),name:n,value:"",favorite:!1,image_filename:null};o(p=>({...p,styles:[...p.styles,r]}))},[o]),y=a.useCallback(n=>{o(r=>({...r,styles:r.styles.map(p=>p.id===n.id?n:p)}))},[o]),m=a.useCallback(n=>{o(r=>({...r,styles:r.styles.filter(p=>p.id!==n),mixes:r.mixes.map(p=>({...p,styles:p.styles.filter(C=>C.style_id!==n)}))}))},[o]),u=a.useCallback(()=>{const n={id:H(),name:`Mix ${e.mixes.length+1}`,favorite:!1,image_filename:null,styles:[]};o(r=>({...r,mixes:[...r.mixes,n]}))},[e.mixes.length,o]),b=a.useCallback(n=>{o(r=>({...r,mixes:r.mixes.map(p=>p.id===n.id?n:p)}))},[o]),v=a.useCallback(n=>{o(r=>({...r,mixes:r.mixes.filter(p=>p.id!==n),current_mix_id:r.current_mix_id===n?null:r.current_mix_id}))},[o]),j=a.useCallback(n=>{o(r=>({...r,current_mix_id:n}))},[o]);if(l)return t.jsx("div",{style:R,children:"Loading…"});if(s)return t.jsxs("div",{style:{...R,color:"#e55"},children:["Error: ",s]});const f=e.mixes.filter(n=>n.favorite),w=e.mixes.filter(n=>!n.favorite),k=[...f,...w];return t.jsxs("div",{style:R,children:[t.jsx(I,{title:"Current Mix",grow:!1,children:d?t.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:6},children:[t.jsx("div",{style:{fontWeight:600,fontSize:14},children:d.name}),t.jsxs("div",{style:{display:"flex",gap:8,flexWrap:"wrap"},children:[d.styles.length===0&&t.jsx("div",{style:{fontSize:12,color:"#666"},children:"No styles in this mix yet."}),d.styles.map(n=>{const r=e.styles.find(p=>p.id===n.style_id);return t.jsxs("div",{style:{border:`1px solid ${n.enabled?"var(--p-primary-color, #6c6)":"var(--p-surface-border, #444)"}`,borderRadius:6,padding:"6px 10px",background:"var(--p-surface-section, #1e1e1e)",opacity:n.enabled?1:.45,fontSize:12,display:"flex",flexDirection:"column",alignItems:"center",gap:4,minWidth:80},children:[t.jsx("span",{style:{fontWeight:600},children:(r==null?void 0:r.name)??"?"}),t.jsxs("span",{style:{color:"#aaa"},children:["×",n.weight.toFixed(2)]})]},n.style_id)})]})]}):t.jsx("div",{style:{fontSize:12,color:"#666"},children:"No mix active — select one from Mixes below."})}),t.jsx(I,{title:"Mixes",children:t.jsxs("div",{style:{display:"flex",gap:10,flexWrap:"wrap"},children:[k.map(n=>t.jsx(V,{mix:n,styles:e.styles,isActive:n.id===e.current_mix_id,onActivate:()=>j(n.id),onUpdate:b,onDelete:()=>v(n.id)},n.id)),t.jsx("button",{title:"Add a new mix",onClick:u,style:{minWidth:80,minHeight:60,border:"1px dashed var(--p-surface-border, #555)",borderRadius:8,background:"transparent",color:"#666",cursor:"pointer",fontSize:22,alignSelf:"flex-start"},children:"+"})]})}),t.jsx(I,{title:"Styles",children:t.jsx(J,{styles:e.styles,onUpdate:y,onDelete:m,onAdd:h})})]})}const R={position:"absolute",inset:0,padding:"0 12px",display:"flex",flexDirection:"column",overflow:"hidden",color:"var(--p-text-color, #eee)",fontSize:13,boxSizing:"border-box"};export{Z as default}; diff --git a/dist/immac_style_mixer/main.js b/dist/immac_style_mixer/main.js index da0e75e..2a589a2 100644 --- a/dist/immac_style_mixer/main.js +++ b/dist/immac_style_mixer/main.js @@ -1,4 +1,4 @@ -const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["immac_style_mixer/StyleMixerPanel-BFSOQjMS.js","immac_style_mixer/vendor-DPfS0z4g.js"])))=>i.map(i=>d[i]); +const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["immac_style_mixer/StyleMixerPanel-CrHXHY0o.js","immac_style_mixer/vendor-DPfS0z4g.js"])))=>i.map(i=>d[i]); import{r as v,a as R,R as h}from"./vendor-DPfS0z4g.js";const g="modulepreload",b=function(t){return"/"+t},f={},I=function(e,n,o){let l=Promise.resolve();if(n&&n.length>0){document.getElementsByTagName("link");const r=document.querySelector("meta[property=csp-nonce]"),i=(r==null?void 0:r.nonce)||(r==null?void 0:r.getAttribute("nonce"));l=Promise.allSettled(n.map(a=>{if(a=b(a),a in f)return;f[a]=!0;const d=a.endsWith(".css"),_=d?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${a}"]${_}`))return;const s=document.createElement("link");if(s.rel=d?"stylesheet":g,d||(s.as="script"),s.crossOrigin="",s.href=a,i&&s.setAttribute("nonce",i),document.head.appendChild(s),d)return new Promise((E,S)=>{s.addEventListener("load",E),s.addEventListener("error",()=>S(new Error(`Unable to preload CSS for ${a}`)))})}))}function c(r){const i=new Event("vite:preloadError",{cancelable:!0});if(i.payload=r,window.dispatchEvent(i),!i.defaultPrevented)throw r}return l.then(r=>{for(const i of r||[])i.status==="rejected"&&c(i.reason);return e().catch(c)})};var x={exports:{}},m={};/** * @license React * react-jsx-runtime.production.min.js @@ -7,4 +7,4 @@ import{r as v,a as R,R as h}from"./vendor-DPfS0z4g.js";const g="modulepreload",b * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - */var P=v,j=Symbol.for("react.element"),k=Symbol.for("react.fragment"),O=Object.prototype.hasOwnProperty,L=P.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,C={key:!0,ref:!0,__self:!0,__source:!0};function w(t,e,n){var o,l={},c=null,r=null;n!==void 0&&(c=""+n),e.key!==void 0&&(c=""+e.key),e.ref!==void 0&&(r=e.ref);for(o in e)O.call(e,o)&&!C.hasOwnProperty(o)&&(l[o]=e[o]);if(t&&t.defaultProps)for(o in e=t.defaultProps,e)l[o]===void 0&&(l[o]=e[o]);return{$$typeof:j,type:t,key:c,ref:r,props:l,_owner:L.current}}m.Fragment=k;m.jsx=w;m.jsxs=w;x.exports=m;var u=x.exports,p={},y=R;p.createRoot=y.createRoot,p.hydrateRoot=y.hydrateRoot;const T=h.lazy(()=>I(()=>import("./StyleMixerPanel-BFSOQjMS.js"),__vite__mapDeps([0,1])));function U(){return new Promise(t=>{function e(){if(window.app){t();return}const n=setInterval(()=>{window.app&&(clearInterval(n),t())},50);setTimeout(()=>{clearInterval(n),console.error("[ImmacStyleMixer] Timeout waiting for ComfyUI app"),t()},5e3)}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",e):e()})}async function M(){if(await U(),!window.app){console.error("[ImmacStyleMixer] ComfyUI app not available");return}window.app.extensionManager.registerSidebarTab({id:"immac-style-mixer",icon:"pi pi-palette",title:"Style Mixer",tooltip:"Immac Style Mixer",type:"custom",render:t=>{const e=document.createElement("div");e.id="immac-style-mixer-root",e.style.position="absolute",e.style.inset="0",e.style.overflow="hidden",t.style.position="relative",t.style.height="100%",t.appendChild(e),p.createRoot(e).render(u.jsx(h.StrictMode,{children:u.jsx(v.Suspense,{fallback:u.jsx("div",{style:{padding:"1rem"},children:"Loading…"}),children:u.jsx(T,{})})}))}}),window.app.registerExtension({name:"ImmacStyleMixer"})}M().catch(console.error);export{u as j}; + */var P=v,j=Symbol.for("react.element"),k=Symbol.for("react.fragment"),O=Object.prototype.hasOwnProperty,L=P.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,C={key:!0,ref:!0,__self:!0,__source:!0};function w(t,e,n){var o,l={},c=null,r=null;n!==void 0&&(c=""+n),e.key!==void 0&&(c=""+e.key),e.ref!==void 0&&(r=e.ref);for(o in e)O.call(e,o)&&!C.hasOwnProperty(o)&&(l[o]=e[o]);if(t&&t.defaultProps)for(o in e=t.defaultProps,e)l[o]===void 0&&(l[o]=e[o]);return{$$typeof:j,type:t,key:c,ref:r,props:l,_owner:L.current}}m.Fragment=k;m.jsx=w;m.jsxs=w;x.exports=m;var u=x.exports,p={},y=R;p.createRoot=y.createRoot,p.hydrateRoot=y.hydrateRoot;const T=h.lazy(()=>I(()=>import("./StyleMixerPanel-CrHXHY0o.js"),__vite__mapDeps([0,1])));function U(){return new Promise(t=>{function e(){if(window.app){t();return}const n=setInterval(()=>{window.app&&(clearInterval(n),t())},50);setTimeout(()=>{clearInterval(n),console.error("[ImmacStyleMixer] Timeout waiting for ComfyUI app"),t()},5e3)}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",e):e()})}async function M(){if(await U(),!window.app){console.error("[ImmacStyleMixer] ComfyUI app not available");return}window.app.extensionManager.registerSidebarTab({id:"immac-style-mixer",icon:"pi pi-palette",title:"Style Mixer",tooltip:"Immac Style Mixer",type:"custom",render:t=>{const e=document.createElement("div");e.id="immac-style-mixer-root",e.style.position="absolute",e.style.inset="0",e.style.overflow="hidden",t.style.position="relative",t.style.height="100%",t.appendChild(e),p.createRoot(e).render(u.jsx(h.StrictMode,{children:u.jsx(v.Suspense,{fallback:u.jsx("div",{style:{padding:"1rem"},children:"Loading…"}),children:u.jsx(T,{})})}))}}),window.app.registerExtension({name:"ImmacStyleMixer"})}M().catch(console.error);export{u as j}; diff --git a/ui/src/components/StyleMixerPanel.tsx b/ui/src/components/StyleMixerPanel.tsx index c7b0fc8..02bcfcd 100644 --- a/ui/src/components/StyleMixerPanel.tsx +++ b/ui/src/components/StyleMixerPanel.tsx @@ -8,13 +8,13 @@ function uid(): string { return crypto.randomUUID() } -function CollapsibleSection({ title, children, defaultOpen = true }: { title: string; children: React.ReactNode; defaultOpen?: boolean }) { +function CollapsibleSection({ title, children, defaultOpen = true, grow = true }: { title: string; children: React.ReactNode; defaultOpen?: boolean; grow?: boolean }) { const [open, setOpen] = useState(defaultOpen) return (