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.
Files changed (127) hide show
  1. comfyui_frontend_package/static/assets/AboutPanel-BwfERTOT.js +2 -0
  2. comfyui_frontend_package/static/assets/{AboutPanel-6wNn9DuA.js.map → AboutPanel-BwfERTOT.js.map} +1 -1
  3. comfyui_frontend_package/static/assets/{AudioPreviewPlayer-ybC6cXRM.js → AudioPreviewPlayer-DT9nrYD6.js} +2 -2
  4. comfyui_frontend_package/static/assets/{AudioPreviewPlayer-ybC6cXRM.js.map → AudioPreviewPlayer-DT9nrYD6.js.map} +1 -1
  5. comfyui_frontend_package/static/assets/ComfyQueueButton-DazIfwpa.js +2 -0
  6. comfyui_frontend_package/static/assets/{ComfyQueueButton-BbIk3ALi.js.map → ComfyQueueButton-DazIfwpa.js.map} +1 -1
  7. comfyui_frontend_package/static/assets/ExtensionPanel-D539Wx81.js +2 -0
  8. comfyui_frontend_package/static/assets/{ExtensionPanel-DYw7d35v.js.map → ExtensionPanel-D539Wx81.js.map} +1 -1
  9. comfyui_frontend_package/static/assets/GraphView-C_FQc1Au.js +16 -0
  10. comfyui_frontend_package/static/assets/GraphView-C_FQc1Au.js.map +1 -0
  11. comfyui_frontend_package/static/assets/{GraphView-DwAYVX4H.css → GraphView-Ck9hVEEV.css} +1 -1
  12. comfyui_frontend_package/static/assets/{KeybindingPanel-D0MD69FX.js → KeybindingPanel-Bj61UMoX.js} +2 -2
  13. comfyui_frontend_package/static/assets/{KeybindingPanel-D0MD69FX.js.map → KeybindingPanel-Bj61UMoX.js.map} +1 -1
  14. comfyui_frontend_package/static/assets/LazyImage.vue_vue_type_script_setup_true_lang-DyOiHvnA.js +2 -0
  15. comfyui_frontend_package/static/assets/LazyImage.vue_vue_type_script_setup_true_lang-DyOiHvnA.js.map +1 -0
  16. comfyui_frontend_package/static/assets/LegacyCreditsPanel-BNqPlgUn.js +2 -0
  17. comfyui_frontend_package/static/assets/{LegacyCreditsPanel-BMvul305.js.map → LegacyCreditsPanel-BNqPlgUn.js.map} +1 -1
  18. comfyui_frontend_package/static/assets/Load3D-CaNKqgIL.js +2 -0
  19. comfyui_frontend_package/static/assets/Load3D-CaNKqgIL.js.map +1 -0
  20. 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
  21. 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
  22. comfyui_frontend_package/static/assets/{Media3DBottom-Bk7TM-zH.js → Media3DBottom-D9M9b2ls.js} +2 -2
  23. comfyui_frontend_package/static/assets/{Media3DBottom-Bk7TM-zH.js.map → Media3DBottom-D9M9b2ls.js.map} +1 -1
  24. comfyui_frontend_package/static/assets/{Media3DTop-CIsQ4Ccc.js → Media3DTop-B-qNqlQF.js} +2 -2
  25. comfyui_frontend_package/static/assets/{Media3DTop-CIsQ4Ccc.js.map → Media3DTop-B-qNqlQF.js.map} +1 -1
  26. comfyui_frontend_package/static/assets/{MediaAudioBottom-CWxtJ5vP.js → MediaAudioBottom-d7EZ2Wx5.js} +2 -2
  27. comfyui_frontend_package/static/assets/{MediaAudioBottom-CWxtJ5vP.js.map → MediaAudioBottom-d7EZ2Wx5.js.map} +1 -1
  28. comfyui_frontend_package/static/assets/{MediaImageBottom-OWiMf_6W.js → MediaImageBottom-B-9SOOhn.js} +2 -2
  29. comfyui_frontend_package/static/assets/{MediaImageBottom-OWiMf_6W.js.map → MediaImageBottom-B-9SOOhn.js.map} +1 -1
  30. 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
  31. 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
  32. comfyui_frontend_package/static/assets/{MediaVideoBottom-OKuLWTbn.js → MediaVideoBottom-D6IR52ja.js} +2 -2
  33. comfyui_frontend_package/static/assets/{MediaVideoBottom-OKuLWTbn.js.map → MediaVideoBottom-D6IR52ja.js.map} +1 -1
  34. comfyui_frontend_package/static/assets/{ServerConfigPanel-5RPRkuvl.js → ServerConfigPanel-BBWOQ7ej.js} +2 -2
  35. comfyui_frontend_package/static/assets/{ServerConfigPanel-5RPRkuvl.js.map → ServerConfigPanel-BBWOQ7ej.js.map} +1 -1
  36. comfyui_frontend_package/static/assets/{SubscriptionRequiredDialogContent-CtCWM_jj.js → SubscriptionRequiredDialogContent-oUSDZGJZ.js} +2 -2
  37. comfyui_frontend_package/static/assets/{SubscriptionRequiredDialogContent-CtCWM_jj.js.map → SubscriptionRequiredDialogContent-oUSDZGJZ.js.map} +1 -1
  38. comfyui_frontend_package/static/assets/{UserPanel-CrxHTRQZ.js → UserPanel-Do_alb49.js} +2 -2
  39. comfyui_frontend_package/static/assets/{UserPanel-CrxHTRQZ.js.map → UserPanel-Do_alb49.js.map} +1 -1
  40. comfyui_frontend_package/static/assets/{UserSelectView-tu0lXAri.js → UserSelectView-DVJzD33o.js} +2 -2
  41. comfyui_frontend_package/static/assets/{UserSelectView-tu0lXAri.js.map → UserSelectView-DVJzD33o.js.map} +1 -1
  42. comfyui_frontend_package/static/assets/{ValueControlPopover-CgyNfIEw.js → ValueControlPopover-CZIsPw9J.js} +2 -2
  43. comfyui_frontend_package/static/assets/{ValueControlPopover-CgyNfIEw.js.map → ValueControlPopover-CZIsPw9J.js.map} +1 -1
  44. comfyui_frontend_package/static/assets/WidgetAudioUI-CbC597q0.js +2 -0
  45. comfyui_frontend_package/static/assets/{WidgetAudioUI-BZL35TlT.js.map → WidgetAudioUI-CbC597q0.js.map} +1 -1
  46. comfyui_frontend_package/static/assets/{WidgetButton-Dkge0J8R.js → WidgetButton-Df2ihQh6.js} +2 -2
  47. comfyui_frontend_package/static/assets/{WidgetButton-Dkge0J8R.js.map → WidgetButton-Df2ihQh6.js.map} +1 -1
  48. comfyui_frontend_package/static/assets/{WidgetColorPicker-vRHta_Kz.js → WidgetColorPicker-DgI8RjHJ.js} +2 -2
  49. comfyui_frontend_package/static/assets/{WidgetColorPicker-vRHta_Kz.js.map → WidgetColorPicker-DgI8RjHJ.js.map} +1 -1
  50. comfyui_frontend_package/static/assets/{WidgetGalleria-BoWBT6i_.js → WidgetGalleria-Cyz9lzP-.js} +2 -2
  51. comfyui_frontend_package/static/assets/{WidgetGalleria-BoWBT6i_.js.map → WidgetGalleria-Cyz9lzP-.js.map} +1 -1
  52. comfyui_frontend_package/static/assets/WidgetInputNumber-wD2uHC32.js +2 -0
  53. comfyui_frontend_package/static/assets/WidgetInputNumber-wD2uHC32.js.map +1 -0
  54. 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
  55. 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
  56. comfyui_frontend_package/static/assets/{WidgetInputText-BRV8PzCv.js → WidgetInputText-BR3C0fCV.js} +2 -2
  57. comfyui_frontend_package/static/assets/{WidgetInputText-BRV8PzCv.js.map → WidgetInputText-BR3C0fCV.js.map} +1 -1
  58. 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
  59. 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
  60. comfyui_frontend_package/static/assets/WidgetLegacy-CkV176Xm.js +2 -0
  61. comfyui_frontend_package/static/assets/WidgetLegacy-CkV176Xm.js.map +1 -0
  62. comfyui_frontend_package/static/assets/WidgetMarkdown-rM_UPCA-.js +2 -0
  63. comfyui_frontend_package/static/assets/{WidgetMarkdown-DIMd79hN.js.map → WidgetMarkdown-rM_UPCA-.js.map} +1 -1
  64. comfyui_frontend_package/static/assets/{WidgetRecordAudio-DwHSqiBz.js → WidgetRecordAudio-CLpvV8e9.js} +2 -2
  65. comfyui_frontend_package/static/assets/{WidgetRecordAudio-DwHSqiBz.js.map → WidgetRecordAudio-CLpvV8e9.js.map} +1 -1
  66. comfyui_frontend_package/static/assets/WidgetSelect-BwcPw-lE.js +2 -0
  67. comfyui_frontend_package/static/assets/WidgetSelect-BwcPw-lE.js.map +1 -0
  68. 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
  69. 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
  70. comfyui_frontend_package/static/assets/{WidgetTextarea-CZnqW4e_.js → WidgetTextarea-CwUMJ-23.js} +2 -2
  71. comfyui_frontend_package/static/assets/{WidgetTextarea-CZnqW4e_.js.map → WidgetTextarea-CwUMJ-23.js.map} +1 -1
  72. comfyui_frontend_package/static/assets/{WidgetToggleSwitch-DwYqmS17.js → WidgetToggleSwitch-DqQpfrDq.js} +2 -2
  73. comfyui_frontend_package/static/assets/{WidgetToggleSwitch-DwYqmS17.js.map → WidgetToggleSwitch-DqQpfrDq.js.map} +1 -1
  74. 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
  75. 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
  76. comfyui_frontend_package/static/assets/{audioService-Bh6LQBV8.js → audioService-DKN4T_Yr.js} +2 -2
  77. comfyui_frontend_package/static/assets/{audioService-Bh6LQBV8.js.map → audioService-DKN4T_Yr.js.map} +1 -1
  78. comfyui_frontend_package/static/assets/{audioUtils-DlA-QHPJ.js → audioUtils-WBbpBG9r.js} +2 -2
  79. comfyui_frontend_package/static/assets/{audioUtils-DlA-QHPJ.js.map → audioUtils-WBbpBG9r.js.map} +1 -1
  80. comfyui_frontend_package/static/assets/{commands-CHktpNSL.js → commands-CRVPkENB.js} +2 -2
  81. comfyui_frontend_package/static/assets/commands-CRVPkENB.js.map +1 -0
  82. comfyui_frontend_package/static/assets/{index-2-qFLlQP.js → index-CuKlxAeN.js} +30 -28
  83. comfyui_frontend_package/static/assets/index-CuKlxAeN.js.map +1 -0
  84. comfyui_frontend_package/static/assets/index-Cv1aHIoL.css +1 -0
  85. comfyui_frontend_package/static/assets/{index-_AAd9eTu.js → index-DEqR9lwu.js} +2 -2
  86. comfyui_frontend_package/static/assets/{index-_AAd9eTu.js.map → index-DEqR9lwu.js.map} +1 -1
  87. comfyui_frontend_package/static/assets/index-KizWjI6s.js +5 -0
  88. comfyui_frontend_package/static/assets/{index-DKofvZ3r.js.map → index-KizWjI6s.js.map} +1 -1
  89. comfyui_frontend_package/static/assets/{keybindingService-CWbdWLPI.js → keybindingService-O5KDQleT.js} +2 -2
  90. comfyui_frontend_package/static/assets/{keybindingService-CWbdWLPI.js.map → keybindingService-O5KDQleT.js.map} +1 -1
  91. comfyui_frontend_package/static/assets/main-10VBfKWj.js +14 -0
  92. comfyui_frontend_package/static/assets/main-10VBfKWj.js.map +1 -0
  93. comfyui_frontend_package/static/assets/nodeDefs-D9VHUZJt.js +53 -0
  94. comfyui_frontend_package/static/assets/nodeDefs-D9VHUZJt.js.map +1 -0
  95. comfyui_frontend_package/static/assets/{vendor-three-BKWXAgVe.js → vendor-three-29bN5sfh.js} +2 -2
  96. comfyui_frontend_package/static/assets/{vendor-three-BKWXAgVe.js.map → vendor-three-29bN5sfh.js.map} +1 -1
  97. comfyui_frontend_package/static/index.html +1 -1
  98. {comfyui_frontend_package-1.37.3.dist-info → comfyui_frontend_package-1.37.4.dist-info}/METADATA +1 -1
  99. {comfyui_frontend_package-1.37.3.dist-info → comfyui_frontend_package-1.37.4.dist-info}/RECORD +101 -101
  100. comfyui_frontend_package/static/assets/AboutPanel-6wNn9DuA.js +0 -2
  101. comfyui_frontend_package/static/assets/ComfyQueueButton-BbIk3ALi.js +0 -2
  102. comfyui_frontend_package/static/assets/ExtensionPanel-DYw7d35v.js +0 -2
  103. comfyui_frontend_package/static/assets/GraphView-CjDjhvN7.js +0 -16
  104. comfyui_frontend_package/static/assets/GraphView-CjDjhvN7.js.map +0 -1
  105. comfyui_frontend_package/static/assets/LazyImage.vue_vue_type_script_setup_true_lang-CcI-aYhS.js +0 -2
  106. comfyui_frontend_package/static/assets/LazyImage.vue_vue_type_script_setup_true_lang-CcI-aYhS.js.map +0 -1
  107. comfyui_frontend_package/static/assets/LegacyCreditsPanel-BMvul305.js +0 -2
  108. comfyui_frontend_package/static/assets/Load3D-BplYUML3.js +0 -2
  109. comfyui_frontend_package/static/assets/Load3D-BplYUML3.js.map +0 -1
  110. comfyui_frontend_package/static/assets/WidgetAudioUI-BZL35TlT.js +0 -2
  111. comfyui_frontend_package/static/assets/WidgetInputNumber-DMqIMaoH.js +0 -2
  112. comfyui_frontend_package/static/assets/WidgetInputNumber-DMqIMaoH.js.map +0 -1
  113. comfyui_frontend_package/static/assets/WidgetLegacy-BWDBwsli.js +0 -2
  114. comfyui_frontend_package/static/assets/WidgetLegacy-BWDBwsli.js.map +0 -1
  115. comfyui_frontend_package/static/assets/WidgetMarkdown-DIMd79hN.js +0 -2
  116. comfyui_frontend_package/static/assets/WidgetSelect-BOvzWMtV.js +0 -2
  117. comfyui_frontend_package/static/assets/WidgetSelect-BOvzWMtV.js.map +0 -1
  118. comfyui_frontend_package/static/assets/commands-CHktpNSL.js.map +0 -1
  119. comfyui_frontend_package/static/assets/index-2-qFLlQP.js.map +0 -1
  120. comfyui_frontend_package/static/assets/index-571Fkv7y.css +0 -1
  121. comfyui_frontend_package/static/assets/index-DKofvZ3r.js +0 -5
  122. comfyui_frontend_package/static/assets/main-DGOENlHZ.js +0 -14
  123. comfyui_frontend_package/static/assets/main-DGOENlHZ.js.map +0 -1
  124. comfyui_frontend_package/static/assets/nodeDefs-DtmuHPr3.js +0 -53
  125. comfyui_frontend_package/static/assets/nodeDefs-DtmuHPr3.js.map +0 -1
  126. {comfyui_frontend_package-1.37.3.dist-info → comfyui_frontend_package-1.37.4.dist-info}/WHEEL +0 -0
  127. {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
- import{c as o}from"./index-2-qFLlQP.js";const e=o(["not-disabled:bg-component-node-widget-background","not-disabled:text-component-node-foreground","border-none","rounded-lg"]);export{e as W};
2
- //# sourceMappingURL=index-_AAd9eTu.js.map
1
+ import{c as o}from"./index-CuKlxAeN.js";const e=o(["not-disabled:bg-component-node-widget-background","not-disabled:text-component-node-foreground","border-none","rounded-lg"]);export{e as W};
2
+ //# sourceMappingURL=index-DEqR9lwu.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index-_AAd9eTu.js","sources":["../../src/renderer/extensions/vueNodes/widgets/components/layout/index.ts"],"sourcesContent":["import { cn } from '@/utils/tailwindUtil'\n\nexport const WidgetInputBaseClass = cn([\n // Background\n 'not-disabled:bg-component-node-widget-background',\n 'not-disabled:text-component-node-foreground',\n // Outline\n 'border-none',\n // Rounded\n 'rounded-lg'\n])\n"],"names":["WidgetInputBaseClass","cn"],"mappings":"wCAEO,MAAMA,EAAuBC,EAAG,CAErC,mDACA,8CAEA,cAEA,YACF,CAAC"}
1
+ {"version":3,"file":"index-DEqR9lwu.js","sources":["../../src/renderer/extensions/vueNodes/widgets/components/layout/index.ts"],"sourcesContent":["import { cn } from '@/utils/tailwindUtil'\n\nexport const WidgetInputBaseClass = cn([\n // Background\n 'not-disabled:bg-component-node-widget-background',\n 'not-disabled:text-component-node-foreground',\n // Outline\n 'border-none',\n // Rounded\n 'rounded-lg'\n])\n"],"names":["WidgetInputBaseClass","cn"],"mappings":"wCAEO,MAAMA,EAAuBC,EAAG,CAErC,mDACA,8CAEA,cAEA,YACF,CAAC"}
@@ -0,0 +1,5 @@
1
+ var at=Object.defineProperty;var u=(o,e)=>at(o,"name",{value:e,configurable:!0});import{r as p,cM as T,cN as Xe,cO as b,al as C,ap as R,cP as lt,ad as J,aJ as ee,cQ as dt,cR as ct,bo as Je,a7 as ut,w as pt,f as S,a0 as gt,t as D,p as te,cS as ft,cT as ht,cU as L,cV as P,a$ as mt,cW as be,cX as yt,cY as wt,cZ as vt,c_ as bt,c$ as Pe,d0 as oe,d1 as F,d2 as $,az as de,d3 as Ke,d4 as Nt,d5 as It,d6 as Ct,d7 as W,B as kt,a as E,D as Dt,d8 as xt,d9 as Qe,da as _t,av as Tt,aA as St,e as Z,db as V,cK as re,dc as Mt,cJ as ce,dd as ke,de as De,df as Et,u as Ze,cI as Ot,dg as et,dh as At,T as Le,di as Pt,c7 as Lt,dj as Gt,dk as Wt,dl as Rt,dm as Ft}from"./index-CuKlxAeN.js";import{bz as Ut,cD as Ge,d4 as H,n as xe,eF as Bt}from"./vendor-other-CSX7WseZ.js";import{_ as _e}from"./Load3D.vue_vue_type_script_setup_true_lang-gf2aN2_8.js";import{g as ue,s as tt}from"./audioUtils-WBbpBG9r.js";import{u as Q}from"./audioService-DKN4T_Yr.js";import"./vendor-primevue-B6rcS73U.js";import"./vendor-vue-CXt3ZZQ3.js";import"./vendor-xterm-CWYFmgbN.js";import"./vendor-three-29bN5sfh.js";import"./vendor-tiptap-BkFTmTb3.js";class M extends Xe{static{u(this,"ClipspaceDialog")}static items=[];static instance=null;static registerButton(e,t,s){const n=b("button",{type:"button",textContent:e,contextPredicate:t,onclick:s});M.items.push(n)}static invalidatePreview(){if(T.clipspace&&T.clipspace.imgs&&T.clipspace.imgs.length>0){const e=document.getElementById("clipspace_preview");e&&(e.src=T.clipspace.imgs[T.clipspace.selectedIndex].src,e.style.maxHeight="100%",e.style.maxWidth="100%")}}static invalidate(){if(M.instance){const e=M.instance,t=b("div.comfy-modal-content",[e.createImgSettings(),...e.createButtons()]);e.element?(e.element.firstChild&&e.element.removeChild(e.element.firstChild),e.element.appendChild(t)):e.element=b("div.comfy-modal",{parent:document.body},[t]),e.element.children[0].children.length<=1&&e.element.children[0].appendChild(b("p",{},["Unable to find the features to edit content of a format stored in the current Clipspace."])),M.invalidatePreview()}}constructor(){super()}createButtons(){const e=[];for(let t in M.items){const s=M.items[t];(!s.contextPredicate||s.contextPredicate())&&e.push(M.items[t])}return e.push(b("button",{type:"button",textContent:"Close",onclick:u(()=>{this.close()},"onclick")})),e}createImgSettings(){if(T.clipspace?.imgs){const e=[],t=T.clipspace.imgs;for(let d=0;d<t.length;d++)e.push(b("option",{value:d},[`${d}`]));const s=b("select",{id:"clipspace_img_selector",onchange:u(d=>{d.target&&T.clipspace&&(T.clipspace.selectedIndex=d.target.selectedIndex,M.invalidatePreview())},"onchange")},e),n=b("tr",{},[b("td",{},[b("font",{color:"white"},["Select Image"])]),b("td",{},[s])]),i=b("select",{id:"clipspace_img_paste_mode",onchange:u(d=>{d.target&&T.clipspace&&(T.clipspace.img_paste_mode=d.target.value)},"onchange")},[b("option",{value:"selected"},"selected"),b("option",{value:"all"},"all")]);i.value=T.clipspace.img_paste_mode;const r=b("tr",{},[b("td",{},[b("font",{color:"white"},["Paste Mode"])]),b("td",{},[i])]),a=b("td",{align:"center",width:"100px",height:"100px",colSpan:"2"},[b("img",{id:"clipspace_preview",ondragstart:u(()=>!1,"ondragstart")},[])]),l=b("tr",{},[a]);return b("table",{},[n,r,l])}else return[]}createImgPreview(){return T.clipspace?.imgs?b("img",{id:"clipspace_preview",ondragstart:u(()=>!1,"ondragstart")}):[]}show(){M.invalidate(),this.element.style.display="block"}}p.registerExtension({name:"Comfy.Clipspace",init(o){o.openClipspace=function(){M.instance||(M.instance=new M,T.clipspace_invalidate_handler=M.invalidate),T.clipspace?M.instance.show():o.ui.dialog.show("Clipspace is Empty!")}}});window.comfyAPI=window.comfyAPI||{};window.comfyAPI.clipspace=window.comfyAPI.clipspace||{};window.comfyAPI.clipspace.ClipspaceDialog=M;const Vt={name:"Comfy.ContextMenuFilter",init(){const o=C.ContextMenu;C.ContextMenu=function(e,t){const s=new o(e,t);if(t?.className==="dark"&&e?.length>4){const n=document.createElement("input");n.classList.add("comfy-context-menu-filter"),n.placeholder="Filter list",s.root.prepend(n);const i=Array.from(s.root.querySelectorAll(".litemenu-entry"));let r=[...i],a=r.length;requestAnimationFrame(()=>{const d=R.active_canvas.current_node?.widgets?.filter(h=>lt(h)&&h.options.values?.length===e.length).find(h=>h.options.values?.every((m,y)=>m===e[y]))?.value;let c=d?e.findIndex(h=>h===d):0;c<0&&(c=0);let f=r[c];v();function v(){f?.style.setProperty("background-color",""),f?.style.setProperty("color",""),f=r[c],f?.style.setProperty("background-color","#ccc","important"),f?.style.setProperty("color","#000","important")}u(v,"updateSelected");const g=u(()=>{if(s.root.getBoundingClientRect().top<0){const m=1-s.root.getBoundingClientRect().height/s.root.clientHeight,y=s.root.clientHeight*m/2;s.root.style.top=-y+"px"}},"positionList");n.addEventListener("keydown",h=>{switch(h.key){case"ArrowUp":h.preventDefault(),c===0?c=a-1:c--,v();break;case"ArrowRight":h.preventDefault(),c=a-1,v();break;case"ArrowDown":h.preventDefault(),c===a-1?c=0:c++,v();break;case"ArrowLeft":h.preventDefault(),c=0,v();break;case"Enter":f?.click();break;case"Escape":s.close();break}}),n.addEventListener("input",()=>{const h=n.value.toLocaleLowerCase();if(r=i.filter(m=>{const y=!h||m.textContent?.toLocaleLowerCase().includes(h);return m.style.display=y?"block":"none",y}),c=0,r.includes(f)&&(c=r.findIndex(m=>m===f)),a=r.length,v(),t.event){let m=t.event.clientY-10;const y=document.body.getBoundingClientRect(),w=s.root.getBoundingClientRect();y.height&&m>y.height-w.height-10&&(m=Math.max(0,y.height-w.height-10)),s.root.style.top=m+"px",g()}}),requestAnimationFrame(()=>{n.focus(),g()})})}return s},C.ContextMenu.prototype=o.prototype}};p.registerExtension(Vt);function $t(o=[]){if(!this.outputs[0].links?.length||!this.graph)return;const e=[...this.outputs[0].links.map(s=>this.graph.links[s]),...o];let t=this.widgets?.[0].value;for(const s of e){const n=this.graph?.getNodeById(s.target_id),i=n?.inputs[s.target_slot];if(!i){console.warn("Unable to resolve node or input for link",s);continue}const r=i.widget?.name;if(!r){console.warn("Invalid widget or widget name",i.widget);continue}const a=n.widgets?.find(l=>l.name===r);if(!a){console.warn(`Unable to find widget "${r}" on node [${n.id}]`);continue}a.value=t,a.callback?.(a.value,p.canvas,n,p.canvas.graph_mouse,{})}}u($t,"applyToGraph");function zt(){this.applyToGraph=J(this.applyToGraph,$t);const o=this.widgets[0],e=Ut([]);o.options.values=e;const t=u(()=>{e.splice(0,e.length,...this.widgets.filter(n=>n.name.startsWith("option")&&n.value).map(n=>`${n.value}`)),!p.configuringGraph&&(e.includes(`${o.value}`)||(o.value=e[0]??"",o.callback?.(o.value)))},"updateCombo");o.callback=J(o.callback,()=>this.applyToGraph());function s(n){if(!n.widgets)return;const i=n.widgets.length-1;n.addWidget("string",`option${i}`,"",()=>{});const r=n.widgets.at(-1);if(!r)return;let a="";Object.defineProperty(r,"value",{get(){return a},set(l){if(a=l,t(),!n.widgets)return;const d=n.widgets.at(-1);if(d===this){l&&s(n);return}l||n.widgets.at(-2)!==this||d?.value||(n.widgets.pop(),n.computeSize(n.size),this.callback(l))}})}u(s,"addOption"),s(this)}u(zt,"onNodeCreated");p.registerExtension({name:"Comfy.CustomCombo",beforeRegisterNodeDef(o,e){e?.name==="CustomCombo"&&(o.prototype.onNodeCreated=J(o.prototype.onNodeCreated,zt))}});ee().registerExtension({name:"Comfy.DynamicPrompts",nodeCreated(o){if(o.widgets){const e=o.widgets.filter(t=>t.dynamicPrompts);for(const t of e)t.serializeValue=(s,n)=>{if(typeof t.value!="string")return t.value;const i=dt(t.value);return s?.widgets_values&&(s.widgets_values[n]=i),i}}}});p.registerExtension({name:"Comfy.EditAttention",init(){const o=p.ui.settings.addSetting({id:"Comfy.EditAttention.Delta",category:["Comfy","EditTokenWeight","Delta"],name:"Ctrl+up/down precision",type:"slider",attrs:{min:.01,max:.5,step:.01},defaultValue:.05});function e(i,r){const a=parseFloat(i);if(isNaN(a))return i;const l=a+r;return String(Number(l.toFixed(10)))}u(e,"incrementWeight");function t(i,r){let a=r,l=r,d=0,c=0;for(;a>=0&&(a--,!(i[a]==="("&&d===c));)i[a]==="("&&d++,i[a]===")"&&c++;if(a<0)return null;for(d=0,c=0;l<i.length&&!(i[l]===")"&&d===c);)i[l]==="("&&d++,i[l]===")"&&c++,l++;return l===i.length?null:{start:a+1,end:l}}u(t,"findNearestEnclosure");function s(i){const r=/^\((.*)\)$/,a=i.match(r),l=/:([+-]?(\d*\.)?\d+([eE][+-]?\d+)?)/,d=i.match(l);return a&&!d?`(${a[1]}:1.0)`:i}u(s,"addWeightToParentheses");function n(i){const r=i.composedPath()[0],a=parseFloat(o.value);if(r.tagName!=="TEXTAREA"||!(i.key==="ArrowUp"||i.key==="ArrowDown")||!i.ctrlKey&&!i.metaKey)return;i.preventDefault();let l=r.selectionStart,d=r.selectionEnd,c=r.value.substring(l,d);if(!c){const g=t(r.value,l);if(g)l=g.start,d=g.end,c=r.value.substring(l,d);else{const h=" .,\\/!?%^*;:{}=-_`~()\r\n ";for(;!h.includes(r.value[l-1])&&l>0;)l--;for(;!h.includes(r.value[d])&&d<r.value.length;)d++;if(c=r.value.substring(l,d),!c)return}}c[c.length-1]===" "&&(c=c.substring(0,c.length-1),d-=1),r.value[l-1]==="("&&r.value[d]===")"&&(l-=1,d+=1,c=r.value.substring(l,d)),(c[0]!=="("||c[c.length-1]!==")")&&(c=`(${c})`),c=s(c);const f=i.key==="ArrowUp"?a:-a,v=c.replace(/\((.*):([+-]?\d+(?:\.\d+)?)\)/,(g,h,m)=>(m=e(m,f),m==1?h:`(${h}:${m})`));r.setSelectionRange(l,d),document.execCommand("insertText",!1,v),r.setSelectionRange(l,l+v.length)}u(n,"editAttention"),window.addEventListener("keydown",n)}});const jt={validationPathSuffix:"/20250115/cpython-3.10.16+20250115-aarch64-apple-darwin-debug-full.tar.zst.sha256"},me=u(async o=>ct(o)&&await Je().NetWork.canAccessUrl(o),"checkMirrorReachable");(async()=>{if(!ut())return;const o=Je(),e=await o.getElectronVersion(),t=pt(),s=S(),{staticUrls:n,buildDocsUrl:i}=gt(),r=u((a,l)=>{l!==void 0&&a!==l&&o.restartApp("Restart ComfyUI to apply changes.",1500)},"onChangeRestartApp");p.registerExtension({name:"Comfy.ElectronAdapter",settings:[{id:"Comfy-Desktop.AutoUpdate",category:["Comfy-Desktop","General","AutoUpdate"],name:"Automatically check for updates",type:"boolean",defaultValue:!0,onChange:r},{id:"Comfy-Desktop.SendStatistics",category:["Comfy-Desktop","General","Send Statistics"],name:"Send anonymous usage metrics",type:"boolean",defaultValue:!0,onChange:r},{id:"Comfy-Desktop.WindowStyle",category:["Comfy-Desktop","General","Window Style"],name:"Window Style",tooltip:"Custom: Replace the system title bar with ComfyUI's Top menu",type:"combo",experimental:!0,defaultValue:"default",options:["default","custom"],onChange:u((a,l)=>{l&&o.Config.setWindowStyle(a)},"onChange")},{id:"Comfy-Desktop.UV.PythonInstallMirror",name:"Python Install Mirror",tooltip:"Managed Python installations are downloaded from the Astral python-build-standalone project. This variable can be set to a mirror URL to use a different source for Python installations. The provided URL will replace https://github.com/astral-sh/python-build-standalone/releases/download in, e.g., https://github.com/astral-sh/python-build-standalone/releases/download/20240713/cpython-3.12.4%2B20240713-aarch64-apple-darwin-install_only.tar.gz. Distributions can be read from a local directory by using the file:// URL scheme.",type:"url",defaultValue:"",attrs:{validateUrlFn(a){return me(a+jt.validationPathSuffix)}}},{id:"Comfy-Desktop.UV.PypiInstallMirror",name:"Pypi Install Mirror",tooltip:"Default pip install mirror",type:"url",defaultValue:"",attrs:{validateUrlFn:me}},{id:"Comfy-Desktop.UV.TorchInstallMirror",name:"Torch Install Mirror",tooltip:"Pip install mirror for pytorch",type:"url",defaultValue:"",attrs:{validateUrlFn:me}}],commands:[{id:"Comfy-Desktop.Folders.OpenLogsFolder",label:"Open Logs Folder",icon:"pi pi-folder-open",function(){o.openLogsFolder()}},{id:"Comfy-Desktop.Folders.OpenModelsFolder",label:"Open Models Folder",icon:"pi pi-folder-open",function(){o.openModelsFolder()}},{id:"Comfy-Desktop.Folders.OpenOutputsFolder",label:"Open Outputs Folder",icon:"pi pi-folder-open",function(){o.openOutputsFolder()}},{id:"Comfy-Desktop.Folders.OpenInputsFolder",label:"Open Inputs Folder",icon:"pi pi-folder-open",function(){o.openInputsFolder()}},{id:"Comfy-Desktop.Folders.OpenCustomNodesFolder",label:"Open Custom Nodes Folder",icon:"pi pi-folder-open",function(){o.openCustomNodesFolder()}},{id:"Comfy-Desktop.Folders.OpenModelConfig",label:"Open extra_model_paths.yaml",icon:"pi pi-file",function(){o.openModelConfig()}},{id:"Comfy-Desktop.OpenDevTools",label:"Open DevTools",icon:"pi pi-code",function(){o.openDevTools()}},{id:"Comfy-Desktop.OpenUserGuide",label:"Desktop User Guide",icon:"pi pi-book",function(){window.open(i("/installation/desktop",{includeLocale:!0,platform:!0}),"_blank")}},{id:"Comfy-Desktop.CheckForUpdates",label:"Check for Updates",icon:"pi pi-sync",async function(){try{const a=await o.checkForUpdates({disableUpdateReadyAction:!0});if(!a.isUpdateAvailable){s.add({severity:"info",summary:D("desktopUpdate.noUpdateFound"),life:5e3});return}if(await te().confirm({title:D("desktopUpdate.updateFoundTitle",{version:a.version}),message:D("desktopUpdate.updateAvailableMessage"),type:"default"}))try{o.restartAndInstall()}catch(d){Ge.error("Error installing update:",d),s.add({severity:"error",summary:D("g.error"),detail:D("desktopUpdate.errorInstallingUpdate"),life:1e4})}}catch(a){Ge.error("Error checking for updates:",a),s.add({severity:"error",summary:D("g.error"),detail:D("desktopUpdate.errorCheckingUpdate"),life:1e4})}}},{id:"Comfy-Desktop.Reinstall",label:"Reinstall",icon:"pi pi-refresh",async function(){await te().confirm({message:D("desktopMenu.confirmReinstall"),title:D("desktopMenu.reinstall"),type:"reinstall"})&&o.reinstall()}},{id:"Comfy-Desktop.Restart",label:"Restart",icon:"pi pi-refresh",function(){o.restartApp()}},{id:"Comfy-Desktop.Quit",label:"Quit",icon:"pi pi-sign-out",async function(){t.modifiedWorkflows.length>0&&!await te().confirm({message:D("desktopMenu.confirmQuit"),title:D("desktopMenu.quit"),type:"default"})||o.quit()}}],menuCommands:[{path:["Help"],commands:["Comfy-Desktop.OpenUserGuide"]},{path:["Help"],commands:["Comfy-Desktop.OpenDevTools"]},{path:["Help","Open Folder"],commands:["Comfy-Desktop.Folders.OpenLogsFolder","Comfy-Desktop.Folders.OpenModelsFolder","Comfy-Desktop.Folders.OpenOutputsFolder","Comfy-Desktop.Folders.OpenInputsFolder","Comfy-Desktop.Folders.OpenCustomNodesFolder","Comfy-Desktop.Folders.OpenModelConfig"]},{path:["Help"],commands:["Comfy-Desktop.CheckForUpdates","Comfy-Desktop.Reinstall"]}],keybindings:[{commandId:"Workspace.CloseWorkflow",combo:{key:"w",ctrl:!0}}],aboutPageBadges:[{label:"ComfyUI_desktop v"+e,url:n.githubElectron,icon:"pi pi-github"}]})})();class Ht extends ft{static{u(this,"ExecutableGroupNodeChildDTO")}groupNodeHandler;constructor(e,t,s,n,i){super(e,t,s,n),this.groupNodeHandler=i}resolveInput(e){if(this.id.split(":").length>2)throw new Error("Group nodes inside subgraphs are not supported. Please convert the group node to a subgraph instead.");const t=this.node.getInputNode(e);if(!t)return;const s=this.node.getInputLink(e);if(!s)throw new Error("Failed to get input link");const n=String(t.id);let i=this.nodesByExecutionId?.get(n);if(!i){const r=n.split(":").at(-1);r!==void 0&&(i=this.nodesByExecutionId?.get(r))}if(!i)throw new Error(`Failed to get input node ${n} for group node child ${this.id} with slot ${e}`);return{node:i,origin_id:n,origin_slot:s.origin_slot}}}const ye=Symbol();function ot(o,e){if(typeof o=="object"&&typeof e=="object")for(const t in e){const s=e[t];if(typeof s=="object"){let n=o[t];n||(n=o[t]={}),ot(n,e[t])}else o[t]=s}return o}u(ot,"merge");class nt extends ht{static{u(this,"ManageGroupDialog")}tabs;selectedNodeIndex;selectedTab="Inputs";selectedGroup;modifications={};nodeItems;app;groupNodeType;groupNodeDef;groupData;innerNodesList;widgetsPage;inputsPage;outputsPage;draggable;get selectedNodeInnerIndex(){return+this.nodeItems[this.selectedNodeIndex].dataset.nodeindex}constructor(e){super(),this.app=e,this.element=b("dialog.comfy-group-manage",{parent:document.body})}changeTab(e){this.tabs[this.selectedTab].tab.classList.remove("active"),this.tabs[this.selectedTab].page.classList.remove("active"),this.tabs[e].tab.classList.add("active"),this.tabs[e].page.classList.add("active"),this.selectedTab=e}changeNode(e,t){!t&&this.selectedNodeIndex===e||(this.selectedNodeIndex!=null&&this.nodeItems[this.selectedNodeIndex].classList.remove("selected"),this.nodeItems[e].classList.add("selected"),this.selectedNodeIndex=e,!this.buildInputsPage()&&this.selectedTab==="Inputs"&&this.changeTab("Widgets"),!this.buildWidgetsPage()&&this.selectedTab==="Widgets"&&this.changeTab("Outputs"),!this.buildOutputsPage()&&this.selectedTab==="Outputs"&&this.changeTab("Inputs"),this.changeTab(this.selectedTab))}getGroupData(){this.groupNodeType=C.registered_node_types[`${L}${P}`+this.selectedGroup],this.groupNodeDef=this.groupNodeType.nodeData,this.groupData=U.getGroupData(this.groupNodeType)}changeGroup(e,t=!0){this.selectedGroup=e,this.getGroupData();const s=this.groupData.nodeData.nodes;if(this.nodeItems=s.map((i,r)=>b("li.draggable-item",{dataset:{nodeindex:i.index+""},onclick:u(()=>{this.changeNode(r)},"onclick")},[b("span.drag-handle"),b("div",{textContent:i.title??i.type},i.title?b("span",{textContent:i.type}):[])])),this.innerNodesList.replaceChildren(...this.nodeItems),t)this.selectedNodeIndex=null,this.changeNode(0);else{let r=this.draggable.getAllItems().findIndex(a=>a.classList.contains("selected"));r===-1&&(r=this.selectedNodeIndex),this.changeNode(r,!0)}const n=[...s];this.draggable?.dispose(),this.draggable=new mt(this.innerNodesList,"li"),this.draggable.addEventListener("dragend",({detail:{oldPosition:i,newPosition:r}})=>{if(i!==r){n.splice(r,0,n.splice(i,1)[0]);for(let a=0;a<n.length;a++)this.storeModification({nodeIndex:n[a].index,section:ye,prop:"order",value:a})}})}storeModification(e){const{nodeIndex:t,section:s,prop:n,value:i}=e,r=this.modifications[this.selectedGroup]??={},a=r.nodes??={},l=a[t??this.selectedNodeInnerIndex]??={},d=l[s]??={};if(typeof i=="object"){const c=d[n]??={};Object.assign(c,i)}else d[n]=i}getEditElement(e,t,s,n,i,r=!0){s===n&&(s="");const a=this.modifications[this.selectedGroup]?.nodes?.[this.selectedNodeInnerIndex]?.[e]?.[t];return a&&(a.name!=null&&(s=a.name),a.visible!=null&&(i=a.visible)),b("div",[b("input",{value:s,placeholder:n,type:"text",onchange:u(l=>{this.storeModification({section:e,prop:t,value:{name:l.target.value}})},"onchange")}),b("label",{textContent:"Visible"},[b("input",{type:"checkbox",checked:i,disabled:!r,onchange:u(l=>{this.storeModification({section:e,prop:t,value:{visible:!!l.target.checked}})},"onchange")})])])}buildWidgetsPage(){const e=this.groupData.oldToNewWidgetMap[this.selectedNodeInnerIndex],t=Object.keys(e??{}),n=p.rootGraph.extra.groupNodes[this.selectedGroup].config?.[this.selectedNodeInnerIndex]?.input;return this.widgetsPage.replaceChildren(...t.map(i=>this.getEditElement("input",i,e[i],i,n?.[i]?.visible!==!1))),!!t.length}buildInputsPage(){const e=this.groupData.nodeInputs[this.selectedNodeInnerIndex],t=Object.keys(e??{}),n=p.rootGraph.extra.groupNodes[this.selectedGroup].config?.[this.selectedNodeInnerIndex]?.input;return this.inputsPage.replaceChildren(...t.map(i=>{let r=e[i];if(r)return this.getEditElement("input",i,r,i,n?.[i]?.visible!==!1)}).filter(Boolean)),!!t.length}buildOutputsPage(){const e=this.groupData.nodeData.nodes,t=this.groupData.getNodeDef(e[this.selectedNodeInnerIndex]),s=t?.output??[],n=this.groupData.oldToNewOutputMap[this.selectedNodeInnerIndex],r=p.rootGraph.extra.groupNodes[this.selectedGroup].config?.[this.selectedNodeInnerIndex]?.output,l=this.groupData.nodeData.nodes[this.selectedNodeInnerIndex].type!=="PrimitiveNode";return this.outputsPage.replaceChildren(...s.map((d,c)=>{const f=n?.[c],v=t.output_name?.[c]??d;let g=r?.[c]?.name;const h=r?.[c]?.visible||f!=null;return(!g||g===v)&&(g=""),this.getEditElement("output",c,g,v,h,l)}).filter(Boolean)),!!s.length}show(e){const t=Object.keys(p.rootGraph.extra?.groupNodes??{}).sort((i,r)=>i.localeCompare(r));this.innerNodesList=b("ul.comfy-group-manage-list-items"),this.widgetsPage=b("section.comfy-group-manage-node-page"),this.inputsPage=b("section.comfy-group-manage-node-page"),this.outputsPage=b("section.comfy-group-manage-node-page");const s=b("div",[this.widgetsPage,this.inputsPage,this.outputsPage]);this.tabs=[["Inputs",this.inputsPage],["Widgets",this.widgetsPage],["Outputs",this.outputsPage]].reduce((i,[r,a])=>(i[r]={tab:b("a",{onclick:u(()=>{this.changeTab(r)},"onclick"),textContent:r}),page:a},i),{});const n=b("div.comfy-group-manage-outer",[b("header",[b("h2","Group Nodes"),b("select",{onchange:u(i=>{this.changeGroup(i.target.value)},"onchange")},t.map(i=>b("option",{textContent:i,selected:`${L}${P}${i}`===e,value:i})))]),b("main",[b("section.comfy-group-manage-list",this.innerNodesList),b("section.comfy-group-manage-node",[b("header",Object.values(this.tabs).map(i=>i.tab)),s])]),b("footer",[b("button.comfy-btn",{onclick:u(()=>{if(p.rootGraph.nodes.find(r=>r.type===`${L}${P}`+this.selectedGroup)){S().addAlert("This group node is in use in the current workflow, please first remove these.");return}confirm(`Are you sure you want to remove the node: "${this.selectedGroup}"`)&&(delete p.rootGraph.extra.groupNodes[this.selectedGroup],C.unregisterNodeType(`${L}${P}`+this.selectedGroup)),this.show()},"onclick")},"Delete Group Node"),b("button.comfy-btn",{onclick:u(async()=>{let i,r=[];const a={};for(const l in this.modifications){const d=p.rootGraph.extra.groupNodes[l];let c=d.config??={},f=this.modifications[l]?.nodes;if(f){const g=Object.keys(f);if(f[g[0]][ye]){const h=[],m={},y={};for(const w of g){const N=f[w][ye].order;h[N]=d.nodes[+w],m[N]=f[w],h[N].index=N}for(const w of d.links)w[0]!=null&&(w[0]=d.nodes[w[0]].index),w[2]!=null&&(w[2]=d.nodes[w[2]].index);if(d.external)for(const w of d.external)w[0]=d.nodes[w[0]];for(const w of g)c[w]&&(y[d.nodes[w].index]=c[w]),delete c[w];d.nodes=h,f=m,d.config=c=y}ot(c,f)}a[l]=d,i||(i=p.rootGraph.nodes.reduce((g,h)=>(g[h.type]??=[],g[h.type].push(h),g),{}));const v=i[`${L}${P}`+l];v&&r.push(...v)}await Y.registerFromWorkflow(a,{});for(const l of r)l.recreate();this.modifications={},this.app.canvas.setDirty(!0,!0),this.changeGroup(this.selectedGroup,!1)},"onclick")},"Save"),b("button.comfy-btn",{onclick:u(()=>this.element.close(),"onclick")},"Close")])]);this.element.replaceChildren(n),this.changeGroup(e?t.find(i=>`${L}${P}${i}`===e)??t[0]:t[0]),this.element.showModal(),this.element.addEventListener("close",()=>{this.draggable?.dispose(),this.element.remove()})}}window.comfyAPI=window.comfyAPI||{};window.comfyAPI.groupNodeManage=window.comfyAPI.groupNodeManage||{};window.comfyAPI.groupNodeManage.ManageGroupDialog=nt;const qt=new Set(["default","forceInput","defaultInput","control_after_generate","multiline","tooltip","dynamicPrompts"]),We=u(o=>{const e=o.min??-1/0,t=o.max??1/0;return{min:e,max:t}},"getRange"),Yt=u((o,e)=>{const t=o[0],s=o[1]??{},n=e[1]??{},i=We(s),r=We(n);if(i.min>r.max||i.max<r.min)return null;const a=s.step??1,l=n.step??1,d={min:Math.max(i.min,r.min),max:Math.min(i.max,r.max),step:bt(a,l)};return Te([t,{...s,...d}],[t,{...n,...d}])},"mergeNumericInputSpec"),Xt=u((o,e)=>{const t=o[1]??{},s=e[1]??{},n=Pe(o),i=Pe(e),r=H.intersection(n,i);return r.length===0?null:Te(["COMBO",{...t,options:r}],["COMBO",{...s,options:r}])},"mergeComboInputSpec"),Te=u((o,e)=>{const t=be(o),s=o[1]??{},n=e[1]??{};return H.union(H.keys(s),H.keys(n)).filter(a=>!qt.has(a)).every(a=>{const l=s[a],d=n[a];return l===d||H.isNil(l)&&H.isNil(d)})?[t,{...s,...n}]:null},"mergeCommonInputSpec"),Jt=u((o,e)=>{const t=be(o),s=be(e);return t!==s?null:yt(o)||wt(o)?Yt(o,e):vt(o)?Xt(o,e):Te(o,e)},"mergeInputSpec"),Kt=u(o=>o.type==="PrimitiveNode","isPrimitiveNode"),we="Run widget replace on values";class Ne extends de{static{u(this,"PrimitiveNode")}controlValues;lastType;static category;constructor(e){super(e),this.addOutput("connect to widget input","*"),this.serialize_widgets=!0,this.isVirtualNode=!0,(!this.properties||!(we in this.properties))&&this.addProperty(we,!1,"boolean")}applyToGraph(e=[]){if(!this.outputs[0].links?.length||!this.graph)return;const t=[...this.outputs[0].links.map(n=>this.graph.links[n]),...e];let s=this.widgets?.[0].value;s&&this.properties[we]&&(s=Ke(this.graph,s));for(const n of t){const i=this.graph?.getNodeById(n.target_id),r=i?.inputs[n.target_slot];if(!r){console.warn("Unable to resolve node or input for link",n);continue}const a=r.widget?.name;if(!a){console.warn("Invalid widget or widget name",r.widget);continue}const l=i.widgets?.find(d=>d.name===a);if(!l){console.warn(`Unable to find widget "${a}" on node [${i.id}]`);continue}l.value=s,l.callback?.(l.value,p.canvas,i,p.canvas.graph_mouse,{})}}refreshComboInNode(){const e=this.widgets?.[0];e?.type==="combo"&&(e.options.values=this.outputs[0].widget[F]()[0],e.options.values.includes(e.value)||(e.value=e.options.values[0],e.callback(e.value)))}onAfterGraphConfigured(){if(this.outputs[0].links?.length&&!this.widgets?.length){if(this.#e(),this.widgets&&this.widgets_values)for(let e=0;e<this.widgets_values.length;e++){const t=this.widgets[e];t&&(t.value=this.widgets_values[e])}this.#t()}}onConnectionsChange(e,t,s){if(p.configuringGraph)return;const n=this.outputs[0].links;s?n?.length&&!this.widgets?.length&&this.#e():(this.#t(),n?.length||this.onLastDisconnect())}onConnectOutput(e,t,s,n,i){if(!s.widget&&!(s.type in $))return!1;if(this.outputs[e].links?.length){const r=this.#o(s);return r&&this.applyToGraph([{target_id:n.id,target_slot:i}]),r}return!0}#e(e){if(!this.outputs[0].links||!this.graph){this.onLastDisconnect();return}const t=this.outputs[0].links[0],s=this.graph.links[t];if(!s)return;const n=this.graph.getNodeById(s.target_id);if(!n||!n.inputs)return;const i=n.inputs[s.target_slot];if(!i)return;let r;if(i.widget)r=i.widget;else{if(!(i.type in $))return;r={name:i.name,[F]:()=>[i.type,{}]}}const a=r[F]?.();if(!a)return;const{type:l}=Zt(a);this.outputs[0].type=l,this.outputs[0].name=l,this.outputs[0].widget=r,this.#i(r[oe]??a,n,r.name,e)}#i(e,t,s,n){let i=e[0];i instanceof Array&&(i="COMBO");const[r,a]=this.size;let l;if(Nt(i)?l=($[i](this,"value",e,p)||{}).widget:l=this.addWidget(i,"value",null,()=>{},{}),t?.widgets&&l){const c=t.widgets.find(f=>f.name===s);c&&(l.value=c.value)}if(!e?.[1]?.control_after_generate&&(l.type==="number"||l.type==="combo")){let c=this.widgets_values?.[1];c||(c="fixed"),It(this,l,c,void 0,e),this.widgets?.[1]&&(l.linkedWidgets=[this.widgets[1]]);let f=this.widgets_values?.[2];f&&this.widgets&&this.widgets.length===3&&(this.widgets[2].value=f)}const d=this.controlValues;if(this.widgets&&this.lastType===this.widgets[0]?.type&&d?.length===this.widgets.length-1)for(let c=0;c<d.length;c++)this.widgets[c+1].value=d[c];if(l.callback=J(l.callback,()=>{this.applyToGraph()}),this.setSize([Math.max(this.size[0],r),Math.max(this.size[1],a)]),!n){const c=this.computeSize();this.size[0]<c[0]&&(this.size[0]=c[0]),this.size[1]<c[1]&&(this.size[1]=c[1]),requestAnimationFrame(()=>{this.onResize?.(this.size)})}}recreateWidget(){const e=this.widgets?.map(t=>t.value);if(this.#n(),this.#e(!0),e?.length&&this.widgets)for(let t=0;t<this.widgets.length;t++)this.widgets[t].value=e[t];return this.widgets?.[0]}#t(){const e=this.outputs[0],t=e.links??[],s=!!e.widget?.[oe];if(s&&delete e.widget?.[oe],t?.length<2&&s){t.length&&this.recreateWidget();return}const n=e.widget?.[F]?.();if(!(!n||!(n[0]==="INT"||n[0]==="FLOAT")||!this.graph))for(const r of t){const a=this.graph.links[r];if(!a)continue;const l=this.graph.getNodeById(a.target_id);if(!l)continue;const d=l.inputs[a.target_slot];this.#o(d,s)}}#o(e,t){const s=this.outputs?.[0],n=e.widget?.[F]?.();return n?!!ae.call(this,s,n,t,this.recreateWidget):!1}#n(){if(this.widgets){for(const e of this.widgets)e.onRemove&&e.onRemove();this.controlValues=[],this.lastType=this.widgets[0]?.type;for(let e=1;e<this.widgets.length;e++)this.controlValues.push(this.widgets[e].value);setTimeout(()=>{delete this.lastType,delete this.controlValues},15),this.widgets.length=0}}onLastDisconnect(){this.outputs[0].type="*",this.outputs[0].name="connect to widget input",delete this.outputs[0].widget,this.#n()}}function Se(o){return o.widget?.[oe]??o.widget?.[F]?.()??["*",{}]}u(Se,"getWidgetConfig");function Re(o){const{nodeData:e}=this.constructor;return e?.input?.required?.[o]??e?.input?.optional?.[o]}u(Re,"getConfig");function Qt(o,e){return console.warn("Please remove call to convertToInput. Widget to socket conversion is no longer necessary, as they co-exist now."),o.inputs.find(t=>t.widget?.name===e.name)}u(Qt,"convertToInput");function Zt(o){let e=o[0];return e instanceof Array&&(e="COMBO"),{type:e}}u(Zt,"getWidgetType");function Ie(o,e){if(!o.widget||(e?o.widget[F]=()=>e:delete o.widget,!(o instanceof Ct)))return;const t=o.node.graph;if(!t)return;const s=t.links[o.link??-1];if(!s)return;const n=t.getNodeById(s.origin_id);!n||!Kt(n)||(e?n.recreateWidget():p.configuringGraph||(n.disconnectOutput(0),n.onLastDisconnect()))}u(Ie,"setWidgetConfig");function ae(o,e,t,s,n){n||(n=Se(o));const i=Jt(n,e);if(i||t){i&&(o.widget[oe]=i);const r=s?.call(this);if(r){const a=r.options.min,l=r.options.max;a!=null&&r.value<a&&(r.value=a),l!=null&&r.value>l&&(r.value=l),r.callback(r.value)}}return{customConfig:i?.[1]??{}}}u(ae,"mergeIfValid");p.registerExtension({name:"Comfy.WidgetInputs",async beforeRegisterNodeDef(o,e,t){o.prototype.convertWidgetToInput=function(){return console.warn("Please remove call to convertWidgetToInput. Widget to socket conversion is no longer necessary, as they co-exist now."),!1},o.prototype.onGraphConfigured=J(o.prototype.onGraphConfigured,function(){if(this.inputs){this.widgets??=[];for(const n of this.inputs)if(n.widget){const i=n.widget.name;n.widget[F]||(n.widget[F]=()=>Re.call(this,i)),this.widgets?.find(a=>a.name===i)||this.removeInput(this.inputs.findIndex(a=>a===n))}}}),o.prototype.onConfigure=J(o.prototype.onConfigure,function(){if(!t.configuringGraph&&this.inputs){for(const n of this.inputs)if(n.widget&&!n.widget[F]){const i=n.widget.name;n.widget[F]=()=>Re.call(this,i)}}});const s=o.prototype.onInputDblClick;o.prototype.onInputDblClick=function(...[n,...i]){const r=s?.apply(this,[n,...i]),a=this.inputs[n];if(!a.widget&&!(a.type in $)&&!(a.widget?.[F]?.()?.[0]instanceof Array))return r;const l=C.createNode("PrimitiveNode"),d=t.canvas.graph;if(!l||!d)return r;d?.add(l);const c=[this.pos[0]-l.size[0]-30,this.pos[1]];for(;d.getNodeOnPos(c[0],c[1],d.nodes);)c[1]+=C.NODE_TITLE_HEIGHT;return l.pos=c,l.connect(0,this,n),l.title=a.name,r}},registerCustomNodes(){C.registerNodeType("PrimitiveNode",Object.assign(Ne,{title:"Primitive"})),Ne.category="utils"}});window.comfyAPI=window.comfyAPI||{};window.comfyAPI.widgetInputs=window.comfyAPI.widgetInputs||{};window.comfyAPI.widgetInputs.PrimitiveNode=Ne;window.comfyAPI.widgetInputs.getWidgetConfig=Se;window.comfyAPI.widgetInputs.convertToInput=Qt;window.comfyAPI.widgetInputs.setWidgetConfig=Ie;window.comfyAPI.widgetInputs.mergeIfValid=ae;const q={InUse:{Free:0,Registered:1,InWorkflow:2},isInUseGroupNode(o){const e=`${L}${P}${o}`;return p.rootGraph.extra?.groupNodes?.[o]?p.rootGraph.nodes.find(t=>t.type===e)?q.InUse.InWorkflow:q.InUse.Registered:q.InUse.Free},storeGroupNode(o,e){let t=p.rootGraph.extra;t||(p.rootGraph.extra=t={});let s=t.groupNodes;s||(t.groupNodes=s={}),s[o]=e}};class Fe{static{u(this,"GroupNodeBuilder")}nodes;nodeData;constructor(e){this.nodes=e}async build(){const e=await this.getName();if(e)return this.sortNodes(),this.nodeData=this.getNodeData(),q.storeGroupNode(e,this.nodeData),{name:e,nodeData:this.nodeData}}async getName(){const e=await te().prompt({title:D("groupNode.create"),message:D("groupNode.enterName"),defaultValue:""});if(!e)return;switch(q.isInUseGroupNode(e)){case q.InUse.InWorkflow:S().addAlert("An in use group node with this name already exists embedded in this workflow, please remove any instances or use a new name.");return;case q.InUse.Registered:if(!confirm("A group node with this name already exists embedded in this workflow, are you sure you want to overwrite it?"))return;break}return e}sortNodes(){const e=p.rootGraph.computeExecutionOrder(!1);this.nodes=this.nodes.map(t=>({index:e.indexOf(t),node:t})).sort((t,s)=>t.index-s.index||t.node.id-s.node.id).map(({node:t})=>t)}getNodeData(){const e=u(s=>{for(const n of s.links){const r=p.rootGraph.getNodeById(n[4]).outputs[n[1]].type;n.push(r)}},"storeLinkTypes"),t=u(s=>{s.external=[];for(let n=0;n<this.nodes.length;n++){const i=this.nodes[n];if(i.outputs?.length)for(let r=0;r<i.outputs.length;r++){let a=!1;const l=i.outputs[r];let d=l.type;if(l.links?.length){for(const c of l.links){const f=p.rootGraph.links[c];if(f&&(d==="*"&&(d=f.type),!p.canvas.selected_nodes[f.target_id])){a=!0;break}}a&&s.external.push([n,r,d])}}}},"storeExternalLinks");{const s=_t(this.nodes,p.canvas?.graph),n=JSON.parse(s);return e(n),t(n),n}}}class Y{static{u(this,"GroupNodeConfig")}name;nodeData;inputCount;oldToNewOutputMap;newToOldOutputMap;oldToNewInputMap;oldToNewWidgetMap;newToOldWidgetMap;primitiveDefs;widgetToPrimitive;primitiveToWidget;nodeInputs;outputVisibility;nodeDef;inputs;linksFrom;linksTo;externalFrom;constructor(e,t){this.name=e,this.nodeData=t,this.getLinks(),this.inputCount=0,this.oldToNewOutputMap={},this.newToOldOutputMap={},this.oldToNewInputMap={},this.oldToNewWidgetMap={},this.newToOldWidgetMap={},this.primitiveDefs={},this.widgetToPrimitive={},this.primitiveToWidget={},this.nodeInputs={},this.outputVisibility=[]}async registerType(e=L){this.nodeDef={output:[],output_name:[],output_is_list:[],output_is_hidden:[],name:e+P+this.name,display_name:this.name,category:"group nodes"+(P+e),input:{required:{}},description:`Group node combining ${this.nodeData.nodes.map(n=>n.type).join(", ")}`,python_module:"custom_nodes."+this.name,[W]:this},this.inputs=[];const t={},s={};for(let n=0;n<this.nodeData.nodes.length;n++){const i=this.nodeData.nodes[n];i.index=n,this.processNode(i,t,s)}for(const n of this.#e)n();this.#e=null,await p.registerNodeDef(`${L}${P}`+this.name,this.nodeDef),Dt().addNodeDef(this.nodeDef)}getLinks(){this.linksFrom={},this.linksTo={},this.externalFrom={};for(const e of this.nodeData.links){const[t,s,n,i]=e;t!=null&&(this.linksFrom[t]||(this.linksFrom[t]={}),this.linksFrom[t][s]||(this.linksFrom[t][s]=[]),this.linksFrom[t][s].push(e),this.linksTo[n]||(this.linksTo[n]={}),this.linksTo[n][i]=e)}if(this.nodeData.external)for(const e of this.nodeData.external)this.externalFrom[e[0]]?this.externalFrom[e[0]][e[1]]=e[2]:this.externalFrom[e[0]]={[e[1]]:e[2]}}processNode(e,t,s){const n=this.getNodeDef(e);if(!n)return;const i={...n.input?.required,...n.input?.optional};this.inputs.push(this.processNodeInputs(e,t,i)),n.output?.length&&this.processNodeOutputs(e,s,n)}getNodeDef(e){const t=ne[e.type];if(t)return t;const s=this.linksFrom[e.index];if(e.type==="PrimitiveNode"){if(!s)return;let n=s[0][0][5];if(n==="COMBO"){const r=e.outputs[0].widget.name,a=this.nodeData.nodes[s[0][0][2]].type,l=ne[a];n=(l.input.required[r]??l.input.optional[r])[0]}return this.primitiveDefs[e.index]={input:{required:{value:[n,{}]}},output:[n],output_name:[],output_is_list:[]}}else if(e.type==="Reroute"){const n=this.linksTo[e.index];if(n&&s&&!this.externalFrom[e.index]?.[0])return null;let i={},r="*";if(s)for(const[,,a,l]of s[0]){const d=this.nodeData.nodes[a],c=d.inputs[l];if(r==="*"&&(r=c.type),c.widget){const f=ne[d.type],v=f.input.required[c.widget.name]??f.input.optional[c.widget.name],g=[v[0],i];i=ae({widget:g},v,!1,null,g)?.customConfig??i}}else if(n){const[a,l]=n[0];r=this.nodeData.nodes[a].outputs[l].type}else{for(const a of this.nodeData.links)if(a[2]===e.index){r=a[5];break}if(r==="*"){const a=this.externalFrom[e.index]?.[0];a&&(r=a)}}return i.forceInput=!0,{input:{required:{[r]:[r,i]}},output:[r],output_name:[],output_is_list:[]}}console.warn("Skipping virtual node "+e.type+" when building group node "+this.name)}getInputConfig(e,t,s,n,i){const r=this.nodeData.config?.[e.index]?.input?.[t];let a=r?.name??e.inputs?.find(c=>c.name===t)?.label??t,l=a,d="";return(e.type==="PrimitiveNode"&&e.title||a in s)&&(d=`${e.title??e.type} `,l=a=`${d}${t}`,a in s&&(a=`${d}${s[a]} ${t}`)),s[l]=(s[l]??1)+1,(t==="seed"||t==="noise_seed")&&(i||(i={}),i.control_after_generate=`${d}control_after_generate`),n[0]==="IMAGEUPLOAD"&&(i||(i={}),i.widget=this.oldToNewWidgetMap[e.index]?.[n[1]?.widget??"image"]??"image"),i&&(n=[n[0],{...n[1],...i}]),{name:a,config:n,customConfig:r}}processWidgetInputs(e,t,s,n){const i=[],r=new Map,a=this.oldToNewWidgetMap[t.index]={};for(const l of s)if(xt().inputIsWidget(e[l])){const d=t.inputs?.findIndex(c=>c.name===l&&c.widget?.name===l);if(d>-1)r.set(d,l),a[l]=null;else{const{name:c,config:f}=this.getInputConfig(t,l,n,e[l]);this.nodeDef.input.required[c]=f,a[l]=c,this.newToOldWidgetMap[c]={node:t,inputName:l}}}else i.push(l);return{converted:r,slots:i}}checkPrimitiveConnection(e,t,s){if(this.nodeData.nodes[e[0]].type==="PrimitiveNode"){const[i,r,a,l]=e,d=this.primitiveDefs[i],c=s[t],f=d.input.required.value,g=ae({widget:f},c,!1,null,f);f[1]=g?.customConfig??s[t][1]?{...s[t][1]}:{};let h=this.oldToNewWidgetMap[i].value;h=h.substr(0,h.length-6),f[1].control_after_generate=!0,f[1].control_prefix=h;let m=this.widgetToPrimitive[a];m||(m=this.widgetToPrimitive[a]={}),m[t]&&m[t].push(i),m[t]=i;let y=this.primitiveToWidget[i];y||(y=this.primitiveToWidget[i]=[]),y.push({nodeId:a,inputName:t})}}processInputSlots(e,t,s,n,i,r){this.nodeInputs[t.index]={};for(let a=0;a<s.length;a++){const l=s[a];if(n[a]){this.checkPrimitiveConnection(n[a],l,e);continue}const{name:d,config:c,customConfig:f}=this.getInputConfig(t,l,r,e[l]);this.nodeInputs[t.index][l]=d,f?.visible!==!1&&(this.nodeDef.input.required[d]=c,i[a]=this.inputCount++)}}processConvertedWidgets(e,t,s,n,i,r,a){const l=[...n.keys()].sort().map(d=>n.get(d));for(let d=0;d<l.length;d++){const c=l[d];if(i[s.length+d]){this.checkPrimitiveConnection(i[s.length+d],c,e);continue}const{name:f,config:v}=this.getInputConfig(t,c,a,e[c],{defaultInput:!0});this.nodeDef.input.required[f]=v,this.newToOldWidgetMap[f]={node:t,inputName:c},this.oldToNewWidgetMap[t.index]||(this.oldToNewWidgetMap[t.index]={}),this.oldToNewWidgetMap[t.index][c]=f,r[s.length+d]=this.inputCount++}}#e=[];processNodeInputs(e,t,s){const n=[],i=Object.keys(s);if(!i.length)return;const{converted:r,slots:a}=this.processWidgetInputs(s,e,i,t),l=this.linksTo[e.index]??{},d=this.oldToNewInputMap[e.index]={};return this.processInputSlots(s,e,a,l,d,t),this.#e.push(()=>this.processConvertedWidgets(s,e,a,r,l,d,t)),n}processNodeOutputs(e,t,s){const n=this.oldToNewOutputMap[e.index]={};for(let i=0;i<s.output.length;i++){const a=this.linksFrom[e.index]?.[i]&&!this.externalFrom[e.index]?.[i],l=this.nodeData.config?.[e.index]?.output?.[i],d=l?.visible??!a;if(this.outputVisibility.push(d),!d)continue;n[i]=this.nodeDef.output.length,this.newToOldOutputMap[this.nodeDef.output.length]={node:e,slot:i},this.nodeDef.output.push(s.output[i]),this.nodeDef.output_is_list.push(s.output_is_list[i]);let c=l?.name;if(!c){c=s.output_name?.[i]??s.output[i];const v=e.outputs.find(g=>g.name===c);v?.label&&(c=v.label)}let f=c;if(f in t){const v=`${e.title??e.type} `;f=`${v}${c}`,f in t&&(f=`${v}${e.index} ${c}`)}t[f]=1,this.nodeDef.output_name.push(f)}}static async registerFromWorkflow(e,t){for(const s in e){const n=e[s];let i=!1;for(const a of n.nodes)a.type in C.registered_node_types||(t.push({type:a.type,hint:` (In group node '${L}${P}${s}')`}),t.push({type:`${L}${P}`+s,action:{text:"Remove from workflow",callback:u(l=>{delete e[s],l.target.textContent="Removed",l.target.style.pointerEvents="none",l.target.style.opacity=.7},"callback")}}),i=!0);if(i)continue;await new Y(s,n).registerType()}}}class U{static{u(this,"GroupNodeHandler")}node;groupData;innerNodes;constructor(e){this.node=e,this.groupData=e.constructor?.nodeData?.[W],this.node.setInnerNodes=g=>{this.innerNodes=g;for(let h=0;h<this.innerNodes.length;h++){const m=this.innerNodes[h];m.graph??=this.node.graph;for(const y of m.widgets??[])y.type==="converted-widget"&&(y.serializeValue=y.origSerializeValue);m.index=h,m.getInputNode=y=>{const w=this.groupData.oldToNewInputMap[m.index]?.[y];if(w!=null)return this.node.getInputNode(w);const N=this.groupData.linksTo[m.index]?.[y];if(!N)return null;const I=g[N[0]];return I.type==="PrimitiveNode"?null:I},m.getInputLink=y=>{const w=this.groupData.oldToNewInputMap[m.index]?.[y];if(w!=null){const I=this.node.inputs[w].link;let k=p.rootGraph.links[I];return k={...k,target_id:m.id,target_slot:+y},k}let N=this.groupData.linksTo[m.index]?.[y];return N?(N={origin_id:g[N[0]].id,origin_slot:N[1],target_id:m.id,target_slot:+y},N):null}}},this.node.updateLink=g=>{g={...g};const h=this.groupData.newToOldOutputMap[g.origin_slot];let m=this.innerNodes[h.node.index],y;for(;m?.type==="Reroute";)y=m.getInputLink(0),m=m.getInputNode(0);return m?y&&U.isGroupNode(m)?m.updateLink(y):(g.origin_id=m.id,g.origin_slot=y?.origin_slot??h.slot,g):null},this.node.getInnerNodes=(g,h=[],m=[],y=new Set)=>{if(y.has(this.node))throw new Error("RecursionError: while flattening subgraph");y.add(this.node),this.innerNodes||this.node.setInnerNodes(this.groupData.nodeData.nodes.map((I,k)=>{const x=C.createNode(I.type);return x.configure(I),x.id=`${this.node.id}:${k}`,x.graph=this.node.graph,x})),this.updateInnerWidgets();const w=[...h,this.node.id],N=this.node.graph?.getNodeById(h.at(-1))??void 0;for(const I of this.innerNodes){I.graph??=this.node.graph;const k=String(I.id);I.id=k.split(":").at(-1);const x=new Ht(I,w,g,N);I.id=k,x.groupNodeHandler=this,m.push(x)}return m},this.node.recreate=async()=>{const g=this.node.id,h=this.node.size,m=this.node.convertToNodes(),y=C.createNode(this.node.type);y.id=g,y.setInnerNodes(m),y[W].populateWidgets(),p.rootGraph.add(y),y.setSize([Math.max(y.size[0],h[0]),Math.max(y.size[1],h[1])]);const N=new Fe(m).getNodeData();return y[W].groupData.nodeData.links=N.links,y[W].replaceNodes(m),y},this.node.convertToNodes=()=>{const g=u(()=>{const y={...this.groupData.nodeData};y.nodes=[...y.nodes];const w=this.node.getInnerNodes();let N=[];for(let A=0;A<y.nodes.length;A++){let X=w?.[A]?.id;X==null||isNaN(X)?X=void 0:N.push(X),y.nodes[A]={...y.nodes[A],id:X}}Qe(JSON.stringify(y),p.canvas);const[I,k]=this.node.pos;let x,_;const O=N.length?N:Object.keys(p.canvas.selected_nodes),j=[];for(let A=0;A<O.length;A++){const X=O[A],z=p.rootGraph.getNodeById(X),Ee=w[A];if(j.push(z),(_==null||z.pos[0]<_)&&(_=z.pos[0]),(x==null||z.pos[1]<x)&&(x=z.pos[1]),!z.widgets)continue;const ge=this.groupData.oldToNewWidgetMap[Ee.index];if(ge){const rt=Object.keys(ge);for(const Oe of rt){const Ae=ge[Oe];if(!Ae)continue;const fe=this.node.widgets.findIndex(B=>B.name===Ae);if(fe!==-1)if(Ee.type==="PrimitiveNode")for(let B=0;B<z.widgets.length;B++)z.widgets[B].value=this.node.widgets[fe+B].value;else{const B=this.node.widgets[fe],he=z.widgets.find(K=>K.name===Oe);if(!he)continue;he.value=B.value;for(let K=0;K<B.linkedWidgets?.length;K++)he.linkedWidgets[K].value=B.linkedWidgets[K].value}}}}for(const A of j)A.pos[0]-=_-I,A.pos[1]-=x-k;return{newNodes:j,selectedIds:O}},"addInnerNodes"),h=u(y=>{for(const w in this.groupData.oldToNewInputMap){const N=y[w],I=p.rootGraph.getNodeById(N),k=this.groupData.oldToNewInputMap[w];for(const x in k){const _=k[x];if(_==null)continue;const O=e.inputs[_];if(O.link==null)continue;const j=p.rootGraph.links[O.link];if(!j)continue;p.rootGraph.getNodeById(j.origin_id).connect(j.origin_slot,I,+x)}}},"reconnectInputs"),m=u(y=>{for(let w=0;w<e.outputs?.length;w++){const N=e.outputs[w];if(!N.links)continue;const I=[...N.links];for(const k of I){const x=this.groupData.newToOldOutputMap[w],_=p.rootGraph.links[k],O=p.rootGraph.getNodeById(_.target_id);p.rootGraph.getNodeById(y[x.node.index]).connect(x.slot,O,_.target_slot)}}},"reconnectOutputs");p.canvas.emitBeforeChange();try{const{newNodes:y,selectedIds:w}=g();return h(w),m(w),p.rootGraph.remove(this.node),y}finally{p.canvas.emitAfterChange()}};const t=this.node.getExtraMenuOptions;this.node.getExtraMenuOptions=function(g,h){t?.apply(this,arguments);let m=h.findIndex(y=>y?.content==="Outputs");m===-1?m=h.length:m++,h.splice(m,0,null,{content:"Convert to nodes",callback:u(()=>this.convertToNodes(),"callback")},{content:"Manage Group Node",callback:u(()=>Ce(this.type),"callback")})};const s=this.node.onDrawTitleBox;this.node.onDrawTitleBox=function(g,h){s?.apply(this,arguments);const m=g.fillStyle;g.beginPath(),g.rect(11,-h+11,2,2),g.rect(14,-h+11,2,2),g.rect(17,-h+11,2,2),g.rect(11,-h+14,2,2),g.rect(14,-h+14,2,2),g.rect(17,-h+14,2,2),g.rect(11,-h+17,2,2),g.rect(14,-h+17,2,2),g.rect(17,-h+17,2,2),g.fillStyle=this.boxcolor||C.NODE_DEFAULT_BOXCOLOR,g.fill(),g.fillStyle=m};const n=e.onDrawForeground,i=this.groupData.nodeData;e.onDrawForeground=function(g){n?.apply?.(this,arguments);const h=kt().nodeProgressStates[this.id];if(h&&h.state==="running"&&this.runningInternalNodeId!==null){const m=i.nodes[this.runningInternalNodeId];if(!m)return;const y=`Running ${m.title||m.type} (${this.runningInternalNodeId}/${i.nodes.length})`;g.save(),g.font="12px sans-serif";const w=g.measureText(y);g.fillStyle=e.boxcolor||C.NODE_DEFAULT_BOXCOLOR,g.beginPath(),g.roundRect(0,-C.NODE_TITLE_HEIGHT-20,w.width+12,20,5),g.fill(),g.fillStyle="#fff",g.fillText(y,6,-C.NODE_TITLE_HEIGHT-6),g.restore()}};const r=this.node.onExecutionStart;this.node.onExecutionStart=function(){return this.resetExecution=!0,r?.apply(this,arguments)};const a=this,l=this.node.onNodeCreated;this.node.onNodeCreated=function(){if(!this.widgets)return;const g=a.groupData.nodeData.config;if(g)for(const h in g){const m=g[h]?.input;for(const y in m){if(m[y].visible!==!1)continue;const w=a.groupData.oldToNewWidgetMap[h][y],N=this.widgets.find(I=>I.name===w);N&&(N.type="hidden",N.computeSize=()=>[0,-4])}}return l?.apply(this,arguments)};function d(g,h,m){const y=u(({detail:w})=>{const N=h(w);if(!N||p.rootGraph.getNodeById(N))return;const k=this.innerNodes?.findIndex(x=>x.id==N);k>-1&&(this.node.runningInternalNodeId=k,E.dispatchCustomEvent(g,m(w,`${this.node.id}`,this.node)))},"handler");return E.addEventListener(g,y),y}u(d,"handleEvent");const c=d.call(this,"executing",g=>g,(g,h)=>h),f=d.call(this,"executed",g=>g?.display_node||g?.node,(g,h,m)=>({...g,node:h,display_node:h,merge:!m.resetExecution})),v=e.onRemoved;this.node.onRemoved=function(){v?.apply(this,arguments),E.removeEventListener("executing",c),E.removeEventListener("executed",f)},this.node.refreshComboInNode=g=>{for(const h in this.groupData.newToOldWidgetMap){const m=this.node.widgets.find(y=>y.name===h);if(m?.type==="combo"){const y=this.groupData.newToOldWidgetMap[h],w=g[y.node.type],N=w?.input?.required?.[y.inputName]??w?.input?.optional?.[y.inputName];if(!N)continue;m.options.values=N[0],y.inputName!=="image"&&!m.options.values.includes(m.value)&&(m.value=m.options.values[0],m.callback(m.value))}}}}updateInnerWidgets(){for(const e in this.groupData.newToOldWidgetMap){const t=this.node.widgets.find(a=>a.name===e);if(!t)continue;const s=t.value,n=this.groupData.newToOldWidgetMap[e];let i=this.innerNodes[n.node.index];if(i.type==="PrimitiveNode"){i.primitiveValue=s;const a=this.groupData.primitiveToWidget[n.node.index];for(const l of a??[]){const c=this.innerNodes[l.nodeId].widgets.find(f=>f.name===l.inputName);c&&(c.value=s)}continue}else if(i.type==="Reroute"){const a=this.groupData.linksFrom[n.node.index];if(a)for(const[l,,d,c]of a[0]){const f=this.innerNodes[d],v=f.inputs[c];if(v.widget){const g=f.widgets?.find(h=>h.name===v.widget.name);g&&(g.value=s)}}}const r=i.widgets?.find(a=>a.name===n.inputName);r&&(r.value=s)}}populatePrimitive(e,t,s){const n=this.groupData.widgetToPrimitive[t]?.[s];if(n==null)return;const i=this.groupData.oldToNewWidgetMap[n].value,r=this.node.widgets.findIndex(a=>a.name===i);if(r>-1){const a=this.innerNodes[n];let l=a.widgets.length;l-1!==this.node.widgets[r].linkedWidgets?.length&&(l=1);for(let d=0;d<l;d++)this.node.widgets[r+d].value=a.widgets[d].value}return!0}populateReroute(e,t,s){if(e.type!=="Reroute")return;const n=this.groupData.linksFrom[t]?.[0]?.[0];if(!n)return;const[,,i,r]=n,a=this.groupData.nodeData.nodes[i],l=a.inputs;if(!l?.[r]?.widget)return;const c=l.length-(a.widgets_values?.length??0),f=a.widgets_values?.[r-c];if(f==null)return;const v=Object.values(s)[0],g=this.node.widgets.find(h=>h.name===v);g&&(g.value=f)}populateWidgets(){if(this.node.widgets)for(let e=0;e<this.groupData.nodeData.nodes.length;e++){const t=this.groupData.nodeData.nodes[e],s=this.groupData.oldToNewWidgetMap[e]??{},n=Object.keys(s);if(!t.widgets_values?.length){this.populateReroute(t,e,s);continue}let i=0;for(let r=0;r<n.length;r++){const a=n[r],l=s[a],d=this.node.widgets.findIndex(f=>f.name===l),c=this.node.widgets[d];if(this.populatePrimitive(t,e,a)||d===-1){const f=this.innerNodes[e].widgets?.find(v=>v.name===a);i+=f?.linkedWidgets?.length??0}if(d!==-1){c.value=t.widgets_values[r+i];for(let f=0;f<c.linkedWidgets?.length;f++)this.node.widgets[d+f+1].value=t.widgets_values[r+ ++i]}}}}replaceNodes(e){let t,s;for(let n=0;n<e.length;n++){const i=e[n];(s==null||i.pos[0]<s)&&(s=i.pos[0]),(t==null||i.pos[1]<t)&&(t=i.pos[1]),this.linkOutputs(i,n),p.rootGraph.remove(i),i.id=`${this.node.id}:${n}`}this.linkInputs(),this.node.pos=[s,t]}linkOutputs(e,t){if(e.outputs)for(const s of e.outputs){if(!s.links)continue;const n=[...s.links];for(const i of n){const r=p.rootGraph.links[i];if(!r)continue;const a=p.rootGraph.getNodeById(r.target_id),l=this.groupData.oldToNewOutputMap[t]?.[r.origin_slot];l!=null&&this.node.connect(l,a,r.target_slot)}}}linkInputs(){for(const e of this.groupData.nodeData.links??[]){const[,t,s,n,i]=e,r=p.rootGraph.getNodeById(i);r&&r.connect(t,this.node.id,this.groupData.oldToNewInputMap[s][n])}}static getGroupData(e){return(e.nodeData??e.constructor?.nodeData)?.[W]}static isGroupNode(e){return!!e.constructor?.nodeData?.[W]}static async fromNodes(e){const t=new Fe(e),s=await t.build();if(!s)return;const{name:n,nodeData:i}=s;await new Y(n,i).registerType();const a=C.createNode(`${L}${P}${n}`);return a.setInnerNodes(t.nodes),a[W].populateWidgets(),p.rootGraph.add(a),a[W].replaceNodes(t.nodes),a}}const eo=u(o=>{for(const e of o)typeof e.type=="string"&&e.type.startsWith("workflow/")&&(e.type=e.type.replace(/^workflow\//,`${L}${P}`))},"replaceLegacySeparators");async function ve(){const o=Object.values(p.canvas.selected_nodes??{});if(o.length===0)throw new Error("No nodes selected");if(o.length===1)throw new Error("Please select multiple nodes to convert to group node");for(const e of o){if(e instanceof Tt)throw new Error("Selected nodes contain a subgraph node");if(U.isGroupNode(e))throw new Error("Selected nodes contain a group node")}return await U.fromNodes(o)}u(ve,"convertSelectedNodesToGroupNode");const Ue=u(o=>o.length<2||!!o.find(e=>U.isGroupNode(e)),"convertDisabled");function to(){const o=Object.values(p.canvas.selected_nodes??{});for(const e of o)U.isGroupNode(e)&&e.convertToNodes?.()}u(to,"ungroupSelectedGroupNodes");function Ce(o){new nt(p).show(o)}u(Ce,"manageGroupNodes");const oo="Comfy.GroupNode";let ne;const no={name:oo,commands:[{id:"Comfy.GroupNode.ConvertSelectedNodesToGroupNode",label:"Convert selected nodes to group node",icon:"pi pi-sitemap",versionAdded:"1.3.17",function:u(()=>ve(),"function")},{id:"Comfy.GroupNode.UngroupSelectedGroupNodes",label:"Ungroup selected group nodes",icon:"pi pi-sitemap",versionAdded:"1.3.17",function:u(()=>to(),"function")},{id:"Comfy.GroupNode.ManageGroupNodes",label:"Manage group nodes",icon:"pi pi-cog",versionAdded:"1.3.17",function:u((...o)=>Ce(o[0]),"function")}],keybindings:[{commandId:"Comfy.GroupNode.ConvertSelectedNodesToGroupNode",combo:{alt:!0,key:"g"}},{commandId:"Comfy.GroupNode.UngroupSelectedGroupNodes",combo:{alt:!0,shift:!0,key:"G"}}],getCanvasMenuItems(o){const e=[],t=Object.values(o.selected_nodes??{}),s=!Ue(t);e.push({content:"Convert to Group Node (Deprecated)",disabled:!s,callback:u(()=>ve(),"callback")});const n=o.graph?.extra?.groupNodes,i=!n||!Object.keys(n).length;return e.push({content:"Manage Group Nodes",disabled:i,callback:u(()=>Ce(),"callback")}),e},getNodeMenuItems(o){if(U.isGroupNode(o))return[];const e=Object.values(p.canvas.selected_nodes??{});return[{content:"Convert to Group Node (Deprecated)",disabled:!!Ue(e),callback:u(()=>ve(),"callback")}]},async beforeConfigureGraph(o,e){const t=o?.extra?.groupNodes;t&&(eo(o.nodes),await Y.registerFromWorkflow(t,e))},addCustomNodeDefs(o){ne=o},nodeCreated(o){U.isGroupNode(o)&&(o[W]=new U(o),o.title&&o[W]?.groupData?.nodeData&&q.storeGroupNode(o.title,o[W].groupData.nodeData))},async refreshComboInNodes(o){Object.assign(ne,o);const e=p.rootGraph.extra?.groupNodes;e&&await Y.registerFromWorkflow(e,{})}};p.registerExtension(no);window.comfyAPI=window.comfyAPI||{};window.comfyAPI.groupNode=window.comfyAPI.groupNode||{};window.comfyAPI.groupNode.GroupNodeConfig=Y;window.comfyAPI.groupNode.GroupNodeHandler=U;function G(o,e){o.mode=e,o.graph?.change()}u(G,"setNodeMode");function Be(o,e){const t=Z().get("Comfy.GroupSelectedNodes.Padding");o.resizeTo([...o.children,...e],t)}u(Be,"addNodesToGroup");const io={name:"Comfy.GroupOptions",getCanvasMenuItems(o){const e=[],t=o.graph.getGroupOnPos(o.graph_mouse[0],o.graph_mouse[1]);if(!t)return o.selectedItems.size>0&&e.push({content:"Add Group For Selected Nodes",callback:u(()=>{const i=new St;Be(i,o.selectedItems),o.graph.add(i),o.graph.change(),i.recomputeInsideNodes()},"callback")}),e;t.recomputeInsideNodes();const s=t.nodes;if(e.push({content:"Add Selected Nodes To Group",disabled:!o.selectedItems?.size,callback:u(()=>{Be(t,o.selectedItems),o.graph.change()},"callback")}),s.length===0)return e;e.push(null);let n=!0;for(let i=1;i<s.length;i++)if(s[i].mode!==s[0].mode){n=!1;break}if(e.push({content:"Fit Group To Nodes",callback:u(()=>{t.recomputeInsideNodes();const i=Z().get("Comfy.GroupSelectedNodes.Padding");t.resizeTo(t.children,i),o.graph.change()},"callback")}),e.push({content:"Select Nodes",callback:u(()=>{o.selectNodes(s),o.graph.change(),o.canvas.focus()},"callback")}),n)switch(s[0].mode){case 0:e.push({content:"Set Group Nodes to Never",callback:u(()=>{for(const r of s)G(r,2)},"callback")}),e.push({content:"Bypass Group Nodes",callback:u(()=>{for(const r of s)G(r,4)},"callback")});break;case 2:e.push({content:"Set Group Nodes to Always",callback:u(()=>{for(const r of s)G(r,0)},"callback")}),e.push({content:"Bypass Group Nodes",callback:u(()=>{for(const r of s)G(r,4)},"callback")});break;case 4:e.push({content:"Set Group Nodes to Always",callback:u(()=>{for(const r of s)G(r,0)},"callback")}),e.push({content:"Set Group Nodes to Never",callback:u(()=>{for(const r of s)G(r,2)},"callback")});break;default:e.push({content:"Set Group Nodes to Always",callback:u(()=>{for(const r of s)G(r,0)},"callback")}),e.push({content:"Set Group Nodes to Never",callback:u(()=>{for(const r of s)G(r,2)},"callback")}),e.push({content:"Bypass Group Nodes",callback:u(()=>{for(const r of s)G(r,4)},"callback")});break}else e.push({content:"Set Group Nodes to Always",callback:u(()=>{for(const i of s)G(i,0)},"callback")}),e.push({content:"Set Group Nodes to Never",callback:u(()=>{for(const i of s)G(i,2)},"callback")}),e.push({content:"Bypass Group Nodes",callback:u(()=>{for(const i of s)G(i,4)},"callback")});return e}};p.registerExtension(io);ee().registerExtension({name:"Comfy.ImageCompare",async nodeCreated(o){if(o.constructor.comfyClass!=="ImageCompare")return;const[e,t]=o.size;o.setSize([Math.max(e,400),Math.max(t,350)]);const s=o.onExecuted;o.onExecuted=function(n){s?.call(this,n);const i=n.a_images,r=n.b_images,a=p.getRandParam(),l=i&&i.length>0?E.apiURL(`/view?${new URLSearchParams(i[0])}${a}`):"",d=r&&r.length>0?E.apiURL(`/view?${new URLSearchParams(r[0])}${a}`):"",c=o.widgets?.find(f=>f.type==="imagecompare");c&&(c.value={before:l,after:d},c.callback?.(c.value))}}});const so=[{label:"GLB",value:"glb"},{label:"OBJ",value:"obj"},{label:"STL",value:"stl"}];function pe(o){return[null,{content:"Save",has_submenu:!0,callback:u((e,t,s,n)=>{const i=so.map(r=>({content:r.label,callback:u(()=>{(async()=>{try{await o.exportModel(r.value),S().add({severity:"success",summary:D("toastMessages.exportSuccess",{format:r.label})})}catch(a){console.error("Export failed:",a),S().addAlert(D("toastMessages.failedToExportModel",{format:r.label}))}})()},"callback")}));new C.ContextMenu(i,{event:s,parentMenu:n})},"callback")}]}u(pe,"createExportMenuItems");window.comfyAPI=window.comfyAPI||{};window.comfyAPI.exportMenuHelper=window.comfyAPI.exportMenuHelper||{};window.comfyAPI.exportMenuHelper.createExportMenuItems=pe;class Me{static{u(this,"Load3DConfiguration")}constructor(e,t){this.load3d=e,this.properties=t}configureForSaveMesh(e,t){this.setupModelHandlingForSaveMesh(t,e),this.setupDefaultProperties()}configure(e){this.setupModelHandling(e.modelWidget,e.loadFolder,e.cameraState),this.setupTargetSize(e.width,e.height),this.setupDefaultProperties(e.bgImagePath)}setupTargetSize(e,t){e&&t&&(this.load3d.setTargetSize(e.value,t.value),e.callback=s=>{this.load3d.setTargetSize(s,t.value)},t.callback=s=>{this.load3d.setTargetSize(e.value,s)})}setupModelHandlingForSaveMesh(e,t){const s=this.createModelUpdateHandler(t);e&&s(e)}setupModelHandling(e,t,s){const n=this.createModelUpdateHandler(t,s);e.value&&n(e.value);const i=e.callback;let r=e.value;Object.defineProperty(e,"value",{get(){return r},set(a){r=a,e.callback&&a!==void 0&&a!==""&&e.callback(a)},enumerable:!0,configurable:!0}),e.callback=a=>{n(a),i&&i(a)}}setupDefaultProperties(e){const t=this.loadSceneConfig();this.applySceneConfig(t,e);const s=this.loadCameraConfig();this.applyCameraConfig(s);const n=this.loadLightConfig();this.applyLightConfig(n)}loadSceneConfig(){return this.properties&&"Scene Config"in this.properties?this.properties["Scene Config"]:{showGrid:Z().get("Comfy.Load3D.ShowGrid"),backgroundColor:"#"+Z().get("Comfy.Load3D.BackgroundColor"),backgroundImage:""}}loadCameraConfig(){return this.properties&&"Camera Config"in this.properties?this.properties["Camera Config"]:{cameraType:Z().get("Comfy.Load3D.CameraType"),fov:35}}loadLightConfig(){return this.properties&&"Light Config"in this.properties?this.properties["Light Config"]:{intensity:Z().get("Comfy.Load3D.LightIntensity")}}loadModelConfig(){return this.properties&&"Model Config"in this.properties?this.properties["Model Config"]:{upDirection:"original",materialMode:"original"}}applySceneConfig(e,t){if(this.load3d.toggleGrid(e.showGrid),this.load3d.setBackgroundColor(e.backgroundColor),e.backgroundImage){if(t&&t!=e.backgroundImage)return;this.load3d.setBackgroundImage(e.backgroundImage),e.backgroundRenderMode&&this.load3d.setBackgroundRenderMode(e.backgroundRenderMode)}}applyCameraConfig(e){this.load3d.toggleCamera(e.cameraType),this.load3d.setFOV(e.fov),e.state&&this.load3d.setCameraState(e.state)}applyLightConfig(e){this.load3d.setLightIntensity(e.intensity)}applyModelConfig(e){this.load3d.setUpDirection(e.upDirection),this.load3d.setMaterialMode(e.materialMode)}createModelUpdateHandler(e,t){let s=!0;return async n=>{if(!n)return;const i=n;this.setResourceFolder(i);const r=E.apiURL(V.getResourceURL(...V.splitFilePath(i),e));await this.load3d.loadModel(r,i);const a=this.loadModelConfig();if(this.applyModelConfig(a),s&&t){try{this.load3d.setCameraState(t)}catch(l){console.warn("Failed to restore camera state:",l)}s=!1}}}setResourceFolder(e){const t=e.split("/").filter(i=>i.trim());if(t.length<=2)return;const n=t.slice(1,-1).join("/");n&&this.properties&&(this.properties["Resource Folder"]=n)}}const ro={name:"image",type:"Load3D",isPreview:!1},Ve={name:"image",type:"Preview3D",isPreview:!0};async function ao(o,e){if(!o?.length)return;const t=e.widgets?.find(s=>s.name==="model_file");try{const s=e.properties["Resource Folder"]||"",n=s.trim()?`3d/${s.trim()}`:"3d",i=await V.uploadFile(o[0],n);if(!i){S().addAlert(D("toastMessages.fileUploadFailed"));return}const r=E.apiURL(V.getResourceURL(...V.splitFilePath(i),"input"));re(e).waitForLoad3d(a=>{try{a.loadModel(r)}catch{S().addAlert(D("toastMessages.failedToLoadModel"))}}),i&&t&&(t.options?.values?.includes(i)||t.options?.values?.push(i),t.value=i)}catch(s){console.error("Model upload failed:",s),S().addAlert(D("toastMessages.fileUploadFailed"))}}u(ao,"handleModelUpload");async function lo(o,e){if(o?.length)try{const t=e.properties["Resource Folder"]||"",s=t.trim()?`3d/${t.trim()}`:"3d";await V.uploadMultipleFiles(o,s)}catch(t){console.error("Extra resources upload failed:",t),S().addAlert(D("toastMessages.extraResourcesUploadFailed"))}}u(lo,"handleResourcesUpload");function $e(o,e=!1){const t=document.createElement("input");return t.type="file",t.accept=o,t.multiple=e,t.style.display="none",t}u($e,"createFileInput");ee().registerExtension({name:"Comfy.Load3D",settings:[{id:"Comfy.Load3D.ShowGrid",category:["3D","Scene","Initial Grid Visibility"],name:"Initial Grid Visibility",tooltip:"Controls whether the grid is visible by default when a new 3D widget is created. This default can still be toggled individually for each widget after creation.",type:"boolean",defaultValue:!0,experimental:!0},{id:"Comfy.Load3D.BackgroundColor",category:["3D","Scene","Initial Background Color"],name:"Initial Background Color",tooltip:"Controls the default background color of the 3D scene. This setting determines the background appearance when a new 3D widget is created, but can be adjusted individually for each widget after creation.",type:"color",defaultValue:"282828",experimental:!0},{id:"Comfy.Load3D.CameraType",category:["3D","Camera","Initial Camera Type"],name:"Initial Camera Type",tooltip:"Controls whether the camera is perspective or orthographic by default when a new 3D widget is created. This default can still be toggled individually for each widget after creation.",type:"combo",options:["perspective","orthographic"],defaultValue:"perspective",experimental:!0},{id:"Comfy.Load3D.LightIntensity",category:["3D","Light","Initial Light Intensity"],name:"Initial Light Intensity",tooltip:"Sets the default brightness level of lighting in the 3D scene. This value determines how intensely lights illuminate objects when a new 3D widget is created, but can be adjusted individually for each widget after creation.",type:"number",defaultValue:3,experimental:!0},{id:"Comfy.Load3D.LightIntensityMaximum",category:["3D","Light","Light Intensity Maximum"],name:"Light Intensity Maximum",tooltip:"Sets the maximum allowable light intensity value for 3D scenes. This defines the upper brightness limit that can be set when adjusting lighting in any 3D widget.",type:"number",defaultValue:10,experimental:!0},{id:"Comfy.Load3D.LightIntensityMinimum",category:["3D","Light","Light Intensity Minimum"],name:"Light Intensity Minimum",tooltip:"Sets the minimum allowable light intensity value for 3D scenes. This defines the lower brightness limit that can be set when adjusting lighting in any 3D widget.",type:"number",defaultValue:1,experimental:!0},{id:"Comfy.Load3D.LightAdjustmentIncrement",category:["3D","Light","Light Adjustment Increment"],name:"Light Adjustment Increment",tooltip:"Controls the increment size when adjusting light intensity in 3D scenes. A smaller step value allows for finer control over lighting adjustments, while a larger value results in more noticeable changes per adjustment.",type:"slider",attrs:{min:.1,max:1,step:.1},defaultValue:.5,experimental:!0},{id:"Comfy.Load3D.3DViewerEnable",category:["3D","3DViewer","Enable"],name:"Enable 3D Viewer (Beta)",tooltip:"Enables the 3D Viewer (Beta) for selected nodes. This feature allows you to visualize and interact with 3D models directly within the full size 3d viewer.",type:"boolean",defaultValue:!1,experimental:!0},{id:"Comfy.Load3D.PLYEngine",category:["3D","PLY","PLY Engine"],name:"PLY Engine",tooltip:'Select the engine for loading PLY files. "threejs" uses the native Three.js PLYLoader (best for mesh PLY files). "fastply" uses an optimized loader for ASCII point cloud PLY files. "sparkjs" uses Spark.js for 3D Gaussian Splatting PLY files.',type:"combo",options:["threejs","fastply","sparkjs"],defaultValue:"threejs",experimental:!0}],commands:[{id:"Comfy.3DViewer.Open3DViewer",icon:"pi pi-pencil",label:"Open 3D Viewer (Beta) for Selected Node",function:u(()=>{const o=p.canvas.selected_nodes;if(!o||Object.keys(o).length!==1)return;const e=o[Object.keys(o)[0]];if(!Et(e))return;T.copyToClipspace(e),T.clipspace_return_node=e;const t={node:e};Ze().showDialog({key:"global-load3d-viewer",title:D("load3d.viewer.title"),component:Ot,props:t,dialogComponentProps:{style:"width: 80vw; height: 80vh;",maximizable:!0,onClose:u(async()=>{await ce().handleViewerClose(t.node)},"onClose")}})},"function")}],getCustomWidgets(){return{LOAD_3D(o){const e=$e(".gltf,.glb,.obj,.fbx,.stl,.ply,.spz,.splat,.ksplat",!1);o.properties["Resource Folder"]="",e.onchange=async()=>{await ao(e.files,o)},o.addWidget("button","upload 3d model","upload3dmodel",()=>{e.click()});const t=$e("*",!0);t.onchange=async()=>{await lo(t.files,o),t.value=""},o.addWidget("button","upload extra resources","uploadExtraResources",()=>{t.click()}),o.addWidget("button","clear","clear",()=>{re(o).waitForLoad3d(i=>{i.clearModel()});const n=o.widgets?.find(i=>i.name==="model_file");n&&(n.value="")});const s=new ke({node:o,name:"image",component:_e,inputSpec:ro,options:{}});return s.type="load3D",De(o,s),{widget:s}}}},getNodeMenuItems(o){if(o.constructor.comfyClass!=="Load3D")return[];const e=ce().getLoad3d(o);return e?e.isSplatModel()?[]:pe(e):[]},async nodeCreated(o){if(o.constructor.comfyClass!=="Load3D")return;const[e,t]=o.size;o.setSize([Math.max(e,300),Math.max(t,600)]),await xe(),re(o).waitForLoad3d(s=>{const i=o.properties["Camera Config"]?.state,r=new Me(s,o.properties),a=o.widgets?.find(f=>f.name==="model_file"),l=o.widgets?.find(f=>f.name==="width"),d=o.widgets?.find(f=>f.name==="height"),c=o.widgets?.find(f=>f.name==="image");if(a&&l&&d&&c){const f={loadFolder:"input",modelWidget:a,cameraState:i,width:l,height:d};r.configure(f),c.serializeValue=async()=>{const v=Mt.get(o);if(!v)return console.error("No load3d instance found for node"),null;const g=o.properties["Camera Config"]||{cameraType:v.getCurrentCameraType(),fov:v.cameraManager.perspectiveCamera.fov};g.state=v.getCameraState(),o.properties["Camera Config"]=g,v.stopRecording();const{scene:h,mask:m,normal:y}=await v.captureScene(l.value,d.value),[w,N,I]=await Promise.all([V.uploadTempImage(h,"scene"),V.uploadTempImage(m,"scene_mask"),V.uploadTempImage(y,"scene_normal")]);v.handleResize();const k={image:`threed/${w.name} [temp]`,mask:`threed/${N.name} [temp]`,normal:`threed/${I.name} [temp]`,camera_info:o.properties["Camera Config"]?.state||null,recording:""},x=v.getRecordingData();if(x){const[_]=await Promise.all([V.uploadTempImage(x,"recording","mp4")]);k.recording=`threed/${_.name} [temp]`}return k}}})}});ee().registerExtension({name:"Comfy.Preview3D",async beforeRegisterNodeDef(o,e){e.name==="Preview3D"&&(e.input.required.image=["PREVIEW_3D"])},getNodeMenuItems(o){if(o.constructor.comfyClass!=="Preview3D")return[];const e=ce().getLoad3d(o);return e?e.isSplatModel()?[]:pe(e):[]},getCustomWidgets(){return{PREVIEW_3D(o){const e=new ke({node:o,name:Ve.name,component:_e,inputSpec:Ve,options:{}});return e.type="load3D",De(o,e),{widget:e}}}},async nodeCreated(o){if(o.constructor.comfyClass!=="Preview3D")return;const[e,t]=o.size;o.setSize([Math.max(e,400),Math.max(t,550)]),await xe();const s=o.onExecuted;re(o).waitForLoad3d(n=>{const i=new Me(n,o.properties),r=o.widgets?.find(a=>a.name==="model_file");if(r){const a=o.properties["Last Time Model File"];if(a){r.value=a;const d=o.properties["Camera Config"]?.state,c={loadFolder:"output",modelWidget:r,cameraState:d};i.configure(c)}o.onExecuted=function(l){s?.apply(this,arguments);let d=l.result[0];if(!d){const g=D("toastMessages.unableToGetModelFilePath");console.error(g),S().addAlert(g)}let c=l.result[1],f=l.result[2];r.value=d.replaceAll("\\","/"),o.properties["Last Time Model File"]=r.value;const v={loadFolder:"output",modelWidget:r,cameraState:c,bgImagePath:f};i.configure(v),f&&n.setBackgroundImage(f)}}})}});function it(o){if(!o){console.error("[MaskEditor] No node provided");return}if(!o.imgs?.length&&o.previewMediaType!=="image"){console.error("[MaskEditor] Node has no images");return}At().openMaskEditor(o)}u(it,"openMaskEditor");function co(){const o=T.clipspace_return_node;if(!o){console.error("[MaskEditor] No clipspace_return_node found");return}it(o)}u(co,"openMaskEditorFromClipspace");function st(){return Ze().isDialogOpen("global-mask-editor")}u(st,"isOpened");const ze=u(async o=>{if(!st())return;const e=et(),t=e.brushSettings.size,s=o(t);e.setBrushSize(s)},"changeBrushSize");p.registerExtension({name:"Comfy.MaskEditor",settings:[{id:"Comfy.MaskEditor.BrushAdjustmentSpeed",category:["Mask Editor","BrushAdjustment","Sensitivity"],name:"Brush adjustment speed multiplier",tooltip:"Controls how quickly the brush size and hardness change when adjusting. Higher values mean faster changes.",type:"slider",attrs:{min:.1,max:2,step:.1},defaultValue:1,versionAdded:"1.0.0"},{id:"Comfy.MaskEditor.UseDominantAxis",category:["Mask Editor","BrushAdjustment","UseDominantAxis"],name:"Lock brush adjustment to dominant axis",tooltip:"When enabled, brush adjustments will only affect size OR hardness based on which direction you move more",type:"boolean",defaultValue:!0}],commands:[{id:"Comfy.MaskEditor.OpenMaskEditor",icon:"pi pi-pencil",label:"Open Mask Editor for Selected Node",function:u(()=>{const o=p.canvas.selected_nodes;if(!o||Object.keys(o).length!==1)return;const e=o[Object.keys(o)[0]];it(e)},"function")},{id:"Comfy.MaskEditor.BrushSize.Increase",icon:"pi pi-plus-circle",label:"Increase Brush Size in MaskEditor",function:u(()=>ze(o=>H.clamp(o+2,1,250)),"function")},{id:"Comfy.MaskEditor.BrushSize.Decrease",icon:"pi pi-minus-circle",label:"Decrease Brush Size in MaskEditor",function:u(()=>ze(o=>H.clamp(o-2,1,250)),"function")},{id:"Comfy.MaskEditor.ColorPicker",icon:"pi pi-palette",label:"Open Color Picker in MaskEditor",function:u(()=>{if(!st())return;et().colorInput?.click()},"function")}],init(){T.open_maskeditor=co,console.warn("[MaskEditor] ComfyApp.open_maskeditor is deprecated. Plugins should migrate to using the command system or direct node context menu integration.")}});const uo="Comfy.NodeTemplates",je="comfy.templates.json";class po extends Xe{static{u(this,"ManageTemplates")}templates;draggedEl;saveVisualCue;emptyImg;importInput;constructor(){super(),this.load().then(e=>{this.templates=e}),this.element.classList.add("comfy-manage-templates"),this.draggedEl=null,this.saveVisualCue=null,this.emptyImg=new Image,this.emptyImg.src="data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs=",this.importInput=b("input",{type:"file",accept:".json",multiple:!0,style:{display:"none"},parent:document.body,onchange:u(()=>this.importAll(),"onchange")})}createButtons(){const e=super.createButtons();return e[0].textContent="Close",e[0].onclick=()=>{clearTimeout(this.saveVisualCue),this.close()},e.unshift(b("button",{type:"button",textContent:"Export",onclick:u(()=>this.exportAll(),"onclick")})),e.unshift(b("button",{type:"button",textContent:"Import",onclick:u(()=>{this.importInput.click()},"onclick")})),e}async load(){let e=[];const t=await E.getUserData(je);if(t.status===200)try{e=await t.json()}catch{}else t.status!==404&&console.error(t.status+" "+t.statusText);return e??[]}async store(){const e=JSON.stringify(this.templates,void 0,4);try{await E.storeUserData(je,e,{stringify:!1})}catch(t){console.error(t),S().addAlert(t.message)}}async importAll(){for(const e of this.importInput.files)if(e.type==="application/json"||e.name.endsWith(".json")){const t=new FileReader;t.onload=async()=>{const s=JSON.parse(t.result);if(s?.templates){for(const n of s.templates)n?.name&&n?.data&&this.templates.push(n);await this.store()}},await t.readAsText(e)}this.importInput.value=null,this.close()}exportAll(){if(this.templates.length==0){S().addAlert(D("toastMessages.noTemplatesToExport"));return}const e=JSON.stringify({templates:this.templates},null,2),t=new Blob([e],{type:"application/json"});Le("node_templates.json",t)}show(){super.show(b("div",{},this.templates.flatMap((e,t)=>{let s;return[b("div",{dataset:{id:t.toString()},className:"templateManagerRow",style:{display:"grid",gridTemplateColumns:"1fr auto",border:"1px dashed transparent",gap:"5px",backgroundColor:"var(--comfy-menu-bg)"},ondragstart:u(n=>{this.draggedEl=n.currentTarget,n.currentTarget.style.opacity="0.6",n.currentTarget.style.border="1px dashed yellow",n.dataTransfer.effectAllowed="move",n.dataTransfer.setDragImage(this.emptyImg,0,0)},"ondragstart"),ondragend:u(n=>{n.target.style.opacity="1",n.currentTarget.style.border="1px dashed transparent",n.currentTarget.removeAttribute("draggable"),this.element.querySelectorAll(".templateManagerRow").forEach((i,r)=>{var a=Number.parseInt(i.dataset.id);i==this.draggedEl&&a!=r&&this.templates.splice(r,0,this.templates.splice(a,1)[0]),i.dataset.id=r.toString()}),this.store()},"ondragend"),ondragover:u(n=>{if(n.preventDefault(),n.currentTarget==this.draggedEl)return;let i=n.currentTarget.getBoundingClientRect();n.clientY>i.top+i.height/2?n.currentTarget.parentNode.insertBefore(this.draggedEl,n.currentTarget.nextSibling):n.currentTarget.parentNode.insertBefore(this.draggedEl,n.currentTarget)},"ondragover")},[b("label",{textContent:"Name: ",style:{cursor:"grab"},onmousedown:u(n=>{n.target.localName=="label"&&(n.currentTarget.parentNode.draggable="true")},"onmousedown")},[b("input",{value:e.name,dataset:{name:e.name},style:{transitionProperty:"background-color",transitionDuration:"0s"},onchange:u(n=>{clearTimeout(this.saveVisualCue);var i=n.target,r=i.parentNode.parentNode;this.templates[r.dataset.id].name=i.value.trim()||"untitled",this.store(),i.style.backgroundColor="rgb(40, 95, 40)",i.style.transitionDuration="0s",this.saveVisualCue=setTimeout(function(){i.style.transitionDuration=".7s",i.style.backgroundColor="var(--comfy-input-bg)"},15)},"onchange"),onkeypress:u(n=>{var i=n.target;clearTimeout(this.saveVisualCue),i.style.transitionDuration="0s",i.style.backgroundColor="var(--comfy-input-bg)"},"onkeypress"),$:u(n=>s=n,"$")})]),b("div",{},[b("button",{textContent:"Export",style:{fontSize:"12px",fontWeight:"normal"},onclick:u(()=>{const n=JSON.stringify({templates:[e]},null,2),i=new Blob([n],{type:"application/json"}),r=(s.value||e.name)+".json";Le(r,i)},"onclick")}),b("button",{textContent:"Delete",style:{fontSize:"12px",color:"red",fontWeight:"normal"},onclick:u(n=>{const i=n.target.parentNode.parentNode;i.parentNode.removeChild(i),this.templates.splice(i.dataset.id*1,1),this.store();var r=this;setTimeout(function(){r.element.querySelectorAll(".templateManagerRow").forEach((a,l)=>{a.dataset.id=l.toString()})},0)},"onclick")})])])]})))}}const le=new po,He=u(async o=>{const e=localStorage.getItem("litegrapheditor_clipboard");await o(),localStorage.setItem("litegrapheditor_clipboard",e)},"clipboardAction"),go={name:uo,getCanvasMenuItems(o){const e=[];e.push(null),e.push({content:"Save Selected as Template",disabled:!Object.keys(p.canvas.selected_nodes||{}).length,callback:u(async()=>{const s=await te().prompt({title:D("nodeTemplates.saveAsTemplate"),message:D("nodeTemplates.enterName"),defaultValue:""});s?.trim()&&He(()=>{p.canvas.copyToClipboard();let n=localStorage.getItem("litegrapheditor_clipboard");n=JSON.parse(n||"{}");const i=Object.keys(p.canvas.selected_nodes);for(let r=0;r<i.length;r++){const a=p.canvas.graph?.getNodeById(i[r]),l=a?.constructor.nodeData;let d=U.getGroupData(a);if(d){if(d=d.nodeData,n.groupNodes||(n.groupNodes={}),l==null)throw new TypeError("nodeData is not set");n.groupNodes[l.name]=d,n.nodes[r].type=l.name}}le.templates.push({name:s,data:JSON.stringify(n)}),le.store()})},"callback")});const t=le.templates.map(s=>({content:s.name,callback:u(()=>{He(async()=>{const n=JSON.parse(s.data);await Y.registerFromWorkflow(n.groupNodes,{}),n.reroutes?(localStorage.setItem("litegrapheditor_clipboard",s.data),p.canvas.pasteFromClipboard()):Qe(s.data,p.canvas)})},"callback")}));return t.push(null,{content:"Manage",callback:u(()=>le.show(),"callback")}),e.push({content:"Node Templates",submenu:{options:t}}),e}};p.registerExtension(go);p.registerExtension({name:"Comfy.NoteNode",registerCustomNodes(){class o extends de{static{u(this,"NoteNode")}static category;static collapsable;static title_mode;groupcolor=R.node_colors.yellow.groupcolor;isVirtualNode;constructor(s){super(s),this.color=R.node_colors.yellow.color,this.bgcolor=R.node_colors.yellow.bgcolor,this.properties||(this.properties={text:""}),$.STRING(this,"text",["STRING",{default:this.properties.text,multiline:!0}],p),this.serialize_widgets=!0,this.isVirtualNode=!0}}C.registerNodeType("Note",Object.assign(o,{title_mode:C.NORMAL_TITLE,title:"Note",collapsable:!0})),o.category="utils";class e extends de{static{u(this,"MarkdownNoteNode")}static title="Markdown Note";groupcolor=R.node_colors.yellow.groupcolor;constructor(s){super(s),this.color=R.node_colors.yellow.color,this.bgcolor=R.node_colors.yellow.bgcolor,this.properties||(this.properties={text:""}),$.MARKDOWN(this,"text",["STRING",{default:this.properties.text}],p),this.serialize_widgets=!0,this.isVirtualNode=!0}}C.registerNodeType("MarkdownNote",e),e.category="utils"}});ee().registerExtension({name:"Comfy.PreviewAny",async beforeRegisterNodeDef(o,e){if(e.name==="PreviewAny"){const t=o.prototype.onNodeCreated;o.prototype.onNodeCreated=function(){t&&t.apply(this,[]);const n=$.MARKDOWN(this,"preview",["MARKDOWN",{}],p).widget,i=$.STRING(this,"preview",["STRING",{multiline:!0}],p).widget,r=$.BOOLEAN(this,"previewMode",["BOOLEAN",{label_on:"Markdown",label_off:"Plaintext",default:!1}],p);r.widget.callback=a=>{n.hidden=!a,n.options.hidden=!a,i.hidden=a,i.options.hidden=a},n.hidden=!0,n.options.hidden=!0,n.options.read_only=!0,n.element.readOnly=!0,n.element.disabled=!0,n.serialize=!1,i.hidden=!1,i.options.hidden=!1,i.options.read_only=!0,i.element.readOnly=!0,i.element.disabled=!0,i.serialize=!1};const s=o.prototype.onExecuted;o.prototype.onExecuted=function(n){s?.apply(this,[n]);const i=this.widgets?.filter(r=>r.name==="preview")??[];for(const r of i){const a=n.text??"";r.value=Array.isArray(a)?a[0]??"":a}}}}});p.registerExtension({name:"Comfy.RerouteNode",registerCustomNodes(o){class e extends de{static{u(this,"RerouteNode")}static category;static defaultVisibility=!1;constructor(s){super(s??""),this.properties||(this.properties={}),this.properties.showOutputText=e.defaultVisibility,this.properties.horizontal=!1,this.addInput("","*"),this.addOutput(this.properties.showOutputText?"*":"","*"),this.isVirtualNode=!0}onAfterGraphConfigured(){requestAnimationFrame(()=>{this.onConnectionsChange(C.INPUT,void 0,!0)})}clone(){const s=super.clone();return s&&(s.removeOutput(0),s.addOutput(this.properties.showOutputText?"*":"","*"),s.setSize(s.computeSize()),s)}onConnectionsChange(s,n,i){const{graph:r}=this;if(!r||o.configuringGraph)return;if(i&&s===C.OUTPUT&&new Set(this.outputs[0].links?.map(N=>r.links[N]?.type)?.filter(N=>N&&N!=="*")??[]).size>1){const N=[];for(const I of this.outputs[0].links??[]){const k=r.links[I];N.push(k)}N.pop();for(const I of N)r.getNodeById(I.target_id)?.disconnectInput(I.target_slot)}let a=this,l=[],d=null,c=null;for(;a;){l.unshift(a);const w=a.inputs[0].link;if(w!==null){const N=r.links[w];if(!N)return;const I=r.getNodeById(N.origin_id);if(!I)return;if(I instanceof e)I===this?(a.disconnectInput(N.target_slot),a=null):a=I;else{c=a,d=I.outputs[N.origin_slot]?.type??null;break}}else{a=null;break}}const f=[this];let v=null;for(;f.length;){a=f.pop();const w=a.outputs?.[0]?.links??[];for(const N of w){const I=r.links[N];if(!I)continue;const k=r.getNodeById(I.target_id);if(k)if(k instanceof e)f.push(k),l.push(k);else{const x=k.inputs[I.target_slot],_=x.type,O=!d||!_||C.isValidConnection(d,_);if(!O){k.disconnectInput(I.target_slot);continue}k.onConnectionsChange?.(C.INPUT,I.target_slot,O,I,x),v=k.inputs[I.target_slot].type}}}const g=d||v||"*",h=R.link_type_colors[g];let m,y;for(const w of l){w.outputs[0].type=d||"*",w.__outputType=g,w.outputs[0].name=w.properties.showOutputText?`${g}`:"",w.setSize(w.computeSize());for(const N of w.outputs[0].links||[]){const I=r.links[N];if(!I||(I.color=h,o.configuringGraph))continue;const k=r.getNodeById(I.target_id);if(!k)continue;const x=k.inputs?.[I.target_slot];if(x?.widget){const _=Se(x);m||(m=_[1]??{},y=_[0]);const O=ae(x,[_[0],m]);O.customConfig&&(m=O.customConfig)}}}for(const w of l)m&&v?(w.inputs[0].widget={name:"value"},Ie(w.inputs[0],[y??`${g}`,m])):Ie(w.inputs[0],void 0);if(c?.inputs?.[0]?.link){const w=r.links[c.inputs[0].link];w&&(w.color=h)}}getExtraMenuOptions(s,n){return n.unshift({content:(this.properties.showOutputText?"Hide":"Show")+" Type",callback:u(()=>{this.properties.showOutputText=!this.properties.showOutputText,this.properties.showOutputText?this.outputs[0].name=`${this.__outputType||this.outputs[0].type}`:this.outputs[0].name="",this.setSize(this.computeSize()),o.canvas.setDirty(!0,!0)},"callback")},{content:(e.defaultVisibility?"Hide":"Show")+" Type By Default",callback:u(()=>{e.setDefaultTextVisibility(!e.defaultVisibility)},"callback")}),[]}computeSize(){return[this.properties.showOutputText&&this.outputs&&this.outputs.length?Math.max(75,C.NODE_TEXT_SIZE*this.outputs[0].name.length*.6+40):75,26]}static setDefaultTextVisibility(s){e.defaultVisibility=s,s?localStorage["Comfy.RerouteNode.DefaultVisibility"]="true":delete localStorage["Comfy.RerouteNode.DefaultVisibility"]}}e.setDefaultTextVisibility(!!localStorage["Comfy.RerouteNode.DefaultVisibility"]),C.registerNodeType("Reroute",Object.assign(e,{title_mode:C.NO_TITLE,title:"Reroute",collapsable:!1})),e.category="utils"}});const fo=new Set(["SaveImage","SaveVideo","SaveAnimatedWEBP","SaveWEBM","SaveAudio","SaveGLB","SaveAnimatedPNG","CLIPSave","VAESave","ModelSave","LoraSave","SaveLatent"]);p.registerExtension({name:"Comfy.SaveImageExtraOutput",async beforeRegisterNodeDef(o,e,t){if(fo.has(e.name)){const s=o.prototype.onNodeCreated;o.prototype.onNodeCreated=function(){const n=s?s.apply(this,arguments):void 0,i=this.widgets.find(r=>r.name==="filename_prefix");return i.serializeValue=()=>Ke(t.graph,i.value),n}}else{const s=o.prototype.onNodeCreated;o.prototype.onNodeCreated=function(){const n=s?s.apply(this,arguments):void 0;return(!this.properties||!("Node name for S&R"in this.properties))&&this.addProperty("Node name for S&R",this.constructor.type,"string"),n}}}});const qe={name:"image",type:"Preview3D",isPreview:!0};ee().registerExtension({name:"Comfy.SaveGLB",async beforeRegisterNodeDef(o,e){e.name==="SaveGLB"&&(e.input.required.image=["PREVIEW_3D"])},getCustomWidgets(){return{PREVIEW_3D(o){const e=new ke({node:o,name:qe.name,component:_e,inputSpec:qe,options:{}});return e.type="load3D",De(o,e),{widget:e}}}},getNodeMenuItems(o){if(o.constructor.comfyClass!=="SaveGLB")return[];const e=ce().getLoad3d(o);return e?e.isSplatModel()?[]:pe(e):[]},async nodeCreated(o){if(o.constructor.comfyClass!=="SaveGLB")return;const[e,t]=o.size;o.setSize([Math.max(e,400),Math.max(t,550)]),await xe();const s=o.onExecuted;o.onExecuted=function(n){s?.apply(this,arguments);const i=n["3d"][0];re(o).waitForLoad3d(r=>{const a=o.widgets?.find(l=>l.name==="image");if(r&&a){const l=i.subfolder+"/"+i.filename;a.value=l,new Me(r,o.properties).configureForSaveMesh(i.type,l)}})}}});function ho(o,e){const t=e.selectedItems;if(t.size<=1)return;const s=Pt(t,10);if(!s)return;const[n,i,r,a]=s;o.save();const l=2/e.ds.scale;o.lineWidth=l,o.strokeStyle=getComputedStyle(document.documentElement).getPropertyValue("--border-color").trim()||"#ffffff66";const d=5/e.ds.scale;o.setLineDash([d,d]),o.beginPath(),o.roundRect(n,i,r,a,8/e.ds.scale),o.stroke(),o.restore()}u(ho,"drawSelectionBorder");const mo={name:"Comfy.SelectionBorder",async init(){const o=p.canvas.onDrawForeground;p.canvas.onDrawForeground=function(e,t){o?.call(this,e,t),ho(e,p.canvas)}}};p.registerExtension(mo);let ie=!1,se=0;p.registerExtension({name:"Comfy.SimpleTouchSupport",setup(){let o=null,e=null,t=null,s=null;function n(a){return Math.hypot(a.touches[0].clientX-a.touches[1].clientX,a.touches[0].clientY-a.touches[1].clientY)}u(n,"getMultiTouchPos");function i(a){return{clientX:(a.touches[0].clientX+a.touches[1].clientX)/2,clientY:(a.touches[0].clientY+a.touches[1].clientY)/2}}u(i,"getMultiTouchCenter"),p.canvasEl.parentElement?.addEventListener("touchstart",a=>{se+=a.changedTouches.length,t=null,s=null,a.touches?.length===1?(e=new Date,t=a.touches[0]):(e=null,a.touches?.length===2&&(s=p.canvas.ds.scale,t=i(a),o=n(a),p.canvas.pointer.isDown=!1))},!0),p.canvasEl.parentElement?.addEventListener("touchend",a=>{if(se-=a.changedTouches.length,a.touches?.length!==1&&(ie=!1),e&&!a.touches?.length){if(new Date().getTime()-e.getTime()>600&&a.target===p.canvasEl){const l={button:2,clientX:a.changedTouches[0].clientX,clientY:a.changedTouches[0].clientY,pointerId:1,isPrimary:!0};p.canvasEl.dispatchEvent(new PointerEvent("pointerdown",l)),setTimeout(()=>{p.canvasEl.dispatchEvent(new PointerEvent("pointerup",l))}),a.preventDefault()}e=null}});const r=u(()=>{se=0,ie=!1,e=null,t=null,s=null,o=null},"resetTouchState");document.addEventListener("visibilitychange",()=>{document.hidden&&r()}),p.canvasEl.parentElement?.addEventListener("touchcancel",r),p.canvasEl.parentElement?.addEventListener("touchmove",a=>{if(e&&t&&a.touches?.length===1){const c=a.touches[0],f=c.clientX-t.clientX,v=c.clientY-t.clientY;f*f+v*v>30&&(e=null)}if(a.touches?.length===2&&t&&!a.ctrlKey&&!a.shiftKey){a.preventDefault(),p.canvas.pointer.isDown=!1,ie=!0,C.closeAllContextMenus(window),p.canvas.search_box?.close();const c=n(a),f=i(a);if(s===null||o===null)return;let v=s*c/o;const g=(f.clientX-t.clientX)/v,h=(f.clientY-t.clientY)/v;v<p.canvas.ds.min_scale?v=p.canvas.ds.min_scale:v>p.canvas.ds.max_scale&&(v=p.canvas.ds.max_scale);const m=p.canvas.ds.scale;p.canvas.ds.scale=v,Math.abs(p.canvas.ds.scale-1)<.01&&(p.canvas.ds.scale=1);const y=p.canvas.ds.scale,w=u(N=>[f.clientX/N-p.canvas.ds.offset[0],f.clientY/N-p.canvas.ds.offset[1]],"convertScaleToOffset");var l=w(m),d=w(y);p.canvas.ds.offset[0]+=g+d[0]-l[0],p.canvas.ds.offset[1]+=h+d[1]-l[1],t.clientX=f.clientX,t.clientY=f.clientY,p.canvas.setDirty(!0,!0)}},!0)}});const yo=R.prototype.processMouseDown;R.prototype.processMouseDown=function(o){if(!(ie||se))return p.canvas.pointer.isDown=!1,yo.apply(this,[o])};const wo=R.prototype.processMouseMove;R.prototype.processMouseMove=function(o){if(!(ie||se>1))return wo.apply(this,[o])};p.registerExtension({name:"Comfy.SlotDefaults",suggestionsNumber:null,init(){C.search_filter_enabled=!0,C.middle_click_slot_add_default_node=!0,this.suggestionsNumber=p.ui.settings.addSetting({id:"Comfy.NodeSuggestions.number",category:["Comfy","Node Search Box","NodeSuggestions"],name:"Number of nodes suggestions",tooltip:"Only for litegraph searchbox/context menu",type:"slider",attrs:{min:1,max:100,step:1},defaultValue:5,onChange:u(o=>{this.setDefaults(o)},"onChange")})},slot_types_default_out:{},slot_types_default_in:{},async beforeRegisterNodeDef(o,e){var t=e.name;const s=e.input?.required;for(const d in s){var n=s[d];if(typeof n[0]!="string")continue;var i=n[0];if(i in $){var r=n[1];if(!r?.forceInput)continue}if(i in this.slot_types_default_out||(this.slot_types_default_out[i]=["Reroute"]),this.slot_types_default_out[i].includes(t))continue;this.slot_types_default_out[i].push(t);const c=i.toLocaleLowerCase();c in C.registered_slot_in_types||(C.registered_slot_in_types[c]={nodes:[]}),C.registered_slot_in_types[c].nodes.push(o.comfyClass)}var a=e.output??[];for(const d of a){const c=d;c in this.slot_types_default_in||(this.slot_types_default_in[c]=["Reroute"]),!this.slot_types_default_in[c].includes(t)&&(this.slot_types_default_in[c].push(t),c in C.registered_slot_out_types||(C.registered_slot_out_types[c]={nodes:[]}),C.registered_slot_out_types[c].nodes.push(o.comfyClass),C.slot_types_out.includes(c)||C.slot_types_out.push(c))}var l=this.suggestionsNumber.value;this.setDefaults(l)},setDefaults(o){C.slot_types_default_out={},C.slot_types_default_in={};for(const e in this.slot_types_default_out)C.slot_types_default_out[e]=this.slot_types_default_out[e].slice(0,o);for(const e in this.slot_types_default_in)C.slot_types_default_in[e]=this.slot_types_default_in[e].slice(0,o)}});async function vo(o,e,t,s,n=!1){try{const i=new FormData;i.append("image",t),n&&i.append("subfolder","pasted");const r=await E.fetchApi("/upload/image",{method:"POST",body:i});if(r.status===200){const a=await r.json();let l=a.name;a.subfolder&&(l=a.subfolder+"/"+l),o.options.values.includes(l)||o.options.values.push(l),s&&(e.element.src=E.apiURL(ue(...tt(l))),o.value=l,o.callback?.(l))}else S().addAlert(r.status+" - "+r.statusText)}catch(i){S().addAlert(i)}}u(vo,"uploadFile");p.registerExtension({name:"Comfy.AudioWidget",async beforeRegisterNodeDef(o,e){["LoadAudio","SaveAudio","PreviewAudio","SaveAudioMP3","SaveAudioOpus"].includes(o.prototype.comfyClass)&&(e.input.required.audioUI=["AUDIO_UI",{}])},getCustomWidgets(){return{AUDIO_UI(o,e){const t=document.createElement("audio");t.controls=!0,t.classList.add("comfy-audio"),t.setAttribute("name","media");const s=o.addDOMWidget(e,"audioUI",t);s.serialize=!1;const{nodeData:n}=o.constructor;if(n==null)throw new TypeError("nodeData is null");if(n.output_node){s.element.classList.add("empty-audio-widget");const r=o.onExecuted;o.onExecuted=function(a){r?.apply(this,arguments);const l=a.audio;if(!l)return;const d=l[0];s.element.src=E.apiURL(ue(d.subfolder,d.filename,d.type)),s.element.classList.remove("empty-audio-widget")}}return s.onRemove=J(s.onRemove,()=>{s.element&&(s.element.pause(),s.element.src="",s.element.remove())}),{widget:s}}}},onNodeOutputsUpdated(o){for(const[e,t]of Object.entries(o))if("audio"in t){const s=Lt(p.rootGraph,e);if(!s)continue;const n=s.widgets.find(r=>r.name==="audioUI"),i=t.audio[0];n.element.src=E.apiURL(ue(i.subfolder,i.filename,i.type)),n.element.classList.remove("empty-audio-widget")}}});p.registerExtension({name:"Comfy.UploadAudio",async beforeRegisterNodeDef(o,e){e?.input?.required?.audio?.[1]?.audio_upload===!0&&(e.input.required.upload=["AUDIOUPLOAD",{}])},getCustomWidgets(){return{AUDIOUPLOAD(o,e){const t=o.widgets.find(c=>c.name==="audio"),s=o.widgets.find(c=>c.name==="audioUI");s.options.canvasOnly=!0;const n=u(()=>{typeof t.value=="string"&&(s.element.src=E.apiURL(ue(...tt(t.value))))},"onAudioWidgetUpdate");t.value&&n(),t.callback=n;const i=o.onGraphConfigured;o.onGraphConfigured=function(){i?.apply(this,arguments),t.value&&n()};const r=u(async c=>(c?.length&&vo(t,s,c[0],!0),c),"handleUpload"),a=u(c=>c.type.startsWith("audio/"),"isAudioFile"),{openFileSelection:l}=Gt(o,{accept:"audio/*",onSelect:r}),d=o.addWidget("button",e,"",l,{serialize:!1,canvasOnly:!0});return d.label=D("g.choose_file_to_upload"),Wt(o,{fileFilter:a,onDrop:r}),Rt(o,{fileFilter:a,onPaste:r}),o.previewMediaType="audio",{widget:d}}}}});p.registerExtension({name:"Comfy.RecordAudio",getCustomWidgets(){return{AUDIO_RECORD(o,e){const t=document.createElement("audio");t.controls=!0,t.classList.add("comfy-audio"),t.setAttribute("name","media");const s=o.addDOMWidget(e,"audioUI",t);s.options.canvasOnly=!1;let n=null,i=!1,r=[],a=null,l=null,d=null,c=null;s.serializeValue=async()=>{i&&n&&(d=new Promise(h=>{c=h}),n.stop(),await d);const v=s.element.src;if(!v)return S().addAlert(D("g.noAudioRecorded")),"";const g=await fetch(v).then(h=>h.blob());return await Q().convertBlobToFileAndSubmit(g)},l=o.addWidget("button",e,"",async()=>{if(i)n&&i&&n.stop();else try{a=await navigator.mediaDevices.getUserMedia({audio:!0}),n=new Bt(a,{mimeType:"audio/wav"}),r=[],n.ondataavailable=v=>{r.push(v.data)},n.onstop=async()=>{const v=new Blob(r,{type:"audio/wav"});Q().stopAllTracks(a),s.element.src&&s.element.src.startsWith("blob:")&&URL.revokeObjectURL(s.element.src),s.element.src=URL.createObjectURL(v),i=!1,l&&(l.label=D("g.startRecording")),c&&(c(),c=null,d=null)},n.onerror=v=>{console.error("MediaRecorder error:",v),Q().stopAllTracks(a),i=!1,l&&(l.label=D("g.startRecording")),c&&(c(),c=null,d=null)},n.start(),i=!0,l&&(l.label=D("g.stopRecording"))}catch(v){if(console.error("Error accessing microphone:",v),S().addAlert(D("g.micPermissionDenied")),n)try{n.stop()}catch{}Q().stopAllTracks(a),a=null,i=!1,l&&(l.label=D("g.startRecording"))}},{serialize:!1,canvasOnly:!1}),l.label=D("g.startRecording"),l.type="audiorecord";const f=o.onRemoved;return o.onRemoved=function(){i&&n&&n.stop(),Q().stopAllTracks(a),s.element.src?.startsWith("blob:")&&URL.revokeObjectURL(s.element.src),f?.call(this)},{widget:l}}}},async nodeCreated(o){o.constructor.comfyClass==="RecordAudio"&&await Q().registerWavEncoder()}});const bo=u(o=>{const[e,t]=o;return t?(t.image_upload===!0||t.video_upload===!0||t.animated_image_upload===!0)&&(Ft(o)||e==="COMBO"):!1},"isMediaUploadComboInput"),No=u((o,e)=>["IMAGEUPLOAD",{...e[1],imageInputName:o}],"createUploadInput");p.registerExtension({name:"Comfy.UploadImage",beforeRegisterNodeDef(o,e){const{input:t}=e??{},{required:s}=t??{};if(!s)return;const n=Object.entries(s).find(([i,r])=>bo(r));if(n){const[i,r]=n;s.upload=No(i,r)}}});const Ye=Symbol();p.registerExtension({name:"Comfy.WebcamCapture",getCustomWidgets(){return{WEBCAM(o,e){let t;o[Ye]=new Promise(r=>t=r);const s=document.createElement("div");s.style.background="rgba(0,0,0,0.25)",s.style.textAlign="center";const n=document.createElement("video");return n.style.height=n.style.width="100%",u(async()=>{try{const r=await navigator.mediaDevices.getUserMedia({video:!0,audio:!1});s.replaceChildren(n),setTimeout(()=>t(n),500),n.addEventListener("loadedmetadata",()=>t(n),!1),n.srcObject=r,n.play()}catch(r){const a=document.createElement("div");a.style.color="red",a.style.overflow="auto",a.style.maxHeight="100%",a.style.whiteSpace="pre-wrap",window.isSecureContext?a.textContent=`Unable to load webcam, please ensure access is granted:
2
+ `+r.message:a.textContent=`Unable to load webcam. A secure context is required, if you are not accessing ComfyUI on localhost (127.0.0.1) you will have to enable TLS (https)
3
+
4
+ `+r.message,s.replaceChildren(a)}},"loadVideo")(),{widget:o.addDOMWidget(e,"WEBCAM",s)}}}},nodeCreated(o){if(o.type,o.constructor.comfyClass!=="WebcamCapture")return;let e;const t=o.widgets.find(d=>d.name==="image"),s=o.widgets.find(d=>d.name==="width"),n=o.widgets.find(d=>d.name==="height"),i=o.widgets.find(d=>d.name==="capture_on_queue"),r=document.createElement("canvas"),a=u(()=>{r.width=s.value,r.height=n.value,r.getContext("2d").drawImage(e,0,0,s.value,n.value);const c=r.toDataURL("image/png"),f=new Image;f.onload=()=>{o.imgs=[f],p.canvas.setDirty(!0)},f.src=c},"capture"),l=o.addWidget("button","waiting for camera...","capture",a,{canvasOnly:!0});l.disabled=!0,l.serializeValue=()=>{},t.serializeValue=async()=>{if(i.value)a();else if(!o.imgs?.length){const h="No webcam image captured";throw S().addAlert(h),new Error(h)}const d=await new Promise(h=>r.toBlob(h)),c=`${+new Date}.png`,f=new File([d],c),v=new FormData;v.append("image",f),v.append("subfolder","webcam"),v.append("type","temp");const g=await E.fetchApi("/upload/image",{method:"POST",body:v});if(g.status!==200){const h=`Error uploading camera image: ${g.status} - ${g.statusText}`;throw S().addAlert(h),new Error(h)}return`webcam/${c} [temp]`},o[Ye].then(d=>{e=d,s.value||(s.value=e.videoWidth||640,n.value=e.videoHeight||480),l.disabled=!1,l.label=D("g.capture")})}});
5
+ //# sourceMappingURL=index-KizWjI6s.js.map