comfyui-frontend-package 1.37.3__py3-none-any.whl → 1.37.4__py3-none-any.whl
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.
- comfyui_frontend_package/static/assets/AboutPanel-BwfERTOT.js +2 -0
- comfyui_frontend_package/static/assets/{AboutPanel-6wNn9DuA.js.map → AboutPanel-BwfERTOT.js.map} +1 -1
- comfyui_frontend_package/static/assets/{AudioPreviewPlayer-ybC6cXRM.js → AudioPreviewPlayer-DT9nrYD6.js} +2 -2
- comfyui_frontend_package/static/assets/{AudioPreviewPlayer-ybC6cXRM.js.map → AudioPreviewPlayer-DT9nrYD6.js.map} +1 -1
- comfyui_frontend_package/static/assets/ComfyQueueButton-DazIfwpa.js +2 -0
- comfyui_frontend_package/static/assets/{ComfyQueueButton-BbIk3ALi.js.map → ComfyQueueButton-DazIfwpa.js.map} +1 -1
- comfyui_frontend_package/static/assets/ExtensionPanel-D539Wx81.js +2 -0
- comfyui_frontend_package/static/assets/{ExtensionPanel-DYw7d35v.js.map → ExtensionPanel-D539Wx81.js.map} +1 -1
- comfyui_frontend_package/static/assets/GraphView-C_FQc1Au.js +16 -0
- comfyui_frontend_package/static/assets/GraphView-C_FQc1Au.js.map +1 -0
- comfyui_frontend_package/static/assets/{GraphView-DwAYVX4H.css → GraphView-Ck9hVEEV.css} +1 -1
- comfyui_frontend_package/static/assets/{KeybindingPanel-D0MD69FX.js → KeybindingPanel-Bj61UMoX.js} +2 -2
- comfyui_frontend_package/static/assets/{KeybindingPanel-D0MD69FX.js.map → KeybindingPanel-Bj61UMoX.js.map} +1 -1
- comfyui_frontend_package/static/assets/LazyImage.vue_vue_type_script_setup_true_lang-DyOiHvnA.js +2 -0
- comfyui_frontend_package/static/assets/LazyImage.vue_vue_type_script_setup_true_lang-DyOiHvnA.js.map +1 -0
- comfyui_frontend_package/static/assets/LegacyCreditsPanel-BNqPlgUn.js +2 -0
- comfyui_frontend_package/static/assets/{LegacyCreditsPanel-BMvul305.js.map → LegacyCreditsPanel-BNqPlgUn.js.map} +1 -1
- comfyui_frontend_package/static/assets/Load3D-CaNKqgIL.js +2 -0
- comfyui_frontend_package/static/assets/Load3D-CaNKqgIL.js.map +1 -0
- comfyui_frontend_package/static/assets/{Load3D.vue_vue_type_script_setup_true_lang-BtNou66j.js → Load3D.vue_vue_type_script_setup_true_lang-gf2aN2_8.js} +2 -2
- comfyui_frontend_package/static/assets/{Load3D.vue_vue_type_script_setup_true_lang-BtNou66j.js.map → Load3D.vue_vue_type_script_setup_true_lang-gf2aN2_8.js.map} +1 -1
- comfyui_frontend_package/static/assets/{Media3DBottom-Bk7TM-zH.js → Media3DBottom-D9M9b2ls.js} +2 -2
- comfyui_frontend_package/static/assets/{Media3DBottom-Bk7TM-zH.js.map → Media3DBottom-D9M9b2ls.js.map} +1 -1
- comfyui_frontend_package/static/assets/{Media3DTop-CIsQ4Ccc.js → Media3DTop-B-qNqlQF.js} +2 -2
- comfyui_frontend_package/static/assets/{Media3DTop-CIsQ4Ccc.js.map → Media3DTop-B-qNqlQF.js.map} +1 -1
- comfyui_frontend_package/static/assets/{MediaAudioBottom-CWxtJ5vP.js → MediaAudioBottom-d7EZ2Wx5.js} +2 -2
- comfyui_frontend_package/static/assets/{MediaAudioBottom-CWxtJ5vP.js.map → MediaAudioBottom-d7EZ2Wx5.js.map} +1 -1
- comfyui_frontend_package/static/assets/{MediaImageBottom-OWiMf_6W.js → MediaImageBottom-B-9SOOhn.js} +2 -2
- comfyui_frontend_package/static/assets/{MediaImageBottom-OWiMf_6W.js.map → MediaImageBottom-B-9SOOhn.js.map} +1 -1
- comfyui_frontend_package/static/assets/{MediaTitle.vue_vue_type_script_setup_true_lang-C59zAxW0.js → MediaTitle.vue_vue_type_script_setup_true_lang-DVzYM9UW.js} +2 -2
- comfyui_frontend_package/static/assets/{MediaTitle.vue_vue_type_script_setup_true_lang-C59zAxW0.js.map → MediaTitle.vue_vue_type_script_setup_true_lang-DVzYM9UW.js.map} +1 -1
- comfyui_frontend_package/static/assets/{MediaVideoBottom-OKuLWTbn.js → MediaVideoBottom-D6IR52ja.js} +2 -2
- comfyui_frontend_package/static/assets/{MediaVideoBottom-OKuLWTbn.js.map → MediaVideoBottom-D6IR52ja.js.map} +1 -1
- comfyui_frontend_package/static/assets/{ServerConfigPanel-5RPRkuvl.js → ServerConfigPanel-BBWOQ7ej.js} +2 -2
- comfyui_frontend_package/static/assets/{ServerConfigPanel-5RPRkuvl.js.map → ServerConfigPanel-BBWOQ7ej.js.map} +1 -1
- comfyui_frontend_package/static/assets/{SubscriptionRequiredDialogContent-CtCWM_jj.js → SubscriptionRequiredDialogContent-oUSDZGJZ.js} +2 -2
- comfyui_frontend_package/static/assets/{SubscriptionRequiredDialogContent-CtCWM_jj.js.map → SubscriptionRequiredDialogContent-oUSDZGJZ.js.map} +1 -1
- comfyui_frontend_package/static/assets/{UserPanel-CrxHTRQZ.js → UserPanel-Do_alb49.js} +2 -2
- comfyui_frontend_package/static/assets/{UserPanel-CrxHTRQZ.js.map → UserPanel-Do_alb49.js.map} +1 -1
- comfyui_frontend_package/static/assets/{UserSelectView-tu0lXAri.js → UserSelectView-DVJzD33o.js} +2 -2
- comfyui_frontend_package/static/assets/{UserSelectView-tu0lXAri.js.map → UserSelectView-DVJzD33o.js.map} +1 -1
- comfyui_frontend_package/static/assets/{ValueControlPopover-CgyNfIEw.js → ValueControlPopover-CZIsPw9J.js} +2 -2
- comfyui_frontend_package/static/assets/{ValueControlPopover-CgyNfIEw.js.map → ValueControlPopover-CZIsPw9J.js.map} +1 -1
- comfyui_frontend_package/static/assets/WidgetAudioUI-CbC597q0.js +2 -0
- comfyui_frontend_package/static/assets/{WidgetAudioUI-BZL35TlT.js.map → WidgetAudioUI-CbC597q0.js.map} +1 -1
- comfyui_frontend_package/static/assets/{WidgetButton-Dkge0J8R.js → WidgetButton-Df2ihQh6.js} +2 -2
- comfyui_frontend_package/static/assets/{WidgetButton-Dkge0J8R.js.map → WidgetButton-Df2ihQh6.js.map} +1 -1
- comfyui_frontend_package/static/assets/{WidgetColorPicker-vRHta_Kz.js → WidgetColorPicker-DgI8RjHJ.js} +2 -2
- comfyui_frontend_package/static/assets/{WidgetColorPicker-vRHta_Kz.js.map → WidgetColorPicker-DgI8RjHJ.js.map} +1 -1
- comfyui_frontend_package/static/assets/{WidgetGalleria-BoWBT6i_.js → WidgetGalleria-Cyz9lzP-.js} +2 -2
- comfyui_frontend_package/static/assets/{WidgetGalleria-BoWBT6i_.js.map → WidgetGalleria-Cyz9lzP-.js.map} +1 -1
- comfyui_frontend_package/static/assets/WidgetInputNumber-wD2uHC32.js +2 -0
- comfyui_frontend_package/static/assets/WidgetInputNumber-wD2uHC32.js.map +1 -0
- comfyui_frontend_package/static/assets/{WidgetInputNumber.vue_vue_type_script_setup_true_lang-aeh2Ot2n.js → WidgetInputNumber.vue_vue_type_script_setup_true_lang-XbRdxGIz.js} +2 -2
- comfyui_frontend_package/static/assets/{WidgetInputNumber.vue_vue_type_script_setup_true_lang-aeh2Ot2n.js.map → WidgetInputNumber.vue_vue_type_script_setup_true_lang-XbRdxGIz.js.map} +1 -1
- comfyui_frontend_package/static/assets/{WidgetInputText-BRV8PzCv.js → WidgetInputText-BR3C0fCV.js} +2 -2
- comfyui_frontend_package/static/assets/{WidgetInputText-BRV8PzCv.js.map → WidgetInputText-BR3C0fCV.js.map} +1 -1
- comfyui_frontend_package/static/assets/{WidgetLayoutField.vue_vue_type_script_setup_true_lang-Dps42A-g.js → WidgetLayoutField.vue_vue_type_script_setup_true_lang-CZj3E4v6.js} +2 -2
- comfyui_frontend_package/static/assets/{WidgetLayoutField.vue_vue_type_script_setup_true_lang-Dps42A-g.js.map → WidgetLayoutField.vue_vue_type_script_setup_true_lang-CZj3E4v6.js.map} +1 -1
- comfyui_frontend_package/static/assets/WidgetLegacy-CkV176Xm.js +2 -0
- comfyui_frontend_package/static/assets/WidgetLegacy-CkV176Xm.js.map +1 -0
- comfyui_frontend_package/static/assets/WidgetMarkdown-rM_UPCA-.js +2 -0
- comfyui_frontend_package/static/assets/{WidgetMarkdown-DIMd79hN.js.map → WidgetMarkdown-rM_UPCA-.js.map} +1 -1
- comfyui_frontend_package/static/assets/{WidgetRecordAudio-DwHSqiBz.js → WidgetRecordAudio-CLpvV8e9.js} +2 -2
- comfyui_frontend_package/static/assets/{WidgetRecordAudio-DwHSqiBz.js.map → WidgetRecordAudio-CLpvV8e9.js.map} +1 -1
- comfyui_frontend_package/static/assets/WidgetSelect-BwcPw-lE.js +2 -0
- comfyui_frontend_package/static/assets/WidgetSelect-BwcPw-lE.js.map +1 -0
- comfyui_frontend_package/static/assets/{WidgetSelect.vue_vue_type_script_setup_true_lang-CMg0GtSC.js → WidgetSelect.vue_vue_type_script_setup_true_lang-CITubFAk.js} +2 -2
- comfyui_frontend_package/static/assets/{WidgetSelect.vue_vue_type_script_setup_true_lang-CMg0GtSC.js.map → WidgetSelect.vue_vue_type_script_setup_true_lang-CITubFAk.js.map} +1 -1
- comfyui_frontend_package/static/assets/{WidgetTextarea-CZnqW4e_.js → WidgetTextarea-CwUMJ-23.js} +2 -2
- comfyui_frontend_package/static/assets/{WidgetTextarea-CZnqW4e_.js.map → WidgetTextarea-CwUMJ-23.js.map} +1 -1
- comfyui_frontend_package/static/assets/{WidgetToggleSwitch-DwYqmS17.js → WidgetToggleSwitch-DqQpfrDq.js} +2 -2
- comfyui_frontend_package/static/assets/{WidgetToggleSwitch-DwYqmS17.js.map → WidgetToggleSwitch-DqQpfrDq.js.map} +1 -1
- comfyui_frontend_package/static/assets/{WidgetWithControl.vue_vue_type_script_setup_true_lang-COy_p9Eh.js → WidgetWithControl.vue_vue_type_script_setup_true_lang-JSl33v3j.js} +3 -3
- comfyui_frontend_package/static/assets/{WidgetWithControl.vue_vue_type_script_setup_true_lang-COy_p9Eh.js.map → WidgetWithControl.vue_vue_type_script_setup_true_lang-JSl33v3j.js.map} +1 -1
- comfyui_frontend_package/static/assets/{audioService-Bh6LQBV8.js → audioService-DKN4T_Yr.js} +2 -2
- comfyui_frontend_package/static/assets/{audioService-Bh6LQBV8.js.map → audioService-DKN4T_Yr.js.map} +1 -1
- comfyui_frontend_package/static/assets/{audioUtils-DlA-QHPJ.js → audioUtils-WBbpBG9r.js} +2 -2
- comfyui_frontend_package/static/assets/{audioUtils-DlA-QHPJ.js.map → audioUtils-WBbpBG9r.js.map} +1 -1
- comfyui_frontend_package/static/assets/{commands-CHktpNSL.js → commands-CRVPkENB.js} +2 -2
- comfyui_frontend_package/static/assets/commands-CRVPkENB.js.map +1 -0
- comfyui_frontend_package/static/assets/{index-2-qFLlQP.js → index-CuKlxAeN.js} +30 -28
- comfyui_frontend_package/static/assets/index-CuKlxAeN.js.map +1 -0
- comfyui_frontend_package/static/assets/index-Cv1aHIoL.css +1 -0
- comfyui_frontend_package/static/assets/{index-_AAd9eTu.js → index-DEqR9lwu.js} +2 -2
- comfyui_frontend_package/static/assets/{index-_AAd9eTu.js.map → index-DEqR9lwu.js.map} +1 -1
- comfyui_frontend_package/static/assets/index-KizWjI6s.js +5 -0
- comfyui_frontend_package/static/assets/{index-DKofvZ3r.js.map → index-KizWjI6s.js.map} +1 -1
- comfyui_frontend_package/static/assets/{keybindingService-CWbdWLPI.js → keybindingService-O5KDQleT.js} +2 -2
- comfyui_frontend_package/static/assets/{keybindingService-CWbdWLPI.js.map → keybindingService-O5KDQleT.js.map} +1 -1
- comfyui_frontend_package/static/assets/main-10VBfKWj.js +14 -0
- comfyui_frontend_package/static/assets/main-10VBfKWj.js.map +1 -0
- comfyui_frontend_package/static/assets/nodeDefs-D9VHUZJt.js +53 -0
- comfyui_frontend_package/static/assets/nodeDefs-D9VHUZJt.js.map +1 -0
- comfyui_frontend_package/static/assets/{vendor-three-BKWXAgVe.js → vendor-three-29bN5sfh.js} +2 -2
- comfyui_frontend_package/static/assets/{vendor-three-BKWXAgVe.js.map → vendor-three-29bN5sfh.js.map} +1 -1
- comfyui_frontend_package/static/index.html +1 -1
- {comfyui_frontend_package-1.37.3.dist-info → comfyui_frontend_package-1.37.4.dist-info}/METADATA +1 -1
- {comfyui_frontend_package-1.37.3.dist-info → comfyui_frontend_package-1.37.4.dist-info}/RECORD +101 -101
- comfyui_frontend_package/static/assets/AboutPanel-6wNn9DuA.js +0 -2
- comfyui_frontend_package/static/assets/ComfyQueueButton-BbIk3ALi.js +0 -2
- comfyui_frontend_package/static/assets/ExtensionPanel-DYw7d35v.js +0 -2
- comfyui_frontend_package/static/assets/GraphView-CjDjhvN7.js +0 -16
- comfyui_frontend_package/static/assets/GraphView-CjDjhvN7.js.map +0 -1
- comfyui_frontend_package/static/assets/LazyImage.vue_vue_type_script_setup_true_lang-CcI-aYhS.js +0 -2
- comfyui_frontend_package/static/assets/LazyImage.vue_vue_type_script_setup_true_lang-CcI-aYhS.js.map +0 -1
- comfyui_frontend_package/static/assets/LegacyCreditsPanel-BMvul305.js +0 -2
- comfyui_frontend_package/static/assets/Load3D-BplYUML3.js +0 -2
- comfyui_frontend_package/static/assets/Load3D-BplYUML3.js.map +0 -1
- comfyui_frontend_package/static/assets/WidgetAudioUI-BZL35TlT.js +0 -2
- comfyui_frontend_package/static/assets/WidgetInputNumber-DMqIMaoH.js +0 -2
- comfyui_frontend_package/static/assets/WidgetInputNumber-DMqIMaoH.js.map +0 -1
- comfyui_frontend_package/static/assets/WidgetLegacy-BWDBwsli.js +0 -2
- comfyui_frontend_package/static/assets/WidgetLegacy-BWDBwsli.js.map +0 -1
- comfyui_frontend_package/static/assets/WidgetMarkdown-DIMd79hN.js +0 -2
- comfyui_frontend_package/static/assets/WidgetSelect-BOvzWMtV.js +0 -2
- comfyui_frontend_package/static/assets/WidgetSelect-BOvzWMtV.js.map +0 -1
- comfyui_frontend_package/static/assets/commands-CHktpNSL.js.map +0 -1
- comfyui_frontend_package/static/assets/index-2-qFLlQP.js.map +0 -1
- comfyui_frontend_package/static/assets/index-571Fkv7y.css +0 -1
- comfyui_frontend_package/static/assets/index-DKofvZ3r.js +0 -5
- comfyui_frontend_package/static/assets/main-DGOENlHZ.js +0 -14
- comfyui_frontend_package/static/assets/main-DGOENlHZ.js.map +0 -1
- comfyui_frontend_package/static/assets/nodeDefs-DtmuHPr3.js +0 -53
- comfyui_frontend_package/static/assets/nodeDefs-DtmuHPr3.js.map +0 -1
- {comfyui_frontend_package-1.37.3.dist-info → comfyui_frontend_package-1.37.4.dist-info}/WHEEL +0 -0
- {comfyui_frontend_package-1.37.3.dist-info → comfyui_frontend_package-1.37.4.dist-info}/top_level.txt +0 -0
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var fe=Object.defineProperty;var v=(t,e)=>fe(t,"name",{value:e,configurable:!0});import{c as x,_ as me,f as oe,t as P,L as ge,a as ve,W as ye,cD as be}from"./index-2-qFLlQP.js";import{E as c,bx as T,cM as F,cN as z,j as I,d as m,k as E,z as B,e as M,by as b,m as ae,p as we,c as $,s as C,q as L,u as j,dG as J,r as D,l as se,dm as he,F as _,y as ee,i as Se,h as ke,A as Me,dv as $e,w as Y,bB as xe,eE as Ue,bl as Ce}from"./vendor-other-CSX7WseZ.js";import{i as ze,p as ne}from"./vendor-primevue-B6rcS73U.js";import"./vendor-xterm-CWYFmgbN.js";import{f as ie,P as re}from"./widgetPropFilter-CygYoMQt.js";import{W as de}from"./index-_AAd9eTu.js";import{_ as ue}from"./WidgetLayoutField.vue_vue_type_script_setup_true_lang-Dps42A-g.js";import{a as Ve,c as Oe}from"./LazyImage.vue_vue_type_script_setup_true_lang-CcI-aYhS.js";import{_ as Ae}from"./WidgetWithControl.vue_vue_type_script_setup_true_lang-COy_p9Eh.js";function ce(t={}){return c(()=>({appendTo:"self",...t}))}v(ce,"useTransformCompatOverlayProps");const De={class:"absolute top-5 right-8 h-4 w-7 -translate-y-4/5 flex"},te=T({__name:"WidgetSelectDefault",props:F({widget:{}},{modelValue:{default(t){return t.widget.options?.values?.[0]||""}},modelModifiers:{}}),emits:["update:modelValue"],setup(t){const e=t,i=z(t,"modelValue"),w=ce(),r=c(()=>{const a=e.widget.options;return a?.values&&Array.isArray(a.values)?a.values:[]}),y=c(()=>!!i.value&&!r.value.includes(i.value)),p=c(()=>({...ie(e.widget.options,re),...w.value,...y.value?{placeholder:`${i.value}`}:{}}));return(a,u)=>(m(),I(ue,{widget:a.widget},{default:E(()=>[B(b(ze),ae({modelValue:i.value,"onUpdate:modelValue":u[0]||(u[0]=g=>i.value=g),invalid:y.value,filter:r.value.length>4,"auto-filter-focus":r.value.length>4,options:r.value},p.value,{class:b(x)(b(de),"w-full text-xs"),"aria-label":a.widget.name,size:"small",pt:{option:"text-xs",dropdown:"w-8",label:b(x)("truncate min-w-[4ch]",a.$slots.default&&"mr-5"),overlay:"w-fit min-w-full"},"data-capture-wheel":"true"}),null,16,["modelValue","invalid","filter","auto-filter-focus","options","class","aria-label","pt"]),M("div",De,[we(a.$slots,"default")])]),_:3},8,["widget"]))}}),Ie={class:"min-w-0 flex-1 px-1 py-2 text-left truncate"},Te={key:0},Qe={key:1},Fe=["multiple","disabled","accept"],Le=T({__name:"FormDropdownInput",props:{isOpen:{type:Boolean,default:!1},placeholder:{default:"Select..."},items:{},selected:{},maxSelectable:{},uploadable:{type:Boolean},disabled:{type:Boolean},accept:{}},emits:["select-click","file-change"],setup(t,{emit:e}){const i=t,w=e,r=c(()=>i.items.filter(p=>i.selected.has(p.id))),y=c(()=>x("border-0 bg-component-node-widget-background outline-none text-text-secondary",i.disabled?"cursor-not-allowed":"hover:bg-component-node-widget-background-hovered cursor-pointer",r.value.length>0&&"text-text-primary"));return(p,a)=>(m(),$("div",{class:C(b(x)(b(de),"flex text-base leading-none",{"opacity-50 cursor-not-allowed !outline-zinc-300/10":p.disabled}))},[M("button",{class:C(b(x)(y.value,"flex justify-between items-center flex-1 min-w-0 h-8",{"rounded-l-lg":p.uploadable,"rounded-lg":!p.uploadable})),onClick:a[0]||(a[0]=u=>w("select-click",u))},[M("span",Ie,[r.value.length?(m(),$("span",Qe,j(r.value.map(u=>u.label??u.name).join(", ")),1)):(m(),$("span",Te,j(p.placeholder),1))]),M("i",{class:C(["icon-[lucide--chevron-down]",b(x)("mr-2 size-4 transition-transform duration-200 flex-shrink-0 text-component-node-foreground-secondary",p.isOpen&&"rotate-180")])},null,2)],2),p.uploadable?(m(),$("label",{key:0,class:C(b(x)(y.value,"relative","size-8 flex justify-center items-center border-l rounded-r-lg border-zinc-300/10"))},[a[2]||(a[2]=M("i",{class:"icon-[lucide--folder-search] size-4"},null,-1)),M("input",{type:"file",class:"absolute inset-0 -z-1 opacity-0",multiple:p.maxSelectable>1,disabled:p.disabled,accept:p.accept,onChange:a[1]||(a[1]=u=>w("file-change",u))},null,40,Fe)],2)):L("",!0)],2))}}),Pe={class:"text-secondary flex gap-2 px-4"},Be={key:0,class:"mr-2 icon-[lucide--loader-circle] size-4 animate-spin"},je={key:1,class:"mr-2 icon-[lucide--search] size-4"},Re=["placeholder"],We={key:0,class:"absolute top-[-2px] left-[-2px] size-2 rounded-full bg-component-node-widget-background-highlighted"},Ke=["onClick"],Ee={key:0,class:"icon-[lucide--check] size-4"},K="bg-transparent border-0 outline-0 ring-0 text-left",le="size-6 flex justify-center items-center rounded-sm cursor-pointer transition-all duration-150 hover:scale-108 hover:text-base-foreground active:scale-95",qe=T({__name:"FormDropdownMenuActions",props:F({isQuerying:{type:Boolean},sortOptions:{}},{layoutMode:{},layoutModeModifiers:{},searchQuery:{},searchQueryModifiers:{},sortSelected:{},sortSelectedModifiers:{}}),emits:["update:layoutMode","update:searchQuery","update:sortSelected"],setup(t){const e=z(t,"layoutMode"),i=z(t,"searchQuery"),w=z(t,"sortSelected"),r=x("h-8 bg-zinc-500/20 rounded-lg outline outline-1 outline-offset-[-1px] outline-node-component-border transition-all duration-150"),y=J("sortPopoverRef"),p=J("sortTriggerRef"),a=D(!1);function u(n){!y.value||!p.value||(a.value=!a.value,y.value.toggle(n,p.value))}v(u,"toggleSortPopover");function g(){a.value=!1,y.value?.hide()}v(g,"closeSortPopover");function o(n){w.value=n.id,g()}return v(o,"handleSortSelected"),(n,f)=>(m(),$("div",Pe,[M("label",{class:C(b(x)(b(r),"flex-1 flex px-2 items-center text-base leading-none cursor-text",i.value?.trim()!==""?"text-base-foreground":"","hover:outline-component-node-widget-background-highlighted/80","focus-within:outline-component-node-widget-background-highlighted/80"))},[n.isQuerying?(m(),$("i",Be)):(m(),$("i",je)),se(M("input",{"onUpdate:modelValue":f[0]||(f[0]=h=>i.value=h),type:"text",autofocus:"",class:C(K),placeholder:n.$t("g.search")},null,8,Re),[[he,i.value]])],2),M("button",{ref_key:"sortTriggerRef",ref:p,class:C(b(x)(K,b(r),"relative w-8 flex justify-center items-center cursor-pointer","hover:outline-component-node-widget-background-highlighted","active:!scale-95")),onClick:u},[w.value!=="default"?(m(),$("div",We)):L("",!0),f[4]||(f[4]=M("i",{class:"icon-[lucide--arrow-up-down] size-4"},null,-1))],2),B(b(ne),{ref_key:"sortPopoverRef",ref:y,dismissable:!0,"close-on-escape":!0,unstyled:"",pt:{root:{class:"absolute z-50"},content:{class:["bg-transparent border-none p-0 pt-2 rounded-lg shadow-lg"]}},onHide:f[1]||(f[1]=h=>a.value=!1)},{default:E(()=>[M("div",{class:C(b(x)("flex flex-col gap-2 p-2 min-w-32","bg-component-node-background","rounded-lg outline outline-offset-[-1px] outline-component-node-border"))},[(m(!0),$(_,null,ee(n.sortOptions,h=>(m(),$("button",{key:h.name,class:C(b(x)(K,"flex justify-between items-center h-6 cursor-pointer","hover:!text-blue-500")),onClick:v(V=>o(h),"onClick")},[M("span",null,j(h.name),1),w.value===h.id?(m(),$("i",Ee)):L("",!0)],10,Ke))),128))],2)]),_:1},512),M("div",{class:C(b(x)(b(r),"flex justify-center items-center p-1 gap-1 hover:outline-component-node-widget-background-highlighted"))},[M("button",{class:C(b(x)(K,le,e.value==="list"?"bg-neutral-500/50 text-base-foreground":"")),onClick:f[2]||(f[2]=h=>e.value="list")},f[5]||(f[5]=[M("i",{class:"icon-[lucide--list] size-4"},null,-1)]),2),M("button",{class:C(b(x)(K,le,e.value==="grid"?"bg-neutral-500/50 text-base-foreground":"")),onClick:f[3]||(f[3]=h=>e.value="grid")},f[6]||(f[6]=[M("i",{class:"icon-[lucide--layout-grid] size-4"},null,-1)]),2)],2)]))}}),He={class:"text-secondary mb-4 flex gap-1 px-4 justify-start"},Ne=["disabled","onClick"],Ge=T({__name:"FormDropdownMenuFilter",props:F({filterOptions:{}},{filterSelected:{},filterSelectedModifiers:{}}),emits:["update:filterSelected"],setup(t){const e=z(t,"filterSelected"),{isUploadButtonEnabled:i,showUploadDialog:w}=Ve(),r=c(()=>t.filterOptions.length===1);return(y,p)=>(m(),$("div",He,[(m(!0),$(_,null,ee(y.filterOptions,a=>(m(),$("button",{key:a.id,type:"button",disabled:r.value,class:C(b(x)("px-4 py-2 rounded-md inline-flex justify-center items-center select-none appearance-none border-0 text-base-foreground",!r.value&&"transition-all duration-150 hover:text-base-foreground hover:bg-interface-menu-component-surface-hovered cursor-pointer active:scale-95",!r.value&&e.value===a.id?"!bg-interface-menu-component-surface-selected text-base-foreground":"bg-transparent")),onClick:v(u=>e.value=a.id,"onClick")},j(a.name),11,Ne))),128)),b(i)&&r.value?(m(),I(me,{key:0,class:"ml-auto",size:"md",variant:"textonly",onClick:b(w)},{default:E(()=>[p[0]||(p[0]=M("i",{class:"icon-[lucide--folder-input]"},null,-1)),M("span",null,j(y.$t("g.import")),1)]),_:1},8,["onClick"])):L("",!0)]))}}),pe=Symbol("assetKind"),Xe={key:0,class:"absolute top-1 left-1 size-4 rounded-full border-1 border-base-foreground bg-primary-background"},Ze=["src"],Je={key:3,class:"size-full bg-gradient-to-tr from-blue-400 via-teal-500 to-green-400"},Ye={class:"text-secondary block text-xs"},_e=T({__name:"FormDropdownMenuItem",props:{index:{},selected:{type:Boolean},mediaSrc:{},name:{},label:{},metadata:{},layout:{}},emits:["click","mediaLoad"],setup(t,{emit:e}){const i=t,w=e,r=D(null),y=Se(pe),p=c(()=>y?.value==="video");function a(){w("click",i.index)}v(a,"handleClick");function u(o){if(w("mediaLoad",o),!o.target||!(o.target instanceof HTMLImageElement))return;const n=o.target;n.naturalWidth&&n.naturalHeight&&(r.value=`${n.naturalWidth} x ${n.naturalHeight}`)}v(u,"handleImageLoad");function g(o){if(w("mediaLoad",o),!o.target||!(o.target instanceof HTMLVideoElement))return;const n=o.target;n.videoWidth&&n.videoHeight&&(r.value=`${n.videoWidth} x ${n.videoHeight}`)}return v(g,"handleVideoLoad"),(o,n)=>{const f=ke("tooltip");return m(),$("div",{class:C(b(x)("flex gap-1 select-none group/item cursor-pointer bg-component-node-widget-background","transition-all duration-150",{"flex-col text-center":o.layout==="grid","flex-row text-left max-h-16 rounded-lg hover:scale-102 active:scale-98":o.layout==="list","flex-row text-left hover:bg-component-node-widget-background-hovered rounded-lg":o.layout==="list-small","ring-2 ring-component-node-widget-background-highlighted":o.layout==="list"&&o.selected})),onClick:a},[o.layout!=="list-small"?(m(),$("div",{key:0,class:C(b(x)("relative","w-full aspect-square overflow-hidden outline-1 outline-offset-[-1px] outline-interface-stroke","transition-all duration-150",{"min-w-16 max-w-16 rounded-l-lg":o.layout==="list","rounded-sm group-hover/item:scale-108 group-active/item:scale-95":o.layout==="grid","ring-2 ring-component-node-widget-background-highlighted":o.layout==="grid"&&o.selected}))},[o.selected?(m(),$("div",Xe,n[0]||(n[0]=[M("i",{class:"icon-[lucide--check] size-3 translate-y-[-0.5px] text-base-foreground bold"},null,-1)]))):L("",!0),o.mediaSrc&&p.value?(m(),$("video",{key:1,src:o.mediaSrc,class:"size-full object-cover",preload:"metadata",muted:"",onLoadeddata:g},null,40,Ze)):o.mediaSrc?(m(),I(Oe,{key:2,src:o.mediaSrc,alt:o.name,"image-class":"size-full object-cover",onLoad:u},null,8,["src","alt"])):(m(),$("div",Je))],2)):L("",!0),M("div",{class:C(b(x)("flex gap-1",{"flex-col":o.layout==="grid","flex-col px-4 py-1 w-full justify-center min-w-0":o.layout==="list","flex-row p-2 items-center justify-between w-full":o.layout==="list-small"}))},[se((m(),$("span",{class:C(b(x)("block text-xs line-clamp-2 break-words overflow-hidden","transition-colors duration-150",!!o.selected&&"text-base-foreground"))},[Me(j(o.label??o.name),1)],2)),[[f,o.layout==="grid"?o.label??o.name:void 0]]),M("span",Ye,j(o.metadata||r.value),1)],2)],2)}}}),et={class:"flex max-h-[640px] w-103 flex-col rounded-lg bg-component-node-background pt-4 outline outline-offset-[-1px] outline-node-component-border"},tt={class:"relative flex h-full mt-2 overflow-y-scroll"},lt={key:0,class:"h-50 col-span-full flex items-center justify-center"},ot=["title","aria-label"],at=T({__name:"FormDropdownMenu",props:F({items:{},isSelected:{type:Function},isQuerying:{type:Boolean},filterOptions:{},sortOptions:{}},{filterSelected:{},filterSelectedModifiers:{},layoutMode:{},layoutModeModifiers:{},sortSelected:{},sortSelectedModifiers:{},searchQuery:{},searchQueryModifiers:{}}),emits:F(["item-click"],["update:filterSelected","update:layoutMode","update:sortSelected","update:searchQuery"]),setup(t,{emit:e}){const i=e,w=z(t,"filterSelected"),r=z(t,"layoutMode"),y=z(t,"sortSelected"),p=z(t,"searchQuery");return(a,u)=>(m(),$("div",et,[a.filterOptions.length>0?(m(),I(Ge,{key:0,"filter-selected":w.value,"onUpdate:filterSelected":u[0]||(u[0]=g=>w.value=g),"filter-options":a.filterOptions},null,8,["filter-selected","filter-options"])):L("",!0),B(qe,{"layout-mode":r.value,"onUpdate:layoutMode":u[1]||(u[1]=g=>r.value=g),"sort-selected":y.value,"onUpdate:sortSelected":u[2]||(u[2]=g=>y.value=g),"search-query":p.value,"onUpdate:searchQuery":u[3]||(u[3]=g=>p.value=g),"sort-options":a.sortOptions,"is-querying":a.isQuerying},null,8,["layout-mode","sort-selected","search-query","sort-options","is-querying"]),M("div",tt,[M("div",{class:C(b(x)("h-full max-h-full grid gap-x-2 gap-y-4 overflow-y-auto px-4 pt-4 pb-4 w-full",{"grid-cols-4":r.value==="grid","grid-cols-1 gap-y-2":r.value==="list","grid-cols-1 gap-y-1":r.value==="list-small"}))},[u[4]||(u[4]=M("div",{class:"pointer-events-none absolute inset-x-3 top-0 z-10 h-5"},null,-1)),a.items.length===0?(m(),$("div",lt,[M("i",{title:a.$t("g.noItems"),"aria-label":a.$t("g.noItems"),class:"icon-[lucide--circle-off] size-30 text-zinc-500/20"},null,8,ot)])):L("",!0),(m(!0),$(_,null,ee(a.items,(g,o)=>(m(),I(_e,{key:g.id,index:o,selected:a.isSelected(g,o),"media-src":g.mediaSrc,name:g.name,label:g.label,metadata:g.metadata,layout:r.value,onClick:v(n=>i("item-click",g,o),"onClick")},null,8,["index","selected","media-src","name","label","metadata","layout","onClick"]))),128))],2)])]))}});async function st(t,e){if(t.trim()==="")return e;const i=t.trim().toLowerCase().split(" ");return e.filter(w=>{const r=w.name.toLowerCase();return i.every(y=>r.includes(y))})}v(st,"defaultSearcher");function nt(){return[{name:"Default",id:"default",sorter:v(({items:t})=>t.slice(),"sorter")},{name:"A-Z",id:"a-z",sorter:v(({items:t})=>t.slice().sort((e,i)=>e.name.localeCompare(i.name)),"sorter")}]}v(nt,"getDefaultSortOptions");const it=T({__name:"FormDropdown",props:F({items:{},placeholder:{default:P("widgets.uploadSelect.placeholder")},multiple:{type:[Boolean,Number],default:!1},uploadable:{type:Boolean,default:!1},disabled:{type:Boolean,default:!1},accept:{},filterOptions:{default:v(()=>[],"default")},sortOptions:{default:v(()=>nt(),"default")},isSelected:{type:Function,default:v((t,e,i)=>t.has(e.id),"default")},searcher:{type:Function,default:st}},{selected:{default:new Set},selectedModifiers:{},filterSelected:{default:""},filterSelectedModifiers:{},sortSelected:{default:"default"},sortSelectedModifiers:{},layoutMode:{default:"grid"},layoutModeModifiers:{},files:{default:[]},filesModifiers:{},searchQuery:{default:""},searchQueryModifiers:{}}),emits:["update:selected","update:filterSelected","update:sortSelected","update:layoutMode","update:files","update:searchQuery"],setup(t){const e=t,i=z(t,"selected"),w=z(t,"filterSelected"),r=z(t,"sortSelected"),y=z(t,"layoutMode"),p=z(t,"files"),a=z(t,"searchQuery"),u=$e(a,700,{maxWait:700}),g=D(!1),o=oe(),n=D(),f=J("triggerRef"),h=D(!1),V=c(()=>e.multiple===!0?1/0:typeof e.multiple=="number"?e.multiple:1),R=D([]);Y(a,k=>{g.value=k!==u.value}),Y([u,()=>e.items],(k,S,l)=>{let s=!1,d;l(()=>{s=!0,d?.()}),e.searcher(u.value,e.items,U=>d=U).then(U=>{s||(R.value=U)}).finally(()=>{s||(g.value=!1)})},{immediate:!0});const O=c(()=>e.sortOptions.find(S=>S.id==="default")?.sorter||(({items:S})=>S.slice())),Q=c(()=>r.value==="default"?O.value:e.sortOptions.find(S=>S.id===r.value)?.sorter||O.value),q=c(()=>Q.value({items:R.value})||[]);function H(k,S){return e.isSelected?.(i.value,k,S)??!1}v(H,"internalIsSelected");const N=v(k=>{e.disabled||n.value&&f.value&&(n.value.toggle(k,f.value),h.value=!h.value)},"toggleDropdown"),G=v(()=>{n.value&&(n.value.hide(),h.value=!1)},"closeDropdown");function X(k){if(e.disabled)return;const S=k.target;S.files&&(p.value=Array.from(S.files)),S.value=""}v(X,"handleFileChange");function Z(k,S){if(e.disabled)return;const l=i.value;if(H(k,S))l.delete(k.id);else if(l.size<V.value)l.add(k.id);else if(V.value===1)l.clear(),l.add(k.id);else{o.addAlert("Maximum selection limit reached");return}i.value=new Set(l),V.value===1&&G()}return v(Z,"handleSelection"),(k,S)=>(m(),$("div",{ref_key:"triggerRef",ref:f},[B(Le,{files:p.value,"is-open":h.value,placeholder:k.placeholder,items:k.items,"max-selectable":V.value,selected:i.value,uploadable:k.uploadable,disabled:k.disabled,accept:k.accept,onSelectClick:N,onFileChange:X},null,8,["files","is-open","placeholder","items","max-selectable","selected","uploadable","disabled","accept"]),B(b(ne),{ref_key:"popoverRef",ref:n,dismissable:!0,"close-on-escape":!0,unstyled:"",pt:{root:{class:"absolute z-50"},content:{class:["bg-transparent border-none p-0 pt-2 rounded-lg shadow-lg"]}},onHide:S[4]||(S[4]=l=>h.value=!1)},{default:E(()=>[B(at,{"filter-selected":w.value,"onUpdate:filterSelected":S[0]||(S[0]=l=>w.value=l),"layout-mode":y.value,"onUpdate:layoutMode":S[1]||(S[1]=l=>y.value=l),"sort-selected":r.value,"onUpdate:sortSelected":S[2]||(S[2]=l=>r.value=l),"search-query":a.value,"onUpdate:searchQuery":S[3]||(S[3]=l=>a.value=l),"filter-options":k.filterOptions,"sort-options":k.sortOptions,disabled:k.disabled,"is-querying":g.value,items:q.value,"is-selected":H,"max-selectable":V.value,onClose:G,onItemClick:Z},null,8,["filter-selected","layout-mode","sort-selected","search-query","filter-options","sort-options","disabled","is-querying","items","max-selectable"])]),_:1},512)],512))}});function rt(t){return{category:c(()=>{}),assets:c(()=>[]),dropdownItems:c(()=>[]),isLoading:c(()=>!1),error:c(()=>null)}}v(rt,"useAssetWidgetData");const dt=T({__name:"WidgetSelectDropdown",props:F({widget:{},nodeType:{},assetKind:{},allowUpload:{type:Boolean},uploadFolder:{},isAssetMode:{type:Boolean},defaultLayoutMode:{}},{modelValue:{default(t){return t.widget.options?.values?.[0]||""}},modelModifiers:{}}),emits:["update:modelValue"],setup(t){const e=t;xe(pe,c(()=>e.assetKind));const i=z(t,"modelValue"),w=oe(),r=ge(),y=ce(),p=c(()=>({...ie(e.widget.options,re),...y.value})),u=v(()=>e.isAssetMode&&e.nodeType?rt(Ce(()=>e.nodeType)):null,"getAssetData")(),g=D("all"),o=c(()=>{if(e.isAssetMode){const l=u?.category.value??"All";return[{id:"all",name:Ue(l)}]}return[{id:"all",name:"All"},{id:"inputs",name:"Inputs"},{id:"outputs",name:"Outputs"}]}),n=D(new Set);function f(l){const s=e.widget.options?.getOptionLabel;if(!s)return l;try{return s(l)}catch(d){return console.error("Failed to map value:",d),l}}v(f,"getDisplayLabel");const h=c(()=>{const l=e.widget.options?.values||[];return Array.isArray(l)?l.map((s,d)=>({id:`input-${d}`,mediaSrc:S(s,"input"),name:s,label:f(s),metadata:""})):[]}),V=c(()=>{if(!["image","video"].includes(e.assetKind??""))return[];const l=new Set;return r.historyTasks.forEach(s=>{s.flatOutputs.forEach(d=>{const U=e.assetKind==="image"&&d.mediaType==="images"||e.assetKind==="video"&&d.mediaType==="video";if(d.type==="output"&&U){const W=`${d.subfolder?`${d.subfolder}/${d.filename}`:d.filename} [output]`;l.add(W)}})}),Array.from(l).map(s=>({id:`output-${s}`,mediaSrc:S(s.replace(" [output]",""),"output"),name:s,label:f(s),metadata:""}))}),R=c(()=>e.isAssetMode&&u?u.dropdownItems.value:[...h.value,...V.value]),O=c(()=>{if(e.isAssetMode)return R.value;switch(g.value){case"inputs":return h.value;case"outputs":return V.value;case"all":default:return[...h.value,...V.value]}}),Q=c(()=>{const l=e.widget.options;if(l?.placeholder)return l.placeholder;switch(e.assetKind){case"image":return P("widgets.uploadSelect.placeholderImage");case"video":return P("widgets.uploadSelect.placeholderVideo");case"audio":return P("widgets.uploadSelect.placeholderAudio");case"model":return P("widgets.uploadSelect.placeholderModel");case"unknown":return P("widgets.uploadSelect.placeholderUnknown")}return P("widgets.uploadSelect.placeholder")}),q=c(()=>e.isAssetMode?!1:e.allowUpload===!0),H=c(()=>{switch(e.assetKind){case"image":return"image/*";case"video":return"video/*";case"audio":return"audio/*";default:return}}),N=D(e.defaultLayoutMode??"grid");Y([i,O],([l,s])=>{if(l===void 0){n.value.clear();return}const d=O.value.find(U=>U.name===l);d&&(n.value.clear(),n.value.add(d.id))},{immediate:!0});function G(l){let s;if(l.size>0&&(s=l.values().next().value),s==null){i.value=void 0;return}const d=O.value.find(U=>U.id===s)?.name;if(!d){i.value=void 0;return}i.value=d}v(G,"updateSelectedItems");const X=v(async(l,s=!1,d={})=>{const U=new FormData;U.append("image",l),s&&U.append("subfolder","pasted"),d.type&&U.append("type",d.type);const A=await ve.fetchApi("/upload/image",{method:"POST",body:U});if(A.status!==200)return w.addAlert(A.status+" - "+A.statusText),null;const W=await A.json();return(d.type==="input"||!d.type&&!s)&&await ye().updateInputs(),W.subfolder?`${W.subfolder}/${W.name}`:W.name},"uploadFile"),Z=v(async l=>{const s=e.uploadFolder??"input",d=l.map(A=>X(A,!1,{type:s}));return(await Promise.all(d)).filter(A=>A!==null)},"uploadFiles");async function k(l){if(!(!l||l.length===0))try{const s=await Z(l);if(s.length===0){w.addAlert("File upload failed");return}e.widget.options?.values&&s.forEach(d=>{const U=e.widget.options.values;U.includes(d)||U.push(d)}),i.value=s[0],e.widget.callback&&e.widget.callback(s[0])}catch(s){console.error("Upload error:",s),w.addAlert(`Upload failed: ${s}`)}}v(k,"handleFilesUpdate");function S(l,s="input"){return["image","video"].includes(e.assetKind??"")?`/api/view?filename=${encodeURIComponent(l)}&type=${s}`:""}return v(S,"getMediaUrl"),(l,s)=>(m(),I(ue,{widget:l.widget},{default:E(()=>[B(it,ae({selected:n.value,"onUpdate:selected":s[0]||(s[0]=d=>n.value=d),"filter-selected":g.value,"onUpdate:filterSelected":s[1]||(s[1]=d=>g.value=d),"layout-mode":N.value,"onUpdate:layoutMode":s[2]||(s[2]=d=>N.value=d),items:O.value,placeholder:Q.value,multiple:!1,uploadable:q.value,accept:H.value,"filter-options":o.value},p.value,{class:"w-full","onUpdate:selected":G,"onUpdate:files":k}),null,16,["selected","filter-selected","layout-mode","items","placeholder","uploadable","accept","filter-options"])]),_:1},8,["widget"]))}}),St=T({__name:"WidgetSelect",props:F({widget:{},nodeType:{}},{modelValue:{},modelModifiers:{}}),emits:["update:modelValue"],setup(t){const e=t,i=z(t,"modelValue"),w=c(()=>{if(e.widget.spec&&be(e.widget.spec))return e.widget.spec}),r=c(()=>{const n=w.value;if(!n)return{kind:"unknown",allowUpload:!1,folder:void 0};const{image_upload:f,animated_image_upload:h,video_upload:V,image_folder:R,audio_upload:O}=n;let Q="unknown";return V?Q="video":f||h?Q="image":O&&(Q="audio"),{kind:Q,allowUpload:f===!0||h===!0||V===!0||O===!0,folder:R}}),y=c(()=>!1),p=c(()=>r.value.kind),a=c(()=>y.value||p.value!=="unknown"),u=c(()=>r.value.allowUpload),g=c(()=>r.value.folder??"input"),o=c(()=>y.value?"list":"grid");return(n,f)=>a.value?(m(),I(dt,{key:0,modelValue:i.value,"onUpdate:modelValue":f[0]||(f[0]=h=>i.value=h),widget:n.widget,"node-type":n.widget.nodeType??n.nodeType,"asset-kind":p.value,"allow-upload":u.value,"upload-folder":g.value,"is-asset-mode":y.value,"default-layout-mode":o.value},null,8,["modelValue","widget","node-type","asset-kind","allow-upload","upload-folder","is-asset-mode","default-layout-mode"])):n.widget.controlWidget?(m(),I(Ae,{key:1,modelValue:i.value,"onUpdate:modelValue":f[1]||(f[1]=h=>i.value=h),component:te,widget:n.widget},null,8,["modelValue","widget"])):(m(),I(te,{key:2,modelValue:i.value,"onUpdate:modelValue":f[2]||(f[2]=h=>i.value=h),widget:n.widget},null,8,["modelValue","widget"]))}});export{St as _};
|
|
2
|
-
//# sourceMappingURL=WidgetSelect.vue_vue_type_script_setup_true_lang-
|
|
1
|
+
var fe=Object.defineProperty;var v=(t,e)=>fe(t,"name",{value:e,configurable:!0});import{c as x,_ as me,f as oe,t as L,M as ge,a as ve,X as ye,cE as be}from"./index-CuKlxAeN.js";import{E as c,bx as T,cM as F,cN as z,j as I,d as m,k as K,z as B,e as M,by as b,m as ae,p as we,c as $,s as C,q as P,u as j,dG as J,r as D,l as se,dm as he,F as _,y as ee,i as Se,h as ke,A as Me,dv as $e,w as Y,bB as xe,eE as Ue,bl as Ce}from"./vendor-other-CSX7WseZ.js";import{i as ze,p as ne}from"./vendor-primevue-B6rcS73U.js";import"./vendor-xterm-CWYFmgbN.js";import{f as ie,P as re}from"./widgetPropFilter-CygYoMQt.js";import{W as de}from"./index-DEqR9lwu.js";import{_ as ue}from"./WidgetLayoutField.vue_vue_type_script_setup_true_lang-CZj3E4v6.js";import{a as Ve,c as Oe}from"./LazyImage.vue_vue_type_script_setup_true_lang-DyOiHvnA.js";import{_ as Ae}from"./WidgetWithControl.vue_vue_type_script_setup_true_lang-JSl33v3j.js";function ce(t={}){return c(()=>({appendTo:"self",...t}))}v(ce,"useTransformCompatOverlayProps");const De={class:"absolute top-5 right-8 h-4 w-7 -translate-y-4/5 flex"},te=T({__name:"WidgetSelectDefault",props:F({widget:{}},{modelValue:{default(t){return t.widget.options?.values?.[0]||""}},modelModifiers:{}}),emits:["update:modelValue"],setup(t){const e=t,i=z(t,"modelValue"),w=ce(),r=c(()=>{const a=e.widget.options;return a?.values&&Array.isArray(a.values)?a.values:[]}),y=c(()=>!!i.value&&!r.value.includes(i.value)),p=c(()=>({...ie(e.widget.options,re),...w.value,...y.value?{placeholder:`${i.value}`}:{}}));return(a,u)=>(m(),I(ue,{widget:a.widget},{default:K(()=>[B(b(ze),ae({modelValue:i.value,"onUpdate:modelValue":u[0]||(u[0]=g=>i.value=g),invalid:y.value,filter:r.value.length>4,"auto-filter-focus":r.value.length>4,options:r.value},p.value,{class:b(x)(b(de),"w-full text-xs"),"aria-label":a.widget.name,size:"small",pt:{option:"text-xs",dropdown:"w-8",label:b(x)("truncate min-w-[4ch]",a.$slots.default&&"mr-5"),overlay:"w-fit min-w-full"},"data-capture-wheel":"true"}),null,16,["modelValue","invalid","filter","auto-filter-focus","options","class","aria-label","pt"]),M("div",De,[we(a.$slots,"default")])]),_:3},8,["widget"]))}}),Ie={class:"min-w-0 flex-1 px-1 py-2 text-left truncate"},Te={key:0},Qe={key:1},Fe=["multiple","disabled","accept"],Pe=T({__name:"FormDropdownInput",props:{isOpen:{type:Boolean,default:!1},placeholder:{default:"Select..."},items:{},selected:{},maxSelectable:{},uploadable:{type:Boolean},disabled:{type:Boolean},accept:{}},emits:["select-click","file-change"],setup(t,{emit:e}){const i=t,w=e,r=c(()=>i.items.filter(p=>i.selected.has(p.id))),y=c(()=>x("border-0 bg-component-node-widget-background outline-none text-text-secondary",i.disabled?"cursor-not-allowed":"hover:bg-component-node-widget-background-hovered cursor-pointer",r.value.length>0&&"text-text-primary"));return(p,a)=>(m(),$("div",{class:C(b(x)(b(de),"flex text-base leading-none",{"opacity-50 cursor-not-allowed !outline-zinc-300/10":p.disabled}))},[M("button",{class:C(b(x)(y.value,"flex justify-between items-center flex-1 min-w-0 h-8",{"rounded-l-lg":p.uploadable,"rounded-lg":!p.uploadable})),onClick:a[0]||(a[0]=u=>w("select-click",u))},[M("span",Ie,[r.value.length?(m(),$("span",Qe,j(r.value.map(u=>u.label??u.name).join(", ")),1)):(m(),$("span",Te,j(p.placeholder),1))]),M("i",{class:C(["icon-[lucide--chevron-down]",b(x)("mr-2 size-4 transition-transform duration-200 flex-shrink-0 text-component-node-foreground-secondary",p.isOpen&&"rotate-180")])},null,2)],2),p.uploadable?(m(),$("label",{key:0,class:C(b(x)(y.value,"relative","size-8 flex justify-center items-center border-l rounded-r-lg border-zinc-300/10"))},[a[2]||(a[2]=M("i",{class:"icon-[lucide--folder-search] size-4"},null,-1)),M("input",{type:"file",class:"absolute inset-0 -z-1 opacity-0",multiple:p.maxSelectable>1,disabled:p.disabled,accept:p.accept,onChange:a[1]||(a[1]=u=>w("file-change",u))},null,40,Fe)],2)):P("",!0)],2))}}),Le={class:"text-secondary flex gap-2 px-4"},Be={key:0,class:"mr-2 icon-[lucide--loader-circle] size-4 animate-spin"},je={key:1,class:"mr-2 icon-[lucide--search] size-4"},Re=["placeholder"],We={key:0,class:"absolute top-[-2px] left-[-2px] size-2 rounded-full bg-component-node-widget-background-highlighted"},Ee=["onClick"],Ke={key:0,class:"icon-[lucide--check] size-4"},E="bg-transparent border-0 outline-0 ring-0 text-left",le="size-6 flex justify-center items-center rounded-sm cursor-pointer transition-all duration-150 hover:scale-108 hover:text-base-foreground active:scale-95",qe=T({__name:"FormDropdownMenuActions",props:F({isQuerying:{type:Boolean},sortOptions:{}},{layoutMode:{},layoutModeModifiers:{},searchQuery:{},searchQueryModifiers:{},sortSelected:{},sortSelectedModifiers:{}}),emits:["update:layoutMode","update:searchQuery","update:sortSelected"],setup(t){const e=z(t,"layoutMode"),i=z(t,"searchQuery"),w=z(t,"sortSelected"),r=x("h-8 bg-zinc-500/20 rounded-lg outline outline-1 outline-offset-[-1px] outline-node-component-border transition-all duration-150"),y=J("sortPopoverRef"),p=J("sortTriggerRef"),a=D(!1);function u(n){!y.value||!p.value||(a.value=!a.value,y.value.toggle(n,p.value))}v(u,"toggleSortPopover");function g(){a.value=!1,y.value?.hide()}v(g,"closeSortPopover");function o(n){w.value=n.id,g()}return v(o,"handleSortSelected"),(n,f)=>(m(),$("div",Le,[M("label",{class:C(b(x)(b(r),"flex-1 flex px-2 items-center text-base leading-none cursor-text",i.value?.trim()!==""?"text-base-foreground":"","hover:outline-component-node-widget-background-highlighted/80","focus-within:outline-component-node-widget-background-highlighted/80"))},[n.isQuerying?(m(),$("i",Be)):(m(),$("i",je)),se(M("input",{"onUpdate:modelValue":f[0]||(f[0]=h=>i.value=h),type:"text",autofocus:"",class:C(E),placeholder:n.$t("g.search")},null,8,Re),[[he,i.value]])],2),M("button",{ref_key:"sortTriggerRef",ref:p,class:C(b(x)(E,b(r),"relative w-8 flex justify-center items-center cursor-pointer","hover:outline-component-node-widget-background-highlighted","active:!scale-95")),onClick:u},[w.value!=="default"?(m(),$("div",We)):P("",!0),f[4]||(f[4]=M("i",{class:"icon-[lucide--arrow-up-down] size-4"},null,-1))],2),B(b(ne),{ref_key:"sortPopoverRef",ref:y,dismissable:!0,"close-on-escape":!0,unstyled:"",pt:{root:{class:"absolute z-50"},content:{class:["bg-transparent border-none p-0 pt-2 rounded-lg shadow-lg"]}},onHide:f[1]||(f[1]=h=>a.value=!1)},{default:K(()=>[M("div",{class:C(b(x)("flex flex-col gap-2 p-2 min-w-32","bg-component-node-background","rounded-lg outline outline-offset-[-1px] outline-component-node-border"))},[(m(!0),$(_,null,ee(n.sortOptions,h=>(m(),$("button",{key:h.name,class:C(b(x)(E,"flex justify-between items-center h-6 cursor-pointer","hover:!text-blue-500")),onClick:v(V=>o(h),"onClick")},[M("span",null,j(h.name),1),w.value===h.id?(m(),$("i",Ke)):P("",!0)],10,Ee))),128))],2)]),_:1},512),M("div",{class:C(b(x)(b(r),"flex justify-center items-center p-1 gap-1 hover:outline-component-node-widget-background-highlighted"))},[M("button",{class:C(b(x)(E,le,e.value==="list"?"bg-neutral-500/50 text-base-foreground":"")),onClick:f[2]||(f[2]=h=>e.value="list")},f[5]||(f[5]=[M("i",{class:"icon-[lucide--list] size-4"},null,-1)]),2),M("button",{class:C(b(x)(E,le,e.value==="grid"?"bg-neutral-500/50 text-base-foreground":"")),onClick:f[3]||(f[3]=h=>e.value="grid")},f[6]||(f[6]=[M("i",{class:"icon-[lucide--layout-grid] size-4"},null,-1)]),2)],2)]))}}),He={class:"text-secondary mb-4 flex gap-1 px-4 justify-start"},Ne=["disabled","onClick"],Xe=T({__name:"FormDropdownMenuFilter",props:F({filterOptions:{}},{filterSelected:{},filterSelectedModifiers:{}}),emits:["update:filterSelected"],setup(t){const e=z(t,"filterSelected"),{isUploadButtonEnabled:i,showUploadDialog:w}=Ve(),r=c(()=>t.filterOptions.length===1);return(y,p)=>(m(),$("div",He,[(m(!0),$(_,null,ee(y.filterOptions,a=>(m(),$("button",{key:a.id,type:"button",disabled:r.value,class:C(b(x)("px-4 py-2 rounded-md inline-flex justify-center items-center select-none appearance-none border-0 text-base-foreground",!r.value&&"transition-all duration-150 hover:text-base-foreground hover:bg-interface-menu-component-surface-hovered cursor-pointer active:scale-95",!r.value&&e.value===a.id?"!bg-interface-menu-component-surface-selected text-base-foreground":"bg-transparent")),onClick:v(u=>e.value=a.id,"onClick")},j(a.name),11,Ne))),128)),b(i)&&r.value?(m(),I(me,{key:0,class:"ml-auto",size:"md",variant:"textonly",onClick:b(w)},{default:K(()=>[p[0]||(p[0]=M("i",{class:"icon-[lucide--folder-input]"},null,-1)),M("span",null,j(y.$t("g.import")),1)]),_:1},8,["onClick"])):P("",!0)]))}}),pe=Symbol("assetKind"),Ge={key:0,class:"absolute top-1 left-1 size-4 rounded-full border-1 border-base-foreground bg-primary-background"},Ze=["src"],Je={key:3,class:"size-full bg-gradient-to-tr from-blue-400 via-teal-500 to-green-400"},Ye={class:"text-secondary block text-xs"},_e=T({__name:"FormDropdownMenuItem",props:{index:{},selected:{type:Boolean},mediaSrc:{},name:{},label:{},metadata:{},layout:{}},emits:["click","mediaLoad"],setup(t,{emit:e}){const i=t,w=e,r=D(null),y=Se(pe),p=c(()=>y?.value==="video");function a(){w("click",i.index)}v(a,"handleClick");function u(o){if(w("mediaLoad",o),!o.target||!(o.target instanceof HTMLImageElement))return;const n=o.target;n.naturalWidth&&n.naturalHeight&&(r.value=`${n.naturalWidth} x ${n.naturalHeight}`)}v(u,"handleImageLoad");function g(o){if(w("mediaLoad",o),!o.target||!(o.target instanceof HTMLVideoElement))return;const n=o.target;n.videoWidth&&n.videoHeight&&(r.value=`${n.videoWidth} x ${n.videoHeight}`)}return v(g,"handleVideoLoad"),(o,n)=>{const f=ke("tooltip");return m(),$("div",{class:C(b(x)("flex gap-1 select-none group/item cursor-pointer bg-component-node-widget-background","transition-all duration-150",{"flex-col text-center":o.layout==="grid","flex-row text-left max-h-16 rounded-lg hover:scale-102 active:scale-98":o.layout==="list","flex-row text-left hover:bg-component-node-widget-background-hovered rounded-lg":o.layout==="list-small","ring-2 ring-component-node-widget-background-highlighted":o.layout==="list"&&o.selected})),onClick:a},[o.layout!=="list-small"?(m(),$("div",{key:0,class:C(b(x)("relative","w-full aspect-square overflow-hidden outline-1 outline-offset-[-1px] outline-interface-stroke","transition-all duration-150",{"min-w-16 max-w-16 rounded-l-lg":o.layout==="list","rounded-sm group-hover/item:scale-108 group-active/item:scale-95":o.layout==="grid","ring-2 ring-component-node-widget-background-highlighted":o.layout==="grid"&&o.selected}))},[o.selected?(m(),$("div",Ge,n[0]||(n[0]=[M("i",{class:"icon-[lucide--check] size-3 translate-y-[-0.5px] text-base-foreground bold"},null,-1)]))):P("",!0),o.mediaSrc&&p.value?(m(),$("video",{key:1,src:o.mediaSrc,class:"size-full object-cover",preload:"metadata",muted:"",onLoadeddata:g},null,40,Ze)):o.mediaSrc?(m(),I(Oe,{key:2,src:o.mediaSrc,alt:o.name,"image-class":"size-full object-cover",onLoad:u},null,8,["src","alt"])):(m(),$("div",Je))],2)):P("",!0),M("div",{class:C(b(x)("flex gap-1",{"flex-col":o.layout==="grid","flex-col px-4 py-1 w-full justify-center min-w-0":o.layout==="list","flex-row p-2 items-center justify-between w-full":o.layout==="list-small"}))},[se((m(),$("span",{class:C(b(x)("block text-xs line-clamp-2 break-words overflow-hidden","transition-colors duration-150",!!o.selected&&"text-base-foreground"))},[Me(j(o.label??o.name),1)],2)),[[f,o.layout==="grid"?o.label??o.name:void 0]]),M("span",Ye,j(o.metadata||r.value),1)],2)],2)}}}),et={class:"flex max-h-[640px] w-103 flex-col rounded-lg bg-component-node-background pt-4 outline outline-offset-[-1px] outline-node-component-border"},tt={class:"relative flex h-full mt-2 overflow-y-scroll"},lt={key:0,class:"h-50 col-span-full flex items-center justify-center"},ot=["title","aria-label"],at=T({__name:"FormDropdownMenu",props:F({items:{},isSelected:{type:Function},isQuerying:{type:Boolean},filterOptions:{},sortOptions:{}},{filterSelected:{},filterSelectedModifiers:{},layoutMode:{},layoutModeModifiers:{},sortSelected:{},sortSelectedModifiers:{},searchQuery:{},searchQueryModifiers:{}}),emits:F(["item-click"],["update:filterSelected","update:layoutMode","update:sortSelected","update:searchQuery"]),setup(t,{emit:e}){const i=e,w=z(t,"filterSelected"),r=z(t,"layoutMode"),y=z(t,"sortSelected"),p=z(t,"searchQuery");return(a,u)=>(m(),$("div",et,[a.filterOptions.length>0?(m(),I(Xe,{key:0,"filter-selected":w.value,"onUpdate:filterSelected":u[0]||(u[0]=g=>w.value=g),"filter-options":a.filterOptions},null,8,["filter-selected","filter-options"])):P("",!0),B(qe,{"layout-mode":r.value,"onUpdate:layoutMode":u[1]||(u[1]=g=>r.value=g),"sort-selected":y.value,"onUpdate:sortSelected":u[2]||(u[2]=g=>y.value=g),"search-query":p.value,"onUpdate:searchQuery":u[3]||(u[3]=g=>p.value=g),"sort-options":a.sortOptions,"is-querying":a.isQuerying},null,8,["layout-mode","sort-selected","search-query","sort-options","is-querying"]),M("div",tt,[M("div",{class:C(b(x)("h-full max-h-full grid gap-x-2 gap-y-4 overflow-y-auto px-4 pt-4 pb-4 w-full",{"grid-cols-4":r.value==="grid","grid-cols-1 gap-y-2":r.value==="list","grid-cols-1 gap-y-1":r.value==="list-small"}))},[u[4]||(u[4]=M("div",{class:"pointer-events-none absolute inset-x-3 top-0 z-10 h-5"},null,-1)),a.items.length===0?(m(),$("div",lt,[M("i",{title:a.$t("g.noItems"),"aria-label":a.$t("g.noItems"),class:"icon-[lucide--circle-off] size-30 text-zinc-500/20"},null,8,ot)])):P("",!0),(m(!0),$(_,null,ee(a.items,(g,o)=>(m(),I(_e,{key:g.id,index:o,selected:a.isSelected(g,o),"media-src":g.mediaSrc,name:g.name,label:g.label,metadata:g.metadata,layout:r.value,onClick:v(n=>i("item-click",g,o),"onClick")},null,8,["index","selected","media-src","name","label","metadata","layout","onClick"]))),128))],2)])]))}});async function st(t,e){if(t.trim()==="")return e;const i=t.trim().toLowerCase().split(" ");return e.filter(w=>{const r=w.name.toLowerCase();return i.every(y=>r.includes(y))})}v(st,"defaultSearcher");function nt(){return[{name:"Default",id:"default",sorter:v(({items:t})=>t.slice(),"sorter")},{name:"A-Z",id:"a-z",sorter:v(({items:t})=>t.slice().sort((e,i)=>e.name.localeCompare(i.name)),"sorter")}]}v(nt,"getDefaultSortOptions");const it=T({__name:"FormDropdown",props:F({items:{},placeholder:{default:L("widgets.uploadSelect.placeholder")},multiple:{type:[Boolean,Number],default:!1},uploadable:{type:Boolean,default:!1},disabled:{type:Boolean,default:!1},accept:{},filterOptions:{default:v(()=>[],"default")},sortOptions:{default:v(()=>nt(),"default")},isSelected:{type:Function,default:v((t,e,i)=>t.has(e.id),"default")},searcher:{type:Function,default:st}},{selected:{default:new Set},selectedModifiers:{},filterSelected:{default:""},filterSelectedModifiers:{},sortSelected:{default:"default"},sortSelectedModifiers:{},layoutMode:{default:"grid"},layoutModeModifiers:{},files:{default:[]},filesModifiers:{},searchQuery:{default:""},searchQueryModifiers:{}}),emits:["update:selected","update:filterSelected","update:sortSelected","update:layoutMode","update:files","update:searchQuery"],setup(t){const e=t,i=z(t,"selected"),w=z(t,"filterSelected"),r=z(t,"sortSelected"),y=z(t,"layoutMode"),p=z(t,"files"),a=z(t,"searchQuery"),u=$e(a,700,{maxWait:700}),g=D(!1),o=oe(),n=D(),f=J("triggerRef"),h=D(!1),V=c(()=>e.multiple===!0?1/0:typeof e.multiple=="number"?e.multiple:1),R=D([]);Y(a,k=>{g.value=k!==u.value}),Y([u,()=>e.items],(k,S,l)=>{let s=!1,d;l(()=>{s=!0,d?.()}),e.searcher(u.value,e.items,U=>d=U).then(U=>{s||(R.value=U)}).finally(()=>{s||(g.value=!1)})},{immediate:!0});const O=c(()=>e.sortOptions.find(S=>S.id==="default")?.sorter||(({items:S})=>S.slice())),Q=c(()=>r.value==="default"?O.value:e.sortOptions.find(S=>S.id===r.value)?.sorter||O.value),q=c(()=>Q.value({items:R.value})||[]);function H(k,S){return e.isSelected?.(i.value,k,S)??!1}v(H,"internalIsSelected");const N=v(k=>{e.disabled||n.value&&f.value&&(n.value.toggle(k,f.value),h.value=!h.value)},"toggleDropdown"),X=v(()=>{n.value&&(n.value.hide(),h.value=!1)},"closeDropdown");function G(k){if(e.disabled)return;const S=k.target;S.files&&(p.value=Array.from(S.files)),S.value=""}v(G,"handleFileChange");function Z(k,S){if(e.disabled)return;const l=i.value;if(H(k,S))l.delete(k.id);else if(l.size<V.value)l.add(k.id);else if(V.value===1)l.clear(),l.add(k.id);else{o.addAlert("Maximum selection limit reached");return}i.value=new Set(l),V.value===1&&X()}return v(Z,"handleSelection"),(k,S)=>(m(),$("div",{ref_key:"triggerRef",ref:f},[B(Pe,{files:p.value,"is-open":h.value,placeholder:k.placeholder,items:k.items,"max-selectable":V.value,selected:i.value,uploadable:k.uploadable,disabled:k.disabled,accept:k.accept,onSelectClick:N,onFileChange:G},null,8,["files","is-open","placeholder","items","max-selectable","selected","uploadable","disabled","accept"]),B(b(ne),{ref_key:"popoverRef",ref:n,dismissable:!0,"close-on-escape":!0,unstyled:"",pt:{root:{class:"absolute z-50"},content:{class:["bg-transparent border-none p-0 pt-2 rounded-lg shadow-lg"]}},onHide:S[4]||(S[4]=l=>h.value=!1)},{default:K(()=>[B(at,{"filter-selected":w.value,"onUpdate:filterSelected":S[0]||(S[0]=l=>w.value=l),"layout-mode":y.value,"onUpdate:layoutMode":S[1]||(S[1]=l=>y.value=l),"sort-selected":r.value,"onUpdate:sortSelected":S[2]||(S[2]=l=>r.value=l),"search-query":a.value,"onUpdate:searchQuery":S[3]||(S[3]=l=>a.value=l),"filter-options":k.filterOptions,"sort-options":k.sortOptions,disabled:k.disabled,"is-querying":g.value,items:q.value,"is-selected":H,"max-selectable":V.value,onClose:X,onItemClick:Z},null,8,["filter-selected","layout-mode","sort-selected","search-query","filter-options","sort-options","disabled","is-querying","items","max-selectable"])]),_:1},512)],512))}});function rt(t){return{category:c(()=>{}),assets:c(()=>[]),dropdownItems:c(()=>[]),isLoading:c(()=>!1),error:c(()=>null)}}v(rt,"useAssetWidgetData");const dt=T({__name:"WidgetSelectDropdown",props:F({widget:{},nodeType:{},assetKind:{},allowUpload:{type:Boolean},uploadFolder:{},isAssetMode:{type:Boolean},defaultLayoutMode:{}},{modelValue:{default(t){return t.widget.options?.values?.[0]||""}},modelModifiers:{}}),emits:["update:modelValue"],setup(t){const e=t;xe(pe,c(()=>e.assetKind));const i=z(t,"modelValue"),w=oe(),r=ge(),y=ce(),p=c(()=>({...ie(e.widget.options,re),...y.value})),u=v(()=>e.isAssetMode&&e.nodeType?rt(Ce(()=>e.nodeType)):null,"getAssetData")(),g=D("all"),o=c(()=>{if(e.isAssetMode){const l=u?.category.value??"All";return[{id:"all",name:Ue(l)}]}return[{id:"all",name:"All"},{id:"inputs",name:"Inputs"},{id:"outputs",name:"Outputs"}]}),n=D(new Set);function f(l){const s=e.widget.options?.getOptionLabel;if(!s)return l;try{return s(l)}catch(d){return console.error("Failed to map value:",d),l}}v(f,"getDisplayLabel");const h=c(()=>{const l=e.widget.options?.values||[];return Array.isArray(l)?l.map((s,d)=>({id:`input-${d}`,mediaSrc:S(s,"input"),name:s,label:f(s),metadata:""})):[]}),V=c(()=>{if(!["image","video"].includes(e.assetKind??""))return[];const l=new Set;return r.historyTasks.forEach(s=>{s.flatOutputs.forEach(d=>{const U=e.assetKind==="image"&&d.mediaType==="images"||e.assetKind==="video"&&d.mediaType==="video";if(d.type==="output"&&U){const W=`${d.subfolder?`${d.subfolder}/${d.filename}`:d.filename} [output]`;l.add(W)}})}),Array.from(l).map(s=>({id:`output-${s}`,mediaSrc:S(s.replace(" [output]",""),"output"),name:s,label:f(s),metadata:""}))}),R=c(()=>e.isAssetMode&&u?u.dropdownItems.value:[...h.value,...V.value]),O=c(()=>{if(e.isAssetMode)return R.value;switch(g.value){case"inputs":return h.value;case"outputs":return V.value;case"all":default:return[...h.value,...V.value]}}),Q=c(()=>{const l=e.widget.options;if(l?.placeholder)return l.placeholder;switch(e.assetKind){case"image":return L("widgets.uploadSelect.placeholderImage");case"video":return L("widgets.uploadSelect.placeholderVideo");case"audio":return L("widgets.uploadSelect.placeholderAudio");case"model":return L("widgets.uploadSelect.placeholderModel");case"unknown":return L("widgets.uploadSelect.placeholderUnknown")}return L("widgets.uploadSelect.placeholder")}),q=c(()=>e.isAssetMode?!1:e.allowUpload===!0),H=c(()=>{switch(e.assetKind){case"image":return"image/*";case"video":return"video/*";case"audio":return"audio/*";default:return}}),N=D(e.defaultLayoutMode??"grid");Y([i,O],([l,s])=>{if(l===void 0){n.value.clear();return}const d=O.value.find(U=>U.name===l);d&&(n.value.clear(),n.value.add(d.id))},{immediate:!0});function X(l){let s;if(l.size>0&&(s=l.values().next().value),s==null){i.value=void 0;return}const d=O.value.find(U=>U.id===s)?.name;if(!d){i.value=void 0;return}i.value=d}v(X,"updateSelectedItems");const G=v(async(l,s=!1,d={})=>{const U=new FormData;U.append("image",l),s&&U.append("subfolder","pasted"),d.type&&U.append("type",d.type);const A=await ve.fetchApi("/upload/image",{method:"POST",body:U});if(A.status!==200)return w.addAlert(A.status+" - "+A.statusText),null;const W=await A.json();return(d.type==="input"||!d.type&&!s)&&await ye().updateInputs(),W.subfolder?`${W.subfolder}/${W.name}`:W.name},"uploadFile"),Z=v(async l=>{const s=e.uploadFolder??"input",d=l.map(A=>G(A,!1,{type:s}));return(await Promise.all(d)).filter(A=>A!==null)},"uploadFiles");async function k(l){if(!(!l||l.length===0))try{const s=await Z(l);if(s.length===0){w.addAlert("File upload failed");return}e.widget.options?.values&&s.forEach(d=>{const U=e.widget.options.values;U.includes(d)||U.push(d)}),i.value=s[0],e.widget.callback&&e.widget.callback(s[0])}catch(s){console.error("Upload error:",s),w.addAlert(`Upload failed: ${s}`)}}v(k,"handleFilesUpdate");function S(l,s="input"){return["image","video"].includes(e.assetKind??"")?`/api/view?filename=${encodeURIComponent(l)}&type=${s}`:""}return v(S,"getMediaUrl"),(l,s)=>(m(),I(ue,{widget:l.widget},{default:K(()=>[B(it,ae({selected:n.value,"onUpdate:selected":s[0]||(s[0]=d=>n.value=d),"filter-selected":g.value,"onUpdate:filterSelected":s[1]||(s[1]=d=>g.value=d),"layout-mode":N.value,"onUpdate:layoutMode":s[2]||(s[2]=d=>N.value=d),items:O.value,placeholder:Q.value,multiple:!1,uploadable:q.value,accept:H.value,"filter-options":o.value},p.value,{class:"w-full","onUpdate:selected":X,"onUpdate:files":k}),null,16,["selected","filter-selected","layout-mode","items","placeholder","uploadable","accept","filter-options"])]),_:1},8,["widget"]))}}),St=T({__name:"WidgetSelect",props:F({widget:{},nodeType:{}},{modelValue:{},modelModifiers:{}}),emits:["update:modelValue"],setup(t){const e=t,i=z(t,"modelValue"),w=c(()=>{if(e.widget.spec&&be(e.widget.spec))return e.widget.spec}),r=c(()=>{const n=w.value;if(!n)return{kind:"unknown",allowUpload:!1,folder:void 0};const{image_upload:f,animated_image_upload:h,video_upload:V,image_folder:R,audio_upload:O}=n;let Q="unknown";return V?Q="video":f||h?Q="image":O&&(Q="audio"),{kind:Q,allowUpload:f===!0||h===!0||V===!0||O===!0,folder:R}}),y=c(()=>!1),p=c(()=>r.value.kind),a=c(()=>y.value||p.value!=="unknown"),u=c(()=>r.value.allowUpload),g=c(()=>r.value.folder??"input"),o=c(()=>y.value?"list":"grid");return(n,f)=>a.value?(m(),I(dt,{key:0,modelValue:i.value,"onUpdate:modelValue":f[0]||(f[0]=h=>i.value=h),widget:n.widget,"node-type":n.widget.nodeType??n.nodeType,"asset-kind":p.value,"allow-upload":u.value,"upload-folder":g.value,"is-asset-mode":y.value,"default-layout-mode":o.value},null,8,["modelValue","widget","node-type","asset-kind","allow-upload","upload-folder","is-asset-mode","default-layout-mode"])):n.widget.controlWidget?(m(),I(Ae,{key:1,modelValue:i.value,"onUpdate:modelValue":f[1]||(f[1]=h=>i.value=h),component:te,widget:n.widget},null,8,["modelValue","widget"])):(m(),I(te,{key:2,modelValue:i.value,"onUpdate:modelValue":f[2]||(f[2]=h=>i.value=h),widget:n.widget},null,8,["modelValue","widget"]))}});export{St as _};
|
|
2
|
+
//# sourceMappingURL=WidgetSelect.vue_vue_type_script_setup_true_lang-CITubFAk.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WidgetSelect.vue_vue_type_script_setup_true_lang-CMg0GtSC.js","sources":["../../src/composables/useTransformCompatOverlayProps.ts","../../src/renderer/extensions/vueNodes/widgets/components/WidgetSelectDefault.vue","../../src/renderer/extensions/vueNodes/widgets/components/form/dropdown/FormDropdownInput.vue","../../src/renderer/extensions/vueNodes/widgets/components/form/dropdown/FormDropdownMenuActions.vue","../../src/renderer/extensions/vueNodes/widgets/components/form/dropdown/FormDropdownMenuFilter.vue","../../src/renderer/extensions/vueNodes/widgets/components/form/dropdown/types.ts","../../src/renderer/extensions/vueNodes/widgets/components/form/dropdown/FormDropdownMenuItem.vue","../../src/renderer/extensions/vueNodes/widgets/components/form/dropdown/FormDropdownMenu.vue","../../src/renderer/extensions/vueNodes/widgets/components/form/dropdown/shared.ts","../../src/renderer/extensions/vueNodes/widgets/components/form/dropdown/FormDropdown.vue","../../src/renderer/extensions/vueNodes/widgets/composables/useAssetWidgetData.ts","../../src/renderer/extensions/vueNodes/widgets/components/WidgetSelectDropdown.vue","../../src/renderer/extensions/vueNodes/widgets/components/WidgetSelect.vue"],"sourcesContent":["import type { HintedString } from '@primevue/core'\nimport { computed } from 'vue'\n\n/**\n * Options for configuring transform-compatible overlay props\n */\ninterface TransformCompatOverlayOptions {\n /**\n * Where to append the overlay. 'self' keeps overlay within component\n * for proper transform inheritance, 'body' teleports to document body\n */\n appendTo?: HintedString<'body' | 'self'> | undefined | HTMLElement\n // Future: other props needed for transform compatibility\n // scrollTarget?: string | HTMLElement\n // autoZIndex?: boolean\n}\n\n/**\n * Composable that provides props to make PrimeVue overlay components\n * compatible with CSS-transformed parent elements.\n *\n * Vue nodes use CSS transforms for positioning/scaling. PrimeVue overlay\n * components (Select, MultiSelect, TreeSelect, etc.) teleport to document\n * body by default, breaking transform inheritance. This composable provides\n * the necessary props to keep overlays within their component elements.\n *\n * @param overrides - Optional overrides for specific use cases\n * @returns Computed props object to spread on PrimeVue overlay components\n *\n * @example\n * ```vue\n * <template>\n * <Select v-bind=\"overlayProps\" />\n * </template>\n *\n * <script setup>\n * const overlayProps = useTransformCompatOverlayProps()\n * </script>\n * ```\n */\nexport function useTransformCompatOverlayProps(\n overrides: TransformCompatOverlayOptions = {}\n) {\n return computed(() => ({\n appendTo: 'self' as const,\n ...overrides\n }))\n}\n","<template>\n <WidgetLayoutField :widget>\n <Select\n v-model=\"modelValue\"\n :invalid\n :filter=\"selectOptions.length > 4\"\n :auto-filter-focus=\"selectOptions.length > 4\"\n :options=\"selectOptions\"\n v-bind=\"combinedProps\"\n :class=\"cn(WidgetInputBaseClass, 'w-full text-xs')\"\n :aria-label=\"widget.name\"\n size=\"small\"\n :pt=\"{\n option: 'text-xs',\n dropdown: 'w-8',\n label: cn('truncate min-w-[4ch]', $slots.default && 'mr-5'),\n overlay: 'w-fit min-w-full'\n }\"\n data-capture-wheel=\"true\"\n />\n <div class=\"absolute top-5 right-8 h-4 w-7 -translate-y-4/5 flex\">\n <slot />\n </div>\n </WidgetLayoutField>\n</template>\n\n<script setup lang=\"ts\">\nimport Select from 'primevue/select'\nimport { computed } from 'vue'\n\nimport { useTransformCompatOverlayProps } from '@/composables/useTransformCompatOverlayProps'\nimport type { SimplifiedWidget } from '@/types/simplifiedWidget'\nimport { cn } from '@/utils/tailwindUtil'\nimport {\n PANEL_EXCLUDED_PROPS,\n filterWidgetProps\n} from '@/utils/widgetPropFilter'\n\nimport { WidgetInputBaseClass } from './layout'\nimport WidgetLayoutField from './layout/WidgetLayoutField.vue'\n\ninterface Props {\n widget: SimplifiedWidget<string | undefined>\n}\n\nconst props = defineProps<Props>()\n\nconst modelValue = defineModel<string | undefined>({\n default(props: Props) {\n return props.widget.options?.values?.[0] || ''\n }\n})\n\n// Transform compatibility props for overlay positioning\nconst transformCompatProps = useTransformCompatOverlayProps()\n\n// Extract select options from widget options\nconst selectOptions = computed(() => {\n const options = props.widget.options\n\n if (options?.values && Array.isArray(options.values)) {\n return options.values\n }\n\n return []\n})\nconst invalid = computed(\n () => !!modelValue.value && !selectOptions.value.includes(modelValue.value)\n)\n\nconst combinedProps = computed(() => ({\n ...filterWidgetProps(props.widget.options, PANEL_EXCLUDED_PROPS),\n ...transformCompatProps.value,\n ...(invalid.value ? { placeholder: `${modelValue.value}` } : {})\n}))\n</script>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport { cn } from '@/utils/tailwindUtil'\n\nimport { WidgetInputBaseClass } from '../../layout'\nimport type { DropdownItem, SelectedKey } from './types'\n\ninterface Props {\n isOpen?: boolean\n placeholder?: string\n items: DropdownItem[]\n selected: Set<SelectedKey>\n maxSelectable: number\n uploadable: boolean\n disabled: boolean\n accept?: string\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n isOpen: false,\n placeholder: 'Select...'\n})\n\nconst emit = defineEmits<{\n (e: 'select-click', event: MouseEvent): void\n (e: 'file-change', event: Event): void\n}>()\n\nconst selectedItems = computed(() => {\n return props.items.filter((item) => props.selected.has(item.id))\n})\n\nconst theButtonStyle = computed(() =>\n cn(\n 'border-0 bg-component-node-widget-background outline-none text-text-secondary',\n props.disabled\n ? 'cursor-not-allowed'\n : 'hover:bg-component-node-widget-background-hovered cursor-pointer',\n selectedItems.value.length > 0 && 'text-text-primary'\n )\n)\n</script>\n\n<template>\n <div\n :class=\"\n cn(WidgetInputBaseClass, 'flex text-base leading-none', {\n 'opacity-50 cursor-not-allowed !outline-zinc-300/10': disabled\n })\n \"\n >\n <!-- Dropdown -->\n <button\n :class=\"\n cn(\n theButtonStyle,\n 'flex justify-between items-center flex-1 min-w-0 h-8',\n {\n 'rounded-l-lg': uploadable,\n 'rounded-lg': !uploadable\n }\n )\n \"\n @click=\"emit('select-click', $event)\"\n >\n <span class=\"min-w-0 flex-1 px-1 py-2 text-left truncate\">\n <span v-if=\"!selectedItems.length\">\n {{ placeholder }}\n </span>\n <span v-else>\n {{ selectedItems.map((item) => item.label ?? item.name).join(', ') }}\n </span>\n </span>\n <i\n class=\"icon-[lucide--chevron-down]\"\n :class=\"\n cn(\n 'mr-2 size-4 transition-transform duration-200 flex-shrink-0 text-component-node-foreground-secondary',\n isOpen && 'rotate-180'\n )\n \"\n />\n </button>\n <!-- Open File -->\n <label\n v-if=\"uploadable\"\n :class=\"\n cn(\n theButtonStyle,\n 'relative',\n 'size-8 flex justify-center items-center border-l rounded-r-lg border-zinc-300/10'\n )\n \"\n >\n <i class=\"icon-[lucide--folder-search] size-4\" />\n <input\n type=\"file\"\n class=\"absolute inset-0 -z-1 opacity-0\"\n :multiple=\"maxSelectable > 1\"\n :disabled=\"disabled\"\n :accept=\"accept\"\n @change=\"emit('file-change', $event)\"\n />\n </label>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport Popover from 'primevue/popover'\nimport { ref, useTemplateRef } from 'vue'\n\nimport { cn } from '@/utils/tailwindUtil'\n\nimport type { LayoutMode, OptionId, SortOption } from './types'\n\ndefineProps<{\n isQuerying: boolean\n sortOptions: SortOption[]\n}>()\n\nconst layoutMode = defineModel<LayoutMode>('layoutMode')\nconst searchQuery = defineModel<string>('searchQuery')\nconst sortSelected = defineModel<OptionId>('sortSelected')\n\nconst actionButtonStyle = cn(\n 'h-8 bg-zinc-500/20 rounded-lg outline outline-1 outline-offset-[-1px] outline-node-component-border transition-all duration-150'\n)\n\nconst resetInputStyle = 'bg-transparent border-0 outline-0 ring-0 text-left'\n\nconst layoutSwitchItemStyle =\n 'size-6 flex justify-center items-center rounded-sm cursor-pointer transition-all duration-150 hover:scale-108 hover:text-base-foreground active:scale-95'\n\nconst sortPopoverRef = useTemplateRef('sortPopoverRef')\nconst sortTriggerRef = useTemplateRef('sortTriggerRef')\nconst isSortPopoverOpen = ref(false)\n\nfunction toggleSortPopover(event: Event) {\n if (!sortPopoverRef.value || !sortTriggerRef.value) return\n isSortPopoverOpen.value = !isSortPopoverOpen.value\n sortPopoverRef.value.toggle(event, sortTriggerRef.value)\n}\nfunction closeSortPopover() {\n isSortPopoverOpen.value = false\n sortPopoverRef.value?.hide()\n}\n\nfunction handleSortSelected(item: SortOption) {\n sortSelected.value = item.id\n closeSortPopover()\n}\n</script>\n\n<template>\n <div class=\"text-secondary flex gap-2 px-4\">\n <!-- TODO: Replace with a common Search input -->\n <label\n :class=\"\n cn(\n actionButtonStyle,\n 'flex-1 flex px-2 items-center text-base leading-none cursor-text',\n searchQuery?.trim() !== '' ? 'text-base-foreground' : '',\n 'hover:outline-component-node-widget-background-highlighted/80',\n 'focus-within:outline-component-node-widget-background-highlighted/80'\n )\n \"\n >\n <i\n v-if=\"isQuerying\"\n class=\"mr-2 icon-[lucide--loader-circle] size-4 animate-spin\"\n />\n <i v-else class=\"mr-2 icon-[lucide--search] size-4\" />\n <input\n v-model=\"searchQuery\"\n type=\"text\"\n autofocus\n :class=\"resetInputStyle\"\n :placeholder=\"$t('g.search')\"\n />\n </label>\n\n <!-- Sort Select -->\n <button\n ref=\"sortTriggerRef\"\n :class=\"\n cn(\n resetInputStyle,\n actionButtonStyle,\n 'relative w-8 flex justify-center items-center cursor-pointer',\n 'hover:outline-component-node-widget-background-highlighted',\n 'active:!scale-95'\n )\n \"\n @click=\"toggleSortPopover\"\n >\n <div\n v-if=\"sortSelected !== 'default'\"\n class=\"absolute top-[-2px] left-[-2px] size-2 rounded-full bg-component-node-widget-background-highlighted\"\n />\n <i class=\"icon-[lucide--arrow-up-down] size-4\" />\n </button>\n <!-- Sort Popover -->\n <Popover\n ref=\"sortPopoverRef\"\n :dismissable=\"true\"\n :close-on-escape=\"true\"\n unstyled\n :pt=\"{\n root: {\n class: 'absolute z-50'\n },\n content: {\n class: ['bg-transparent border-none p-0 pt-2 rounded-lg shadow-lg']\n }\n }\"\n @hide=\"isSortPopoverOpen = false\"\n >\n <div\n :class=\"\n cn(\n 'flex flex-col gap-2 p-2 min-w-32',\n 'bg-component-node-background',\n 'rounded-lg outline outline-offset-[-1px] outline-component-node-border'\n )\n \"\n >\n <button\n v-for=\"item of sortOptions\"\n :key=\"item.name\"\n :class=\"\n cn(\n resetInputStyle,\n 'flex justify-between items-center h-6 cursor-pointer',\n 'hover:!text-blue-500'\n )\n \"\n @click=\"handleSortSelected(item)\"\n >\n <span>{{ item.name }}</span>\n <i\n v-if=\"sortSelected === item.id\"\n class=\"icon-[lucide--check] size-4\"\n />\n </button>\n </div>\n </Popover>\n\n <!-- Layout Switch -->\n <div\n :class=\"\n cn(\n actionButtonStyle,\n 'flex justify-center items-center p-1 gap-1 hover:outline-component-node-widget-background-highlighted'\n )\n \"\n >\n <button\n :class=\"\n cn(\n resetInputStyle,\n layoutSwitchItemStyle,\n layoutMode === 'list'\n ? 'bg-neutral-500/50 text-base-foreground'\n : ''\n )\n \"\n @click=\"layoutMode = 'list'\"\n >\n <i class=\"icon-[lucide--list] size-4\" />\n </button>\n <button\n :class=\"\n cn(\n resetInputStyle,\n layoutSwitchItemStyle,\n layoutMode === 'grid'\n ? 'bg-neutral-500/50 text-base-foreground'\n : ''\n )\n \"\n @click=\"layoutMode = 'grid'\"\n >\n <i class=\"icon-[lucide--layout-grid] size-4\" />\n </button>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport Button from '@/components/ui/button/Button.vue'\nimport { useModelUpload } from '@/platform/assets/composables/useModelUpload'\nimport { cn } from '@/utils/tailwindUtil'\n\nimport type { FilterOption, OptionId } from './types'\n\nconst { filterOptions } = defineProps<{\n filterOptions: FilterOption[]\n}>()\n\nconst filterSelected = defineModel<OptionId>('filterSelected')\n\nconst { isUploadButtonEnabled, showUploadDialog } = useModelUpload()\n\n// TODO: Add real check to differentiate between the Model dialogs and Load Image\nconst singleFilterOption = computed(() => filterOptions.length === 1)\n</script>\n\n<template>\n <div class=\"text-secondary mb-4 flex gap-1 px-4 justify-start\">\n <button\n v-for=\"option in filterOptions\"\n :key=\"option.id\"\n type=\"button\"\n :disabled=\"singleFilterOption\"\n :class=\"\n cn(\n 'px-4 py-2 rounded-md inline-flex justify-center items-center select-none appearance-none border-0 text-base-foreground',\n !singleFilterOption &&\n 'transition-all duration-150 hover:text-base-foreground hover:bg-interface-menu-component-surface-hovered cursor-pointer active:scale-95',\n !singleFilterOption && filterSelected === option.id\n ? '!bg-interface-menu-component-surface-selected text-base-foreground'\n : 'bg-transparent'\n )\n \"\n @click=\"filterSelected = option.id\"\n >\n {{ option.name }}\n </button>\n <Button\n v-if=\"isUploadButtonEnabled && singleFilterOption\"\n class=\"ml-auto\"\n size=\"md\"\n variant=\"textonly\"\n @click=\"showUploadDialog\"\n >\n <i class=\"icon-[lucide--folder-input]\" />\n <span>{{ $t('g.import') }}</span>\n </Button>\n </div>\n</template>\n","import type { ComputedRef, InjectionKey } from 'vue'\n\nimport type { AssetKind } from '@/types/widgetTypes'\n\nexport type OptionId = string | number | symbol\nexport type SelectedKey = OptionId\n\nexport interface DropdownItem {\n id: SelectedKey\n mediaSrc: string // URL for image, video, or other media\n name: string\n label?: string\n metadata: string\n}\nexport interface SortOption {\n id: OptionId\n name: string\n sorter: (ctx: { items: readonly DropdownItem[] }) => DropdownItem[]\n}\n\nexport interface FilterOption {\n id: OptionId\n name: string\n}\n\nexport type LayoutMode = 'list' | 'grid' | 'list-small'\n\nexport const AssetKindKey: InjectionKey<ComputedRef<AssetKind | undefined>> =\n Symbol('assetKind')\n","<script setup lang=\"ts\">\nimport { computed, inject, ref } from 'vue'\n\nimport LazyImage from '@/components/common/LazyImage.vue'\nimport { cn } from '@/utils/tailwindUtil'\n\nimport { AssetKindKey } from './types'\nimport type { LayoutMode } from './types'\n\ninterface Props {\n index: number\n selected: boolean\n mediaSrc: string\n name: string\n label?: string\n metadata?: string\n layout?: LayoutMode\n}\n\nconst props = defineProps<Props>()\n\nconst emit = defineEmits<{\n click: [index: number]\n mediaLoad: [event: Event]\n}>()\n\nconst actualDimensions = ref<string | null>(null)\n\nconst assetKind = inject(AssetKindKey)\n\nconst isVideo = computed(() => assetKind?.value === 'video')\n\nfunction handleClick() {\n emit('click', props.index)\n}\n\nfunction handleImageLoad(event: Event) {\n emit('mediaLoad', event)\n if (!event.target || !(event.target instanceof HTMLImageElement)) return\n const img = event.target\n if (img.naturalWidth && img.naturalHeight) {\n actualDimensions.value = `${img.naturalWidth} x ${img.naturalHeight}`\n }\n}\n\nfunction handleVideoLoad(event: Event) {\n emit('mediaLoad', event)\n if (!event.target || !(event.target instanceof HTMLVideoElement)) return\n const video = event.target\n if (video.videoWidth && video.videoHeight) {\n actualDimensions.value = `${video.videoWidth} x ${video.videoHeight}`\n }\n}\n</script>\n\n<template>\n <div\n :class=\"\n cn(\n 'flex gap-1 select-none group/item cursor-pointer bg-component-node-widget-background',\n 'transition-all duration-150',\n {\n 'flex-col text-center': layout === 'grid',\n 'flex-row text-left max-h-16 rounded-lg hover:scale-102 active:scale-98':\n layout === 'list',\n 'flex-row text-left hover:bg-component-node-widget-background-hovered rounded-lg':\n layout === 'list-small',\n // selection\n 'ring-2 ring-component-node-widget-background-highlighted':\n layout === 'list' && selected\n }\n )\n \"\n @click=\"handleClick\"\n >\n <!-- Image -->\n <div\n v-if=\"layout !== 'list-small'\"\n :class=\"\n cn(\n 'relative',\n 'w-full aspect-square overflow-hidden outline-1 outline-offset-[-1px] outline-interface-stroke',\n 'transition-all duration-150',\n {\n 'min-w-16 max-w-16 rounded-l-lg': layout === 'list',\n 'rounded-sm group-hover/item:scale-108 group-active/item:scale-95':\n layout === 'grid',\n // selection\n 'ring-2 ring-component-node-widget-background-highlighted':\n layout === 'grid' && selected\n }\n )\n \"\n >\n <!-- Selected Icon -->\n <div\n v-if=\"selected\"\n class=\"absolute top-1 left-1 size-4 rounded-full border-1 border-base-foreground bg-primary-background\"\n >\n <i\n class=\"icon-[lucide--check] size-3 translate-y-[-0.5px] text-base-foreground bold\"\n />\n </div>\n <video\n v-if=\"mediaSrc && isVideo\"\n :src=\"mediaSrc\"\n class=\"size-full object-cover\"\n preload=\"metadata\"\n muted\n @loadeddata=\"handleVideoLoad\"\n />\n <LazyImage\n v-else-if=\"mediaSrc\"\n :src=\"mediaSrc\"\n :alt=\"name\"\n image-class=\"size-full object-cover\"\n @load=\"handleImageLoad\"\n />\n <div\n v-else\n class=\"size-full bg-gradient-to-tr from-blue-400 via-teal-500 to-green-400\"\n />\n </div>\n <!-- Name -->\n <div\n :class=\"\n cn('flex gap-1', {\n 'flex-col': layout === 'grid',\n 'flex-col px-4 py-1 w-full justify-center min-w-0': layout === 'list',\n 'flex-row p-2 items-center justify-between w-full':\n layout === 'list-small'\n })\n \"\n >\n <span\n v-tooltip=\"layout === 'grid' ? (label ?? name) : undefined\"\n :class=\"\n cn(\n 'block text-xs line-clamp-2 break-words overflow-hidden',\n 'transition-colors duration-150',\n // selection\n !!selected && 'text-base-foreground'\n )\n \"\n >\n {{ label ?? name }}\n </span>\n <!-- Meta Data -->\n <span class=\"text-secondary block text-xs\">{{\n metadata || actualDimensions\n }}</span>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { cn } from '@/utils/tailwindUtil'\n\nimport FormDropdownMenuActions from './FormDropdownMenuActions.vue'\nimport FormDropdownMenuFilter from './FormDropdownMenuFilter.vue'\nimport FormDropdownMenuItem from './FormDropdownMenuItem.vue'\nimport type {\n DropdownItem,\n FilterOption,\n LayoutMode,\n OptionId,\n SortOption\n} from './types'\n\ninterface Props {\n items: DropdownItem[]\n isSelected: (item: DropdownItem, index: number) => boolean\n isQuerying: boolean\n filterOptions: FilterOption[]\n sortOptions: SortOption[]\n}\n\ndefineProps<Props>()\nconst emit = defineEmits<{\n (e: 'item-click', item: DropdownItem, index: number): void\n}>()\n\n// Define models for two-way binding\nconst filterSelected = defineModel<OptionId>('filterSelected')\nconst layoutMode = defineModel<LayoutMode>('layoutMode')\nconst sortSelected = defineModel<OptionId>('sortSelected')\nconst searchQuery = defineModel<string>('searchQuery')\n\n// Handle item selection\n</script>\n\n<template>\n <div\n class=\"flex max-h-[640px] w-103 flex-col rounded-lg bg-component-node-background pt-4 outline outline-offset-[-1px] outline-node-component-border\"\n >\n <!-- Filter -->\n <FormDropdownMenuFilter\n v-if=\"filterOptions.length > 0\"\n v-model:filter-selected=\"filterSelected\"\n :filter-options=\"filterOptions\"\n />\n <!-- Actions -->\n <FormDropdownMenuActions\n v-model:layout-mode=\"layoutMode\"\n v-model:sort-selected=\"sortSelected\"\n v-model:search-query=\"searchQuery\"\n :sort-options=\"sortOptions\"\n :is-querying=\"isQuerying\"\n />\n <!-- List -->\n <div class=\"relative flex h-full mt-2 overflow-y-scroll\">\n <div\n :class=\"\n cn(\n 'h-full max-h-full grid gap-x-2 gap-y-4 overflow-y-auto px-4 pt-4 pb-4 w-full',\n {\n 'grid-cols-4': layoutMode === 'grid',\n 'grid-cols-1 gap-y-2': layoutMode === 'list',\n 'grid-cols-1 gap-y-1': layoutMode === 'list-small'\n }\n )\n \"\n >\n <div class=\"pointer-events-none absolute inset-x-3 top-0 z-10 h-5\" />\n <div\n v-if=\"items.length === 0\"\n class=\"h-50 col-span-full flex items-center justify-center\"\n >\n <i\n :title=\"$t('g.noItems')\"\n :aria-label=\"$t('g.noItems')\"\n class=\"icon-[lucide--circle-off] size-30 text-zinc-500/20\"\n />\n </div>\n <!-- Item -->\n <FormDropdownMenuItem\n v-for=\"(item, index) in items\"\n :key=\"item.id\"\n :index=\"index\"\n :selected=\"isSelected(item, index)\"\n :media-src=\"item.mediaSrc\"\n :name=\"item.name\"\n :label=\"item.label\"\n :metadata=\"item.metadata\"\n :layout=\"layoutMode\"\n @click=\"emit('item-click', item, index)\"\n />\n </div>\n </div>\n </div>\n</template>\n","import type { DropdownItem, SortOption } from './types'\n\nexport async function defaultSearcher(query: string, items: DropdownItem[]) {\n if (query.trim() === '') return items\n const words = query.trim().toLowerCase().split(' ')\n return items.filter((item) => {\n const name = item.name.toLowerCase()\n return words.every((word) => name.includes(word))\n })\n}\n\nexport function getDefaultSortOptions(): SortOption[] {\n return [\n {\n name: 'Default',\n id: 'default',\n sorter: ({ items }) => items.slice()\n },\n {\n name: 'A-Z',\n id: 'a-z',\n sorter: ({ items }) =>\n items.slice().sort((a, b) => {\n return a.name.localeCompare(b.name)\n })\n }\n ]\n}\n","<script setup lang=\"ts\">\nimport { refDebounced } from '@vueuse/core'\nimport Popover from 'primevue/popover'\nimport { computed, ref, useTemplateRef, watch } from 'vue'\n\nimport { t } from '@/i18n'\nimport { useToastStore } from '@/platform/updates/common/toastStore'\n\nimport FormDropdownInput from './FormDropdownInput.vue'\nimport FormDropdownMenu from './FormDropdownMenu.vue'\nimport { defaultSearcher, getDefaultSortOptions } from './shared'\nimport type {\n DropdownItem,\n FilterOption,\n LayoutMode,\n OptionId,\n SelectedKey,\n SortOption\n} from './types'\n\ninterface Props {\n items: DropdownItem[]\n placeholder?: string\n /**\n * If true, allows multiple selections. If a number is provided,\n * it specifies the maximum number of selections allowed.\n */\n multiple?: boolean | number\n\n uploadable?: boolean\n disabled?: boolean\n accept?: string\n filterOptions?: FilterOption[]\n sortOptions?: SortOption[]\n isSelected?: (\n selected: Set<SelectedKey>,\n item: DropdownItem,\n index: number\n ) => boolean\n searcher?: (\n query: string,\n items: DropdownItem[],\n onCleanup: (cleanupFn: () => void) => void\n ) => Promise<DropdownItem[]>\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n placeholder: t('widgets.uploadSelect.placeholder'),\n multiple: false,\n uploadable: false,\n disabled: false,\n filterOptions: () => [],\n sortOptions: () => getDefaultSortOptions(),\n isSelected: (selected, item, _index) => selected.has(item.id),\n searcher: defaultSearcher\n})\n\nconst selected = defineModel<Set<SelectedKey>>('selected', {\n default: new Set()\n})\nconst filterSelected = defineModel<OptionId>('filterSelected', { default: '' })\nconst sortSelected = defineModel<OptionId>('sortSelected', {\n default: 'default'\n})\nconst layoutMode = defineModel<LayoutMode>('layoutMode', {\n default: 'grid'\n})\nconst files = defineModel<File[]>('files', { default: [] })\nconst searchQuery = defineModel<string>('searchQuery', { default: '' })\n\nconst debouncedSearchQuery = refDebounced(searchQuery, 700, {\n maxWait: 700\n})\nconst isQuerying = ref(false)\nconst toastStore = useToastStore()\nconst popoverRef = ref<InstanceType<typeof Popover>>()\nconst triggerRef = useTemplateRef('triggerRef')\nconst isOpen = ref(false)\n\nconst maxSelectable = computed(() => {\n if (props.multiple === true) return Infinity\n if (typeof props.multiple === 'number') return props.multiple\n return 1\n})\n\nconst filteredItems = ref<DropdownItem[]>([])\n\nwatch(searchQuery, (value) => {\n isQuerying.value = value !== debouncedSearchQuery.value\n})\n\nwatch(\n [debouncedSearchQuery, () => props.items],\n (_, __, onCleanup) => {\n let isCleanup = false\n let cleanupFn: undefined | (() => void)\n onCleanup(() => {\n isCleanup = true\n cleanupFn?.()\n })\n\n void props\n .searcher(\n debouncedSearchQuery.value,\n props.items,\n (cb) => (cleanupFn = cb)\n )\n .then((result) => {\n if (!isCleanup) filteredItems.value = result\n })\n .finally(() => {\n if (!isCleanup) isQuerying.value = false\n })\n },\n { immediate: true }\n)\n\nconst defaultSorter = computed<SortOption['sorter']>(() => {\n const sorter = props.sortOptions.find(\n (option) => option.id === 'default'\n )?.sorter\n return sorter || (({ items }) => items.slice())\n})\nconst selectedSorter = computed<SortOption['sorter']>(() => {\n if (sortSelected.value === 'default') return defaultSorter.value\n const sorter = props.sortOptions.find(\n (option) => option.id === sortSelected.value\n )?.sorter\n return sorter || defaultSorter.value\n})\nconst sortedItems = computed(() => {\n return selectedSorter.value({ items: filteredItems.value }) || []\n})\n\nfunction internalIsSelected(item: DropdownItem, index: number): boolean {\n return props.isSelected?.(selected.value, item, index) ?? false\n}\n\nconst toggleDropdown = (event: Event) => {\n if (props.disabled) return\n if (popoverRef.value && triggerRef.value) {\n popoverRef.value.toggle(event, triggerRef.value)\n isOpen.value = !isOpen.value\n }\n}\n\nconst closeDropdown = () => {\n if (popoverRef.value) {\n popoverRef.value.hide()\n isOpen.value = false\n }\n}\n\nfunction handleFileChange(event: Event) {\n if (props.disabled) return\n const input = event.target as HTMLInputElement\n if (input.files) {\n files.value = Array.from(input.files)\n }\n // Clear the input value to allow re-selecting the same file\n input.value = ''\n}\n\nfunction handleSelection(item: DropdownItem, index: number) {\n if (props.disabled) return\n const sel = selected.value\n if (internalIsSelected(item, index)) {\n sel.delete(item.id)\n } else {\n if (sel.size < maxSelectable.value) {\n sel.add(item.id)\n } else if (maxSelectable.value === 1) {\n sel.clear()\n sel.add(item.id)\n } else {\n toastStore.addAlert(`Maximum selection limit reached`)\n return\n }\n }\n selected.value = new Set(sel)\n\n if (maxSelectable.value === 1) {\n closeDropdown()\n }\n}\n</script>\n\n<template>\n <div ref=\"triggerRef\">\n <FormDropdownInput\n :files=\"files\"\n :is-open=\"isOpen\"\n :placeholder=\"placeholder\"\n :items=\"items\"\n :max-selectable=\"maxSelectable\"\n :selected=\"selected\"\n :uploadable=\"uploadable\"\n :disabled=\"disabled\"\n :accept=\"accept\"\n @select-click=\"toggleDropdown\"\n @file-change=\"handleFileChange\"\n />\n <Popover\n ref=\"popoverRef\"\n :dismissable=\"true\"\n :close-on-escape=\"true\"\n unstyled\n :pt=\"{\n root: {\n class: 'absolute z-50'\n },\n content: {\n class: ['bg-transparent border-none p-0 pt-2 rounded-lg shadow-lg']\n }\n }\"\n @hide=\"isOpen = false\"\n >\n <FormDropdownMenu\n v-model:filter-selected=\"filterSelected\"\n v-model:layout-mode=\"layoutMode\"\n v-model:sort-selected=\"sortSelected\"\n v-model:search-query=\"searchQuery\"\n :filter-options=\"filterOptions\"\n :sort-options=\"sortOptions\"\n :disabled=\"disabled\"\n :is-querying=\"isQuerying\"\n :items=\"sortedItems\"\n :is-selected=\"internalIsSelected\"\n :max-selectable=\"maxSelectable\"\n @close=\"closeDropdown\"\n @item-click=\"handleSelection\"\n />\n </Popover>\n </div>\n</template>\n","import { computed, toValue, watch } from 'vue'\nimport type { MaybeRefOrGetter } from 'vue'\n\nimport { isCloud } from '@/platform/distribution/types'\nimport type { AssetItem } from '@/platform/assets/schemas/assetSchema'\nimport type { DropdownItem } from '@/renderer/extensions/vueNodes/widgets/components/form/dropdown/types'\nimport { useAssetsStore } from '@/stores/assetsStore'\nimport { useModelToNodeStore } from '@/stores/modelToNodeStore'\n\n/**\n * Composable for fetching and transforming asset data for Vue node widgets.\n * Provides reactive asset data based on node type with automatic category detection.\n * Uses store-based caching to avoid duplicate fetches across multiple instances.\n *\n * Cloud-only composable - returns empty data when not in cloud environment.\n *\n * @param nodeType - ComfyUI node type (ref, getter, or plain value). Can be undefined.\n * Accepts: ref('CheckpointLoaderSimple'), () => 'CheckpointLoaderSimple', or 'CheckpointLoaderSimple'\n * @returns Reactive data including category, assets, dropdown items, loading state, and errors\n */\nexport function useAssetWidgetData(\n nodeType: MaybeRefOrGetter<string | undefined>\n) {\n if (isCloud) {\n const assetsStore = useAssetsStore()\n const modelToNodeStore = useModelToNodeStore()\n\n const category = computed(() => {\n const resolvedType = toValue(nodeType)\n return resolvedType\n ? modelToNodeStore.getCategoryForNodeType(resolvedType)\n : undefined\n })\n\n const assets = computed<AssetItem[]>(() => {\n const resolvedType = toValue(nodeType)\n return resolvedType\n ? (assetsStore.modelAssetsByNodeType.get(resolvedType) ?? [])\n : []\n })\n\n const isLoading = computed(() => {\n const resolvedType = toValue(nodeType)\n return resolvedType\n ? (assetsStore.modelLoadingByNodeType.get(resolvedType) ?? false)\n : false\n })\n\n const error = computed<Error | null>(() => {\n const resolvedType = toValue(nodeType)\n return resolvedType\n ? (assetsStore.modelErrorByNodeType.get(resolvedType) ?? null)\n : null\n })\n\n const dropdownItems = computed<DropdownItem[]>(() => {\n return assets.value.map((asset) => ({\n id: asset.id,\n name:\n (asset.user_metadata?.filename as string | undefined) ?? asset.name,\n label: asset.name,\n mediaSrc: asset.preview_url ?? '',\n metadata: ''\n }))\n })\n\n watch(\n () => toValue(nodeType),\n async (currentNodeType) => {\n if (!currentNodeType) {\n return\n }\n\n const hasData = assetsStore.modelAssetsByNodeType.has(currentNodeType)\n\n if (!hasData) {\n await assetsStore.updateModelsForNodeType(currentNodeType)\n }\n },\n { immediate: true }\n )\n\n return {\n category,\n assets,\n dropdownItems,\n isLoading,\n error\n }\n }\n\n return {\n category: computed(() => undefined),\n assets: computed(() => []),\n dropdownItems: computed(() => []),\n isLoading: computed(() => false),\n error: computed(() => null)\n }\n}\n","<script setup lang=\"ts\">\nimport { capitalize } from 'es-toolkit'\nimport { computed, provide, ref, toRef, watch } from 'vue'\n\nimport { useTransformCompatOverlayProps } from '@/composables/useTransformCompatOverlayProps'\nimport { t } from '@/i18n'\nimport { useToastStore } from '@/platform/updates/common/toastStore'\nimport FormDropdown from '@/renderer/extensions/vueNodes/widgets/components/form/dropdown/FormDropdown.vue'\nimport { AssetKindKey } from '@/renderer/extensions/vueNodes/widgets/components/form/dropdown/types'\nimport type {\n DropdownItem,\n FilterOption,\n LayoutMode,\n SelectedKey\n} from '@/renderer/extensions/vueNodes/widgets/components/form/dropdown/types'\nimport WidgetLayoutField from '@/renderer/extensions/vueNodes/widgets/components/layout/WidgetLayoutField.vue'\nimport { useAssetWidgetData } from '@/renderer/extensions/vueNodes/widgets/composables/useAssetWidgetData'\nimport type { ResultItemType } from '@/schemas/apiSchema'\nimport { api } from '@/scripts/api'\nimport { useAssetsStore } from '@/stores/assetsStore'\nimport { useQueueStore } from '@/stores/queueStore'\nimport type { SimplifiedWidget } from '@/types/simplifiedWidget'\nimport type { AssetKind } from '@/types/widgetTypes'\nimport {\n PANEL_EXCLUDED_PROPS,\n filterWidgetProps\n} from '@/utils/widgetPropFilter'\n\ninterface Props {\n widget: SimplifiedWidget<string | undefined>\n nodeType?: string\n assetKind?: AssetKind\n allowUpload?: boolean\n uploadFolder?: ResultItemType\n isAssetMode?: boolean\n defaultLayoutMode?: LayoutMode\n}\n\nconst props = defineProps<Props>()\n\nprovide(\n AssetKindKey,\n computed(() => props.assetKind)\n)\n\nconst modelValue = defineModel<string | undefined>({\n default(props: Props) {\n return props.widget.options?.values?.[0] || ''\n }\n})\n\nconst toastStore = useToastStore()\nconst queueStore = useQueueStore()\n\nconst transformCompatProps = useTransformCompatOverlayProps()\n\nconst combinedProps = computed(() => ({\n ...filterWidgetProps(props.widget.options, PANEL_EXCLUDED_PROPS),\n ...transformCompatProps.value\n}))\n\nconst getAssetData = () => {\n if (props.isAssetMode && props.nodeType) {\n return useAssetWidgetData(toRef(() => props.nodeType))\n }\n return null\n}\nconst assetData = getAssetData()\n\nconst filterSelected = ref('all')\nconst filterOptions = computed<FilterOption[]>(() => {\n if (props.isAssetMode) {\n const categoryName = assetData?.category.value ?? 'All'\n return [{ id: 'all', name: capitalize(categoryName) }]\n }\n return [\n { id: 'all', name: 'All' },\n { id: 'inputs', name: 'Inputs' },\n { id: 'outputs', name: 'Outputs' }\n ]\n})\n\nconst selectedSet = ref<Set<SelectedKey>>(new Set())\n\n/**\n * Transforms a value using getOptionLabel if available.\n * Falls back to the original value if getOptionLabel is not provided or throws an error.\n */\nfunction getDisplayLabel(value: string): string {\n const getOptionLabel = props.widget.options?.getOptionLabel\n if (!getOptionLabel) return value\n\n try {\n return getOptionLabel(value)\n } catch (e) {\n console.error('Failed to map value:', e)\n return value\n }\n}\n\nconst inputItems = computed<DropdownItem[]>(() => {\n const values = props.widget.options?.values || []\n\n if (!Array.isArray(values)) {\n return []\n }\n\n return values.map((value: string, index: number) => ({\n id: `input-${index}`,\n mediaSrc: getMediaUrl(value, 'input'),\n name: value,\n label: getDisplayLabel(value),\n metadata: ''\n }))\n})\nconst outputItems = computed<DropdownItem[]>(() => {\n if (!['image', 'video'].includes(props.assetKind ?? '')) return []\n\n const outputs = new Set<string>()\n\n // Extract output images/videos from queue history\n queueStore.historyTasks.forEach((task) => {\n task.flatOutputs.forEach((output) => {\n const isTargetType =\n (props.assetKind === 'image' && output.mediaType === 'images') ||\n (props.assetKind === 'video' && output.mediaType === 'video')\n\n if (output.type === 'output' && isTargetType) {\n const path = output.subfolder\n ? `${output.subfolder}/${output.filename}`\n : output.filename\n // Add [output] annotation so the preview component knows the type\n const annotatedPath = `${path} [output]`\n outputs.add(annotatedPath)\n }\n })\n })\n\n return Array.from(outputs).map((output) => ({\n id: `output-${output}`,\n mediaSrc: getMediaUrl(output.replace(' [output]', ''), 'output'),\n name: output,\n label: getDisplayLabel(output),\n metadata: ''\n }))\n})\n\nconst allItems = computed<DropdownItem[]>(() => {\n if (props.isAssetMode && assetData) {\n return assetData.dropdownItems.value\n }\n return [...inputItems.value, ...outputItems.value]\n})\n\nconst dropdownItems = computed<DropdownItem[]>(() => {\n if (props.isAssetMode) {\n return allItems.value\n }\n\n switch (filterSelected.value) {\n case 'inputs':\n return inputItems.value\n case 'outputs':\n return outputItems.value\n case 'all':\n default:\n return [...inputItems.value, ...outputItems.value]\n }\n})\n\nconst mediaPlaceholder = computed(() => {\n const options = props.widget.options\n\n if (options?.placeholder) {\n return options.placeholder\n }\n\n switch (props.assetKind) {\n case 'image':\n return t('widgets.uploadSelect.placeholderImage')\n case 'video':\n return t('widgets.uploadSelect.placeholderVideo')\n case 'audio':\n return t('widgets.uploadSelect.placeholderAudio')\n case 'model':\n return t('widgets.uploadSelect.placeholderModel')\n case 'unknown':\n return t('widgets.uploadSelect.placeholderUnknown')\n }\n\n return t('widgets.uploadSelect.placeholder')\n})\n\nconst uploadable = computed(() => {\n if (props.isAssetMode) return false\n return props.allowUpload === true\n})\n\nconst acceptTypes = computed(() => {\n // Be permissive with accept types because backend uses libraries\n // that can handle a wide range of formats\n switch (props.assetKind) {\n case 'image':\n return 'image/*'\n case 'video':\n return 'video/*'\n case 'audio':\n return 'audio/*'\n default:\n return undefined // model or unknown\n }\n})\n\nconst layoutMode = ref<LayoutMode>(props.defaultLayoutMode ?? 'grid')\n\nwatch(\n [modelValue, dropdownItems],\n ([currentValue, _dropdownItems]) => {\n if (currentValue === undefined) {\n selectedSet.value.clear()\n return\n }\n\n const item = dropdownItems.value.find((item) => item.name === currentValue)\n if (item) {\n selectedSet.value.clear()\n selectedSet.value.add(item.id)\n }\n },\n { immediate: true }\n)\n\nfunction updateSelectedItems(selectedItems: Set<SelectedKey>) {\n let id: SelectedKey | undefined = undefined\n if (selectedItems.size > 0) {\n id = selectedItems.values().next().value!\n }\n if (id == null) {\n modelValue.value = undefined\n return\n }\n const name = dropdownItems.value.find((item) => item.id === id)?.name\n if (!name) {\n modelValue.value = undefined\n return\n }\n modelValue.value = name\n}\n\n// Upload file function (copied from useNodeImageUpload.ts)\nconst uploadFile = async (\n file: File,\n isPasted: boolean = false,\n formFields: Partial<{ type: ResultItemType }> = {}\n) => {\n const body = new FormData()\n body.append('image', file)\n if (isPasted) body.append('subfolder', 'pasted')\n if (formFields.type) body.append('type', formFields.type)\n\n const resp = await api.fetchApi('/upload/image', {\n method: 'POST',\n body\n })\n\n if (resp.status !== 200) {\n toastStore.addAlert(resp.status + ' - ' + resp.statusText)\n return null\n }\n\n const data = await resp.json()\n\n // Update AssetsStore when uploading to input folder\n if (formFields.type === 'input' || (!formFields.type && !isPasted)) {\n const assetsStore = useAssetsStore()\n await assetsStore.updateInputs()\n }\n\n return data.subfolder ? `${data.subfolder}/${data.name}` : data.name\n}\n\n// Handle multiple file uploads\nconst uploadFiles = async (files: File[]): Promise<string[]> => {\n const folder = props.uploadFolder ?? 'input'\n const uploadPromises = files.map((file) =>\n uploadFile(file, false, { type: folder })\n )\n const results = await Promise.all(uploadPromises)\n return results.filter((path): path is string => path !== null)\n}\n\nasync function handleFilesUpdate(files: File[]) {\n if (!files || files.length === 0) return\n\n try {\n // 1. Upload files to server\n const uploadedPaths = await uploadFiles(files)\n\n if (uploadedPaths.length === 0) {\n toastStore.addAlert('File upload failed')\n return\n }\n\n // 2. Update widget options to include new files\n // This simulates what addToComboValues does but for SimplifiedWidget\n if (props.widget.options?.values) {\n uploadedPaths.forEach((path) => {\n const values = props.widget.options!.values as string[]\n if (!values.includes(path)) {\n values.push(path)\n }\n })\n }\n\n // 3. Update widget value to the first uploaded file\n modelValue.value = uploadedPaths[0]\n\n // 4. Trigger callback to notify underlying LiteGraph widget\n if (props.widget.callback) {\n props.widget.callback(uploadedPaths[0])\n }\n } catch (error) {\n console.error('Upload error:', error)\n toastStore.addAlert(`Upload failed: ${error}`)\n }\n}\n\nfunction getMediaUrl(\n filename: string,\n type: 'input' | 'output' = 'input'\n): string {\n if (!['image', 'video'].includes(props.assetKind ?? '')) return ''\n return `/api/view?filename=${encodeURIComponent(filename)}&type=${type}`\n}\n</script>\n\n<template>\n <WidgetLayoutField :widget>\n <FormDropdown\n v-model:selected=\"selectedSet\"\n v-model:filter-selected=\"filterSelected\"\n v-model:layout-mode=\"layoutMode\"\n :items=\"dropdownItems\"\n :placeholder=\"mediaPlaceholder\"\n :multiple=\"false\"\n :uploadable=\"uploadable\"\n :accept=\"acceptTypes\"\n :filter-options=\"filterOptions\"\n v-bind=\"combinedProps\"\n class=\"w-full\"\n @update:selected=\"updateSelectedItems\"\n @update:files=\"handleFilesUpdate\"\n />\n </WidgetLayoutField>\n</template>\n","<template>\n <WidgetSelectDropdown\n v-if=\"isDropdownUIWidget\"\n v-model=\"modelValue\"\n :widget\n :node-type=\"widget.nodeType ?? nodeType\"\n :asset-kind=\"assetKind\"\n :allow-upload=\"allowUpload\"\n :upload-folder=\"uploadFolder\"\n :is-asset-mode=\"isAssetMode\"\n :default-layout-mode=\"defaultLayoutMode\"\n />\n <WidgetWithControl\n v-else-if=\"widget.controlWidget\"\n v-model=\"modelValue\"\n :component=\"WidgetSelectDefault\"\n :widget=\"widget as StringControlWidget\"\n />\n <WidgetSelectDefault v-else v-model=\"modelValue\" :widget />\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport { assetService } from '@/platform/assets/services/assetService'\nimport { isCloud } from '@/platform/distribution/types'\nimport { useSettingStore } from '@/platform/settings/settingStore'\nimport WidgetSelectDefault from '@/renderer/extensions/vueNodes/widgets/components/WidgetSelectDefault.vue'\nimport WidgetSelectDropdown from '@/renderer/extensions/vueNodes/widgets/components/WidgetSelectDropdown.vue'\nimport WidgetWithControl from '@/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vue'\nimport type { LayoutMode } from '@/renderer/extensions/vueNodes/widgets/components/form/dropdown/types'\nimport type { ResultItemType } from '@/schemas/apiSchema'\nimport { isComboInputSpec } from '@/schemas/nodeDef/nodeDefSchemaV2'\nimport type { ComboInputSpec } from '@/schemas/nodeDef/nodeDefSchemaV2'\nimport type {\n SimplifiedControlWidget,\n SimplifiedWidget\n} from '@/types/simplifiedWidget'\nimport type { AssetKind } from '@/types/widgetTypes'\n\ntype StringControlWidget = SimplifiedControlWidget<string | undefined>\n\nconst props = defineProps<{\n widget: SimplifiedWidget<string | undefined>\n nodeType?: string\n}>()\n\nconst modelValue = defineModel<string | undefined>()\n\nconst comboSpec = computed<ComboInputSpec | undefined>(() => {\n if (props.widget.spec && isComboInputSpec(props.widget.spec)) {\n return props.widget.spec\n }\n return undefined\n})\n\nconst specDescriptor = computed<{\n kind: AssetKind\n allowUpload: boolean\n folder: ResultItemType | undefined\n}>(() => {\n const spec = comboSpec.value\n if (!spec) {\n return {\n kind: 'unknown',\n allowUpload: false,\n folder: undefined\n }\n }\n\n const {\n image_upload,\n animated_image_upload,\n video_upload,\n image_folder,\n audio_upload\n } = spec\n\n let kind: AssetKind = 'unknown'\n if (video_upload) {\n kind = 'video'\n } else if (image_upload || animated_image_upload) {\n kind = 'image'\n } else if (audio_upload) {\n kind = 'audio'\n }\n // TODO: add support for models (checkpoints, VAE, LoRAs, etc.) -- get widgetType from spec\n\n const allowUpload =\n image_upload === true ||\n animated_image_upload === true ||\n video_upload === true ||\n audio_upload === true\n return {\n kind,\n allowUpload,\n folder: image_folder\n }\n})\n\nconst isAssetMode = computed(() => {\n if (isCloud) {\n const settingStore = useSettingStore()\n const isUsingAssetAPI = settingStore.get('Comfy.Assets.UseAssetAPI')\n const isEligible =\n assetService.isAssetBrowserEligible(props.nodeType, props.widget.name) ||\n props.widget.type === 'asset'\n\n return isUsingAssetAPI && isEligible\n }\n\n return false\n})\n\nconst assetKind = computed(() => specDescriptor.value.kind)\nconst isDropdownUIWidget = computed(\n () => isAssetMode.value || assetKind.value !== 'unknown'\n)\nconst allowUpload = computed(() => specDescriptor.value.allowUpload)\nconst uploadFolder = computed<ResultItemType>(() => {\n return specDescriptor.value.folder ?? 'input'\n})\nconst defaultLayoutMode = computed<LayoutMode>(() => {\n return isAssetMode.value ? 'list' : 'grid'\n})\n</script>\n"],"names":["useTransformCompatOverlayProps","overrides","computed","__name","props","__props","modelValue","_useModel","transformCompatProps","selectOptions","options","invalid","combinedProps","filterWidgetProps","PANEL_EXCLUDED_PROPS","emit","__emit","selectedItems","item","theButtonStyle","cn","resetInputStyle","layoutSwitchItemStyle","layoutMode","searchQuery","sortSelected","actionButtonStyle","sortPopoverRef","useTemplateRef","sortTriggerRef","isSortPopoverOpen","ref","toggleSortPopover","event","closeSortPopover","handleSortSelected","filterSelected","isUploadButtonEnabled","showUploadDialog","useModelUpload","singleFilterOption","AssetKindKey","actualDimensions","assetKind","inject","isVideo","handleClick","handleImageLoad","img","handleVideoLoad","video","defaultSearcher","query","items","words","name","word","getDefaultSortOptions","a","b","selected","files","debouncedSearchQuery","refDebounced","isQuerying","toastStore","useToastStore","popoverRef","triggerRef","isOpen","maxSelectable","filteredItems","watch","value","_","__","onCleanup","isCleanup","cleanupFn","cb","result","defaultSorter","option","selectedSorter","sortedItems","internalIsSelected","index","toggleDropdown","closeDropdown","handleFileChange","input","handleSelection","sel","useAssetWidgetData","nodeType","provide","queueStore","useQueueStore","assetData","toRef","filterOptions","categoryName","capitalize","selectedSet","getDisplayLabel","getOptionLabel","e","inputItems","values","getMediaUrl","outputItems","outputs","task","output","isTargetType","annotatedPath","allItems","dropdownItems","mediaPlaceholder","t","uploadable","acceptTypes","currentValue","_dropdownItems","updateSelectedItems","id","uploadFile","file","isPasted","formFields","body","resp","api","data","useAssetsStore","uploadFiles","folder","uploadPromises","path","handleFilesUpdate","uploadedPaths","error","filename","type","comboSpec","isComboInputSpec","specDescriptor","spec","image_upload","animated_image_upload","video_upload","image_folder","audio_upload","kind","isAssetMode","isDropdownUIWidget","allowUpload","uploadFolder","defaultLayoutMode"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"WidgetSelect.vue_vue_type_script_setup_true_lang-CITubFAk.js","sources":["../../src/composables/useTransformCompatOverlayProps.ts","../../src/renderer/extensions/vueNodes/widgets/components/WidgetSelectDefault.vue","../../src/renderer/extensions/vueNodes/widgets/components/form/dropdown/FormDropdownInput.vue","../../src/renderer/extensions/vueNodes/widgets/components/form/dropdown/FormDropdownMenuActions.vue","../../src/renderer/extensions/vueNodes/widgets/components/form/dropdown/FormDropdownMenuFilter.vue","../../src/renderer/extensions/vueNodes/widgets/components/form/dropdown/types.ts","../../src/renderer/extensions/vueNodes/widgets/components/form/dropdown/FormDropdownMenuItem.vue","../../src/renderer/extensions/vueNodes/widgets/components/form/dropdown/FormDropdownMenu.vue","../../src/renderer/extensions/vueNodes/widgets/components/form/dropdown/shared.ts","../../src/renderer/extensions/vueNodes/widgets/components/form/dropdown/FormDropdown.vue","../../src/renderer/extensions/vueNodes/widgets/composables/useAssetWidgetData.ts","../../src/renderer/extensions/vueNodes/widgets/components/WidgetSelectDropdown.vue","../../src/renderer/extensions/vueNodes/widgets/components/WidgetSelect.vue"],"sourcesContent":["import type { HintedString } from '@primevue/core'\nimport { computed } from 'vue'\n\n/**\n * Options for configuring transform-compatible overlay props\n */\ninterface TransformCompatOverlayOptions {\n /**\n * Where to append the overlay. 'self' keeps overlay within component\n * for proper transform inheritance, 'body' teleports to document body\n */\n appendTo?: HintedString<'body' | 'self'> | undefined | HTMLElement\n // Future: other props needed for transform compatibility\n // scrollTarget?: string | HTMLElement\n // autoZIndex?: boolean\n}\n\n/**\n * Composable that provides props to make PrimeVue overlay components\n * compatible with CSS-transformed parent elements.\n *\n * Vue nodes use CSS transforms for positioning/scaling. PrimeVue overlay\n * components (Select, MultiSelect, TreeSelect, etc.) teleport to document\n * body by default, breaking transform inheritance. This composable provides\n * the necessary props to keep overlays within their component elements.\n *\n * @param overrides - Optional overrides for specific use cases\n * @returns Computed props object to spread on PrimeVue overlay components\n *\n * @example\n * ```vue\n * <template>\n * <Select v-bind=\"overlayProps\" />\n * </template>\n *\n * <script setup>\n * const overlayProps = useTransformCompatOverlayProps()\n * </script>\n * ```\n */\nexport function useTransformCompatOverlayProps(\n overrides: TransformCompatOverlayOptions = {}\n) {\n return computed(() => ({\n appendTo: 'self' as const,\n ...overrides\n }))\n}\n","<template>\n <WidgetLayoutField :widget>\n <Select\n v-model=\"modelValue\"\n :invalid\n :filter=\"selectOptions.length > 4\"\n :auto-filter-focus=\"selectOptions.length > 4\"\n :options=\"selectOptions\"\n v-bind=\"combinedProps\"\n :class=\"cn(WidgetInputBaseClass, 'w-full text-xs')\"\n :aria-label=\"widget.name\"\n size=\"small\"\n :pt=\"{\n option: 'text-xs',\n dropdown: 'w-8',\n label: cn('truncate min-w-[4ch]', $slots.default && 'mr-5'),\n overlay: 'w-fit min-w-full'\n }\"\n data-capture-wheel=\"true\"\n />\n <div class=\"absolute top-5 right-8 h-4 w-7 -translate-y-4/5 flex\">\n <slot />\n </div>\n </WidgetLayoutField>\n</template>\n\n<script setup lang=\"ts\">\nimport Select from 'primevue/select'\nimport { computed } from 'vue'\n\nimport { useTransformCompatOverlayProps } from '@/composables/useTransformCompatOverlayProps'\nimport type { SimplifiedWidget } from '@/types/simplifiedWidget'\nimport { cn } from '@/utils/tailwindUtil'\nimport {\n PANEL_EXCLUDED_PROPS,\n filterWidgetProps\n} from '@/utils/widgetPropFilter'\n\nimport { WidgetInputBaseClass } from './layout'\nimport WidgetLayoutField from './layout/WidgetLayoutField.vue'\n\ninterface Props {\n widget: SimplifiedWidget<string | undefined>\n}\n\nconst props = defineProps<Props>()\n\nconst modelValue = defineModel<string | undefined>({\n default(props: Props) {\n return props.widget.options?.values?.[0] || ''\n }\n})\n\n// Transform compatibility props for overlay positioning\nconst transformCompatProps = useTransformCompatOverlayProps()\n\n// Extract select options from widget options\nconst selectOptions = computed(() => {\n const options = props.widget.options\n\n if (options?.values && Array.isArray(options.values)) {\n return options.values\n }\n\n return []\n})\nconst invalid = computed(\n () => !!modelValue.value && !selectOptions.value.includes(modelValue.value)\n)\n\nconst combinedProps = computed(() => ({\n ...filterWidgetProps(props.widget.options, PANEL_EXCLUDED_PROPS),\n ...transformCompatProps.value,\n ...(invalid.value ? { placeholder: `${modelValue.value}` } : {})\n}))\n</script>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport { cn } from '@/utils/tailwindUtil'\n\nimport { WidgetInputBaseClass } from '../../layout'\nimport type { DropdownItem, SelectedKey } from './types'\n\ninterface Props {\n isOpen?: boolean\n placeholder?: string\n items: DropdownItem[]\n selected: Set<SelectedKey>\n maxSelectable: number\n uploadable: boolean\n disabled: boolean\n accept?: string\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n isOpen: false,\n placeholder: 'Select...'\n})\n\nconst emit = defineEmits<{\n (e: 'select-click', event: MouseEvent): void\n (e: 'file-change', event: Event): void\n}>()\n\nconst selectedItems = computed(() => {\n return props.items.filter((item) => props.selected.has(item.id))\n})\n\nconst theButtonStyle = computed(() =>\n cn(\n 'border-0 bg-component-node-widget-background outline-none text-text-secondary',\n props.disabled\n ? 'cursor-not-allowed'\n : 'hover:bg-component-node-widget-background-hovered cursor-pointer',\n selectedItems.value.length > 0 && 'text-text-primary'\n )\n)\n</script>\n\n<template>\n <div\n :class=\"\n cn(WidgetInputBaseClass, 'flex text-base leading-none', {\n 'opacity-50 cursor-not-allowed !outline-zinc-300/10': disabled\n })\n \"\n >\n <!-- Dropdown -->\n <button\n :class=\"\n cn(\n theButtonStyle,\n 'flex justify-between items-center flex-1 min-w-0 h-8',\n {\n 'rounded-l-lg': uploadable,\n 'rounded-lg': !uploadable\n }\n )\n \"\n @click=\"emit('select-click', $event)\"\n >\n <span class=\"min-w-0 flex-1 px-1 py-2 text-left truncate\">\n <span v-if=\"!selectedItems.length\">\n {{ placeholder }}\n </span>\n <span v-else>\n {{ selectedItems.map((item) => item.label ?? item.name).join(', ') }}\n </span>\n </span>\n <i\n class=\"icon-[lucide--chevron-down]\"\n :class=\"\n cn(\n 'mr-2 size-4 transition-transform duration-200 flex-shrink-0 text-component-node-foreground-secondary',\n isOpen && 'rotate-180'\n )\n \"\n />\n </button>\n <!-- Open File -->\n <label\n v-if=\"uploadable\"\n :class=\"\n cn(\n theButtonStyle,\n 'relative',\n 'size-8 flex justify-center items-center border-l rounded-r-lg border-zinc-300/10'\n )\n \"\n >\n <i class=\"icon-[lucide--folder-search] size-4\" />\n <input\n type=\"file\"\n class=\"absolute inset-0 -z-1 opacity-0\"\n :multiple=\"maxSelectable > 1\"\n :disabled=\"disabled\"\n :accept=\"accept\"\n @change=\"emit('file-change', $event)\"\n />\n </label>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport Popover from 'primevue/popover'\nimport { ref, useTemplateRef } from 'vue'\n\nimport { cn } from '@/utils/tailwindUtil'\n\nimport type { LayoutMode, OptionId, SortOption } from './types'\n\ndefineProps<{\n isQuerying: boolean\n sortOptions: SortOption[]\n}>()\n\nconst layoutMode = defineModel<LayoutMode>('layoutMode')\nconst searchQuery = defineModel<string>('searchQuery')\nconst sortSelected = defineModel<OptionId>('sortSelected')\n\nconst actionButtonStyle = cn(\n 'h-8 bg-zinc-500/20 rounded-lg outline outline-1 outline-offset-[-1px] outline-node-component-border transition-all duration-150'\n)\n\nconst resetInputStyle = 'bg-transparent border-0 outline-0 ring-0 text-left'\n\nconst layoutSwitchItemStyle =\n 'size-6 flex justify-center items-center rounded-sm cursor-pointer transition-all duration-150 hover:scale-108 hover:text-base-foreground active:scale-95'\n\nconst sortPopoverRef = useTemplateRef('sortPopoverRef')\nconst sortTriggerRef = useTemplateRef('sortTriggerRef')\nconst isSortPopoverOpen = ref(false)\n\nfunction toggleSortPopover(event: Event) {\n if (!sortPopoverRef.value || !sortTriggerRef.value) return\n isSortPopoverOpen.value = !isSortPopoverOpen.value\n sortPopoverRef.value.toggle(event, sortTriggerRef.value)\n}\nfunction closeSortPopover() {\n isSortPopoverOpen.value = false\n sortPopoverRef.value?.hide()\n}\n\nfunction handleSortSelected(item: SortOption) {\n sortSelected.value = item.id\n closeSortPopover()\n}\n</script>\n\n<template>\n <div class=\"text-secondary flex gap-2 px-4\">\n <!-- TODO: Replace with a common Search input -->\n <label\n :class=\"\n cn(\n actionButtonStyle,\n 'flex-1 flex px-2 items-center text-base leading-none cursor-text',\n searchQuery?.trim() !== '' ? 'text-base-foreground' : '',\n 'hover:outline-component-node-widget-background-highlighted/80',\n 'focus-within:outline-component-node-widget-background-highlighted/80'\n )\n \"\n >\n <i\n v-if=\"isQuerying\"\n class=\"mr-2 icon-[lucide--loader-circle] size-4 animate-spin\"\n />\n <i v-else class=\"mr-2 icon-[lucide--search] size-4\" />\n <input\n v-model=\"searchQuery\"\n type=\"text\"\n autofocus\n :class=\"resetInputStyle\"\n :placeholder=\"$t('g.search')\"\n />\n </label>\n\n <!-- Sort Select -->\n <button\n ref=\"sortTriggerRef\"\n :class=\"\n cn(\n resetInputStyle,\n actionButtonStyle,\n 'relative w-8 flex justify-center items-center cursor-pointer',\n 'hover:outline-component-node-widget-background-highlighted',\n 'active:!scale-95'\n )\n \"\n @click=\"toggleSortPopover\"\n >\n <div\n v-if=\"sortSelected !== 'default'\"\n class=\"absolute top-[-2px] left-[-2px] size-2 rounded-full bg-component-node-widget-background-highlighted\"\n />\n <i class=\"icon-[lucide--arrow-up-down] size-4\" />\n </button>\n <!-- Sort Popover -->\n <Popover\n ref=\"sortPopoverRef\"\n :dismissable=\"true\"\n :close-on-escape=\"true\"\n unstyled\n :pt=\"{\n root: {\n class: 'absolute z-50'\n },\n content: {\n class: ['bg-transparent border-none p-0 pt-2 rounded-lg shadow-lg']\n }\n }\"\n @hide=\"isSortPopoverOpen = false\"\n >\n <div\n :class=\"\n cn(\n 'flex flex-col gap-2 p-2 min-w-32',\n 'bg-component-node-background',\n 'rounded-lg outline outline-offset-[-1px] outline-component-node-border'\n )\n \"\n >\n <button\n v-for=\"item of sortOptions\"\n :key=\"item.name\"\n :class=\"\n cn(\n resetInputStyle,\n 'flex justify-between items-center h-6 cursor-pointer',\n 'hover:!text-blue-500'\n )\n \"\n @click=\"handleSortSelected(item)\"\n >\n <span>{{ item.name }}</span>\n <i\n v-if=\"sortSelected === item.id\"\n class=\"icon-[lucide--check] size-4\"\n />\n </button>\n </div>\n </Popover>\n\n <!-- Layout Switch -->\n <div\n :class=\"\n cn(\n actionButtonStyle,\n 'flex justify-center items-center p-1 gap-1 hover:outline-component-node-widget-background-highlighted'\n )\n \"\n >\n <button\n :class=\"\n cn(\n resetInputStyle,\n layoutSwitchItemStyle,\n layoutMode === 'list'\n ? 'bg-neutral-500/50 text-base-foreground'\n : ''\n )\n \"\n @click=\"layoutMode = 'list'\"\n >\n <i class=\"icon-[lucide--list] size-4\" />\n </button>\n <button\n :class=\"\n cn(\n resetInputStyle,\n layoutSwitchItemStyle,\n layoutMode === 'grid'\n ? 'bg-neutral-500/50 text-base-foreground'\n : ''\n )\n \"\n @click=\"layoutMode = 'grid'\"\n >\n <i class=\"icon-[lucide--layout-grid] size-4\" />\n </button>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport Button from '@/components/ui/button/Button.vue'\nimport { useModelUpload } from '@/platform/assets/composables/useModelUpload'\nimport { cn } from '@/utils/tailwindUtil'\n\nimport type { FilterOption, OptionId } from './types'\n\nconst { filterOptions } = defineProps<{\n filterOptions: FilterOption[]\n}>()\n\nconst filterSelected = defineModel<OptionId>('filterSelected')\n\nconst { isUploadButtonEnabled, showUploadDialog } = useModelUpload()\n\n// TODO: Add real check to differentiate between the Model dialogs and Load Image\nconst singleFilterOption = computed(() => filterOptions.length === 1)\n</script>\n\n<template>\n <div class=\"text-secondary mb-4 flex gap-1 px-4 justify-start\">\n <button\n v-for=\"option in filterOptions\"\n :key=\"option.id\"\n type=\"button\"\n :disabled=\"singleFilterOption\"\n :class=\"\n cn(\n 'px-4 py-2 rounded-md inline-flex justify-center items-center select-none appearance-none border-0 text-base-foreground',\n !singleFilterOption &&\n 'transition-all duration-150 hover:text-base-foreground hover:bg-interface-menu-component-surface-hovered cursor-pointer active:scale-95',\n !singleFilterOption && filterSelected === option.id\n ? '!bg-interface-menu-component-surface-selected text-base-foreground'\n : 'bg-transparent'\n )\n \"\n @click=\"filterSelected = option.id\"\n >\n {{ option.name }}\n </button>\n <Button\n v-if=\"isUploadButtonEnabled && singleFilterOption\"\n class=\"ml-auto\"\n size=\"md\"\n variant=\"textonly\"\n @click=\"showUploadDialog\"\n >\n <i class=\"icon-[lucide--folder-input]\" />\n <span>{{ $t('g.import') }}</span>\n </Button>\n </div>\n</template>\n","import type { ComputedRef, InjectionKey } from 'vue'\n\nimport type { AssetKind } from '@/types/widgetTypes'\n\nexport type OptionId = string | number | symbol\nexport type SelectedKey = OptionId\n\nexport interface DropdownItem {\n id: SelectedKey\n mediaSrc: string // URL for image, video, or other media\n name: string\n label?: string\n metadata: string\n}\nexport interface SortOption {\n id: OptionId\n name: string\n sorter: (ctx: { items: readonly DropdownItem[] }) => DropdownItem[]\n}\n\nexport interface FilterOption {\n id: OptionId\n name: string\n}\n\nexport type LayoutMode = 'list' | 'grid' | 'list-small'\n\nexport const AssetKindKey: InjectionKey<ComputedRef<AssetKind | undefined>> =\n Symbol('assetKind')\n","<script setup lang=\"ts\">\nimport { computed, inject, ref } from 'vue'\n\nimport LazyImage from '@/components/common/LazyImage.vue'\nimport { cn } from '@/utils/tailwindUtil'\n\nimport { AssetKindKey } from './types'\nimport type { LayoutMode } from './types'\n\ninterface Props {\n index: number\n selected: boolean\n mediaSrc: string\n name: string\n label?: string\n metadata?: string\n layout?: LayoutMode\n}\n\nconst props = defineProps<Props>()\n\nconst emit = defineEmits<{\n click: [index: number]\n mediaLoad: [event: Event]\n}>()\n\nconst actualDimensions = ref<string | null>(null)\n\nconst assetKind = inject(AssetKindKey)\n\nconst isVideo = computed(() => assetKind?.value === 'video')\n\nfunction handleClick() {\n emit('click', props.index)\n}\n\nfunction handleImageLoad(event: Event) {\n emit('mediaLoad', event)\n if (!event.target || !(event.target instanceof HTMLImageElement)) return\n const img = event.target\n if (img.naturalWidth && img.naturalHeight) {\n actualDimensions.value = `${img.naturalWidth} x ${img.naturalHeight}`\n }\n}\n\nfunction handleVideoLoad(event: Event) {\n emit('mediaLoad', event)\n if (!event.target || !(event.target instanceof HTMLVideoElement)) return\n const video = event.target\n if (video.videoWidth && video.videoHeight) {\n actualDimensions.value = `${video.videoWidth} x ${video.videoHeight}`\n }\n}\n</script>\n\n<template>\n <div\n :class=\"\n cn(\n 'flex gap-1 select-none group/item cursor-pointer bg-component-node-widget-background',\n 'transition-all duration-150',\n {\n 'flex-col text-center': layout === 'grid',\n 'flex-row text-left max-h-16 rounded-lg hover:scale-102 active:scale-98':\n layout === 'list',\n 'flex-row text-left hover:bg-component-node-widget-background-hovered rounded-lg':\n layout === 'list-small',\n // selection\n 'ring-2 ring-component-node-widget-background-highlighted':\n layout === 'list' && selected\n }\n )\n \"\n @click=\"handleClick\"\n >\n <!-- Image -->\n <div\n v-if=\"layout !== 'list-small'\"\n :class=\"\n cn(\n 'relative',\n 'w-full aspect-square overflow-hidden outline-1 outline-offset-[-1px] outline-interface-stroke',\n 'transition-all duration-150',\n {\n 'min-w-16 max-w-16 rounded-l-lg': layout === 'list',\n 'rounded-sm group-hover/item:scale-108 group-active/item:scale-95':\n layout === 'grid',\n // selection\n 'ring-2 ring-component-node-widget-background-highlighted':\n layout === 'grid' && selected\n }\n )\n \"\n >\n <!-- Selected Icon -->\n <div\n v-if=\"selected\"\n class=\"absolute top-1 left-1 size-4 rounded-full border-1 border-base-foreground bg-primary-background\"\n >\n <i\n class=\"icon-[lucide--check] size-3 translate-y-[-0.5px] text-base-foreground bold\"\n />\n </div>\n <video\n v-if=\"mediaSrc && isVideo\"\n :src=\"mediaSrc\"\n class=\"size-full object-cover\"\n preload=\"metadata\"\n muted\n @loadeddata=\"handleVideoLoad\"\n />\n <LazyImage\n v-else-if=\"mediaSrc\"\n :src=\"mediaSrc\"\n :alt=\"name\"\n image-class=\"size-full object-cover\"\n @load=\"handleImageLoad\"\n />\n <div\n v-else\n class=\"size-full bg-gradient-to-tr from-blue-400 via-teal-500 to-green-400\"\n />\n </div>\n <!-- Name -->\n <div\n :class=\"\n cn('flex gap-1', {\n 'flex-col': layout === 'grid',\n 'flex-col px-4 py-1 w-full justify-center min-w-0': layout === 'list',\n 'flex-row p-2 items-center justify-between w-full':\n layout === 'list-small'\n })\n \"\n >\n <span\n v-tooltip=\"layout === 'grid' ? (label ?? name) : undefined\"\n :class=\"\n cn(\n 'block text-xs line-clamp-2 break-words overflow-hidden',\n 'transition-colors duration-150',\n // selection\n !!selected && 'text-base-foreground'\n )\n \"\n >\n {{ label ?? name }}\n </span>\n <!-- Meta Data -->\n <span class=\"text-secondary block text-xs\">{{\n metadata || actualDimensions\n }}</span>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { cn } from '@/utils/tailwindUtil'\n\nimport FormDropdownMenuActions from './FormDropdownMenuActions.vue'\nimport FormDropdownMenuFilter from './FormDropdownMenuFilter.vue'\nimport FormDropdownMenuItem from './FormDropdownMenuItem.vue'\nimport type {\n DropdownItem,\n FilterOption,\n LayoutMode,\n OptionId,\n SortOption\n} from './types'\n\ninterface Props {\n items: DropdownItem[]\n isSelected: (item: DropdownItem, index: number) => boolean\n isQuerying: boolean\n filterOptions: FilterOption[]\n sortOptions: SortOption[]\n}\n\ndefineProps<Props>()\nconst emit = defineEmits<{\n (e: 'item-click', item: DropdownItem, index: number): void\n}>()\n\n// Define models for two-way binding\nconst filterSelected = defineModel<OptionId>('filterSelected')\nconst layoutMode = defineModel<LayoutMode>('layoutMode')\nconst sortSelected = defineModel<OptionId>('sortSelected')\nconst searchQuery = defineModel<string>('searchQuery')\n\n// Handle item selection\n</script>\n\n<template>\n <div\n class=\"flex max-h-[640px] w-103 flex-col rounded-lg bg-component-node-background pt-4 outline outline-offset-[-1px] outline-node-component-border\"\n >\n <!-- Filter -->\n <FormDropdownMenuFilter\n v-if=\"filterOptions.length > 0\"\n v-model:filter-selected=\"filterSelected\"\n :filter-options=\"filterOptions\"\n />\n <!-- Actions -->\n <FormDropdownMenuActions\n v-model:layout-mode=\"layoutMode\"\n v-model:sort-selected=\"sortSelected\"\n v-model:search-query=\"searchQuery\"\n :sort-options=\"sortOptions\"\n :is-querying=\"isQuerying\"\n />\n <!-- List -->\n <div class=\"relative flex h-full mt-2 overflow-y-scroll\">\n <div\n :class=\"\n cn(\n 'h-full max-h-full grid gap-x-2 gap-y-4 overflow-y-auto px-4 pt-4 pb-4 w-full',\n {\n 'grid-cols-4': layoutMode === 'grid',\n 'grid-cols-1 gap-y-2': layoutMode === 'list',\n 'grid-cols-1 gap-y-1': layoutMode === 'list-small'\n }\n )\n \"\n >\n <div class=\"pointer-events-none absolute inset-x-3 top-0 z-10 h-5\" />\n <div\n v-if=\"items.length === 0\"\n class=\"h-50 col-span-full flex items-center justify-center\"\n >\n <i\n :title=\"$t('g.noItems')\"\n :aria-label=\"$t('g.noItems')\"\n class=\"icon-[lucide--circle-off] size-30 text-zinc-500/20\"\n />\n </div>\n <!-- Item -->\n <FormDropdownMenuItem\n v-for=\"(item, index) in items\"\n :key=\"item.id\"\n :index=\"index\"\n :selected=\"isSelected(item, index)\"\n :media-src=\"item.mediaSrc\"\n :name=\"item.name\"\n :label=\"item.label\"\n :metadata=\"item.metadata\"\n :layout=\"layoutMode\"\n @click=\"emit('item-click', item, index)\"\n />\n </div>\n </div>\n </div>\n</template>\n","import type { DropdownItem, SortOption } from './types'\n\nexport async function defaultSearcher(query: string, items: DropdownItem[]) {\n if (query.trim() === '') return items\n const words = query.trim().toLowerCase().split(' ')\n return items.filter((item) => {\n const name = item.name.toLowerCase()\n return words.every((word) => name.includes(word))\n })\n}\n\nexport function getDefaultSortOptions(): SortOption[] {\n return [\n {\n name: 'Default',\n id: 'default',\n sorter: ({ items }) => items.slice()\n },\n {\n name: 'A-Z',\n id: 'a-z',\n sorter: ({ items }) =>\n items.slice().sort((a, b) => {\n return a.name.localeCompare(b.name)\n })\n }\n ]\n}\n","<script setup lang=\"ts\">\nimport { refDebounced } from '@vueuse/core'\nimport Popover from 'primevue/popover'\nimport { computed, ref, useTemplateRef, watch } from 'vue'\n\nimport { t } from '@/i18n'\nimport { useToastStore } from '@/platform/updates/common/toastStore'\n\nimport FormDropdownInput from './FormDropdownInput.vue'\nimport FormDropdownMenu from './FormDropdownMenu.vue'\nimport { defaultSearcher, getDefaultSortOptions } from './shared'\nimport type {\n DropdownItem,\n FilterOption,\n LayoutMode,\n OptionId,\n SelectedKey,\n SortOption\n} from './types'\n\ninterface Props {\n items: DropdownItem[]\n placeholder?: string\n /**\n * If true, allows multiple selections. If a number is provided,\n * it specifies the maximum number of selections allowed.\n */\n multiple?: boolean | number\n\n uploadable?: boolean\n disabled?: boolean\n accept?: string\n filterOptions?: FilterOption[]\n sortOptions?: SortOption[]\n isSelected?: (\n selected: Set<SelectedKey>,\n item: DropdownItem,\n index: number\n ) => boolean\n searcher?: (\n query: string,\n items: DropdownItem[],\n onCleanup: (cleanupFn: () => void) => void\n ) => Promise<DropdownItem[]>\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n placeholder: t('widgets.uploadSelect.placeholder'),\n multiple: false,\n uploadable: false,\n disabled: false,\n filterOptions: () => [],\n sortOptions: () => getDefaultSortOptions(),\n isSelected: (selected, item, _index) => selected.has(item.id),\n searcher: defaultSearcher\n})\n\nconst selected = defineModel<Set<SelectedKey>>('selected', {\n default: new Set()\n})\nconst filterSelected = defineModel<OptionId>('filterSelected', { default: '' })\nconst sortSelected = defineModel<OptionId>('sortSelected', {\n default: 'default'\n})\nconst layoutMode = defineModel<LayoutMode>('layoutMode', {\n default: 'grid'\n})\nconst files = defineModel<File[]>('files', { default: [] })\nconst searchQuery = defineModel<string>('searchQuery', { default: '' })\n\nconst debouncedSearchQuery = refDebounced(searchQuery, 700, {\n maxWait: 700\n})\nconst isQuerying = ref(false)\nconst toastStore = useToastStore()\nconst popoverRef = ref<InstanceType<typeof Popover>>()\nconst triggerRef = useTemplateRef('triggerRef')\nconst isOpen = ref(false)\n\nconst maxSelectable = computed(() => {\n if (props.multiple === true) return Infinity\n if (typeof props.multiple === 'number') return props.multiple\n return 1\n})\n\nconst filteredItems = ref<DropdownItem[]>([])\n\nwatch(searchQuery, (value) => {\n isQuerying.value = value !== debouncedSearchQuery.value\n})\n\nwatch(\n [debouncedSearchQuery, () => props.items],\n (_, __, onCleanup) => {\n let isCleanup = false\n let cleanupFn: undefined | (() => void)\n onCleanup(() => {\n isCleanup = true\n cleanupFn?.()\n })\n\n void props\n .searcher(\n debouncedSearchQuery.value,\n props.items,\n (cb) => (cleanupFn = cb)\n )\n .then((result) => {\n if (!isCleanup) filteredItems.value = result\n })\n .finally(() => {\n if (!isCleanup) isQuerying.value = false\n })\n },\n { immediate: true }\n)\n\nconst defaultSorter = computed<SortOption['sorter']>(() => {\n const sorter = props.sortOptions.find(\n (option) => option.id === 'default'\n )?.sorter\n return sorter || (({ items }) => items.slice())\n})\nconst selectedSorter = computed<SortOption['sorter']>(() => {\n if (sortSelected.value === 'default') return defaultSorter.value\n const sorter = props.sortOptions.find(\n (option) => option.id === sortSelected.value\n )?.sorter\n return sorter || defaultSorter.value\n})\nconst sortedItems = computed(() => {\n return selectedSorter.value({ items: filteredItems.value }) || []\n})\n\nfunction internalIsSelected(item: DropdownItem, index: number): boolean {\n return props.isSelected?.(selected.value, item, index) ?? false\n}\n\nconst toggleDropdown = (event: Event) => {\n if (props.disabled) return\n if (popoverRef.value && triggerRef.value) {\n popoverRef.value.toggle(event, triggerRef.value)\n isOpen.value = !isOpen.value\n }\n}\n\nconst closeDropdown = () => {\n if (popoverRef.value) {\n popoverRef.value.hide()\n isOpen.value = false\n }\n}\n\nfunction handleFileChange(event: Event) {\n if (props.disabled) return\n const input = event.target as HTMLInputElement\n if (input.files) {\n files.value = Array.from(input.files)\n }\n // Clear the input value to allow re-selecting the same file\n input.value = ''\n}\n\nfunction handleSelection(item: DropdownItem, index: number) {\n if (props.disabled) return\n const sel = selected.value\n if (internalIsSelected(item, index)) {\n sel.delete(item.id)\n } else {\n if (sel.size < maxSelectable.value) {\n sel.add(item.id)\n } else if (maxSelectable.value === 1) {\n sel.clear()\n sel.add(item.id)\n } else {\n toastStore.addAlert(`Maximum selection limit reached`)\n return\n }\n }\n selected.value = new Set(sel)\n\n if (maxSelectable.value === 1) {\n closeDropdown()\n }\n}\n</script>\n\n<template>\n <div ref=\"triggerRef\">\n <FormDropdownInput\n :files=\"files\"\n :is-open=\"isOpen\"\n :placeholder=\"placeholder\"\n :items=\"items\"\n :max-selectable=\"maxSelectable\"\n :selected=\"selected\"\n :uploadable=\"uploadable\"\n :disabled=\"disabled\"\n :accept=\"accept\"\n @select-click=\"toggleDropdown\"\n @file-change=\"handleFileChange\"\n />\n <Popover\n ref=\"popoverRef\"\n :dismissable=\"true\"\n :close-on-escape=\"true\"\n unstyled\n :pt=\"{\n root: {\n class: 'absolute z-50'\n },\n content: {\n class: ['bg-transparent border-none p-0 pt-2 rounded-lg shadow-lg']\n }\n }\"\n @hide=\"isOpen = false\"\n >\n <FormDropdownMenu\n v-model:filter-selected=\"filterSelected\"\n v-model:layout-mode=\"layoutMode\"\n v-model:sort-selected=\"sortSelected\"\n v-model:search-query=\"searchQuery\"\n :filter-options=\"filterOptions\"\n :sort-options=\"sortOptions\"\n :disabled=\"disabled\"\n :is-querying=\"isQuerying\"\n :items=\"sortedItems\"\n :is-selected=\"internalIsSelected\"\n :max-selectable=\"maxSelectable\"\n @close=\"closeDropdown\"\n @item-click=\"handleSelection\"\n />\n </Popover>\n </div>\n</template>\n","import { computed, toValue, watch } from 'vue'\nimport type { MaybeRefOrGetter } from 'vue'\n\nimport { isCloud } from '@/platform/distribution/types'\nimport type { AssetItem } from '@/platform/assets/schemas/assetSchema'\nimport type { DropdownItem } from '@/renderer/extensions/vueNodes/widgets/components/form/dropdown/types'\nimport { useAssetsStore } from '@/stores/assetsStore'\nimport { useModelToNodeStore } from '@/stores/modelToNodeStore'\n\n/**\n * Composable for fetching and transforming asset data for Vue node widgets.\n * Provides reactive asset data based on node type with automatic category detection.\n * Uses store-based caching to avoid duplicate fetches across multiple instances.\n *\n * Cloud-only composable - returns empty data when not in cloud environment.\n *\n * @param nodeType - ComfyUI node type (ref, getter, or plain value). Can be undefined.\n * Accepts: ref('CheckpointLoaderSimple'), () => 'CheckpointLoaderSimple', or 'CheckpointLoaderSimple'\n * @returns Reactive data including category, assets, dropdown items, loading state, and errors\n */\nexport function useAssetWidgetData(\n nodeType: MaybeRefOrGetter<string | undefined>\n) {\n if (isCloud) {\n const assetsStore = useAssetsStore()\n const modelToNodeStore = useModelToNodeStore()\n\n const category = computed(() => {\n const resolvedType = toValue(nodeType)\n return resolvedType\n ? modelToNodeStore.getCategoryForNodeType(resolvedType)\n : undefined\n })\n\n const assets = computed<AssetItem[]>(() => {\n const resolvedType = toValue(nodeType)\n return resolvedType\n ? (assetsStore.modelAssetsByNodeType.get(resolvedType) ?? [])\n : []\n })\n\n const isLoading = computed(() => {\n const resolvedType = toValue(nodeType)\n return resolvedType\n ? (assetsStore.modelLoadingByNodeType.get(resolvedType) ?? false)\n : false\n })\n\n const error = computed<Error | null>(() => {\n const resolvedType = toValue(nodeType)\n return resolvedType\n ? (assetsStore.modelErrorByNodeType.get(resolvedType) ?? null)\n : null\n })\n\n const dropdownItems = computed<DropdownItem[]>(() => {\n return assets.value.map((asset) => ({\n id: asset.id,\n name:\n (asset.user_metadata?.filename as string | undefined) ?? asset.name,\n label: asset.name,\n mediaSrc: asset.preview_url ?? '',\n metadata: ''\n }))\n })\n\n watch(\n () => toValue(nodeType),\n async (currentNodeType) => {\n if (!currentNodeType) {\n return\n }\n\n const hasData = assetsStore.modelAssetsByNodeType.has(currentNodeType)\n\n if (!hasData) {\n await assetsStore.updateModelsForNodeType(currentNodeType)\n }\n },\n { immediate: true }\n )\n\n return {\n category,\n assets,\n dropdownItems,\n isLoading,\n error\n }\n }\n\n return {\n category: computed(() => undefined),\n assets: computed(() => []),\n dropdownItems: computed(() => []),\n isLoading: computed(() => false),\n error: computed(() => null)\n }\n}\n","<script setup lang=\"ts\">\nimport { capitalize } from 'es-toolkit'\nimport { computed, provide, ref, toRef, watch } from 'vue'\n\nimport { useTransformCompatOverlayProps } from '@/composables/useTransformCompatOverlayProps'\nimport { t } from '@/i18n'\nimport { useToastStore } from '@/platform/updates/common/toastStore'\nimport FormDropdown from '@/renderer/extensions/vueNodes/widgets/components/form/dropdown/FormDropdown.vue'\nimport { AssetKindKey } from '@/renderer/extensions/vueNodes/widgets/components/form/dropdown/types'\nimport type {\n DropdownItem,\n FilterOption,\n LayoutMode,\n SelectedKey\n} from '@/renderer/extensions/vueNodes/widgets/components/form/dropdown/types'\nimport WidgetLayoutField from '@/renderer/extensions/vueNodes/widgets/components/layout/WidgetLayoutField.vue'\nimport { useAssetWidgetData } from '@/renderer/extensions/vueNodes/widgets/composables/useAssetWidgetData'\nimport type { ResultItemType } from '@/schemas/apiSchema'\nimport { api } from '@/scripts/api'\nimport { useAssetsStore } from '@/stores/assetsStore'\nimport { useQueueStore } from '@/stores/queueStore'\nimport type { SimplifiedWidget } from '@/types/simplifiedWidget'\nimport type { AssetKind } from '@/types/widgetTypes'\nimport {\n PANEL_EXCLUDED_PROPS,\n filterWidgetProps\n} from '@/utils/widgetPropFilter'\n\ninterface Props {\n widget: SimplifiedWidget<string | undefined>\n nodeType?: string\n assetKind?: AssetKind\n allowUpload?: boolean\n uploadFolder?: ResultItemType\n isAssetMode?: boolean\n defaultLayoutMode?: LayoutMode\n}\n\nconst props = defineProps<Props>()\n\nprovide(\n AssetKindKey,\n computed(() => props.assetKind)\n)\n\nconst modelValue = defineModel<string | undefined>({\n default(props: Props) {\n return props.widget.options?.values?.[0] || ''\n }\n})\n\nconst toastStore = useToastStore()\nconst queueStore = useQueueStore()\n\nconst transformCompatProps = useTransformCompatOverlayProps()\n\nconst combinedProps = computed(() => ({\n ...filterWidgetProps(props.widget.options, PANEL_EXCLUDED_PROPS),\n ...transformCompatProps.value\n}))\n\nconst getAssetData = () => {\n if (props.isAssetMode && props.nodeType) {\n return useAssetWidgetData(toRef(() => props.nodeType))\n }\n return null\n}\nconst assetData = getAssetData()\n\nconst filterSelected = ref('all')\nconst filterOptions = computed<FilterOption[]>(() => {\n if (props.isAssetMode) {\n const categoryName = assetData?.category.value ?? 'All'\n return [{ id: 'all', name: capitalize(categoryName) }]\n }\n return [\n { id: 'all', name: 'All' },\n { id: 'inputs', name: 'Inputs' },\n { id: 'outputs', name: 'Outputs' }\n ]\n})\n\nconst selectedSet = ref<Set<SelectedKey>>(new Set())\n\n/**\n * Transforms a value using getOptionLabel if available.\n * Falls back to the original value if getOptionLabel is not provided or throws an error.\n */\nfunction getDisplayLabel(value: string): string {\n const getOptionLabel = props.widget.options?.getOptionLabel\n if (!getOptionLabel) return value\n\n try {\n return getOptionLabel(value)\n } catch (e) {\n console.error('Failed to map value:', e)\n return value\n }\n}\n\nconst inputItems = computed<DropdownItem[]>(() => {\n const values = props.widget.options?.values || []\n\n if (!Array.isArray(values)) {\n return []\n }\n\n return values.map((value: string, index: number) => ({\n id: `input-${index}`,\n mediaSrc: getMediaUrl(value, 'input'),\n name: value,\n label: getDisplayLabel(value),\n metadata: ''\n }))\n})\nconst outputItems = computed<DropdownItem[]>(() => {\n if (!['image', 'video'].includes(props.assetKind ?? '')) return []\n\n const outputs = new Set<string>()\n\n // Extract output images/videos from queue history\n queueStore.historyTasks.forEach((task) => {\n task.flatOutputs.forEach((output) => {\n const isTargetType =\n (props.assetKind === 'image' && output.mediaType === 'images') ||\n (props.assetKind === 'video' && output.mediaType === 'video')\n\n if (output.type === 'output' && isTargetType) {\n const path = output.subfolder\n ? `${output.subfolder}/${output.filename}`\n : output.filename\n // Add [output] annotation so the preview component knows the type\n const annotatedPath = `${path} [output]`\n outputs.add(annotatedPath)\n }\n })\n })\n\n return Array.from(outputs).map((output) => ({\n id: `output-${output}`,\n mediaSrc: getMediaUrl(output.replace(' [output]', ''), 'output'),\n name: output,\n label: getDisplayLabel(output),\n metadata: ''\n }))\n})\n\nconst allItems = computed<DropdownItem[]>(() => {\n if (props.isAssetMode && assetData) {\n return assetData.dropdownItems.value\n }\n return [...inputItems.value, ...outputItems.value]\n})\n\nconst dropdownItems = computed<DropdownItem[]>(() => {\n if (props.isAssetMode) {\n return allItems.value\n }\n\n switch (filterSelected.value) {\n case 'inputs':\n return inputItems.value\n case 'outputs':\n return outputItems.value\n case 'all':\n default:\n return [...inputItems.value, ...outputItems.value]\n }\n})\n\nconst mediaPlaceholder = computed(() => {\n const options = props.widget.options\n\n if (options?.placeholder) {\n return options.placeholder\n }\n\n switch (props.assetKind) {\n case 'image':\n return t('widgets.uploadSelect.placeholderImage')\n case 'video':\n return t('widgets.uploadSelect.placeholderVideo')\n case 'audio':\n return t('widgets.uploadSelect.placeholderAudio')\n case 'model':\n return t('widgets.uploadSelect.placeholderModel')\n case 'unknown':\n return t('widgets.uploadSelect.placeholderUnknown')\n }\n\n return t('widgets.uploadSelect.placeholder')\n})\n\nconst uploadable = computed(() => {\n if (props.isAssetMode) return false\n return props.allowUpload === true\n})\n\nconst acceptTypes = computed(() => {\n // Be permissive with accept types because backend uses libraries\n // that can handle a wide range of formats\n switch (props.assetKind) {\n case 'image':\n return 'image/*'\n case 'video':\n return 'video/*'\n case 'audio':\n return 'audio/*'\n default:\n return undefined // model or unknown\n }\n})\n\nconst layoutMode = ref<LayoutMode>(props.defaultLayoutMode ?? 'grid')\n\nwatch(\n [modelValue, dropdownItems],\n ([currentValue, _dropdownItems]) => {\n if (currentValue === undefined) {\n selectedSet.value.clear()\n return\n }\n\n const item = dropdownItems.value.find((item) => item.name === currentValue)\n if (item) {\n selectedSet.value.clear()\n selectedSet.value.add(item.id)\n }\n },\n { immediate: true }\n)\n\nfunction updateSelectedItems(selectedItems: Set<SelectedKey>) {\n let id: SelectedKey | undefined = undefined\n if (selectedItems.size > 0) {\n id = selectedItems.values().next().value!\n }\n if (id == null) {\n modelValue.value = undefined\n return\n }\n const name = dropdownItems.value.find((item) => item.id === id)?.name\n if (!name) {\n modelValue.value = undefined\n return\n }\n modelValue.value = name\n}\n\n// Upload file function (copied from useNodeImageUpload.ts)\nconst uploadFile = async (\n file: File,\n isPasted: boolean = false,\n formFields: Partial<{ type: ResultItemType }> = {}\n) => {\n const body = new FormData()\n body.append('image', file)\n if (isPasted) body.append('subfolder', 'pasted')\n if (formFields.type) body.append('type', formFields.type)\n\n const resp = await api.fetchApi('/upload/image', {\n method: 'POST',\n body\n })\n\n if (resp.status !== 200) {\n toastStore.addAlert(resp.status + ' - ' + resp.statusText)\n return null\n }\n\n const data = await resp.json()\n\n // Update AssetsStore when uploading to input folder\n if (formFields.type === 'input' || (!formFields.type && !isPasted)) {\n const assetsStore = useAssetsStore()\n await assetsStore.updateInputs()\n }\n\n return data.subfolder ? `${data.subfolder}/${data.name}` : data.name\n}\n\n// Handle multiple file uploads\nconst uploadFiles = async (files: File[]): Promise<string[]> => {\n const folder = props.uploadFolder ?? 'input'\n const uploadPromises = files.map((file) =>\n uploadFile(file, false, { type: folder })\n )\n const results = await Promise.all(uploadPromises)\n return results.filter((path): path is string => path !== null)\n}\n\nasync function handleFilesUpdate(files: File[]) {\n if (!files || files.length === 0) return\n\n try {\n // 1. Upload files to server\n const uploadedPaths = await uploadFiles(files)\n\n if (uploadedPaths.length === 0) {\n toastStore.addAlert('File upload failed')\n return\n }\n\n // 2. Update widget options to include new files\n // This simulates what addToComboValues does but for SimplifiedWidget\n if (props.widget.options?.values) {\n uploadedPaths.forEach((path) => {\n const values = props.widget.options!.values as string[]\n if (!values.includes(path)) {\n values.push(path)\n }\n })\n }\n\n // 3. Update widget value to the first uploaded file\n modelValue.value = uploadedPaths[0]\n\n // 4. Trigger callback to notify underlying LiteGraph widget\n if (props.widget.callback) {\n props.widget.callback(uploadedPaths[0])\n }\n } catch (error) {\n console.error('Upload error:', error)\n toastStore.addAlert(`Upload failed: ${error}`)\n }\n}\n\nfunction getMediaUrl(\n filename: string,\n type: 'input' | 'output' = 'input'\n): string {\n if (!['image', 'video'].includes(props.assetKind ?? '')) return ''\n return `/api/view?filename=${encodeURIComponent(filename)}&type=${type}`\n}\n</script>\n\n<template>\n <WidgetLayoutField :widget>\n <FormDropdown\n v-model:selected=\"selectedSet\"\n v-model:filter-selected=\"filterSelected\"\n v-model:layout-mode=\"layoutMode\"\n :items=\"dropdownItems\"\n :placeholder=\"mediaPlaceholder\"\n :multiple=\"false\"\n :uploadable=\"uploadable\"\n :accept=\"acceptTypes\"\n :filter-options=\"filterOptions\"\n v-bind=\"combinedProps\"\n class=\"w-full\"\n @update:selected=\"updateSelectedItems\"\n @update:files=\"handleFilesUpdate\"\n />\n </WidgetLayoutField>\n</template>\n","<template>\n <WidgetSelectDropdown\n v-if=\"isDropdownUIWidget\"\n v-model=\"modelValue\"\n :widget\n :node-type=\"widget.nodeType ?? nodeType\"\n :asset-kind=\"assetKind\"\n :allow-upload=\"allowUpload\"\n :upload-folder=\"uploadFolder\"\n :is-asset-mode=\"isAssetMode\"\n :default-layout-mode=\"defaultLayoutMode\"\n />\n <WidgetWithControl\n v-else-if=\"widget.controlWidget\"\n v-model=\"modelValue\"\n :component=\"WidgetSelectDefault\"\n :widget=\"widget as StringControlWidget\"\n />\n <WidgetSelectDefault v-else v-model=\"modelValue\" :widget />\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport { assetService } from '@/platform/assets/services/assetService'\nimport { isCloud } from '@/platform/distribution/types'\nimport { useSettingStore } from '@/platform/settings/settingStore'\nimport WidgetSelectDefault from '@/renderer/extensions/vueNodes/widgets/components/WidgetSelectDefault.vue'\nimport WidgetSelectDropdown from '@/renderer/extensions/vueNodes/widgets/components/WidgetSelectDropdown.vue'\nimport WidgetWithControl from '@/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vue'\nimport type { LayoutMode } from '@/renderer/extensions/vueNodes/widgets/components/form/dropdown/types'\nimport type { ResultItemType } from '@/schemas/apiSchema'\nimport { isComboInputSpec } from '@/schemas/nodeDef/nodeDefSchemaV2'\nimport type { ComboInputSpec } from '@/schemas/nodeDef/nodeDefSchemaV2'\nimport type {\n SimplifiedControlWidget,\n SimplifiedWidget\n} from '@/types/simplifiedWidget'\nimport type { AssetKind } from '@/types/widgetTypes'\n\ntype StringControlWidget = SimplifiedControlWidget<string | undefined>\n\nconst props = defineProps<{\n widget: SimplifiedWidget<string | undefined>\n nodeType?: string\n}>()\n\nconst modelValue = defineModel<string | undefined>()\n\nconst comboSpec = computed<ComboInputSpec | undefined>(() => {\n if (props.widget.spec && isComboInputSpec(props.widget.spec)) {\n return props.widget.spec\n }\n return undefined\n})\n\nconst specDescriptor = computed<{\n kind: AssetKind\n allowUpload: boolean\n folder: ResultItemType | undefined\n}>(() => {\n const spec = comboSpec.value\n if (!spec) {\n return {\n kind: 'unknown',\n allowUpload: false,\n folder: undefined\n }\n }\n\n const {\n image_upload,\n animated_image_upload,\n video_upload,\n image_folder,\n audio_upload\n } = spec\n\n let kind: AssetKind = 'unknown'\n if (video_upload) {\n kind = 'video'\n } else if (image_upload || animated_image_upload) {\n kind = 'image'\n } else if (audio_upload) {\n kind = 'audio'\n }\n // TODO: add support for models (checkpoints, VAE, LoRAs, etc.) -- get widgetType from spec\n\n const allowUpload =\n image_upload === true ||\n animated_image_upload === true ||\n video_upload === true ||\n audio_upload === true\n return {\n kind,\n allowUpload,\n folder: image_folder\n }\n})\n\nconst isAssetMode = computed(() => {\n if (isCloud) {\n const settingStore = useSettingStore()\n const isUsingAssetAPI = settingStore.get('Comfy.Assets.UseAssetAPI')\n const isEligible =\n assetService.isAssetBrowserEligible(props.nodeType, props.widget.name) ||\n props.widget.type === 'asset'\n\n return isUsingAssetAPI && isEligible\n }\n\n return false\n})\n\nconst assetKind = computed(() => specDescriptor.value.kind)\nconst isDropdownUIWidget = computed(\n () => isAssetMode.value || assetKind.value !== 'unknown'\n)\nconst allowUpload = computed(() => specDescriptor.value.allowUpload)\nconst uploadFolder = computed<ResultItemType>(() => {\n return specDescriptor.value.folder ?? 'input'\n})\nconst defaultLayoutMode = computed<LayoutMode>(() => {\n return isAssetMode.value ? 'list' : 'grid'\n})\n</script>\n"],"names":["useTransformCompatOverlayProps","overrides","computed","__name","props","__props","modelValue","_useModel","transformCompatProps","selectOptions","options","invalid","combinedProps","filterWidgetProps","PANEL_EXCLUDED_PROPS","emit","__emit","selectedItems","item","theButtonStyle","cn","resetInputStyle","layoutSwitchItemStyle","layoutMode","searchQuery","sortSelected","actionButtonStyle","sortPopoverRef","useTemplateRef","sortTriggerRef","isSortPopoverOpen","ref","toggleSortPopover","event","closeSortPopover","handleSortSelected","filterSelected","isUploadButtonEnabled","showUploadDialog","useModelUpload","singleFilterOption","AssetKindKey","actualDimensions","assetKind","inject","isVideo","handleClick","handleImageLoad","img","handleVideoLoad","video","defaultSearcher","query","items","words","name","word","getDefaultSortOptions","a","b","selected","files","debouncedSearchQuery","refDebounced","isQuerying","toastStore","useToastStore","popoverRef","triggerRef","isOpen","maxSelectable","filteredItems","watch","value","_","__","onCleanup","isCleanup","cleanupFn","cb","result","defaultSorter","option","selectedSorter","sortedItems","internalIsSelected","index","toggleDropdown","closeDropdown","handleFileChange","input","handleSelection","sel","useAssetWidgetData","nodeType","provide","queueStore","useQueueStore","assetData","toRef","filterOptions","categoryName","capitalize","selectedSet","getDisplayLabel","getOptionLabel","e","inputItems","values","getMediaUrl","outputItems","outputs","task","output","isTargetType","annotatedPath","allItems","dropdownItems","mediaPlaceholder","t","uploadable","acceptTypes","currentValue","_dropdownItems","updateSelectedItems","id","uploadFile","file","isPasted","formFields","body","resp","api","data","useAssetsStore","uploadFiles","folder","uploadPromises","path","handleFilesUpdate","uploadedPaths","error","filename","type","comboSpec","isComboInputSpec","specDescriptor","spec","image_upload","animated_image_upload","video_upload","image_folder","audio_upload","kind","isAssetMode","isDropdownUIWidget","allowUpload","uploadFolder","defaultLayoutMode"],"mappings":"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"}
|
comfyui_frontend_package/static/assets/{WidgetTextarea-CZnqW4e_.js → WidgetTextarea-CwUMJ-23.js}
RENAMED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{bx as m,cM as f,cN as g,E as r,ec as w,j as c,d as C,k as y,z as P,e as V,by as o,m as b,I as s,u as v,s as B}from"./vendor-other-CSX7WseZ.js";import{a9 as I,B as M}from"./vendor-primevue-B6rcS73U.js";import{c as d}from"./index-
|
|
2
|
-
//# sourceMappingURL=WidgetTextarea-
|
|
1
|
+
import{bx as m,cM as f,cN as g,E as r,ec as w,j as c,d as C,k as y,z as P,e as V,by as o,m as b,I as s,u as v,s as B}from"./vendor-other-CSX7WseZ.js";import{a9 as I,B as M}from"./vendor-primevue-B6rcS73U.js";import{c as d}from"./index-CuKlxAeN.js";import{f as N,I as h}from"./widgetPropFilter-CygYoMQt.js";import{W as k}from"./index-DEqR9lwu.js";import"./vendor-vue-CXt3ZZQ3.js";import"./vendor-xterm-CWYFmgbN.js";import"./vendor-three-29bN5sfh.js";import"./vendor-tiptap-BkFTmTb3.js";const x=["for"],O=m({__name:"WidgetTextarea",props:f({widget:{},placeholder:{default:""}},{modelValue:{default:""},modelModifiers:{}}),emits:["update:modelValue"],setup(t){const l=g(t,"modelValue"),n=r(()=>N(t.widget.options,h)),u=r(()=>t.widget.label||t.widget.name),i=w();return(a,e)=>(C(),c(o(M),{variant:"in",class:B(o(d)("rounded-lg space-y-1 focus-within:ring focus-within:ring-component-node-widget-background-highlighted transition-all",a.widget.borderStyle))},{default:y(()=>[P(o(I),b(n.value,{id:o(i),modelValue:l.value,"onUpdate:modelValue":e[0]||(e[0]=p=>l.value=p),class:o(d)(o(k),"size-full text-xs resize-none"),placeholder:a.placeholder,readonly:a.widget.options?.read_only,disabled:a.widget.options?.read_only,fluid:"","data-capture-wheel":"true",onPointerdownCapture:e[1]||(e[1]=s(()=>{},["stop"])),onPointermoveCapture:e[2]||(e[2]=s(()=>{},["stop"])),onPointerupCapture:e[3]||(e[3]=s(()=>{},["stop"])),onContextmenuCapture:e[4]||(e[4]=s(()=>{},["stop"]))}),null,16,["id","modelValue","class","placeholder","readonly","disabled"]),V("label",{for:o(i)},v(u.value),9,x)]),_:1},8,["class"]))}});export{O as default};
|
|
2
|
+
//# sourceMappingURL=WidgetTextarea-CwUMJ-23.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WidgetTextarea-
|
|
1
|
+
{"version":3,"file":"WidgetTextarea-CwUMJ-23.js","sources":["../../src/renderer/extensions/vueNodes/widgets/components/WidgetTextarea.vue"],"sourcesContent":["<template>\n <FloatLabel\n variant=\"in\"\n :class=\"\n cn(\n 'rounded-lg space-y-1 focus-within:ring focus-within:ring-component-node-widget-background-highlighted transition-all',\n widget.borderStyle\n )\n \"\n >\n <Textarea\n v-bind=\"filteredProps\"\n :id\n v-model=\"modelValue\"\n :class=\"cn(WidgetInputBaseClass, 'size-full text-xs resize-none')\"\n :placeholder\n :readonly=\"widget.options?.read_only\"\n :disabled=\"widget.options?.read_only\"\n fluid\n data-capture-wheel=\"true\"\n @pointerdown.capture.stop\n @pointermove.capture.stop\n @pointerup.capture.stop\n @contextmenu.capture.stop\n />\n <label :for=\"id\">{{ displayName }}</label>\n </FloatLabel>\n</template>\n\n<script setup lang=\"ts\">\nimport FloatLabel from 'primevue/floatlabel'\nimport Textarea from 'primevue/textarea'\nimport { computed, useId } from 'vue'\n\nimport type { SimplifiedWidget } from '@/types/simplifiedWidget'\nimport { cn } from '@/utils/tailwindUtil'\nimport {\n INPUT_EXCLUDED_PROPS,\n filterWidgetProps\n} from '@/utils/widgetPropFilter'\n\nimport { WidgetInputBaseClass } from './layout'\n\nconst { widget, placeholder = '' } = defineProps<{\n widget: SimplifiedWidget<string>\n placeholder?: string\n}>()\n\nconst modelValue = defineModel<string>({ default: '' })\n\nconst filteredProps = computed(() =>\n filterWidgetProps(widget.options, INPUT_EXCLUDED_PROPS)\n)\n\nconst displayName = computed(() => widget.label || widget.name)\nconst id = useId()\n</script>\n"],"names":["modelValue","_useModel","__props","filteredProps","computed","filterWidgetProps","INPUT_EXCLUDED_PROPS","displayName","id","useId"],"mappings":"ipBAgDA,MAAMA,EAAaC,EAAmBC,EAAA,YAAgB,EAEhDC,EAAgBC,EAAS,IAC7BC,EAAkBH,EAAA,OAAO,QAASI,CAAoB,CAAA,EAGlDC,EAAcH,EAAS,IAAMF,EAAA,OAAO,OAASA,SAAO,IAAI,EACxDM,EAAKC,EAAA"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{L as r}from"./vendor-primevue-B6rcS73U.js";import{f as s,S as i}from"./widgetPropFilter-CygYoMQt.js";import{_ as d}from"./WidgetLayoutField.vue_vue_type_script_setup_true_lang-
|
|
2
|
-
//# sourceMappingURL=WidgetToggleSwitch-
|
|
1
|
+
import{L as r}from"./vendor-primevue-B6rcS73U.js";import{f as s,S as i}from"./widgetPropFilter-CygYoMQt.js";import{_ as d}from"./WidgetLayoutField.vue_vue_type_script_setup_true_lang-CZj3E4v6.js";import{bx as p,cM as u,cN as n,E as f,j as c,d as g,k as w,z as V,by as _,m as b}from"./vendor-other-CSX7WseZ.js";import"./index-CuKlxAeN.js";import"./vendor-vue-CXt3ZZQ3.js";import"./vendor-xterm-CWYFmgbN.js";import"./vendor-three-29bN5sfh.js";import"./vendor-tiptap-BkFTmTb3.js";const N=p({__name:"WidgetToggleSwitch",props:u({widget:{}},{modelValue:{type:Boolean},modelModifiers:{}}),emits:["update:modelValue"],setup(e){const o=n(e,"modelValue"),l=f(()=>s(e.widget.options,i));return(a,t)=>(g(),c(d,{widget:a.widget},{default:w(()=>[V(_(r),b({modelValue:o.value,"onUpdate:modelValue":t[0]||(t[0]=m=>o.value=m)},l.value,{class:"ml-auto block","aria-label":a.widget.name}),null,16,["modelValue","aria-label"])]),_:1},8,["widget"]))}});export{N as default};
|
|
2
|
+
//# sourceMappingURL=WidgetToggleSwitch-DqQpfrDq.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WidgetToggleSwitch-
|
|
1
|
+
{"version":3,"file":"WidgetToggleSwitch-DqQpfrDq.js","sources":["../../src/renderer/extensions/vueNodes/widgets/components/WidgetToggleSwitch.vue"],"sourcesContent":["<template>\n <WidgetLayoutField :widget>\n <ToggleSwitch\n v-model=\"modelValue\"\n v-bind=\"filteredProps\"\n class=\"ml-auto block\"\n :aria-label=\"widget.name\"\n />\n </WidgetLayoutField>\n</template>\n\n<script setup lang=\"ts\">\nimport ToggleSwitch from 'primevue/toggleswitch'\nimport { computed } from 'vue'\n\nimport type { SimplifiedWidget } from '@/types/simplifiedWidget'\nimport {\n STANDARD_EXCLUDED_PROPS,\n filterWidgetProps\n} from '@/utils/widgetPropFilter'\n\nimport WidgetLayoutField from './layout/WidgetLayoutField.vue'\n\nconst { widget } = defineProps<{\n widget: SimplifiedWidget<boolean>\n}>()\n\nconst modelValue = defineModel<boolean>()\n\nconst filteredProps = computed(() =>\n filterWidgetProps(widget.options, STANDARD_EXCLUDED_PROPS)\n)\n</script>\n"],"names":["modelValue","_useModel","__props","filteredProps","computed","filterWidgetProps","STANDARD_EXCLUDED_PROPS"],"mappings":"4mBA2BA,MAAMA,EAAaC,EAAoBC,EAAA,YAAC,EAElCC,EAAgBC,EAAS,IAC7BC,EAAkBH,SAAO,QAASI,CAAuB,CAAA"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./ValueControlPopover-
|
|
2
|
-
var v=Object.defineProperty;var d=(o,s)=>v(o,"name",{value:s,configurable:!0});import{_ as V}from"./vendor-primevue-B6rcS73U.js";import{bx as _,cM as w,cN as x,r as u,E as C,w as b,c as M,d as c,j as P,z as m,t as h,m as k,k as p,I as y,e as B,s as z,by as E,dt as W}from"./vendor-other-CSX7WseZ.js";import{_ as I}from"./index-
|
|
3
|
-
//# sourceMappingURL=WidgetWithControl.vue_vue_type_script_setup_true_lang-
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./ValueControlPopover-CZIsPw9J.js","./vendor-primevue-B6rcS73U.js","./vendor-other-CSX7WseZ.js","./vendor-other-DYX1NpEr.css","./index-CuKlxAeN.js","./vendor-vue-CXt3ZZQ3.js","./vendor-xterm-CWYFmgbN.js","./vendor-xterm-xj0gfbX3.css","./vendor-three-29bN5sfh.js","./vendor-tiptap-BkFTmTb3.js","./index-Cv1aHIoL.css"])))=>i.map(i=>d[i]);
|
|
2
|
+
var v=Object.defineProperty;var d=(o,s)=>v(o,"name",{value:s,configurable:!0});import{_ as V}from"./vendor-primevue-B6rcS73U.js";import{bx as _,cM as w,cN as x,r as u,E as C,w as b,c as M,d as c,j as P,z as m,t as h,m as k,k as p,I as y,e as B,s as z,by as E,dt as W}from"./vendor-other-CSX7WseZ.js";import{_ as I}from"./index-CuKlxAeN.js";const N={class:"relative grid grid-cols-subgrid"},j=_({__name:"WidgetWithControl",props:w({widget:{},component:{}},{modelValue:{},modelModifiers:{}}),emits:["update:modelValue"],setup(o){const s=W(()=>V(()=>import("./ValueControlPopover-CZIsPw9J.js"),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10]),import.meta.url)),n=o,r=x(o,"modelValue"),i=u(),t=u(n.widget.controlWidget.value),f=C(()=>{switch(t.value){case"increment":return"pi pi-plus";case"decrement":return"pi pi-minus";case"fixed":return"icon-[lucide--pencil-off]";default:return"icon-[lucide--shuffle]"}});b(t,n.widget.controlWidget.update);const g=d(e=>{i.value.toggle(e)},"togglePopover");return(e,l)=>(c(),M("div",N,[(c(),P(h(e.component),k(e.$attrs,{modelValue:r.value,"onUpdate:modelValue":l[0]||(l[0]=a=>r.value=a),widget:e.widget}),{default:p(()=>[m(I,{variant:"textonly",size:"sm",class:"h-4 w-7 self-center rounded-xl bg-blue-100/30 p-0",onPointerdown:y(g,["stop","prevent"])},{default:p(()=>[B("i",{class:z(`${f.value} text-blue-100 text-xs size-3.5`)},null,2)]),_:1})]),_:1},16,["modelValue","widget"])),m(E(s),{ref_key:"popover",ref:i,modelValue:t.value,"onUpdate:modelValue":l[1]||(l[1]=a=>t.value=a)},null,8,["modelValue"])]))}});export{j as _};
|
|
3
|
+
//# sourceMappingURL=WidgetWithControl.vue_vue_type_script_setup_true_lang-JSl33v3j.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"mappings":";+gBAUA,MAAMA,EAAsBC,EAC1B,IAAAC,EAAA,IAAM,OAAO,mCAA2B,8DAGpCC,EAAQC,EAKRC,EAAaC,EAAcF,EAAA,YAAC,EAE5BG,EAAUC,EAAA,EAEVC,EAAeD,EAAIL,EAAM,OAAO,cAAc,KAAK,EAEnDO,EAAoBC,EAAS,IAAM,CACvC,OAAQF,EAAa,OACnB,IAAK,YACH,MAAO,aACT,IAAK,YACH,MAAO,cACT,IAAK,QACH,MAAO,4BACT,QACE,MAAO,yBAEb,CAAC,EAEDG,EAAMH,EAAcN,EAAM,OAAO,cAAc,MAAM,EAErD,MAAMU,EAAgBC,EAACC,GAAiB,CACtCR,EAAQ,MAAM,OAAOQ,CAAK,CAC5B,EAFsB","names":["ValueControlPopover","defineAsyncComponent","__vitePreload","props","__props","modelValue","_useModel","popover","ref","controlModel","controlButtonIcon","computed","watch","togglePopover","__name","event"],"ignoreList":[],"sources":["../../src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vue"],"sourcesContent":["<script setup lang=\"ts\" generic=\"T extends WidgetValue\">\nimport { computed, defineAsyncComponent, ref, watch } from 'vue'\nimport type { Component } from 'vue'\n\nimport Button from '@/components/ui/button/Button.vue'\nimport type {\n SimplifiedControlWidget,\n WidgetValue\n} from '@/types/simplifiedWidget'\n\nconst ValueControlPopover = defineAsyncComponent(\n () => import('./ValueControlPopover.vue')\n)\n\nconst props = defineProps<{\n widget: SimplifiedControlWidget<T>\n component: Component\n}>()\n\nconst modelValue = defineModel<T>()\n\nconst popover = ref()\n\nconst controlModel = ref(props.widget.controlWidget.value)\n\nconst controlButtonIcon = computed(() => {\n switch (controlModel.value) {\n case 'increment':\n return 'pi pi-plus'\n case 'decrement':\n return 'pi pi-minus'\n case 'fixed':\n return 'icon-[lucide--pencil-off]'\n default:\n return 'icon-[lucide--shuffle]'\n }\n})\n\nwatch(controlModel, props.widget.controlWidget.update)\n\nconst togglePopover = (event: Event) => {\n popover.value.toggle(event)\n}\n</script>\n\n<template>\n <div class=\"relative grid grid-cols-subgrid\">\n <component :is=\"component\" v-bind=\"$attrs\" v-model=\"modelValue\" :widget>\n <Button\n variant=\"textonly\"\n size=\"sm\"\n class=\"h-4 w-7 self-center rounded-xl bg-blue-100/30 p-0\"\n @pointerdown.stop.prevent=\"togglePopover\"\n >\n <i :class=\"`${controlButtonIcon} text-blue-100 text-xs size-3.5`\" />\n </Button>\n </component>\n <ValueControlPopover ref=\"popover\" v-model=\"controlModel\" />\n </div>\n</template>\n"],"file":"WidgetWithControl.vue_vue_type_script_setup_true_lang-
|
|
1
|
+
{"version":3,"mappings":";+gBAUA,MAAMA,EAAsBC,EAC1B,IAAAC,EAAA,IAAM,OAAO,mCAA2B,8DAGpCC,EAAQC,EAKRC,EAAaC,EAAcF,EAAA,YAAC,EAE5BG,EAAUC,EAAA,EAEVC,EAAeD,EAAIL,EAAM,OAAO,cAAc,KAAK,EAEnDO,EAAoBC,EAAS,IAAM,CACvC,OAAQF,EAAa,OACnB,IAAK,YACH,MAAO,aACT,IAAK,YACH,MAAO,cACT,IAAK,QACH,MAAO,4BACT,QACE,MAAO,yBAEb,CAAC,EAEDG,EAAMH,EAAcN,EAAM,OAAO,cAAc,MAAM,EAErD,MAAMU,EAAgBC,EAACC,GAAiB,CACtCR,EAAQ,MAAM,OAAOQ,CAAK,CAC5B,EAFsB","names":["ValueControlPopover","defineAsyncComponent","__vitePreload","props","__props","modelValue","_useModel","popover","ref","controlModel","controlButtonIcon","computed","watch","togglePopover","__name","event"],"ignoreList":[],"sources":["../../src/renderer/extensions/vueNodes/widgets/components/WidgetWithControl.vue"],"sourcesContent":["<script setup lang=\"ts\" generic=\"T extends WidgetValue\">\nimport { computed, defineAsyncComponent, ref, watch } from 'vue'\nimport type { Component } from 'vue'\n\nimport Button from '@/components/ui/button/Button.vue'\nimport type {\n SimplifiedControlWidget,\n WidgetValue\n} from '@/types/simplifiedWidget'\n\nconst ValueControlPopover = defineAsyncComponent(\n () => import('./ValueControlPopover.vue')\n)\n\nconst props = defineProps<{\n widget: SimplifiedControlWidget<T>\n component: Component\n}>()\n\nconst modelValue = defineModel<T>()\n\nconst popover = ref()\n\nconst controlModel = ref(props.widget.controlWidget.value)\n\nconst controlButtonIcon = computed(() => {\n switch (controlModel.value) {\n case 'increment':\n return 'pi pi-plus'\n case 'decrement':\n return 'pi pi-minus'\n case 'fixed':\n return 'icon-[lucide--pencil-off]'\n default:\n return 'icon-[lucide--shuffle]'\n }\n})\n\nwatch(controlModel, props.widget.controlWidget.update)\n\nconst togglePopover = (event: Event) => {\n popover.value.toggle(event)\n}\n</script>\n\n<template>\n <div class=\"relative grid grid-cols-subgrid\">\n <component :is=\"component\" v-bind=\"$attrs\" v-model=\"modelValue\" :widget>\n <Button\n variant=\"textonly\"\n size=\"sm\"\n class=\"h-4 w-7 self-center rounded-xl bg-blue-100/30 p-0\"\n @pointerdown.stop.prevent=\"togglePopover\"\n >\n <i :class=\"`${controlButtonIcon} text-blue-100 text-xs size-3.5`\" />\n </Button>\n </component>\n <ValueControlPopover ref=\"popover\" v-model=\"controlModel\" />\n </div>\n</template>\n"],"file":"WidgetWithControl.vue_vue_type_script_setup_true_lang-JSl33v3j.js"}
|
comfyui_frontend_package/static/assets/{audioService-Bh6LQBV8.js → audioService-DKN4T_Yr.js}
RENAMED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var p=Object.defineProperty;var r=(s,c)=>p(s,"name",{value:c,configurable:!0});import{eH as l,eI as u}from"./vendor-other-CSX7WseZ.js";import{a as m,f}from"./index-
|
|
2
|
-
//# sourceMappingURL=audioService-
|
|
1
|
+
var p=Object.defineProperty;var r=(s,c)=>p(s,"name",{value:c,configurable:!0});import{eH as l,eI as u}from"./vendor-other-CSX7WseZ.js";import{a as m,f}from"./index-CuKlxAeN.js";let i=!1;const T=r(()=>{const s=r((e,o,n)=>{console.error(`Audio Service Error (${e}):`,o,n)},"handleError");return{convertBlobToFileAndSubmit:r(async e=>{const o=`recording-${Date.now()}.wav`,n=new File([e],o,{type:e.type||"audio/wav"}),t=new FormData;t.append("image",n),t.append("subfolder","audio"),t.append("type","temp");const a=await m.fetchApi("/upload/image",{method:"POST",body:t});if(a.status!==200){const d=`Error uploading temp file: ${a.status} - ${a.statusText}`;throw f().addAlert(d),new Error(d)}return`audio/${(await a.json()).name} [temp]`},"convertBlobToFileAndSubmit"),registerWavEncoder:r(async()=>{if(!i)try{await l(await u()),i=!0}catch(e){e instanceof Error&&e.message.includes("already an encoder stored")?i=!0:s("encoder","Failed to register WAV encoder",e)}},"registerWavEncoder"),stopAllTracks:r(e=>{e&&(e.getTracks().forEach(o=>{o.stop()}),e=null)},"stopAllTracks")}},"useAudioService");export{T as u};
|
|
2
|
+
//# sourceMappingURL=audioService-DKN4T_Yr.js.map
|